HOMELAB-2195: B11/B12 record contracts (frozen writer contract) #23
No reviewers
Labels
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
aaron/lab-director!23
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "plane/HOMELAB-2195-b3-contracts"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Design-repo record for HOMELAB-2195 (W2 redo) item B3: the frozen writer contract for W2's path (B11) and W3's evidence path (B12).
What this document is
One table per write path: which row each path produces, with which columns, which payload keys, and which frozen value — plus which component writes it and which wave owns it. It is the artifact the runtime is reviewed against, so a reviewer can read a diff and say "this write is / is not in the contract" without re-deriving the vocabulary from code.
It is read off the authority, not invented:
design/ld5/measurement.mdM0-R42 anddesign/ld5/report.sql, and cross-checked against the code of record —record/record.go(kinds, statuses),run/loop.go(pickup, slots, attribution),run/run.go+cmd/ld-runtime/main.go(path steps),run/pane.go(pane hold/prompt),run/panes_close_journal.go+run/panes_timer.go(pane close, transcript),watch/*(Plane reads). Schema:prodmanifests/ld-record/migrations/00001_record_schema.sql.Where it lives
design/ld5/contracts-b11-b12.md(added, 180 lines).Contents
workflows,node_instances,events(append-only), with which status at which moment and why (merged, notdone;abandonedfor a refused pickup)run/loop.go/watch/*, 3.2run/pane.go/run/panes*.go)report.sqlPrecedence rule (the part to hold us to)
Where this document and
measurement.mddisagree about a value,measurement.mdwins and the code is wrong. Where they disagree about what W2's path writes, this document wins, because it was read off the code that actually runs. Adding a value is a rules change: recorded inmeasurement.mdbefore the LD5 sign, then here — never silently in code.Docs only; no code, manifest or schema change.
Review —
design/ld5/contracts-b11-b12.md(docs-only, single reviewer)Reviewed head
0e8e07cvsmain204abb6. Sources of record used:design/ld5/measurement.md(M0-R42, plus M0-R12/R16/R24/R29/R36/R37 as cited) anddesign/ld5/report.sqlboth onmain; code read atinfra-coreplane/HOMELAB-2195-b3-records@fdb36f2, pathlab-director/dispatcher.Verdict: REQUEST CHANGES — blocking on #1 and #6. The vocabulary half of the document is exact; the "what W2's path writes" half has two gaps that would hide a NOT_CERTIFIABLE at proof P3, which is the one thing this document exists to prevent.
Verified good
goal.checkverdict and evidence kinds,escape.kind,infra.rerun.cause/evidence_kind,gate.decision.decision+head_sha/canary,hold.hold_kind,accept.test.result,ci.live,version.probe,workflows.status, probeok/contains_merge_commit) match the measurement.md table value-for-value, no invented or dropped value.version.probe/ci.liveexemption.sign.snapshotpayload keys incl.plane_activity_id(run/loop.go:270-279);pickup.positionkeys (loop.go:517-519);watch.positionkeyshigh_water/cursor/emitted(record/watermark.go:35,50-62);pane.holdkeys and the readiness-deferral extras (run/pane.go:183,697-730);pane.promptcarriesatin the payload (pane.go:868-882);pane.close/pane.transcriptkeys (run/panes_close_journal.go:41-49,cmd/ld-runtime/main.go:337-338);probe.livedeclared and unwritten (record/record.goKindProbe); statusesqueued/running/merged/abandoned/failed(record.go);pr= land's andbump_pr= the pin repo's (run/run.go:162-165,run_test.go:668-685); gate keepsgate.decisionwithstate, notdecision(main.go:519-534).Findings
(blocking, P3) §1's
sample_idrule does not describe what the step writer does, and §6 does not list the consequence.recordJournal.Stephard-codesSampleID: "runtime"for every step row (cmd/ld-runtime/main.go:530-547), including thegate.decisionrow. §1 saysruntimeis for "the runtime's own housekeeping (pickup.position,watch.position, pane lifecycle in a lane run); the sample id for sample rows" — a gate row is a sample row, and it carriesruntime.report.sqlreads gate decisions only undere.sample_id = (SELECT sample_id FROM current_sample)(lines ~1017-1019, ~1077, ~1100). So on an official run R1–R4 every gate row is invisible and condition 2 is uncomputable — a NOT_CERTIFIABLE that §6 declares absent. W2 does write this row, so §6's framing ("a rowreport.sqlreads that no W2 writer produces") misses it. Fix: state thesample_idthe step writer actually writes in §1/§2, and add a §6 line — "sample_idonpath.step/gate.decisionisruntime, not the sample id; report.sql reads gate rows by sample id" — with an owning wave (B12 or a W2 fix).(fix, docs accuracy) §3.1 says
pickup.skipped'skind∈not-fleet,not-ready. Onlynot-fleetwrites that row:RefusalNotReadydoesres.Skipped++plus a log line and no journal row (loop.go:244-249;traceSkipis called only forRefusalNotFleet,loop.go:222-226). A not-ready item is therefore silent, and a not-ready compile failure lands aspickup.rejectedwith reason"not ready: …"(loop.go:250-258). Either say the row coversnot-fleetonly and add the silent-not-ready gap to §6, or record it as a known gap.(fix, docs accuracy) §3.1 gives
pickup.rejectedthe payloadreason,item_id,dispatched: falsefor every row. The compile-failure path writes{reason, item_id}with nodispatchedkey (loop.go:255); only the unsigned (loop.go:234) and attribution-refused (loop.go:287) paths writedispatched: false. Say "when the row ends a dispatch attempt".(note, §2 wording) "Every step row carries:
step,state,at, …" reads as payload keys.atis the event column;main.go:530-531writes onlystepandstateplus the step's fields. One clause ("atis the event's column") removes the ambiguity.(verified, no change) §2's claims about the bump row, the gate keeping its own kind,
probe.livebeing declared-but-unwritten, andnode_instanceshaving no W2 writer all check out againstfdb36f2; §3.1's operator-attribution narrative matchesSignerPolicy.ConfirmAttributionbeing applied inappendEventfor any operator-actor, withabandonSloton refusal.(blocking, P3 completeness) §6 omits report.sql kinds that have no writer and, unlike the rows it does list, also no named owner. Missing from §6 entirely:
canary.outcome({kind,target,bracket,caught}→ M0-R29 recall, report.sql ~1745),gateway.spend({workflow_id,usd_gateway}→ M0-R37 ±15%, ~1794),hold.refused(M0-R24 count, ~246),sign.sample(the sample sign and every rebaseline — the earliestsign.sampleis the report's whole baseline, and it must carrypin_file=deploy-image.txtandauditor_egress=anthropic_only, report.sql ~125-140, ~438),drain.start/drain.end(M0-R16, ~248-249) andfailure_review(M0-R36, ~226-229). Several of those are operator-only kinds per report.sql's own header (sign.sample,drain.start/drain.end,intervention,failure_review), so they may be deliberately outside the runtime contract — but the document never says who writes them, and §6's own framing ("each line is a rowreport.sqlreads that no W2 writer produces") is then incomplete.canary.outcomeandgateway.spendare not in the operator-only list, so they are unowned runtime rows. Fix: one line each — owner wave, or "operator/out of runtime scope, written by …" — so proof P3 cannot discover a missing sign or a missing canary row at the gate.(note, §7) §7's retention paragraph is consistent with the HOMELAB-2137 ruling and correctly says no sweeper is wired; nothing to change, recorded here so the paragraph is known to have been read rather than skipped.
Scope note: this was a read-only review; no files were edited. The unfixed items are document changes for the author, not reviewer edits.
Two contract-doc blockers from reviews 794/795 on infra-core#636. §1 sample_id — the rule described a writer that did not exist. Every step row (including ) was written under the literal `runtime`, while scopes each CTE to the sample named at its call (M0-R35): a named run's gate rows were in the database and invisible to the report at P3, with report.sql/M0 frozen. The row now states what the writer does: step, gate and infra.rerun rows carry the ticket's sign ; a ticket with no sign.snapshot row keeps ; a failed sample lookup is an error, never a silent fallback. Companion writer fix: infra-core `plane/HOMELAB-2195-batch`. §3.1 pickup.rejected — the payload row lists the keys the loop actually writes, including the vocabulary split `refusal` (boundary | dor | compile | attribution | admission) and `transient`, and the two-row shape of a DoR refusal (`write_state: decided` before any Plane write, then `outcome` with `missing_writes`). One kind no longer carries three meanings. §6 — every kind report.sql reads now names its owner instead of being discovered at P3, verified against report.sql on this branch: - operator-only per the report.sql header: sign.sample (and every rebaseline), drain.start/drain.end, failure_review, release with `replaces`; - W3: hold.refused (the macro lane does not exist yet), canary.outcome (the W3/E3 harness plants them), gateway.spend (needs node_instances cost rows).b57769cbddto88cb21382eContracts doc fixes (F2 pre-landing round) — new head
88cb213Two blockers from reviews 794/795 on infra-core#636, in
design/ld5/contracts-b11-b12.md.§1
sample_id— the rule described a writer that did not exist. Every step row(including
gate.decision) was written under the literalruntime, whilereport.sqlscopes each CTE to the sample named at its call (M0-R35): a named run'sgate rows R1–R4 were in the database and invisible to the report at P3, with
report.sql/M0 frozen. The row now states what the writer does — step, gate and
infra.rerunrows carry the ticket'ssign.snapshotsample; a ticket with nosnapshot row keeps
runtime; a failed sample lookup is an error on the write, nevera silent fallback. Companion writer fix: infra-core
plane/HOMELAB-2195-batch@
e507450(that PR carries the read trace forLastStep,InfraRunsandPoolInflight, the three reads that filtered on sample).§6 — every kind
report.sqlreads now names its owner, verified againstreport.sql on this branch. Added rows:
sign.sample(and every rebaseline)drain.start/drain.endfailure_reviewreleasewithreplaceshold.refusedcanary.outcomegateway.spendnode_instancescost rows first)§3.1
pickup.rejected— the payload row now lists the keys the loop actuallywrites, including the vocabulary split added in the code fix (
refusal∈ boundary |dor | compile | attribution | admission, and
transient), and the two-row shape of aDoR refusal (
write_state: decidedbefore any Plane write, thenoutcomewithmissing_writes). One kind no longer carries three meanings.Disclosure: the branch was force-pushed once to correct a mangled commit message
(backticks were shell-expanded, leaving gaps mid-sentence in the commit body). The
content of the change is unchanged between the two pushes; the tree at
88cb213isthe fix as described. No review is pinned to this head yet — this comment is the
record.
Review —
design/ld5/contracts-b11-b12.md@88cb213— VERDICT: APPROVEDScope verified
§1
sample_id— matches the writer exactly (writer atinfra-coreplane/HOMELAB-2195-b3-records@e507450):sign.snapshotrow is the single resolution point — it scopes the step row (path.stepandgate.decision),RecordInfra,InfraRunsand bothLastStepreads;runtime;runtimefallback applies only when the ticket has nosign.snapshotrow (lane runs, manual runs, tests);InFlightreads throughListKindAnySample, and its test asserts the single-sample read is empty as a control.§6 — owns every kind
report.sqlreads. I enumerated all 24 kinds the query reads (panel_only_defectis acanary_kindvalue, not an event kind) and each one is either owned in §2/§3 by a W2 writer or explicitly named in §6 with an owning wave. Nothingreport.sqlreads is left unowned and unstated.Findings carried (non-blocking; pre-R3 / W3 follow-ups, not gates)
priordoes not persistVerdict.Marker(), so a later refusal of the same ticket for different reasons is demoted without a new comment: the journal dedup is broader than the marker. Fix is one payload key plus a comparison inpriorRefusal. (Code lives oninfra-core#636, not in this doc PR.)Shape
Docs-only: 1 file,
+187 / −0(design/ld5/contracts-b11-b12.md). No CI workflow exists inaaron/lab-director, so no check was expected or waited on.Verdict: APPROVED on head
88cb213.APPROVED on
88cb213— see the full verdict comment below (transported by the landing worker).