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
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>
60 lines
2.0 KiB
Python
60 lines
2.0 KiB
Python
"""milestone_embeddings — a plan becomes findable by meaning
|
|
|
|
Revision ID: 0102
|
|
Revises: 0101
|
|
Create Date: 2026-09-15
|
|
|
|
`search` covered notes, tasks and rules, and a milestone — the record a plan
|
|
lives in — could not be found at all. So "is there already a plan for this?"
|
|
had no tool, and a project whose roadmap was written as milestones had every
|
|
later plan opened as a new milestone beside the one that already described it.
|
|
|
|
The sibling of rule_embeddings (0089), for the reasons its model docstring
|
|
gives. The vectors are DERIVED: nothing is backfilled here, the startup
|
|
backfill writes them.
|
|
"""
|
|
import sqlalchemy as sa
|
|
from alembic import op
|
|
|
|
revision = "0102"
|
|
down_revision = "0101"
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
# Matches note_embeddings and rule_embeddings — bge-small-en-v1.5, 384-dim.
|
|
_EMBEDDING_DIM = 384
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.create_table(
|
|
"milestone_embeddings",
|
|
sa.Column(
|
|
"milestone_id", sa.Integer(),
|
|
sa.ForeignKey("milestones.id", ondelete="CASCADE"), primary_key=True,
|
|
),
|
|
sa.Column("chunk_index", sa.Integer(), primary_key=True),
|
|
sa.Column("chunk_text", sa.Text(), nullable=False),
|
|
sa.Column("chunker_version", sa.Integer(), nullable=False),
|
|
sa.Column(
|
|
"updated_at", sa.DateTime(timezone=True), nullable=False,
|
|
server_default=sa.text("now()"),
|
|
),
|
|
)
|
|
# Raw DDL for the vector column, as 0067 and 0089 do: the type comes from
|
|
# the pgvector extension, not SQLAlchemy's type system.
|
|
op.execute(
|
|
f"ALTER TABLE milestone_embeddings ADD COLUMN embedding vector({_EMBEDDING_DIM}) NOT NULL"
|
|
)
|
|
op.execute(
|
|
"""
|
|
CREATE INDEX ix_milestone_embeddings_embedding_hnsw
|
|
ON milestone_embeddings
|
|
USING hnsw (embedding vector_cosine_ops)
|
|
"""
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.execute("DROP INDEX IF EXISTS ix_milestone_embeddings_embedding_hnsw")
|
|
op.drop_table("milestone_embeddings")
|