Conversation
An operator who has consciously decided against an optional tool had no way to say so: bin/fm-bootstrap.sh reported every absent COMMON_TOOLS entry as a MISSING: line at every session start, forever. config/backlog-backend=manual already lets a home run without tasks-axi while still nagging about it. Add a local, gitignored config/optional-tools file, one declined tool per non-empty non-comment line (same line shape as config/wedge-alarm). An absent tool named there prints no MISSING: line. Only genuinely optional tools are declinable, each with a real fallback or degraded path: gh-axi and chrome-devtools-axi gate convenience work rather than a lifecycle step, lavish-axi is the optional visual surface for decisions plain chat already carries, tasks-axi has the declared backlog-backend=manual fallback, and quota-axi is read only to resolve a crew-dispatch profile array. node, git, gh, jq, no-mistakes, and the resolved backend's own required tools from fm_backend_required_tools are never declinable; naming one, or a typo, prints OPTIONAL_TOOLS: instead of being honored, so declination can never silence a tool a home actually needs. Declination covers absence only. The version-floor and feature-probe checks are untouched: installing a tool is not declining it. The file joins the declared FM_INHERITABLE_CONFIG allowlist, matching the backlog-backend precedent for a "this home runs without tool X" choice. That is safe under the primary-authoritative contract because each home resolves the non-declinable set against its OWN backend, so an inherited name that home requires is reported there rather than honored. With no config/optional-tools present, bootstrap output is byte-identical.
…inherited optional-tools
…tools declination
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.
Intent
Add a local, gitignored config/optional-tools knob so an operator can declare that they have consciously declined an OPTIONAL tool, and stop bin/fm-bootstrap.sh reporting it as MISSING: at every session start.
PROBLEM: bin/fm-bootstrap.sh hardcodes COMMON_TOOLS="node git gh no-mistakes gh-axi chrome-devtools-axi lavish-axi tasks-axi quota-axi", and every absent entry prints a MISSING: line at every single session start, forever, with no way to say 'I know, I have decided against it'. Firstmate already has a gitignored config/ surface for exactly this class of local operating choice (config/backend, config/crew-harness, config/backlog-backend, and a dozen more; see docs/configuration.md). The inconsistency is already documented: config/backlog-backend=manual exists precisely so a home can run without tasks-axi, and the bootstrap-diagnostics skill states that setting it only suppresses the verbose BOOTSTRAP_INFO fact, not the missing-tool report. So firstmate already supports running without the tool while still nagging about it.
REQUIREMENTS AS BUILT:
EXPLICITLY OUT OF SCOPE - do not flag these as gaps, they were ruled out deliberately:
HARD CONSTRAINT: keep the change small and reviewable. A tight diff is a requirement, not a preference - this repo's upstream has left two larger PRs unreviewed for five weeks, and size is the main thing working against it. Prefer patching existing language over adding new paragraphs.
VERIFICATION ALREADY DONE: bin/fm-lint.sh clean (ShellCheck 0.11.0), bin/fm-doc-audience-check.sh clean, and the compatibility requirement was verified rather than assumed - origin/main's bootstrap and this branch's were run against the same home with no config file and diffed byte-identical. All four acceptance criteria were also reproduced against the real toolchain. The full 146-script suite was run: 14 failures, of which 12 reproduce on a clean origin/main clone and 3 pass on both baseline and branch when re-run serially (parallel-load flakes); none are caused by this change.
What Changed
bin/fm-bootstrap.shreads a new local, gitignoredconfig/optional-toolsfile (one tool name per line, blank and#lines ignored) and suppresses theMISSING:line for each declined tool. Onlygh-axi,chrome-devtools-axi,lavish-axi,tasks-axi, andquota-axiare declinable; any other name — a typo, or a tool the resolved backend requires — gets its ownOPTIONAL_TOOLS:diagnostic instead of being honored, and aquota-axideclination is refused whileconfig/crew-dispatch.jsonexists. Version-floor and feature-probe reporting is deliberately untouched, andFM_BOOTSTRAP_VERBOSE_FACTS=1surfaces the honored declinations as aBOOTSTRAP_INFOfact.config/optional-toolswas added toFM_INHERITABLE_CONFIGinbin/fm-config-inherit-lib.sh, so declinations propagate to secondmate homes; each home still re-resolves the non-declinable set against its own backend, so an inherited name that home requires is reported there rather than honored.docs/configuration.md(new "Declined optional tools" section, plus corrections to the Toolchain and backlog-backend paragraphs that previously assertedtasks-axiandquota-axiwere unconditionally required), added the config line toAGENTS.md, gavebootstrap-diagnosticsan owner entry for theOPTIONAL_TOOLS:line, and extendedtests/fm-bootstrap.test.shwith table-driven coverage for declined, undeclared, non-declinable, backend-required, typo'd, empty, and absent-file cases plus unaffected version floors.Risk Assessment
✅ Low: The behavioral surface is small and well-guarded - a new opt-in local config file whose absence is a no-op, applied only to the absence branch of the existing tool loop, with the one enforced condition and the verbose fact covered by new table-driven rows in the existing test script - and the remaining issue is a one-clause documentation gap in an agent playbook.
Testing
Ran the colocated bootstrap test script (covering both new declination cases) plus the inheritance, gitignore, and documentation tests — all green — then demonstrated the feature manually against this machine's real toolchain, where the five axi-family tools are actually absent. The captured CLI transcript shows the before/after nag suppression, complete silence when all declinable tools are declined, the verbose audit fact, all four refusal paths (core tool, runtime-required tool, typo, conditional quota-axi), an unaffected version-floor upgrade report, byte-identical output versus the base commit when no config file exists, and inheritance into a second mate home with per-home re-resolution. No UI surface is involved — this is a CLI diagnostic change, so the transcript is the end-user-visible artifact. Temp homes and the version shim were removed and the working tree is clean.
Evidence: Real-toolchain bootstrap transcript: declining optional tools end-to-end
--- 1. BEFORE: no config/optional-tools -- every absent optional tool nags at every session start --- $ bin/fm-bootstrap.sh MISSING: gh-axi (install: npm install -g gh-axi && gh-axi setup hooks) MISSING: chrome-devtools-axi (install: npm install -g chrome-devtools-axi && chrome-devtools-axi setup hooks) MISSING: lavish-axi (install: npm install -g lavish-axi && lavish-axi setup hooks) MISSING: tasks-axi (install: npm install -g tasks-axi) MISSING: quota-axi (install: npm install -g quota-axi) --- 2. AFTER: the operator declares the tools they have consciously declined --- $ cat config/optional-tools # declined on purpose: this home uses plain chat and the manual backlog lavish-axi tasks-axi chrome-devtools-axi $ bin/fm-bootstrap.sh MISSING: gh-axi (install: npm install -g gh-axi && gh-axi setup hooks) MISSING: quota-axi (install: npm install -g quota-axi) (only the two tools NOT declined still report -- silence for the declined ones) --- 4. Declining ALL five genuinely-optional tools: the session start goes completely quiet --- $ bin/fm-bootstrap.sh (no output at all) --- 9. Backward compatibility: a home with NO config/optional-tools sees byte-identical output to before the change --- $ diff <(base-commit bootstrap) <(branch bootstrap) identical (5 lines each)Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
.agents/skills/afk/SKILL.md- branch carries 182 commit(s) that exist on your local main branch but were never pushed to origin/main; rebasing would bundle this unrelated work (363 file(s)) into the PR:Push main to origin, or rebase your branch onto origin/main, before gating.
bin/fm-bootstrap.sh:841-gh-axiis in DECLINABLE_TOOLS, and the comment above it (line 832) justifies this as gating "GitHub ... convenience work rather than any lifecycle step". The codebase contradicts that:bin/fm-pr-merge.sh:84invokesgh-axi pr mergedirectly with no fallback, and AGENTS.md section 7 mandates that script for every task PR merge ("never call a lower-level merge command around their guards");bin/fm-brief.sh:363likewise instructs the direct-PR worker to open the PR withgh-axi. Unliketasks-axi(which genuinely degrades viafm_tasks_axi_backend_availablefalling back to hand-editing),gh-axihas no fallback or degraded path, so it does not meet the stated inclusion criterion. Either drop it from the declinable set, or correct the comment and the matching docs/configuration.md paragraph to state that declining it disables the PR merge and direct-PR delivery paths rather than claiming no lifecycle step depends on it.bin/fm-bootstrap.sh:841-quota-axi's declinability rests on an explicitly conditional premise (comment lines 837-839, repeated in docs/configuration.md): it is only optional for "a home without config/crew-dispatch.json". Nothing enforces that condition. A home that has dispatch profiles and declinesquota-axigoes silent, yet AGENTS.md section 4 requires runningquota-axi --jsonat every intake that resolves a matched profile array and forbids guessing or silently falling back, and docs/configuration.md already states firstmate "cannot resolve a profile array without a compatible binary" - so dispatch is blocked with no bootstrap warning. Bootstrap already reads$CONFIG/crew-dispatch.jsonin the same run (crew_dispatch_validate, line 1041), so honoring aquota-axideclination only when that file is absent, and otherwise emitting the OPTIONAL_TOOLS error, is a few lines and keeps the stated rationale true in code.docs/configuration.md:308- The Toolchain section still asserts "tasks-axiandquota-axiare required bootstrap tools in every profile, the same class aslavish-axi" without qualification, while the new "Declined optional tools" section in the same file (which docs/configuration.md owns as the single owner of the config schema) says all three may be declined. A reader following the Toolchain section reaches the opposite conclusion from the one following the new section. Qualify line 308 with the declination path the same way the neighbouring tasks-axi line at 309 already qualifies itself with the backlog-backend fallback.bin/fm-config-inherit-lib.sh:70-optional-toolswas inserted mid-list, ahead ofstartup-memory-budget,trace-context, anddata/captain-shared.md. On a remote secondmate whose code root has not yet fast-forwarded,bin/fm-remote-inherit.shrejects the unknown path ("path is not inherited material") andbin/fm-remote-inherit-push.shruns underset -eu, so the push aborts at that item - and it aborts even for a primary that has noconfig/optional-toolsat all, because the absence mirror still sendsabsent config/optional-tools. This fail-closed-on-revision-skew behavior is documented and accepted (fm-config-inherit-lib.sh lines 50-56), so it is not a defect; the only observation is that appending the new item at the end of the list instead would let the pre-existing items still propagate during the skew window, shrinking the blast radius tocaptain-shared.mdalone.🔧 Fix: enforce quota-axi declination condition, append inherited optional-tools
1 warning still open:
bin/fm-bootstrap.sh:852- Thetasks-axientry in DECLINABLE_TOOLS justifies itself with "tasks-axi has the declared config/backlog-backend=manual fallback", but that fallback is scoped to firstmate's own routine backlog mutations only.bin/fm-backlog-handoff.shdelegates the secondmate item move totasks-axi mvunconditionally (its header: "The move needs compatibletasks-axion PATH, including atomic multi-IDmv"), andfm_tasks_axi_backend_availablein bin/fm-tasks-axi-lib.sh:119 is not consulted on that path. docs/configuration.md:43 states this in so many words: "Secondmate handoffs are separate and unconditional:fm-backlog-handoff.sh... always delegates the item move totasks-axi mv... Because bootstrap requirestasks-axionPATHon every profile, that delegation works fleet-wide, and theconfig/backlog-backend=manualknob governs firstmate's own hand-editing of its backlog, not this validated helper." Line 45 repeats the same unqualified premise. This change makes that premise false whenevertasks-axiis declined, yet only the parallel sentence at line 308 was qualified by FIX 3. Consequence: declaringtasks-axiin config/optional-tools without also settingconfig/backlog-backend=manualsilences the only signal (docs:309 - "it hand-edits data/backlog.md until installation is approved and completed") and leaves the secondmate handoff to fail at use time with no bootstrap warning. This is the same shape as the quota-axi issue already fixed in commit 3ece094 - a conditional fallback stated as rationale but not enforced - and unlike gh-axi it is not merely a pre-existing call-site failure, because the code comment and docs actively assert a guarantee this change invalidates. Minimal fix: qualify docs/configuration.md:43 and :45 the same way line 308 was patched, and correct the DECLINABLE_TOOLS comment to scope the tasks-axi fallback to firstmate's own backlog editing. Stronger fix, mirroring FIX 1: extenddeclination_blocked_reasonso atasks-axideclination is refused unlessconfig/backlog-backendismanual, reusing the existing OPTIONAL_TOOLS line shape.🔧 Fix: document tasks-axi declination handoff limitation
4 infos still open:
.agents/skills/bootstrap-diagnostics/SKILL.md:19- TheMISSING: <tool>entry is the playbook an agent actually loads when a tool is absent, and its prescribed response is still only "list the missing tools ... wait for consent ... then run bin/fm-bootstrap.sh install". Nothing there references the new config/optional-tools path, so an agent facingMISSING: gh-axievery session has no sanctioned way to act on a captain who says "I've decided against it" - which is the exact problem this change exists to solve. The pointer was added to docs/configuration.md:313 ("To stop reporting an optional tool you have decided against, see 'Declined optional tools' below"), but that is operator-facing prose, not the agent-facing trigger surface. Minimal fix: add one clause to the MISSING entry noting that a genuinely optional tool the captain has decided against can be recorded in config/optional-tools instead of re-proposed each session, cross-referencing the docs section as the one owner rather than restating the declinable set..agents/skills/bootstrap-diagnostics/SKILL.md:39- The new entry's remediation is "have the captain correct or remove the offending line", with no mention that config/optional-tools is now primary-authoritative inherited material (added to FM_INHERITABLE_CONFIG in bin/fm-config-inherit-lib.sh:70). Per that lib's own contract, "the primary's value wins and is re-pushed on every convergence", so on a secondmate home a local correction is silently reverted at the next bootstrap sweep or fm-config-push.sh run and the same OPTIONAL_TOOLS line returns. The STARTUP_MEMORY_BUDGET entry two lines above already handles exactly this shape correctly - "Correct the local primary file, then rerun session start so the normal convergence path can deliver the validated value to secondmate homes" - and is the pattern to mirror. Reachable case: an invalid or typo'd name is never removed from the file by bootstrap, so it propagates downstream and is reported on every home.docs/configuration.md:342- The rationale that now backs the enforced condition states flatly that "quota-axiis read only to resolve a crew-dispatch profile array, which a home with noconfig/crew-dispatch.jsonnever has", and bin/fm-bootstrap.sh:855 repeats it. That is not the only read: .agents/skills/harness-adapters/SKILL.md:139 - a skill AGENTS.md section 4 requires loading before every spawn, not only before array resolution - directs firstmate to "establish which credential store a tuple reads from the discovery surfaces below plusquota-axi auth --json's per-provider sources" for ambiguous harness/model tuples such asharness=piwithmodel=xai/grok-*. That path is reachable in a home with no dispatch profiles at all, via an explicit per-task captain harness/model override. Consequence is narrow and non-silent (the agent hits an absent binary and must report it), but the enforced condition is presented as exactly matching the hazard when it covers only the array-resolution half. Minimal fix: qualify the sentence so the condition is scoped to the profile-array read it actually gates rather than claimed as the tool's only use. No behavior change implied - this is not an argument to widen the enforcement.docs/configuration.md:344- The newly documented tasks-axi residual gap names bin/fm-backlog-handoff.sh as the consequence. There is a second, harder one it does not mention: bin/fm-remote-doctor.sh:59 declaresREQUIRED_TOOLS=(git jq herdr tasks-axi treehouse)and report_required_tools printsrequired tasks-axi=MISSINGfor an absent or incompatible build, which bin/fm-remote-readiness-lib.sh treats as a readiness failure and bin/fm-remote-home-seed.sh:241 turns into "remote runtime preflight failed; nothing was provisioned". So declining tasks-axi silences the local report while a remote secondmate route still hard-blocks at provisioning, and that enforcement point is not reached by the declinable-set logic at all. The failure is loud and self-describing, so this is a documentation-completeness gap rather than a hazard - but it is a second consequence a reader of the current sentence would not predict. Worth noting for whoever extends declination support later: bin/fm-remote-doctor.sh:61 already binds a variable literally namedOPTIONAL_TOOLSto an unrelated meaning (tools whose absence is merely reported), so the two concepts will collide by name there.🔧 Fix: qualify quota-axi and tasks-axi declination limits in docs
2 infos still open:
bin/fm-bootstrap.sh:788- The refusal message for a conditionally-blockedquota-axideclination reads "...; remove config/crew-dispatch.json or install quota-axi", and docs/configuration.md:343 mirrors it ("clear it by removing the dispatch profiles or installingquota-axi"). Both omit the least-destructive and most likely correct remedy: delete thequota-axiline fromconfig/optional-tools. As written, the first suggested action is to delete the captain's dispatch profiles - a real configuration loss - in order to silence a report. The bootstrap-diagnostics skill entry gets this right ("have the captain correct or remove the offending line"), but the emitted line is what a reader or a yolo-authorized agent acts on first, and it is the one surface that never mentions the declination line itself. Suggest reordering so the primary remedy is removing thequota-axientry fromconfig/optional-tools, then installing the tool, and dropping or de-emphasizing the dispatch-profile deletion. The same wording change applies to docs/configuration.md:343.docs/configuration.md:345- Lines 345 and 347 state the same fact twice: 345 says the partial quota-axi guard is worth keeping "unlike atasks-axicondition, which was rejected for guarding nothing at all", and 347 says "Nothing gates that declination, since gating it onconfig/backlog-backend=manualwould guard nothing". Beyond the duplication, line 345 references a rejection decision with no antecedent anywhere in the document - a reader who was not in the review has no idea whattasks-axicondition was rejected, and it appears two sentences before thetasks-axiparagraph that would give it context. Line 347 carries the reasoning in a place where it reads naturally. Suggest dropping the comparative clause from 345 (keeping "real enforcement of the hazard it does cover") and letting 347 own the rejected-alternative rationale, which also matches the one-owner rule the rest of this section follows.🔧 Fix: lead quota-axi declination refusal with least-destructive remedy
1 warning still open:
docs/configuration.md:347- The residual-limitation wording says atasks-axideclination "matters only for a home with registered secondmates", and the DECLINABLE_TOOLS rationale at bin/fm-bootstrap.sh:852-855 names only secondmate handoff and remote provisioning as the gaps. Both miss a lifecycle hard-block that applies to EVERY home. bin/fm-teardown.sh:2325 runsfm-decision-hold.sh verifyfor every scout teardown that is not--force, and command_verify calls require_tasks_axi (bin/fm-decision-hold.sh:473 -> :159fm_tasks_axi_compatible || fail), which is NOT routed throughfm_tasks_axi_backend_availableand so is not relaxed byconfig/backlog-backend=manual. Reachable case: a home declinestasks-axiin config/optional-tools, bootstrap goes silent, a scout finishes and writes its report, andbin/fm-teardown.sh <id>printsREFUSED: scout task <id> has not passed the unresolved-decision completion gate- a message that misattributes the cause, since the gate did not fail, the tool needed to evaluate it is absent. The operator cannot clear it either:review,resolve,decline, andrepairall call the same require_tasks_axi (lines 361, 402, 515, 584, 623), so thedecisions_reviewedmarker the gate checks can never be set. The only remaining exit is--force, which AGENTS.md hard rule 3 reserves for explicit captain discard authority. bin/fm-public-followup.sh:142 (die "tasks-axi is required") is a second unconditional dependency on the Relay path. Minimal fix, matching how round 3 handled the remote-doctor gap: extend the existing sentence at docs/configuration.md:346 to name the scout unresolved-decision completion gate (bin/fm-decision-hold.sh, enforced by bin/fm-teardown.sh) as a third consequence, drop or correct the "matters only for a home with registered secondmates" clause at line 347 since scout cleanup is universal, and adjust the bin/fm-bootstrap.sh comment's brief rationale to stop implying the gaps are secondmate-scoped. Whether that instead argues for removingtasks-axifrom DECLINABLE_TOOLS is the captain's call - a lifecycle step that refuses with a misleading message is a different class from the convenience gaps the inclusion criterion was written for.🔧 Fix: correct tasks-axi declination limitation scope and completeness
2 infos still open:
docs/configuration.md:347- The sentence claims "every command of that script needs a compatibletasks-axi" for bin/fm-decision-hold.sh. Two of its seven commands do not:command_id(bin/fm-decision-hold.sh:338) is a pure ID-derivation helper with no require_tasks_axi call, and-h|--help(line 660) dispatches straight to usage. require_tasks_axi is called only from hold, complete, verify, resolve, decline, and repair (lines 361, 402, 473, 515, 584, 623). The substantive conclusion is unaffected and correct - verify cannot pass and resolve/decline/repair cannot clear it - but the universal quantifier is the one part of the newly-completed limitation list that does not survive a check against the script. Narrow it to the gate-relevant commands (verify, resolve, decline, repair) so the sentence is exactly as verifiable as the rest of the list.bin/fm-bootstrap.sh:848- The DECLINABLE_TOOLS comment has grown to sixteen lines (848-863) that restate material docs/configuration.md "Declined optional tools" is designated to own: the per-tool fallback evidence (docs:342), the enforced quota-axi condition and its uncovered second read surface (docs:343-345), the tasks-axi residual gap (docs:346-348), and the never-declinable list, which is close to verbatim against docs:350. Two rounds of review instruction asked for "a brief accurate rationale that points at the docs owner", and this is the one place the change carries the same contract twice - the practical cost is that a future correction to the declination contract must land in both places or they drift, which is exactly the failure mode rounds 2 through 5 kept surfacing. Reducing it to the inclusion criterion (a real fallback or degraded path), the fact that declination_blocked_reason enforces the quota-axi condition, and a pointer to the docs section would keep every fact recoverable from one owner.🔧 Fix: narrow decision-hold claim, trim declinable-tools comment
2 infos still open:
bin/fm-bootstrap.sh:67- The file-header comment says "The declinable set and its per-tool fallback evidence are owned beside DECLINABLE_TOOLS below", but commit 903c510 trimmed that comment (lines 848-853) precisely so it no longer owns that material - it now reads "docs/configuration.md 'Declined optional tools' owns the per-tool rationale, the never-declinable set, the conditions declination_blocked_reason enforces, and what a declination still leaves broken." So the header now sends a reader to a pointer rather than to evidence; only the declinable set itself is genuinely owned at that line. Minimal fix: point the header at docs/configuration.md "Declined optional tools" for the per-tool rationale and keep the DECLINABLE_TOOLS reference for the set alone. While editing that block, note lines 61-65 immediately above still assert unqualified that "tasks-axi and quota-axi are required bootstrap tools" and that "quota-axi is required for the agent-owned dispatch-profile array procedure" - the same sentence FIX 3 qualified at docs/configuration.md:314 with "unless declined through config/optional-tools". A one-clause qualification there keeps the header from contradicting the paragraph six lines below it. Comment-only, no behavior change.bin/fm-bootstrap.sh:816- An honored declination is durable, primary-authoritative, and inherited into every secondmate home, yet it leaves no trace on any bootstrap surface -DECLINED_TOOLSis consumed only bytool_declinedand never reported. Silence in the default session start is the explicit requirement and should stay, but this repo already has a channel for exactly this class of fact:FM_BOOTSTRAP_VERBOSE_FACTS=1is off by default and never set bybin/fm-session-start.sh, and it is what surfacesBOOTSTRAP_INFO: crew harness override active: <crew>(line 1243) andBOOTSTRAP_INFO: crew dispatch active config/crew-dispatch.json(line 1128) - both durable local operating choices with the same forgettability problem. Reachable case: a captain declinesgh-axion the primary, it propagates fleet-wide, and months later there is no way to notice the declination short of reading the file on each home. One line guarded by the same flag (BOOTSTRAP_INFO: declined optional tools: $DECLINED_TOOLS) would restore on-demand discoverability without adding a substitute nag to any normal session. Raising this as a question rather than a fix, since requirement 2 deliberately chose silence and the flag semantics are the author's call.🔧 Fix: surface honored tool declinations as verbose bootstrap fact
1 info still open:
.agents/skills/bootstrap-diagnostics/SKILL.md:25- The new clause in theMISSING:entry tells an agent to "record that once inconfig/optional-tools" without saying which home's file to write. TheOPTIONAL_TOOLS:entry two rules below (line 41) states the missing half correctly - "config/optional-toolsis primary-authoritative inherited material, so correcting it on a secondmate home is reverted at the next convergence and the same line returns; correct the local primary file" - but that entry only fires on a configuration error, while line 25 is the clause an agent reaches on the ordinary path (captain says "I've decided against gh-axi" in response to a MISSING line). Reachable loop on a secondmate home: the agent writes the secondmate's ownconfig/optional-tools, the tool goes quiet for that session,propagate_inheritable_config(bin/fm-config-inherit-lib.sh:521-526) mirrors the primary's absence downstream at the next bootstrap sweep orbin/fm-config-push.sh, and the MISSING line returns next session - so the agent re-records it, indefinitely. Minimal fix: add "on the primary home" (or the same cross-reference line 41 already uses) to the line 25 clause. The STARTUP_MEMORY_BUDGET entry at line 37 is the established phrasing to mirror.✅ **Test** - passed
✅ No issues found.
./bin/fm-test-run.sh tests/fm-bootstrap.test.sh(includes newtest_optional_tools_declinationandtest_optional_tools_do_not_suppress_version_floors)./bin/fm-test-run.sh tests/fm-trace-context-lib.test.sh tests/fm-secondmate-harness.test.sh tests/fm-gitignore-config.test.sh tests/fm-documentation-audiences.test.shManual: real-toolchainFM_HOME=<temp home> bin/fm-bootstrap.shwith noconfig/optional-tools, capturing the five MISSING lines an operator sees at every session startManual: same home withconfig/optional-toolsdeclaring lavish-axi/tasks-axi/chrome-devtools-axi (plus a comment and blank lines) — only the two undeclared tools reportManual:FM_BOOTSTRAP_VERBOSE_FACTS=1 bin/fm-bootstrap.sh— honored declinations surface as aBOOTSTRAP_INFOfactManual: all five declinable tools declined — bootstrap emits no output at allManual:git,treehouse,lavish-axy, andquota-axi-with-crew-dispatch.jsoneach declined in turn — distinct OPTIONAL_TOOLS errors, tool still reported missingManual: base-commitbin/fm-bootstrap.sh(viagit archive f1a4af4 bin) vs branch, same home, no config file —diffbyte-identicalManual: temp PATH shim reportinggh-axi 0.1.1while gh-axi is declined — version-floor report still printedManual:propagate_inheritable_config <primary>/config <secondmate>/configthen bootstrap in the second mate home — inherited declinations honored thereManual: identicalconfig/optional-tools(treehouse) run against a tmux-runtime home and an orca-runtime home — different verdict per home✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.