Files
FabledGrimoire/alembic/versions/0080_code_shape_proposals.py
bvandeusenandClaude Opus 5.5 79655fd19f
CI & Build / Python lint (push) Successful in 2s
CI & Build / Plugin hooks (push) Successful in 13s
CI & Build / TypeScript typecheck (push) Successful in 59s
CI & Build / integration (push) Successful in 1m32s
CI & Build / Python tests (push) Successful in 2m33s
CI & Build / Build & push image (push) Successful in 26s
docs(6207): the remaining migrations state their rationale in terms of the data
Record, milestone, phase and plan citations go from every migration header;
the "end before start" fix (0043) and the suppressed-count column (0095)
state the condition they prevent rather than the incident. 0053 and 0055
pointed at design specs under docs/superpowers that are not in the repo;
those pointers are removed.

Kept: alembic's generated "Create Date:" headers (template metadata, not
rationale), 0121's ARM_BORN justification beside the constant, and 0051's
illustrative "update task 42" format example.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 20:49:32 -04:00

55 lines
2.2 KiB
Python

"""Shape fingerprints + the mechanical proposer's columns
Revision ID: 0080
Revises: 0079
Create Date: 2026-08-21
Two additions to the ledger. `signature` / `body_sha` fingerprint each shape
(definition line + a whitespace/comment-insensitive hash of its block) so the
proposer can match on content and a later drift recheck can notice change,
without the ledger ever storing code. The proposal columns carry the
proposer's standing suggestion for an unclassified row — instance-of-#N with
a basis and score, or a derive-first group key — and `proposed_sha`
remembers the content it was judged at so a refresh re-examines only what
changed. Mechanical and recomputable: a restore that lacks them loses
nothing the next refresh does not rebuild.
"""
import sqlalchemy as sa
from alembic import op
revision = "0080"
down_revision = "0079"
branch_labels = None
depends_on = None
def upgrade() -> None:
op.add_column("code_shapes", sa.Column("signature", sa.Text(), nullable=False, server_default=""))
op.add_column("code_shapes", sa.Column("body_sha", sa.Text(), nullable=False, server_default=""))
op.add_column(
"code_shapes",
sa.Column(
"proposed_snippet_id",
sa.BigInteger(),
sa.ForeignKey("notes.id", ondelete="SET NULL"),
nullable=True,
),
)
op.add_column("code_shapes", sa.Column("proposal_basis", sa.Text(), nullable=True))
op.add_column("code_shapes", sa.Column("proposal_score", sa.Float(), nullable=True))
op.add_column("code_shapes", sa.Column("proposal_group", sa.Text(), nullable=True))
op.add_column("code_shapes", sa.Column("proposed_at", sa.DateTime(timezone=True), nullable=True))
op.add_column("code_shapes", sa.Column("proposed_sha", sa.Text(), nullable=False, server_default=""))
op.create_index(
"ix_code_shapes_proposed", "code_shapes", ["project_id", "proposed_snippet_id"]
)
def downgrade() -> None:
op.drop_index("ix_code_shapes_proposed", table_name="code_shapes")
for col in (
"proposed_sha", "proposed_at", "proposal_group", "proposal_score",
"proposal_basis", "proposed_snippet_id", "body_sha", "signature",
):
op.drop_column("code_shapes", col)