feat(bin): record why every agent dispatch was necessary at the spawn chokepoint (land of upstream #1830) - #58
Open
sbracewell64 wants to merge 4 commits into
Open
feat(bin): record why every agent dispatch was necessary at the spawn chokepoint (land of upstream #1830)#58sbracewell64 wants to merge 4 commits into
sbracewell64 wants to merge 4 commits into
Conversation
… chokepoint CFVC-08. bin/fm-spawn.sh is the last gate before an agent turn exists and it already writes state/<id>.meta, so it is where the justification record belongs. Every ship and scout dispatch now records four fields: reasoning_required derived from the reason code reason_code a closed nine-token enum; an unknown value is refused capability_floor verbatim from config/crew-dispatch.json escalation_policy derived from kind plus the delivery contract bin/fm-reasoning-lib.sh is the single owner of the enum, the derivations and the stable refusal tokens. It records; it does not enforce - no dispatch is blocked for reasoning too little. The vocabulary is closed because a free-text reason cannot be counted, and the two derived fields are never caller-supplied so they cannot disagree with the record they summarize. TOOLING_GAP is the one code that is NOT a reasoning code. It names a turn taken only because a deterministic reader is broken or absent. It records reasoning_required=no so it can never be counted as justified reasoning, and it requires --tooling-gap-item naming a work item that is currently OPEN in this home's data/backlog.md. Without that check the code would launder every unfixed tool into a permanent "necessary agent turn" - the single failure mode that would make this record worse than no record at all. SCOPE, and a documented replacement of completion criterion (a). The spec says every new spawn record carries all four fields. A --secondmate spawn is excluded and refuses all three flags: it provisions a standing home rather than dispatching a task - AGENTS.md section 10 keeps a secondmate out of the backlog for the same reason - and Lane B derived the enum entirely from task invocations, so demanding one of its codes for a provisioning action would manufacture exactly the rubber-stamp answer the enum exists to prevent. Absent fields read as unknown and never as justified, so a secondmate record cannot be miscounted either way. The criterion is replaced by a stronger tested pair: every TASK dispatch carries all four fields, AND a secondmate spawn that passes one is refused with a stable token rather than silently defaulted. bin/fm-promote.sh recomputes escalation_policy, because promotion changes the delivery contract that field is derived from. Leaving it would keep a scout's report-only posture on a task that can now reach a merge gate. RETIREMENT. The record was ABSENT, so no mechanism is replaced in code. What retires is the untracked category of agent turns taken because a reader is broken: before this, such a turn was indistinguishable in the record from justified reasoning, and TOOLING_GAP plus its refusing filing check is what ends that. No transitional second path is left alive - --reason-code is the only way to record a reason, and it is required rather than optional. CERTIFICATION. tests/fm-reasoning-required.test.sh, eight cases. Every case was witnessed RED against the pre-change bin/fm-spawn.sh and bin/fm-promote.sh before being accepted green. Three further targeted negative controls were run and witnessed red: loosening the open-item match (the already-closed and prefix rows go red), making reasoning_required always yes (the TOOLING_GAP row goes red), and degrading an unreadable dispatch config to "unconfigured" (the unverifiable-floor row goes red). The published-codes case asserts the recorded value positively rather than the absence of a refusal, because the absence-only version of it was vacuously green against the reverted implementation and so proved nothing. The lint gate was also shown able to reject (exit 1 on a deliberate violation) rather than trusted for being quiet. Existing spawn call sites in 18 test files carry the new required flag. Three failures remain in the touched set and were each proven PRE-EXISTING on the unmodified contribution base by a stashed baseline run, not asserted: two scout teardown decision gates refused because this environment has tasks-axi 0.2.3 against the required 0.2.4 floor, and one Pi extension case fails on a Node ESM loader error. All three reproduce identically with these changes reverted.
…h, meta injection
The landed contribution makes --reason-code required for every ship and scout dispatch. Five suites that exist only on the fork trunk, or that grew fork-only spawn call sites since the contribution was cut upstream, still spawned without it and were refused before reaching the behavior they pin. Each call site now declares NL_RULE_CLASSIFICATION, matching how the contribution adapted the suites it could see upstream. The Herdr launcher helper picks the flag conditionally: a --secondmate spawn provisions a standing home and refuses --reason-code outright, so passing it to every spawn the helper drives would break the secondmate case instead. No product behavior changes here; this is the fork-side half of the same mechanical adaptation.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Lands CFVC-08, the reasoning-required spawn record, onto the fork trunk.
The contribution exists upstream as kunchenguid#1830 (head
e17ecfe1). That branch was left untouched: this branch was cut fresh from the fork trunk (ed376cf) and carries only that contribution's own three commits, plus one fork-side test adaptation described below.What changes
Every agent dispatch now records why an agent turn was necessary, so the question is answerable from the record rather than reconstructed.
bin/fm-reasoning-lib.sh(new): owns the closed nine-code reason vocabulary, the capability-floor vocabulary read fromconfig/crew-dispatch.json, and the derivations forreasoning_requiredandescalation_policy.bin/fm-spawn.sh:--reason-codeis required for every ship and scout dispatch and refused on--secondmate. An out-of-enum value is refused rather than recorded.--capability-flooris validated against the vocabulary the dispatch config defines.reasoning_required,reason_code,capability_floor,escalation_policy, andtooling_gap_itemland instate/<id>.meta.TOOLING_GAPis the one code that is not a reasoning code: it is never counted as justified reasoning and requires--tooling-gap-itemnaming a currently open item in this home's backlog, so an unfixed tool cannot launder itself into a permanent "necessary agent turn". Its item match is literal, with ERE-injection and newline-injection hardening.escalation_policyhonours the delivery mode, including a distinct captain-approves-local-merge token, andbin/fm-promote.shrecomputes it on promotion so a promoted task never keeps a scout's report-only posture._floorsvocabulary indocs/configuration.mdanddocs/examples/crew-dispatch.json; the dispatch axis indocs/architecture.md.tests/fm-reasoning-required.test.sh(new, 629 lines): the contribution's own witnessed-red suite.Conflict resolution against the current fork trunk
git merge-tree --write-tree fork/main HEADexits 0 and its result tree equals this branch's own tree, so the branch carries only this contribution's changes and merges cleanly.Six conflicts were resolved. Main won everywhere the contribution did not deliberately change:
AGENTS.mdmeta-line: kept the fork's line (slot_base/contribution_target/base_state,merge_verification, X-mode wording) and inserted only the agent-justification clause. The fork has no muse backend, so the upstream side'smuse-sessionline was dropped. The cross-reference was corrected to section 7, which is where the fork's dispatch contract lives.AGENTS.mddispatch section: kept both the fork's pool-slot refusal sentence and the contribution's new reason-code sentence.bin/fm-spawn.sh(five hunks): all purely additive on both sides, so both were kept: the fork's--slot-base/--contribution-targetaxes and the contribution's justification axes now coexist in the header, the variable block, the parser, the batch forwarding, and the meta writer.docs/examples/crew-dispatch.json: kept the fork's_schedulingadmission-control block and added"floor": "F-GEN"to the two default profiles.tests/fm-muse-harness.test.sh: deleted on the fork trunk, so it stays deleted; the contribution's mechanical edit to it does not apply.Test evidence
All runs are on this branch's final head
529141d, against baseed376cf.Changed-file selection, 70 suites:
bin/fm-test-run.sh $(bin/fm-test-run.sh --list --changed --base fork/main)The contribution's own suite and every suite this landing touched are green:
Also green:
bin/fm-lint.sh(ShellCheck 0.11.0 pinned),bin/fm-test-run.sh --check-coverage(total=134 parallel=24 serial=99 serial_shards=4 herdr=11),bin/fm-doc-audience-check.sh(surfaces=72 local_links=215). The lint pass was negative-controlled: an injected SC2086 violation madefm-lint.shexit 1 before the file was restored, so the clean pass is not an empty-check artifact.Failures, disclosed
Six suites failed. None is caused by this change, and each was proven on the unmodified base first.
Five fail identically on base
ed376cfin this environment, before any of this branch's commits:The sixth,
tests/fm-secondmate-harness.test.sh, is an artifact of running the suite from a checkout that sits on a feature branch: the worktree-tangle guard fires and its banner lands in the captured output the assertion reads. Control run, on the unmodified base clone with no code change at all, only checked out onto a feature branch:On base at its normal head the same suite exits 0. CI checks out a merge ref rather than a feature branch, so this one is expected to pass there.
Fork-side test adaptation
Commit
529141dis not part of the upstream contribution. Making--reason-coderequired refused five suites' spawn call sites before they reached the behavior they pin:fm-task-base,fm-launch-lib,fm-model-zero-budget,fm-backend, andfm-backend-herdr-launcher-workspace-e2e. These are fork-only suites, or grew fork-only call sites after the contribution was cut upstream, so the contribution could not adapt them. Each now declaresNL_RULE_CLASSIFICATION, matching how the contribution adapted every suite it could see. The Herdr launcher helper adds the flag conditionally, because a--secondmatespawn refuses--reason-codeoutright. No product behavior changes in that commit.Venue check state
The fork's own CI has unrelated red on other landing PRs: #54's
Behavior portable serial 1shard failed with onesecondmateand onewatcher-wake-lockfamily failure, and itsPR must be raised via no-mistakesgate fails by design for a direct-PR landing. If this PR shows the same pattern, that is the trunk's current state rather than a result of this change; the local evidence above is what this branch stands on.