Skip to content

feat(bin): let the terminal record say a task failed (land of upstream #1978) - #62

Merged
sbracewell64 merged 4 commits into
mainfrom
fm/land-cfvc-12-onto-fork
Aug 9, 2026
Merged

feat(bin): let the terminal record say a task failed (land of upstream #1978)#62
sbracewell64 merged 4 commits into
mainfrom
fm/land-cfvc-12-onto-fork

Conversation

@sbracewell64

Copy link
Copy Markdown
Owner

Fork landing of CFVC-12, the task-outcome-failure work.

What this changes

The terminal record can now say a task failed.

  • bin/fm-wake-ledger.sh derives a task's terminal outcome from what the task itself declared and records the evidence behind it, so an outcome nothing corroborated cannot pass as an observed one. The outcome-source vocabulary is closed; an unstated evidence records as assumed.
  • A recording sweep captures declared failures that teardown never sees, because a task that fails and is never released would otherwise leave the ledger silent, and silence there is indistinguishable from a task that never failed. It is idempotent through a per-task state/<id>.terminal-recorded receipt.
  • Reporting stays diagnostic and refuses to print a success rate, naming the gap between this ledger's released-task count and the pipeline's validation-run count on every run.
  • bin/fm-bootstrap.sh runs the sweep as a mutating sweep (dry run under FM_BOOTSTRAP_DETECT_ONLY=1, so a read-only session still reports the failures it declined to record) and counts durable appends rather than intent.
  • bin/fm-teardown.sh removes the terminal-recorded receipt, including on the remote-secondmate path.
  • AGENTS.md and bin/fm-session-start.sh drop their drifted mutating-sweep counts and point at bin/fm-bootstrap.sh's header as the single owner of that list.
  • Added coverage in tests/fm-bootstrap.test.sh, tests/fm-teardown.test.sh, and tests/fm-wake-ledger.test.sh.

Provenance

This is a fork landing of content that was validated by the no-mistakes pipeline upstream; the run evidence lives on upstream PR kunchenguid#1978. That upstream branch was replayed onto the upstream base, so its commit ids diverge from this branch while the content matches. This branch was cut fresh from the fork trunk and carries only this contribution's own changes; bin/fm-wake-ledger.sh, its tests, and the bin/fm-wake-drain.sh recording call already exist on the fork, so the diff here is the delta on top of them rather than the upstream file additions.

No pipeline run was executed against this fork branch, and this PR carries no validation attestation.

Test evidence (run on this branch)

Base for comparison: fork trunk ed376cf.

Check Result
bin/fm-lint.sh clean (ShellCheck 0.11.0, pinned)
bin/fm-doc-audience-check.sh ok, surfaces=72 local_links=213
tests/fm-wake-ledger.test.sh 19 ok, 0 failures
tests/fm-teardown.test.sh 71 ok, 0 failures
tests/fm-bootstrap.test.sh 26 ok, 0 failures
tests/fm-session-start.test.sh 5 ok, 1 failure

Disclosed failure: tests/fm-session-start.test.sh fails on MISSING diagnostic did not appear at all. This failure reproduces identically on the unmodified fork trunk ed376cf (checked out separately and run there: same single failing case, same 5 passing cases), so it is pre-existing on the base and not introduced here.

Branch cleanliness was verified with git merge-tree --write-tree fork/main HEAD, exit status 0.

Known in-flight sibling work on the fork trunk (the serial-2 red fix and the head-bound check replacement) may surface as red checks on this PR that are not caused by this change.

@sbracewell64
sbracewell64 force-pushed the fm/land-cfvc-12-onto-fork branch from c586a96 to 04f5761 Compare August 9, 2026 14:41
The fleet's terminal outcome was a constant. Teardown set outcome=landed
and only --force changed it, so nothing anywhere produced failed: a record
reading "40 terminal (landed 40)" was not a success rate, because the
numerator could not move.

Definition first. bin/fm-wake-ledger.sh now owns what a terminal outcome
means and what evidence stands behind it. The enum stays three members
pinned to the v1 line schema; every terminal record gains outcome_source
naming where its outcome came from - declared, discarded, unreleased, or
assumed. A record written before the field existed reads as assumed, which
is exactly what those records were, so the append-only file needs no
rewrite.

Field second. Teardown derives the outcome from the task's own last
declaration instead of a constant, and a --force discard still outranks it.
A second producer covers the case teardown never sees: a task that fails and
is never released was silent in the ledger, and silence there is
indistinguishable from a task that never failed. `sweep` records those once,
receipt-guarded, and a locked session start runs it.

Diagnostic only, deliberately. The report breaks outcomes down by evidence
and refuses to print a rate: this ledger counts released tasks while the
no-mistakes pipeline counts validation runs, and until that divergence is
reconciled any ratio would describe neither. The report names that gap on
every run.

The attempt counter and the unified terminal vocabulary are separate
increments and are not absorbed here.
@sbracewell64
sbracewell64 force-pushed the fm/land-cfvc-12-onto-fork branch from 04f5761 to 7480694 Compare August 9, 2026 16:57
@sbracewell64

Copy link
Copy Markdown
Owner Author

Rebased onto the current fork trunk

Rebased onto 5004452 (fork main, after #60 merged). Pre-rewrite head 04f5761 is preserved at archive/prerebase-2026-08-09/land-cfvc-12-onto-fork; the head branch is fork-only and is not shared with any open upstream PR. All four commits, including the three pipeline-fix commits, survived the rebase.

Conflicts and how they were resolved

Both landed in the same review commit, and both are cases where the trunk and this branch edited the same prose for different reasons:

  • bin/fm-session-start.sh header - trunk rewrote this paragraph to add the ruling-index rebuild to the list of steps a read-only session skips. This branch's only edit to it was to drop the literal count from "the five bootstrap mutating sweeps", because this branch adds a sixth sweep and the count belongs to bin/fm-bootstrap.sh's header, its single owner. Kept trunk's richer paragraph and reapplied the de-counting, so the ruling-index detail survives and no stale count is reintroduced.
  • tests/fm-bootstrap.test.sh - trunk appended six validation-daemon liveness cases and this branch appended the terminal-sweep case at the same point, and both then appended to the runner list. Resolved as a union in both places: all seven test functions and all seven runner entries are present.

No other integration fix was needed.

Test results, disclosed in full

bin/fm-test-run.sh --changed --base fork/main selected 61 suites; 6 failed.

Every one of the six fails identically on unmodified trunk in a clean checkout, so none is a defect in this branch:

Suite Failure on this branch and on bare trunk
fm-bootstrap VALIDATION_DAEMON: down - no pid file at /tmp/fm-test-absent-nm-home/daemon.pid
fm-session-start MISSING diagnostic did not appear at all
fm-pi-watch-extension external healthy watcher not surfaced as an owned-wake failure
fm-turnend-guard Pi guard injection case
fm-watcher-lock restart did not attach to the verified healthy peer
fm-calm-pi-extension local Node ESM loader error, node:internal/modules/esm/get_format:219

These are local-environment failures, not branch failures: the same behavior lanes pass in CI, as #60's green lanes on the same trunk show.

bin/fm-lint.sh is clean.

The reporting was not trusted on absence: the runner produced real not ok lines and a non-zero exit on both this branch and the bare-trunk control, and the control was run in a separate clean checkout of fork/main rather than inferred.

@sbracewell64

Copy link
Copy Markdown
Owner Author

CI note

The first CI pass had one red beyond the structural gate: Behavior portable serial 3, failing tests/fm-remote-job.test.sh on "an expired queued job did not publish a timeout result". That is a timing-sensitive expiry case in a suite this branch touches no file in. It passed twice locally on this exact head, and a re-run of the same job on the same head went green, so it was a flake and not a defect this branch introduced.

Settled state on head 7480694: 13 passed, 1 failed, 14 total. The only remaining red is the known structural PR must be raised via no-mistakes gate that every fork landing PR carries.

@sbracewell64
sbracewell64 merged commit faf131b into main Aug 9, 2026
25 of 27 checks passed
sbracewell64 added a commit that referenced this pull request Aug 9, 2026
…kunchenguid#1978) (#62)

* feat(bin): let the terminal record say a task failed

The fleet's terminal outcome was a constant. Teardown set outcome=landed
and only --force changed it, so nothing anywhere produced failed: a record
reading "40 terminal (landed 40)" was not a success rate, because the
numerator could not move.

Definition first. bin/fm-wake-ledger.sh now owns what a terminal outcome
means and what evidence stands behind it. The enum stays three members
pinned to the v1 line schema; every terminal record gains outcome_source
naming where its outcome came from - declared, discarded, unreleased, or
assumed. A record written before the field existed reads as assumed, which
is exactly what those records were, so the append-only file needs no
rewrite.

Field second. Teardown derives the outcome from the task's own last
declaration instead of a constant, and a --force discard still outranks it.
A second producer covers the case teardown never sees: a task that fails and
is never released was silent in the ledger, and silence there is
indistinguishable from a task that never failed. `sweep` records those once,
receipt-guarded, and a locked session start runs it.

Diagnostic only, deliberately. The report breaks outcomes down by evidence
and refuses to print a rate: this ledger counts released tasks while the
no-mistakes pipeline counts validation runs, and until that divergence is
reconciled any ratio would describe neither. The report names that gap on
every run.

The attempt counter and the unified terminal vocabulary are separate
increments and are not absorbed here.

* no-mistakes(review): count terminal sweep records from durable appends, add coverage

* no-mistakes(review): remove terminal-recorded receipt in remote-secondmate teardown

* no-mistakes(document): point AGENTS.md mutating-sweep list at bootstrap header owner
sbracewell64 added a commit that referenced this pull request Aug 10, 2026
…kunchenguid#1978) (#62)

* feat(bin): let the terminal record say a task failed

The fleet's terminal outcome was a constant. Teardown set outcome=landed
and only --force changed it, so nothing anywhere produced failed: a record
reading "40 terminal (landed 40)" was not a success rate, because the
numerator could not move.

Definition first. bin/fm-wake-ledger.sh now owns what a terminal outcome
means and what evidence stands behind it. The enum stays three members
pinned to the v1 line schema; every terminal record gains outcome_source
naming where its outcome came from - declared, discarded, unreleased, or
assumed. A record written before the field existed reads as assumed, which
is exactly what those records were, so the append-only file needs no
rewrite.

Field second. Teardown derives the outcome from the task's own last
declaration instead of a constant, and a --force discard still outranks it.
A second producer covers the case teardown never sees: a task that fails and
is never released was silent in the ledger, and silence there is
indistinguishable from a task that never failed. `sweep` records those once,
receipt-guarded, and a locked session start runs it.

Diagnostic only, deliberately. The report breaks outcomes down by evidence
and refuses to print a rate: this ledger counts released tasks while the
no-mistakes pipeline counts validation runs, and until that divergence is
reconciled any ratio would describe neither. The report names that gap on
every run.

The attempt counter and the unified terminal vocabulary are separate
increments and are not absorbed here.

* no-mistakes(review): count terminal sweep records from durable appends, add coverage

* no-mistakes(review): remove terminal-recorded receipt in remote-secondmate teardown

* no-mistakes(document): point AGENTS.md mutating-sweep list at bootstrap header owner
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