- Authoritative candidate capture with server-issued artifacts and raw-byte
immutability hashing (source_response_hash server-owned)
- Closed-period lifecycle: request-hash bound approvals, persisted closure
immutability violations, byte-for-byte catalog stability on reclosure
- Verification runs: persisted VerificationRun model + FK migration,
publish gate (block_publish), scheduled observability runs (02:00 UTC)
- FR-013 baseline inheritance: prior_release_id migration, plan_inheritance/
execute_inheritance classification and re-extraction, API endpoints
- Visual executor bound to release-deployment environment; caller mismatch
rejected; visual SSIM/reconciliation modules
- Query execution decomposed: envelope/model/executor split, no direct SQL
- AgentRun approvals extracted to submodule; evidence adapter; _utils
- Dashboard testing service decomposed into 30+ modules (all <400 LOC)
- Five Feature-037 agent tools with permission guards (tools_037.py)
- API readiness endpoint; Alembic env/migrations; test fixture repos
- Specs 036/037 contracts, openapi.yaml, schema.json, tasks/traceability
updated; semantic index rebuilt with 0 parse warnings
- Fix ADR-0003 parser ambiguity: remove [DEF🆔ADR] prose example
- Add axiom-mcp-agent-feedback.md: agent findings for MCP rework plan
- Tests: 298 service + 1464 API + 45 agent passing; ruff clean
84 lines
3.2 KiB
Python
84 lines
3.2 KiB
Python
# #region Alembic.AddVerificationRuns [C:3] [TYPE Module] [SEMANTICS alembic,verification,run,persistence]
|
|
# @ingroup Alembic
|
|
# @BRIEF Add verification_runs table for per-category verification outcome persistence.
|
|
# @LAYER Database
|
|
# @RELATION DEPENDS_ON -> [Models.VerificationRun]
|
|
# @INVARIANT FK on agent_run_id uses ON DELETE SET NULL — run survives agent run deletion.
|
|
# @INVARIANT FK on release_id uses ON DELETE SET NULL — run survives release deletion (audit retention).
|
|
# @RATIONALE Verification runs have their own identity and lifecycle independent of agent
|
|
# scenarios. The table stores immutable per-category outcomes with evidence refs.
|
|
# Release FK uses SET NULL so historical runs are preserved for audit when a release
|
|
# is deleted (audit-retention requirement).
|
|
# @REJECTED Embedding outcomes in AgentRun.events was rejected — verification runs have
|
|
# their own lifecycle. Storing as JSON on DashboardRelease was rejected — a
|
|
# release may have multiple verification runs over time.
|
|
|
|
"""add verification_runs table
|
|
|
|
Revision ID: h2i3j4k5l6m7
|
|
Revises: g1h2i3j4k5l6
|
|
Create Date: 2026-07-30 12:00:00.000000
|
|
"""
|
|
|
|
from collections.abc import Sequence
|
|
|
|
import sqlalchemy as sa
|
|
|
|
from alembic import op
|
|
|
|
# revision identifiers, used by Alembic.
|
|
revision: str = "h2i3j4k5l6m7"
|
|
down_revision: str | Sequence[str] | None = "g1h2i3j4k5l6"
|
|
branch_labels: str | Sequence[str] | None = None
|
|
depends_on: str | Sequence[str] | None = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
"""Create verification_runs table with FK to agent_runs and dashboard_releases."""
|
|
op.create_table(
|
|
"verification_runs",
|
|
sa.Column("id", sa.String(), nullable=False),
|
|
sa.Column(
|
|
"agent_run_id",
|
|
sa.String(),
|
|
sa.ForeignKey("agent_runs.id", ondelete="SET NULL"),
|
|
nullable=True,
|
|
index=True,
|
|
),
|
|
sa.Column("repository_id", sa.String(), nullable=False),
|
|
sa.Column(
|
|
"release_id",
|
|
sa.String(),
|
|
sa.ForeignKey("dashboard_releases.id", ondelete="SET NULL"),
|
|
nullable=True,
|
|
index=True,
|
|
),
|
|
sa.Column("trigger", sa.String(), nullable=False),
|
|
sa.Column("environment_id", sa.String(), nullable=False),
|
|
sa.Column("categories_run", sa.JSON(), nullable=False),
|
|
sa.Column("category_outcomes", sa.JSON(), nullable=False),
|
|
sa.Column("overall_status", sa.String(), nullable=False),
|
|
sa.Column("summary", sa.Text(), nullable=True),
|
|
sa.Column("created_at", sa.DateTime(), nullable=False),
|
|
sa.Column("created_by", sa.String(), nullable=False),
|
|
sa.PrimaryKeyConstraint("id"),
|
|
)
|
|
op.create_index(
|
|
"ix_verification_runs_agent_run",
|
|
"verification_runs",
|
|
["agent_run_id"],
|
|
)
|
|
op.create_index(
|
|
"ix_verification_runs_created",
|
|
"verification_runs",
|
|
["created_at"],
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
"""Drop verification_runs table and its indexes."""
|
|
op.drop_index("ix_verification_runs_agent_run", table_name="verification_runs")
|
|
op.drop_index("ix_verification_runs_created", table_name="verification_runs")
|
|
op.drop_table("verification_runs")
|
|
# #endregion Alembic.AddVerificationRuns
|