Skip to content

roadmap: convert Filesystem.Read sites to the read-outcome and file-observation folds - #13281

Merged
gunbai-bot[bot] merged 17 commits into
mainfrom
session/swift-bee-237-b2
Oct 5, 2026
Merged

gunbai-bot[bot] merged 17 commits into
mainfrom
session/swift-bee-237-b2

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

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 new roadmap_event_admitted_after result-binding gate inside the extracted no-receipt path).

Reds first — where an unreadable file used to read as empty/default:

  1. belt_occurrence_record_for_attempt read occurrences with a silent [] default: an unreadable occurrence record file became "no occurrences". Now returns AttemptOccurrenceRecordRead = Decoded | Refused, and the census aggregate BeltAttemptOccurrenceRecords carries Observed | Refused; the population caller rides the existing OccurrencePopulationRefused channel instead of silently shrinking the population.
  2. belt_workflow_attempt_evidence_for_ref and the publication gate read the modeled-state pointer with a silent default; an unreadable pointer file was indistinguishable from an absent one. Now WorkflowModeledStatePointerState = Absent | Unreadable{cause}; the absent arm keeps today's text, the unreadable arm refuses honestly.
  3. 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) over filesystem_file_observation_of_path — an established fact, not a string comparison (the same construction the parent ruled for event_carrier:232).
  4. attempt_request_binding_read_of classified error_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.
  5. served_observation_body_read_from_filesystem mapped !success to BodyMissing — a failed read claimed absence. Now BodyMissing only on established absence (the row's absence detail names what was established), and the type gains ServedObservationBodyUnreadable{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) and attempt_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_intake proc_read_outcome sites 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.
  • Counted debt, ruled out of conversion by the parent: belt_actuate:5670 (admission) and :5672 (spawn_failure) in belt_workflow_attempt_evidence_for_key feed 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 base b7543755c8b: 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 at b7543755c8b in #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-existing extdeps/gunbc/gunbc.dag:108-110 shell-transport cluster, untouched here. CI is the verifier for the whole-corpus runs (session runners OOM on them).

gunbc-ci-auto-heal added 8 commits October 4, 2026 04:28
…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).
…ng gate inside the extracted no-receipt path
…ody reads to the file-observation fold; result-binding gate threaded through the extracted proceed path

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two semantic blockers remain. The rest of the conversion is sound.

  1. 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.

  1. Two consumers overclaim what FilesystemFileIndeterminate proves.

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.

gunbc-ci-auto-heal added 6 commits October 4, 2026 19:58
…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 briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

gunbc-ci-auto-heal added 2 commits October 5, 2026 05:53
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 briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review at ae53cd5: approved.

The remaining pointer-standing collapse is closed at both seams.

  1. 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.”

  2. 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.

@gunbai-bot
gunbai-bot Bot added this pull request to the merge queue Oct 5, 2026
@gunbai-bot
gunbai-bot Bot removed this pull request from the merge queue due to a manual request Oct 5, 2026
@gunbai-bot

gunbai-bot Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor Author

Agreed — the placeholder refused read in the HOME-unset arm of belt_claude_preflight_for_instance is fabricated shape: the arm owes the function's typed read-outcome, but nothing downstream reads it because belt_claude_preflight_decision refuses on the empty HOME before that argument is touched. The honest fix is to return the refusal directly rather than mint a read that pretends to have been observed. The branch is deliberately confined to the merge-conflict resolution right now (dequeued for re-review on the conflict-only diff), so I'll make that change as a follow-up immediately after it requeues rather than dirtying the diff under confirmation.

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved at d1a3669.

The merge resolution preserves both parent semantics in the WorktreeBind arm, in the right order:

  1. Filesystem.Read is classified through filesystem_read_outcome; FilesystemReadRefused retains the previously approved located refusal text.
  2. FilesystemReadSucceeded feeds the content into main's belt_scm_delta_resident_for re-bind check.
  3. DeltaResidentRefused retains main's refusal text and halts the fold.
  4. 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.

@gunbai-bot
gunbai-bot Bot added this pull request to the merge queue Oct 5, 2026
Merged via the queue into main with commit 312a0cb Oct 5, 2026
4 checks passed
@gunbai-bot
gunbai-bot Bot deleted the session/swift-bee-237-b2 branch October 5, 2026 15:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant