Repository navigation
roadmap: convert Filesystem.Read sites to the read-outcome and file-observation folds - #13281
Conversation
…reds first)
- belt_occurrence_record_for_attempt: an unreadable launch record returned []
and the occurrence census lost the attempt silently. The per-attempt read is
now a typed outcome (AttemptOccurrenceRecordRead: Decoded | Refused with the
cause naming the attempt), and one unreadable attempt refuses the whole
census (BeltAttemptOccurrenceRecords) instead of shrinking it -- the refusal
rides the existing OccurrencePopulationRefused channel with the reason.
- belt_workflow_attempt_evidence_for_ref and the publish gate: a failed
current-attempt-key pointer read claimed 'this attempt has no modeled state
pointer' / 'this node has no current attempt' -- absences the read never
established. The pointer read folds through filesystem_read_outcome and the
two facts split (WorkflowModeledStatePointerState: Absent |
Unreadable{cause}); absent keeps today's text, unreadable says the pointer
could not be read and what is therefore unknown.
- Excluded as argued_collapse (owner's argument, not converted):
attempt_launch_revision_hex in roadmap_served_observation -- stale_attempt_nodes
dims nothing for any failure and for empty alike, and the presentation
witness pins the empty wire for an unreadable record.
Every remaining mechanical site read individually, each feeding an existing typed local outcome, reason texts preserved verbatim except where the host error is quoted (the fold's Refused error replaces read.error): - belt_actuate: submission artifact, capture-roster fold, capture-for-head, spawn origin, worktree-bind fold, integration receipt, validation oracle (classifier re-signature to take FilesystemReadOutcome, shared with closing_contract_authoring), claude preflight (decision re-signature; witness calls construct fold outcomes), belt tick receipt (old classifier TEXT-MATCHED host errors 'No such file'/'not found' -- deleted; the wet path classifies a filesystem_file_observation instead, absence established from the listing; witness drives both facts through the owner's producers). - served_observation: same observation conversion (old classifier text-matched host errors -- deleted; witness drives absence through the producers). - acceptance_history_carrier, publication_helper (both sites), closing_contract_authoring: fold + match. - event_carrier: the operation-receipt flow no longer compares receipt.error_kind to 'not_found' -- the observation authority establishes absence (proceed), listed-but-unreadable refuses (whether the operation ran is unknown), readable decodes; the committed-event read folds too. - Parked for a wire-shape ruling: belt_workflow_attempt_evidence_for_key's admission and spawn_failure reads feed Bool+String evidence fields with no cause slot; converting them honestly needs an evidence-shape change. - Excluded as argued_collapse: belt_read_or_empty (absence row owns it), attempt_launch_revision_hex (presentation witness pins the empty wire).
…odule gunbc.filesystem_file_observe
…ng gate inside the extracted no-receipt path
…ody reads to the file-observation fold; result-binding gate threaded through the extracted proceed path
…atured classifier
briansrls
left a comment
There was a problem hiding this comment.
Two semantic blockers remain. The rest of the conversion is sound.
- An unreadable current-attempt pointer is still collapsed into the legacy/absent state downstream.
WorkflowModeledStatePointerState distinguishes Absent from Unreadable, but belt_workflow_attempt_evidence_without_modeled_state turns both into one WorkflowAttemptEvidence with modeled_state_present: false. It also fills several downstream facts with absence-shaped values (SelectionAbsent, VerificationReceiptAbsent, ReceiptSourceAbsent, review_report_absent, empty goal-audit rows).
That distinction is then lost immediately: workflow_provider_from_evidence treats every modeled_state_present == false as the legacy-attempt arm, and gunbc.roadmap_workflow_command.is_legacy_attempt is literally !modeled_state_present. A pointer read refusal can therefore be presented and consumed as “attempt predates modeled admission / legacy — supersedable,” which is a factual default, not the new unreadable state.
Please carry the typed pointer standing into WorkflowAttemptEvidence (Observed/Absent/Unreadable), or refuse the evidence construction at a distinct top-level arm. The unreadable route must not mint legacy standing or absence-shaped receipt facts. Add a composed control through workflow_provider_from_evidence/the workflow projection, not only a helper-level message test.
- Two consumers overclaim what
FilesystemFileIndeterminateproves.
That arm is produced in two materially different worlds:
- the directory listing itself failed, so whether the entry exists is unknown;
- the listing named the entry and its read failed, so existence is established but content is unavailable.
The new served-body response maps every FilesystemFileIndeterminate to text saying the body “exists but could not be read.” The event carrier maps every one to “the operation receipt is listed and could not be read.” Both are false for the listing-refused world.
Please use wording valid for the carrier’s whole domain (for example, the subject could not be observed, so existence/content is unknown), or preserve a richer distinction before rendering. Add listing-refused controls at both loci; the current witnesses cover only the listed-but-unreadable case.
What passed:
- the occurrence-record conversion correctly refuses the whole census, names the attempt, and no longer silently returns
[]; - request-binding, tick-receipt, served-index, and served-body absence is reached only through
FilesystemFileAbsent, with witnesses deriving the sealed absence through a successful listing omission; - the new served-body unreadable arm correctly maps the listed-but-unreadable case to HTTP 503 and is discriminated from
BodyMissing; - the mechanical read-outcome conversions retain their former refusal text/behavior rather than defaulting;
- the validation-oracle and Claude-preflight re-signatures are updated at their production and witness callers; exact-head whole-tree compilation found no stale old-signature caller.
All four exact-head lanes are green. They do not catch these two cross-carrier semantic collapses.
…ndeterminate wording Side chat on #13281 (msg_b89ab669): two semantic blockers. 1. An unreadable current-attempt pointer still collapsed downstream into absence-shaped facts and minted legacy, supersedable standing. Introduce WorkflowModeledStateStanding (Observed | Absent | Unreadable { cause }), carry it in WorkflowAttemptEvidence.modeled_state, and match it: workflow_provider_from_evidence refuses supersession on Unreadable with 'attempt standing unknown' (never legacy); WorkspaceWorkflowSegment refuses the segment on Unreadable; is_legacy_attempt matches Absent only. Composed control: workflow_provider_from_evidence driven with Unreadable asserts refusal and never-legacy; absent asserts the legacy arm. 2. FilesystemFileIndeterminate covers two worlds (listing refused -> existence unknown; listed but read refused -> existence established) but both refusal texts claimed facts about one world. Wording is now domain-valid ('could not be observed; existence and content unknown' shape) and the owner's cause distinguishes the worlds. Controls: a composed served-body control through the listing producer, and an observation-boundary control at the receipt site (the append flow itself is wet).
The rework added workflow_command -> workflow_progress (for the standing type) while workflow_progress already imports workflow_command -- a dependency cycle every importer closure refused. The type moves to the lower module; workflow_progress and the witnesses import it from there, along the existing edge. No other change.
Conflict in roadmap_event_carrier_witness_test.dag: main added the snapshot-removal standing tests to the same file the listing-refused control was added to; both are additive and both are kept.
The wildcard arm over the closed coproduct refused the floor (NonFoldResidueRosterDiverged, unrostered live site). Observed and Unreadable are matched by name; Unreadable's cause is carried but the arm's answer is the same as before: not legacy.
…ames its real detail
The composed control went red in CI: my extraction of the observed chain had
mangled its first arm — the legacy label leaked in and the real refusal
('attempt state refused' for an unreadable admission receipt) became a dead
duplicate of the same condition. The observed chain now matches main's: unreadable
receipt refuses with 'attempt state refused', then receipt-record, spawn failure,
event capture, reconcile. The witness's absent-arm assertion checked the detail
for the word 'legacy'; the detail says 'predates modeled admission' — assert
that instead.
briansrls
left a comment
There was a problem hiding this comment.
One blocker remains from review 5407300746.
The top-level standing repair is correct: WorkflowAttemptEvidence now carries Observed | Absent | Unreadable, workflow_provider_from_evidence refuses Unreadable as “attempt standing unknown,” Workspace refuses it, and is_legacy_attempt names all three arms and returns true only for Absent.
But belt_workflow_attempt_evidence_without_modeled_state still unconditionally mints the same absence-shaped subordinate facts for BOTH pointer states:
- verification_selection: SelectionAbsent
- verification_source: VerificationReceiptAbsent
- publication_source: ReceiptSourceAbsent
- review_report_absent(...)
- goal_audit: []
This is observable, not merely an inert record inconsistency. workflow_attempt_progress passes verification_selection directly to verification_segment without first gating on modeled_state. verification_segment matches SelectionAbsent first and renders VerificationWorkflowSegment as Pending (“the belt has not selected…”). ReviewWorkflowSegment and GoalAuditWorkflowSegment then also render Pending. Thus an unreadable current-attempt pointer still becomes absence/pending in three workflow projections even though provider and workspace now refuse it as unknown.
The new composed control does not catch this because it stops at workflow_provider_from_evidence; it never calls workflow_attempt_progress or inspects the segment roster.
Please make the unreadable branch non-absent all the way through. A sufficient repair is to populate SelectionUnaddressable { cause }, VerificationReceiptUnreadable { detail }, and ReceiptSourceUnreadable { detail } for WorkflowModeledStatePointerUnreadable, and/or gate every dependent segment on WorkflowModeledStateUnreadable before it consumes subordinate fields. Add a composed control through workflow_attempt_progress requiring the unreadable case to refuse as unknown rather than producing pending/absent verification, review, or goal-audit standing. The established-absent case should continue to take the legacy arm.
The second prior blocker is closed. Served-body and event-receipt indeterminate wording is valid for both producer worlds (“could not be observed”), the listing-refused controls preserve the owner’s cause without claiming existence, and listed-but-unreadable remains a distinct 503 at the served-body boundary. The observed-state provider chain also preserves main’s ordering: admission receipt, receipt content, spawn failure, event capture, then process reconciliation.
All four exact-head lanes are green. I found no other blocker.
Side chat review 5409834403, blocker 1 (rest): both pointer branches of belt_workflow_attempt_evidence_without_modeled_state minted the same absence-shaped subordinate facts, and verification_segment reads SelectionAbsent as pending, with review and goal audit inheriting it -- an unreadable pointer still rendered as pending downstream. Fix (a), closer to the ruling: the pointer standing now decides the subordinate facts' standing. Established ABSENCE keeps the absence-shaped facts the legacy arm means; an UNREADABLE pointer carries SelectionUnaddressable, VerificationReceiptUnreadable, ReceiptSourceUnreadable and review_report_refused -- the wrong state is unwritable. Fix (b) for the fold: workflow_segment_from_evidence gates on the modeled standing before reading subordinate fields -- an unreadable pointer refuses every segment (verification, review, goal audit) with the located cause, while Observed and Absent take the existing fold. Controls: through workflow_attempt_progress (unreadable refuses verify/review/audit, absent still renders pending) and over the pure standing helpers (each non-absence variant carries the pointer's cause; absent still yields the absence variants).
Conflict in roadmap_belt_actuate_witness_test.dag: main added the refused-metering-write control to the same file the pointer-standing control was appended to; both are additive and both are kept.
briansrls
left a comment
There was a problem hiding this comment.
Re-review at ae53cd5: approved.
The remaining pointer-standing collapse is closed at both seams.
-
Evidence construction now derives subordinate standings from WorkflowModeledStatePointerState. Established absence alone produces SelectionAbsent / VerificationReceiptAbsent / ReceiptSourceAbsent / review_report_absent. An unreadable pointer instead produces SelectionUnaddressable, VerificationReceiptUnreadable, ReceiptSourceUnreadable, and review_report_refused, each carrying the located pointer-read cause. The unreadable route can no longer mint the absence-shaped subordinate facts that previously rendered as “not yet.”
-
workflow_segment_from_evidence now gates on WorkflowModeledStateStanding before reading any subordinate field. WorkflowModeledStateUnreadable produces a refused segment for every workflow obligation with the pointer cause; Observed and Absent alone enter the existing fold. That closes verification, review, and goal-audit even if a future subordinate field regresses.
The controls are at the right grain: one checks the pure standing projections, and the composed workflow_attempt_progress control requires unreadable standing to refuse verify/review/audit while established absence retains the legacy pending behavior. is_legacy_attempt remains exhaustive and true only for WorkflowModeledStateAbsent.
The prior indeterminate-wording repair remains intact, and the fresh main merge preserved both sides of its only conflict. Exact-head floor, generated, emit-build, and aggregate witnesses are green. No remaining blocker.
|
Agreed — the placeholder refused read in the HOME-unset arm of |
briansrls
left a comment
There was a problem hiding this comment.
Approved at d1a3669.
The merge resolution preserves both parent semantics in the WorktreeBind arm, in the right order:
- Filesystem.Read is classified through filesystem_read_outcome; FilesystemReadRefused retains the previously approved located refusal text.
- FilesystemReadSucceeded feeds the content into main's belt_scm_delta_resident_for re-bind check.
- DeltaResidentRefused retains main's refusal text and halts the fold.
- DeltaResident passes its resident store to store_authored_source; SourceStored carries the resulting store and re-binds the path's unique target.
The merge commit's parents are the previously approved head ae53cd5 and main@864c9ce0c9. The exact head is mergeable, and floor, generated, emit-build, and aggregate witnesses all passed. No remaining blocker.
Batch 2 of the read-outcome adoption trial (filesystem sibling of DP-M5), on the roadmap subsystem, per the parent trial's rulings. Branch is current with origin/main
b7543755c8b(merged; the event-carrier proceed path keeps main's newroadmap_event_admitted_afterresult-binding gate inside the extracted no-receipt path).Reds first — where an unreadable file used to read as empty/default:
belt_occurrence_record_for_attemptread occurrences with a silent[]default: an unreadable occurrence record file became "no occurrences". Now returnsAttemptOccurrenceRecordRead=Decoded | Refused, and the census aggregateBeltAttemptOccurrenceRecordscarriesObserved | Refused; the population caller rides the existingOccurrencePopulationRefusedchannel instead of silently shrinking the population.belt_workflow_attempt_evidence_for_refand the publication gate read the modeled-state pointer with a silent default; an unreadable pointer file was indistinguishable from an absent one. NowWorkflowModeledStatePointerState=Absent | Unreadable{cause}; the absent arm keeps today's text, the unreadable arm refuses honestly.ci_app-style kind-string matching deleted in the roadmap receipt paths: the tick receipt and served-observation receipt classifiers text-matched host error strings ("No such file", "not found") and were deleted, replaced by*_from_observation(observation: FilesystemFileObservation)overfilesystem_file_observation_of_path— an established fact, not a string comparison (the same construction the parent ruled for event_carrier:232).attempt_request_binding_read_ofclassifiederror_kind == "not_found"into RequestBindingAbsent — presence inference from a kind string. Deleted; the classifier now takes the observation: established absence →RequestBindingAbsent, readable → decode, listed-but-refused or otherwise unreadable →RequestBindingUnreadable{cause}. The witness's absent arm is driven through the owner's producers (filesystem_listing_observation omitting the record → filesystem_file_observation → absent), not sealed construction. This site is new on main (Dogfood G4: return a typed attempt result to the requester on the issue event log #13075 added it) and was found by the batch's re-measure.served_observation_body_read_from_filesystemmapped!successtoBodyMissing— a failed read claimed absence. NowBodyMissingonly on established absence (the row's absence detail names what was established), and the type gainsServedObservationBodyUnreadable{cause}; the consumer refuses 503 with the unreadable label. New red control: a listed body that cannot be read refuses as unreadable and the rendered refusal does not contain the Missing string.Mechanical conversions (read result bound and matched as the typed outcome, refusals carry the prior default-message): belt_actuate — submission artifact, capture roster, capture for head, spawn origin, worktree bind, integration receipt, tick receipt; acceptance_history_carrier:35; closing_contract_authoring:134; publication_helper:261/906; validation_oracle classifier re-signature plus both callers; event_carrier receipt flow (error_kind comparison replaced by observation arms; committed read folds; proceed path extracted, main's result-binding gate preserved); event_carrier:317; claude preflight decision re-signature plus live caller and four witness call sites construct fold outcomes.
Findings recorded on the row (via #13262, not here):
argued_collapse(both branches take the same action at every remaining caller):belt_read_or_empty(belt_actuate:7290; annotation above its definition, review 45271; exempted in the absence row) andattempt_launch_revision_hex(served_observation:208; presentation note pinned by roadmap_presentation_witness_test). Not converted here; if a caller is found where the branches act differently, that falsifies the argument and the site becomes a target — reported, not converted silently.domain_read_fold: the gunbc.machine_intakeproc_read_outcomesites are typed outcomes, not silent defaults — excluded from targets as their own class; the DESIGN 3 fork (it carries error_kind, which the shared fold lacks) has its next-rung trigger and owner named on the row in filesystem: read-outcome adoption row prose corrected; no live remainder claimed #13262.belt_workflow_attempt_evidence_for_keyfeed the attempt evidence wire fields (Bool + String) which have no cause slot — an honest conversion needs a typed evidence outcome on the wire, and the wire and its consumers are owned by gunbc.roadmap_belt_actuate. Per the parent's ruling these are NOT a fourth excluded class (an exclusion says "this is not debt"; these are debt): they stay unconverted and COUNTED in the remainder, and the row (via filesystem: read-outcome adoption row prose corrected; no live remainder claimed #13262) names what they need and who owns it.Delta at identity grain (instrument = the row's RE-DERIVATION recipe; re-measured at this head
acf387f894): before the batch, at the merged baseb7543755c8b: 222 unconverted consumption sites across 102 files (65 fixtures), 53 converted. After: 207 unconverted across 101 files (65 fixtures), 70 converted — non-fixture unconverted 157 → 142; two new sites #13075 added are converted, not added to the debt. Roadmap non-fixture unconverted: 21 → 4 (2 argued, 2 parked). The row's REMAINDER sentence is re-measured atb7543755c8bin #13262; when this lands the row re-measures again at this head (207/101/65).Verification: all eight roadmap modules and all three touched witness tests compile on this tree with
gunbc compile(dependency pool primary-precedence, source roots dag + src/v2): the only diagnostics in their closures are the pre-existingextdeps/gunbc/gunbc.dag:108-110 shell-transport cluster, untouched here. CI is the verifier for the whole-corpus runs (session runners OOM on them).