CI & Build / Plugin hooks (push) Successful in 18s
CI & Build / Python lint (push) Successful in 3s
CI & Build / TypeScript typecheck (push) Successful in 55s
CI & Build / integration (push) Successful in 1m23s
CI & Build / Python tests (push) Successful in 2m0s
CI & Build / Build & push image (push) Successful in 36s
moment_actions.resolve(tool, input) names every moment a call reaches and the action that reached it. One call can reach several: kubectl apply is a run, a deliver and a reach outside the workspace. Command tools match by how each segment of the line starts, with a word boundary; other tools by field=value arguments. The MCP server prefix and case are ignored. 56 shipped defaults cover the harness tools, Scribe tools and common command shapes. moment_mappings (migration 0116) holds what an install adds and the defaults it switches off. A removal is a stored row, so an upgrade does not switch the default back on. Per the operator ruling, corrections happen in the session: map_action and unmap_action (write tools) return now_reaches so the fix can be confirmed in the same reply. list_moments now shows each moment's actions on this install. REST mirrors both doors, recorded as human. Backup v21 carries the mappings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
48 lines
1.6 KiB
Python
48 lines
1.6 KiB
Python
"""moment_mappings — an install's own corrections to which actions reach which
|
|
moment (milestone 458 step 2)
|
|
|
|
Revision ID: 0116
|
|
Revises: 0115
|
|
Create Date: 2026-10-05
|
|
|
|
The moments and their default actions are code; this table holds what an
|
|
install adds ("make ship" is a deliver here) and the defaults it switches off.
|
|
User-owned configuration, so it cascades with the user. No CHECK on `effect`,
|
|
which the service validates (rule 36).
|
|
"""
|
|
import sqlalchemy as sa
|
|
from alembic import op
|
|
|
|
revision = "0116"
|
|
down_revision = "0115"
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.create_table(
|
|
"moment_mappings",
|
|
sa.Column("id", sa.BigInteger(), primary_key=True),
|
|
sa.Column(
|
|
"created_at", sa.DateTime(timezone=True), nullable=False,
|
|
server_default=sa.text("now()"),
|
|
),
|
|
sa.Column(
|
|
"user_id", sa.Integer(),
|
|
sa.ForeignKey("users.id", ondelete="CASCADE"), nullable=False,
|
|
),
|
|
sa.Column("tool", sa.Text(), nullable=False),
|
|
sa.Column("match", sa.Text(), nullable=False, server_default=""),
|
|
sa.Column("moment", sa.Text(), nullable=False),
|
|
sa.Column("effect", sa.Text(), nullable=False, server_default="add"),
|
|
sa.Column("reason", sa.Text(), nullable=False, server_default=""),
|
|
sa.Column("actor", sa.Text(), nullable=False, server_default="model"),
|
|
sa.UniqueConstraint(
|
|
"user_id", "tool", "match", "moment", name="uq_moment_mapping",
|
|
),
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_table("moment_mappings")
|