Version. v0.10
Date. 2026-07-31
Author. Claude.ai (drafting session). Approving: Marvin Percival.
Charter. standing-notes/dunin7-standing-authorization-charter-v0_1. No session executes a change request it drafted (§1).
Target. /Users/dunin7/loomworks-engine, branch cr-2026-159-option-a.
Supersedes. v0.9, drafted and never filed — halted at pre-flight. v0.8 at record 9c6f9a5, v0.6 at c53476b, v0.5 at 6165bf6, v0.1–v0.4. All filed versions stand as siblings, unaltered. The record holds no v0.7 — drafted, halted at pre-flight, never filed.
Status. RESUME. src/ is complete at branch head f3a1bbf. The remaining work is the test tree.
Changes from v0.9. One stale anchor, no design change. §4 told the executing session to re-derive the test-tree counts "at Step 0" — a step this run does not contain, since §5 begins at Step 3 and §8 forbids performing Step 0. The instruction was right and its anchor was stale, so §4 and §8 gave the same instruction pointing at two different places, one of them prohibited. Second occurrence of the same defect — v0.7 left §9 anchored to a renumbered sequence in the same way. The generator is renumbering a sequence without sweeping for references to the old numbers. (v0.9 was halted at pre-flight and never filed.)
Changes from v0.8, carried. The design is confirmed and the test tree is scoped. v0.8 sized the work at 83 sites in src/ and was silent on the test tree, which holds a reported 322 append_event calls across 88 files that a required parameter breaks. Option A is confirmed by Operator ruling (2026-07-31). This version adds the invariant that makes option A correct, the constraint on pass-through that v0.8 stated nowhere, two test helpers that make the work mechanical rather than 322 hand edits, and the second shape-three site the build found.
The build halted at a real fork. Finishing option A required deciding something no prior version had: what happens when a model_copy advances an object's version without re-minting its provenance. Under the old fabricated-value regime that was silently wrong and worked. Under option A it is a hard IntegrityError — the build session reproduced 292 of them, all duplicate key value violates unique constraint "substrate_events_pkey".
Three alternatives were put to the Operator. He ruled: finish option A.
Set aside — drop the field. Provenance loses wasGeneratedBy; a provenance walk joins on memory_events.event_id, which is already the primary key with a uuid4 default. The drafting session leaned this way, on the ground that a field required to equal a column in the row carrying it is a denormalisation, and that this arc's whole cost is maintaining it. Set aside by the Operator. Recorded here in full because it is the alternative most likely to be revisited, and because the reasoning against maintaining the duplicate does not disappear by being overruled — it becomes a known, accepted cost.
Set aside — option C, stamp-and-return. append_event stamps the field and returns the corrected object, repairing option B's one defect. Cheapest to build; the test tree would need no change at all. Set aside. It keeps the duplicate permanently and leaves 83 sites stamping a discarded value.
Chosen — option A, finished. The caller mints; the object the caller holds and the row written carry one value by construction. Highest build cost, and the only option in which no value anywhere in the system is fabricated, corrected, or derived after the fact.
One object version is one event is one freshly minted identifier.
This was implicit in every prior version and is why the build broke. Stated plainly:
MemoryObject version that will be appended carries its own wasGeneratedBy, minted for that version.model_copy that advances version must re-mint provenance.wasGeneratedBy. Copying it forward attaches to version 2 the identifier of the event that produced version 1 — which contradicts the field's own definition and, since event_id is the primary key, is now rejected by the database.memory_events.event_id is primary_key=True. A duplicate is an IntegrityError, not a silent wrong value. That enforcement is a feature of option A: the invariant cannot rot.
v0.6 introduced shape three — the constructor mints, the append passes through event_id=obj.provenance.wasGeneratedBy. It did not say when that is safe, and the build found the boundary the hard way.
Pass-through is valid only where the object was freshly constructed and is appended exactly once.
It is invalid for any object obtained by model_copy from an already-appended version, because that object carries the prior version's identifier. A pass-through at such a site is the 292-error case.
[EXECUTING SESSION: every pass-through site must satisfy both conditions — freshly constructed, appended once. Name the constructor in a comment per acceptance item 9. Any site where either condition cannot be established halts.]
Branch cr-2026-159-option-a at f3a1bbf. main unmoved at a317051.
test_stele_router_mount.py::test_stele_router_mounts_and_begin_resolves_end_to_end (baseline 1 failed / 3439 passed / 68 skipped). Sweep confirmed 83 sites across 36 files. Option-B branch deleted, SHAs recorded. CR archived to docs/phase-crs/.append_event takes a required event_id; docstring correction applied.src/ complete, 93 of 93 appends. All three shapes resolved. No uuid.uuid4() remains as a direct argument to wasGeneratedBy anywhere in src/.
A second shape-three site the build found, not listed in v0.8: reconciliation_evaluator.surface_proposal_to_accounting_room, whose constructor detect_reconciliation_drift mints one identifier per proposal in a loop sized by the number of drifting accounts. Same structure as the Finding case, same treatment, constructor named in a comment. Recorded so the count of shape-three sites is two, not one.
Nothing in src/ is revised by this version.
Reported by the build session and to be re-derived at the resume re-confirmation (§8), not inherited: roughly 322 append_event calls across 88 files, and roughly 54 version-advancing model_copy sites. [EXECUTING SESSION: report the actual counts alongside the other re-confirmations, before Step 3. If they diverge materially from these, say so — these are one session's numbers, not a verified baseline.] (Anchor corrected at v0.10. v0.9 said "at Step 0", which this run does not contain — §5 begins at Step 3 and §8 forbids performing Step 0. The instruction was right and its anchor was stale.)
Hand-editing 322 sites is where a transform pass produced invalid Python once already. Add two helpers to the test support module and route the sites through them.
Helper one — mint and stamp at construction.
def with_event_id(obj: MemoryObject) -> tuple[MemoryObject, UUID]:
"""Mint a fresh event id, stamp it into provenance, return both.
The object returned is the one to append; the id returned is the one
to pass. One value, two destinations — the same guarantee src/ gives.
"""
Helper two — advance a version and re-mint.
def next_object_version(obj: MemoryObject, **updates) -> MemoryObject:
"""model_copy that advances version AND re-mints provenance.
Copying provenance forward attaches the prior version's event id to a
new version. Under the option-A invariant that is an IntegrityError,
not a silent wrong value. Use this instead of model_copy wherever the
result will be appended.
"""
Helper two is the fix for the 292 failures, and it is the reason the test tree is a mechanical pass rather than a redesign.
Do not pass event_id=uuid.uuid4() at test append sites. It restores the prior behaviour exactly: the row's event_id and the object's wasGeneratedBy diverge, and the fabrication this CR exists to remove persists in every fixture. (This was alternative 1 in the build session's halt report; it is rejected here rather than left open.)
Do not pass through from a model_copy result. §2.1.
Some tests assert on provenance values. Where an assertion compares a copied-forward identifier, it encodes the defect. Update the assertion to the invariant — the appended row's event_id equals that object version's wasGeneratedBy — rather than to whatever the new value happens to be.
Resume at Step 3. Steps 0, 1 and 2 are done and are not repeated.
Step 3 — the helpers. §4.1, in the test support module. No call site changed yet.
Commit: CR-2026-159 step 3: test helpers for minting and version advance
Step 4 — the version-advancing sites first. Route every model_copy that advances a version and will be appended through next_object_version. This before the append sites — it is the smaller set and the one that causes the integrity failures, so doing it first means Step 5's failures are missing-argument errors only.
Commit: CR-2026-159 step 4: version-advancing copies re-mint provenance
Step 5 — the append sites, in tranches. By directory or module cluster, suite run at each tranche against the Step 0 baseline set. Commit per tranche.
Commit per tranche: CR-2026-159 step 5/N: <cluster> test append sites
Step 6 — the two backfills. wasderivedfrom_backfill.py:75, redirect_edge_backfill.py:148. Unchanged from v0.4 §6.3–§6.4; neither calls append_event.
Commit: CR-2026-159 step 6: repair the two backfill provenance fabrications
Step 7 — regression tests. Row-and-object agreement at a mechanical site, a shape-two site, and a shape-three site. Plus one asserting that a version-advancing copy re-mints — the invariant that broke this build.
Commit: CR-2026-159 step 7: provenance equality and invariant regression tests
CHECKPOINT A — report, then proceed. Failure set versus the Step 0 baseline; the regression tests; live verification on a throwaway database showing row, both JSONB columns, and the returned object agreeing. No Operator confirmation. Halt and queue on: any failure outside the baseline set; any pass-through site failing §2.1's two conditions; any charter §6 anomaly.
Step 8 — implementation notes, carrying D-4's recorded statement unchanged.
CHECKPOINT B — merge and tag. --no-ff to main, tag provenance-seam-v0_1, push. Authorized under R-2 including the push. Deployment is never autonomous (F-1).
append_event cannot be called without an event identifier.provenance.wasGeneratedBy equals the row's event_id, in both the provenance column and the nested payload.wasGeneratedBy with any other.model_copy whose result is appended copies provenance forward.personal_engagement.py sites still satisfy it.uuid.uuid4() as a direct argument to wasGeneratedBy anywhere — src/ or tests/.memory/events.py's docstring names all four write paths.0102.loomworks-engine; no database touched except a throwaway.wasGeneratedBy from Provenance. Set aside by Operator ruling; recorded at §1.test_stele_router_mount's 401. Baseline, out of scope, owed a build-list item.This block names the resume point and the fences. It does not restate §5's steps — §5 is the sequence, §8 says where to enter it.
CR-2026-159 — B-29, the provenance seam. RESUMING session.
CR: loomworks-record/change-requests/cr-2026-159-provenance-seam-v0_10.md
Confirm v0_10 is the highest version present. v0_1 through v0_9 are superseded.
Read the CR in full. Section 5 is the step sequence; follow it there, not from
this block. Section 2 is the invariant — read it before touching any test.
Charter dunin7-standing-authorization-charter-v0_1 governs.
THIS IS A RESUME.
Branch cr-2026-159-option-a holds Steps 0-2 with src/ COMPLETE at f3a1bbf.
loomworks-engine main is unmoved at a317051.
Enter at Section 5, Step 3 — the test helpers.
Do NOT perform Steps 0, 1 or 2. Do NOT re-touch src/. Do NOT delete any
branch. The option-B branch was deleted two runs ago and no longer exists.
Re-confirm and derive nothing else: HEAD; working tree; that
cr-2026-159-option-a is at f3a1bbf; that the baseline failure set is still the
single entry test_stele_router_mount.py::test_stele_router_mounts_and_begin_
resolves_end_to_end. Then report the ACTUAL test-tree counts — appends, files,
version-advancing copies. Section 4's numbers are one session's report, not a
verified baseline.
Operator ruling 2026-07-31: finish option A. Dropping the field and the
stamp-and-return alternative are both set aside — do not reopen them.
Commit to the branch, never to main. Check the current branch before the first
commit of the session.
playground_dev is the live production database and is not touched. Verification
runs on the walk-audit dev pattern: spare port, inline environment, throwaway
database, live processes and .env untouched, teardown after.
"Suite green" is not the criterion; "no new failures against the Step 0 baseline
set" is.
Halt and queue on: any failure outside the baseline set; any pass-through site
that is not freshly constructed and appended exactly once; any charter section 6
anomaly.
Append the outcome to current-status/dunin7-status-brief at close.
DUNIN7 — Done In Seven LLC — Miami, Florida CR-2026-159 — B-29: the provenance seam — v0.10 — 2026-07-31 One object version, one event, one identifier. The database enforces it now.