Shape ledger steps 5–7: write-path stamping, mechanical proposer, divergence readout (#2791, #2792, #2793) #117

Merged
bvandeusen merged 6 commits from dev into main 2026-08-21 07:32:23 -04:00
2 changed files with 5 additions and 3 deletions
Showing only changes of commit a9e1cddba7 - Show all commits
+1 -1
View File
@@ -512,7 +512,7 @@ async def stamp_write_path_instances(
{path, symbol, kind, snippet_id, reason} — empty in the common case. {path, symbol, kind, snippet_id, reason} — empty in the common case.
A shape the ledger has no live row for yet (it is being written right A shape the ledger has no live row for yet (it is being written right
now) gets a PROVISIONAL row under ``repo_key`` — first/last-seen unset now) gets a PROVISIONAL row under ``repo_key`` — first/last-seen empty
so the stamp is not lost to the next sync, which either confirms the so the stamp is not lost to the next sync, which either confirms the
shape (sets its seen marker) or stamps it vanished. No repo key → only shape (sets its seen marker) or stamps it vanished. No repo key → only
existing rows are stamped. existing rows are stamped.
+4 -2
View File
@@ -284,7 +284,7 @@ async def test_write_path_stamp_is_evidence_that_yields_to_judgment(seeded):
@pytest.mark.integration @pytest.mark.integration
async def test_a_brand_new_shape_gets_a_provisional_row_the_sync_settles(seeded): async def test_a_brand_new_shape_gets_a_provisional_row_the_sync_settles(seeded):
"""The shape being written right now has no ledger row yet. With the """The shape being written right now has no ledger row yet. With the
hook's repo key it gets a provisional one — seen markers unset — so the hook's repo key it gets a provisional one — seen markers empty — so the
stamp survives until the next sync, which confirms it (sets the marker) stamp survives until the next sync, which confirms it (sets the marker)
or stamps it vanished. Without a repo key only existing rows are touched.""" or stamps it vanished. Without a repo key only existing rows are touched."""
from datetime import datetime, timezone from datetime import datetime, timezone
@@ -309,7 +309,9 @@ async def test_a_brand_new_shape_gets_a_provisional_row_the_sync_settles(seeded)
CodeShape.project_id == pid, CodeShape.path == "src/new.py", CodeShape.project_id == pid, CodeShape.path == "src/new.py",
))).scalar_one() ))).scalar_one()
assert row.status == "instance" and row.classified_by == "hook" assert row.status == "instance" and row.classified_by == "hook"
assert row.first_seen_commit is None and row.last_seen_commit is None # "Unset" is the column's empty default — the markers are non-null
# Text, and the sync is what first fills them.
assert row.first_seen_commit == "" and row.last_seen_commit == ""
# The sync sees the shape in the tree → confirmed, stamp intact. # The sync sees the shape in the tree → confirmed, stamp intact.
await sync_repo_shapes( await sync_repo_shapes(