Skip to content

fix(bin): read the configured tasks-axi backlog in the fleet snapshot - #6349

Open
KhalilouKarl wants to merge 9 commits into
kunchenguid:mainfrom
KhalilouKarl:fm/si-loop-fleet-beads-projection
Open

KhalilouKarl wants to merge 9 commits into
kunchenguid:mainfrom
KhalilouKarl:fm/si-loop-fleet-beads-projection

Conversation

@KhalilouKarl

@KhalilouKarl KhalilouKarl commented Oct 2, 2026 •

Copy link
Copy Markdown

Intent

yes do it and make sure our self-improvement worker looks at such things and optimizes them until we get the best solution

are we not using beads? I see the same beads open and in progress and blocked since a few days?

also go through every blocked bead and see if we still need it if its still blocked or if we can resolve it. also how is our selfimprovement system working give me an honest answer

The fleet-friction finding selected from that audit is that this Firstmate home uses Beads through tasks-axi, but the fleet overview reads a Markdown file instead and presents an empty, valid backlog while the configured queue contains real work. This slice repairs that misleading overview as part of the standing self-improvement order.

Decisions and constraints already made for this slice (so they are not mistaken for surprises in the diff): the structured fleet snapshot reads the configured backend through the existing shared backlog owner (bin/fm-backlog-transition-lib.sh, fm_backlog_rows_json) with exactly one bounded tasks-axi list and at most one count-driven re-read, no per-row show reads, no direct Beads command and no new dependency or general TOON framework; the strict table decoder accepts only the observed tasks-axi 0.2.5 envelope and treats an absent, unreadable, malformed or incomplete adapter output as a "Backlog unavailable" diagnostic through the existing main_inventory consumer, never as a valid empty inventory; links are read with the installed adapter's own first-match grammar with strict full consumption, and a cell that cannot be consumed keeps links_raw, withholds parsed artifacts and is disclosed through main_inventory; truncated titles keep the raw cell and render with an ellipsis; markdown and manual backends keep their existing behavior byte for byte. Local evidence includes the real installed tasks-axi and Beads adapter in isolated fixture homes with a guarded br and refusing endpoint stubs (tests/fm-fleet-snapshot-view.test.sh), captured real adapter output as a supplement, and red-on-base then green evidence. The session-start digest has a separate backlog path that is deliberately not changed here. tests/fm-contributions.test.sh already fails identically on the unmodified base (watcher did not surface the new contribution signal) and is not part of this change. Test and fixture homes must be isolated throwaway FM_HOME values, never the inherited live fleet home. Deliver through the mandatory no-mistakes fork workflow; upstream merge authority stays off.

What Changed

  • The fleet snapshot (bin/fm-fleet-snapshot.sh) now reads a non-markdown tasks-axi/Beads backlog through the shared backlog owner (fm_backlog_rows_json in bin/fm-backlog-transition-lib.sh) instead of an empty Markdown file. A strict decoder accepts only the observed tasks-axi 0.2.5 table envelope. Absent, unreadable, malformed or incomplete adapter output is reported as a "Backlog unavailable" diagnostic through main_inventory, never as a valid empty backlog. Rows that carry links the adapter grammar cannot fully consume keep links_raw, withhold parsed artifacts and are disclosed through main_inventory. Truncated titles keep the raw cell and render with an ellipsis. Markdown and manual backends are unchanged.
  • bin/fm-fleet-view.sh renders "Backlog unavailable: …" in the Queued and Done sections and shows links ambiguous: <raw> in the Artifact column. bin/fm-bearings-snapshot.sh surfaces a count of backlog rows with ambiguous artifact links. docs/architecture.md and docs/documentation-audiences.json describe the configured backlog backend.
  • tests/fm-fleet-snapshot-view.test.sh adds coverage in isolated throwaway fixture homes, running against the installed tasks-axi/Beads adapter with a guarded br and refusing endpoint stubs. It also covers hold-reason decode parity. Real captured tasks-axi 0.2.5 output is added under tests/captures/tasks-axi-0.2.5/ as a supplement.

Risk Assessment

✅ Low: The rebase resolution keeps upstream's markdown hold-reason decode and pipefail unchanged, and the adapter path is bounded and fails loudly as a "Backlog unavailable" diagnostic rather than an empty inventory. The new tests drive the real adapter and captured output, so I found no concrete defect or intent violation. I only read the diff and call sites and did not run any tests.

Testing

I re-drove the round-1 failure against the real installed tasks-axi 0.2.5 and Beads (br) in an isolated throwaway home. The Beads snapshot's hold_reason is now Pick (A) or (B)\n100% sure?, matching the markdown home's decoded value. tests/fm-fleet-snapshot-view.test.sh passes in full, including the new adapter-path decode assertion. tests/fm-captain-hold-lifecycle.test.sh could not run here: the installed tasks-axi 0.2.5 is below the 0.2.6 floor in bin/fm-tasks-axi-lib.sh, so bin/fm-captain-hold.sh refuses. This branch touches neither file, and the markdown hold-reason path is covered by the markdown probe instead.

  • Live validation: ✅ go - 6 of 7 scenarios driven live against the product
Scenario Result Live Evidence
Captain-hold with an fm-hold-v1 reason on a real Beads home: the snapshot shows the decoded reason ✅ pass live probe-encoded-hold-after-fix.log: tasks-axi list still returns the encoded text, while the snapshot record has hold_reason 'Pick (A) or (B)\n100% sure?'
Markdown home decodes the same reason identically (parity) ✅ pass live probe-markdown-hold-after.log
Fleet view on a Beads home renders the held captain row without breaking ✅ pass live probe-encoded-hold-after-fix.log: the view lists held-choice with kind captain. The view's table has no hold-reason column, so the decoded text is only checked in the snapshot.
Real tasks-axi/Beads backlog reaches the snapshot, fleet view and bearings, ignoring a stale shadow markdown file, with the encoded-hold assertion ✅ pass live tests/fm-fleet-snapshot-view.test.sh, case 'a real tasks-axi/Beads backlog reaches the snapshot, view and bearings...'
Unavailable, unreadable and empty adapter backlogs are diagnosed rather than shown as a valid empty backlog ✅ pass live tests/fm-fleet-snapshot-view.test.sh, case 'unavailable, unreadable and empty adapter backlogs are told apart'
Real adapter link cells parse faithfully, and an unprovable cell is withheld with a disclosure ✅ pass live tests/fm-fleet-snapshot-view.test.sh, case 'real adapter link cells parse faithfully...'
Upstream #6331 markdown hold-reason lifecycle regression still passes after the rebase ⏸️ untested no The installed tasks-axi is 0.2.5 and fm-tasks-axi-lib.sh requires at least 0.2.6, so bin/fm-captain-hold.sh refuses on this host. Install tasks-axi 0.2.6 or later to run tests/fm-captain-hold-lifecycl…
Evidence: Encoded hold reason after fix (Beads home)

Source: Encoded hold reason after fix (Beads home)

stored reason: fm-hold-v1:UGljayAoQSkgb3IgKEIpCjEwMCUgc3VyZT8=
help[2]:
  - Run `tasks-axi unhold held-choice` to resume dispatch
  - Run `tasks-axi ready --include-held` to review paused work
--- tasks-axi list (raw)
  held-choice,queued,captain,fixture,Decision,"fm-hold-v1:UGljayAoQSkgb3IgKEIpCjEwMCUgc3VyZT8=",captain
help[2]:
  - Run `tasks-axi show <id>` for full notes on a task
  - Run `tasks-axi ready` to see unblocked queued work
--- snapshot records
"tasks-axi"
{"id":"held-choice","hold_reason":"Pick (A) or (B)\n100% sure?","hold_kind":"captain"}
--- fleet view
| --- | --- | --- | --- | --- | --- |
| held-choice | Decision | fixture | captain | - | - |
Evidence: Markdown parity probe after fix

Source: Markdown parity probe after fix

## In flight
- [ ] held-choice - Decision (repo: fixture) (kind: captain) (hold: fm-hold-v1:UGljayAoQSkgb3IgKEIpCjEwMCUgc3VyZT8=) (hold-kind: captain)
null
null
{"id":"held-choice","hold_reason":"Pick (A) or (B)\n100% sure?","hold_kind":"captain"}
Evidence: Targeted test run

Source: Targeted test run

## tests/fm-fleet-snapshot-view.test.sh
ok - snapshot includes durable scout reports after teardown
ok - snapshot parses tasks-axi rows and respects operational overrides
ok - fleet view renders the snapshot without secondmate peek guidance
ok - fleet view renders secondmate agent liveness
ok - adapter reads are bounded, complete or diagnosed, strictly decoded, and markdown homes are untouched
ok - a real tasks-axi/Beads backlog reaches the snapshot, view and bearings, ignoring a stale shadow file
ok - unavailable, unreadable and empty adapter backlogs are told apart
ok - real adapter link cells parse faithfully, and an unprovable doc-link cell is withheld with a disclosure
exit=0
## tests/fm-captain-hold-lifecycle.test.sh
fm-captain-hold: compatible tasks-axi is required
not ok - hold refused the reason for sample-reason-call
exit=1
Evidence: Round-1 failing probe output (before fix)

Source: Round-1 failing probe output (before fix)

stored reason: fm-hold-v1:UGljayAoQSkgb3IgKEIpCjEwMCUgc3VyZT8=
help[2]:
  - Run `tasks-axi unhold held-choice` to resume dispatch
  - Run `tasks-axi ready --include-held` to review paused work
--- tasks-axi list (raw)
  held-choice,queued,captain,fixture,Decision,"fm-hold-v1:UGljayAoQSkgb3IgKEIpCjEwMCUgc3VyZT8=",captain
help[2]:
  - Run `tasks-axi show <id>` for full notes on a task
  - Run `tasks-axi ready` to see unblocked queued work
--- snapshot records
"tasks-axi"
{"id":"held-choice","hold_reason":"fm-hold-v1:UGljayAoQSkgb3IgKEIpCjEwMCUgc3VyZT8=","hold_kind":"captain"}
--- fleet view
| --- | --- | --- | --- | --- | --- |
| held-choice | Decision | fixture | captain | - | - |
- Outcome: 🔧 2 issues found → auto-fixed ✅ across 2 runs (22m30s)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

🔧 **Rebase** - 1 issue found → auto-fixed ✅
  • ⚠️ bin/fm-fleet-snapshot.sh - merge conflict rebasing onto origin/main

🔧 Fix applied.
✅ Re-checked - no issues remain.

✅ **Review** - passed

✅ No issues found.

🔧 **Test** - 2 issues found → auto-fixed ✅
  • ⚠️ bin/fm-fleet-snapshot.sh:497 - The rebase resolution assumed hold reasons from tasks-axi list are already plain decoded text, so the adapter path skips fm_hold_reason_decode_stream. That premise is false for real Beads. bin/fm-captain-hold.sh stores reasons encoded as fm-hold-v1:&lt;base64&gt;, and tasks-axi list --fields hold_reason returns that string unchanged. On a real Beads home with a held captain row, the snapshot's .backlog.records[].hold_reason and the fleet view both show fm-hold-v1:UGljayAoQSkgb3IgKEIpCjEwMCUgc3VyZT8=. The same reason in a markdown home decodes to Pick (A) or (B)\n100% sure?. The captain therefore sees an opaque string for the very case fix(bin): preserve hold reasons and reject invalid completion inventories #6331 introduced the encoding for: reasons containing parentheses, line breaks or percent signs. tests/fm-fleet-snapshot-view.test.sh only covers a plain reason with a comma, so it passes. This conflicts with the recorded rebase decision (3), which says not to decode adapter records. The decision rests on that wrong premise. A single decode of the adapter records' hold_reason is idempotent for plain text (decode_reason returns unmarked values unchanged), so decoding does not corrupt plain reasons. Decide whether to apply fm_hold_reason_decode_stream json to the adapter output as well, or accept the encoded display. Reproduce with evidence/.../probe-encoded-hold.sh.
  • 🚨 live validation verdict: no-go (6 of 7 scenarios were driven live against the product); failed: Captain-hold with an fm-hold-v1-encoded reason on a real Beads home shows the decoded reason in the snapshot and fleet view
  • Live validation: ❌ no-go - 6 of 7 scenarios driven live against the product
Scenario Result Live Evidence
Configured Beads backlog appears in the fleet snapshot, view and bearings instead of an empty markdown backlog (real tasks-axi/Beads fixture homes, stale shadow file ignored) ✅ pass live snapshot-view.log: 'a real tasks-axi/Beads backlog reaches the snapshot, view and bearings, ignoring a stale shadow file'
Unavailable, unreadable and empty adapter backlogs give a 'Backlog unavailable' diagnostic or an empty inventory as appropriate, never a silent empty one ✅ pass live snapshot-view.log: 'unavailable, unreadable and empty adapter backlogs are told apart'
Adapter reads are bounded, strictly decoded, and markdown homes are untouched ✅ pass live snapshot-view.log: 'adapter reads are bounded, complete or diagnosed, strictly decoded, and markdown homes are untouched'
Real adapter link cells parse faithfully, and an unparseable link cell is withheld and disclosed ✅ pass live snapshot-view.log: 'real adapter link cells parse faithfully...'
Markdown home still decodes an fm-hold-v1 captain-hold reason in the snapshot after the rebase ✅ pass live probe-markdown-hold.log shows hold_reason decoded to 'Pick (A) or (B)\n100% sure?'
Captain-hold with an fm-hold-v1-encoded reason on a real Beads home shows the decoded reason in the snapshot and fleet view ❌ fail live probe-encoded-hold.log: snapshot hold_reason is 'fm-hold-v1:UGljayAoQSkgb3IgKEIpCjEwMCUgc3VyZT8=' and the fleet view prints the raw string
Upstream #6331 hold-lifecycle regression (test_hold_reason_round_trips_awkward_characters) still passes with the merged code ⏸️ untested no The machine has tasks-axi 0.2.5 and the repo's minimum is 0.2.6 (FM_TASKS_AXI_MIN in bin/fm-tasks-axi-lib.sh). Install tasks-axi 0.2.6 or newer, or run in CI, to drive it. The markdown decode path was…
  • bash tests/fm-fleet-snapshot-view.test.sh (22 ok, 0 failures: real tasks-axi/Beads adapter reaches snapshot, view and bearings; unavailable, unreadable and empty adapter backlogs are told apart; link cells; bounded reads; markdown homes untouched)
  • bash evidence/.../probe-encoded-hold.sh: live probe on an isolated throwaway real Beads home (br and tasks-axi 0.2.5) with an fm-hold-v1-encoded captain-hold reason; snapshot and fleet view show the raw encoded text
  • bash evidence/.../probe-markdown-hold.sh: live probe on an isolated markdown home; the snapshot decodes the same encoded reason correctly (markdown behaviour kept)
  • Trimmed copy of test_hold_reason_round_trips_awkward_characters from tests/fm-captain-hold-lifecycle.test.sh: could not run, because upstream requires tasks-axi >= 0.2.6 and 0.2.5 is installed (fm-captain-hold: compatible tasks-axi is required). Not caused by this change; the temporary copy was removed.

🔧 Fix applied.
✅ Re-checked - no issues remain.

  • Live validation: ✅ go - 6 of 7 scenarios driven live against the product
Scenario Result Live Evidence
Captain-hold with an fm-hold-v1 reason on a real Beads home: the snapshot shows the decoded reason ✅ pass live probe-encoded-hold-after-fix.log: tasks-axi list still returns the encoded text, while the snapshot record has hold_reason 'Pick (A) or (B)\n100% sure?'
Markdown home decodes the same reason identically (parity) ✅ pass live probe-markdown-hold-after.log
Fleet view on a Beads home renders the held captain row without breaking ✅ pass live probe-encoded-hold-after-fix.log: the view lists held-choice with kind captain. The view's table has no hold-reason column, so the decoded text is only checked in the snapshot.
Real tasks-axi/Beads backlog reaches the snapshot, fleet view and bearings, ignoring a stale shadow markdown file, with the encoded-hold assertion ✅ pass live tests/fm-fleet-snapshot-view.test.sh, case 'a real tasks-axi/Beads backlog reaches the snapshot, view and bearings...'
Unavailable, unreadable and empty adapter backlogs are diagnosed rather than shown as a valid empty backlog ✅ pass live tests/fm-fleet-snapshot-view.test.sh, case 'unavailable, unreadable and empty adapter backlogs are told apart'
Real adapter link cells parse faithfully, and an unprovable cell is withheld with a disclosure ✅ pass live tests/fm-fleet-snapshot-view.test.sh, case 'real adapter link cells parse faithfully...'
Upstream #6331 markdown hold-reason lifecycle regression still passes after the rebase ⏸️ untested no The installed tasks-axi is 0.2.5 and fm-tasks-axi-lib.sh requires at least 0.2.6, so bin/fm-captain-hold.sh refuses on this host. Install tasks-axi 0.2.6 or later to run tests/fm-captain-hold-lifecycl…
  • bash evidence/.../probe-encoded-hold.sh: isolated real Beads home, tasks-axi hold with an fm-hold-v1 reason, then bin/fm-fleet-snapshot.sh --json and bin/fm-fleet-view.sh
  • bash evidence/.../probe-markdown-hold.sh: the same reason in a markdown home, as the parity baseline
  • bash tests/fm-fleet-snapshot-view.test.sh: all cases pass, including the new encoded-hold assertion, the real tasks-axi/Beads backlog case, the unavailable/unreadable/empty cases and the link-cell case
  • bash tests/fm-captain-hold-lifecycle.test.sh: fails on this host with fm-captain-hold: compatible tasks-axi is required
✅ **Document** - passed

✅ No issues found.

⚠️ **Lint** - 1 warning
  • ⚠️ linter found issues (exit code 1)

🔧 No changes applied.
1 warning still open:

  • ⚠️ linter found issues (exit code 1)

🔧 No changes applied.
1 warning still open:

  • ⚠️ linter found issues (exit code 1)

🔧 Fix applied.
1 warning still open:

  • ⚠️ linter found issues (exit code 1)
✅ **Push** - passed

✅ No issues found.

Author notes: manual evidence and limitations (added after PR open)

These notes are the author's, not output of the no-mistakes pipeline. Each result names the head it was run on.

  • Lint. The native lint step failed for an environmental reason: the private pipeline daemon's PATH had no ShellCheck (fm-lint.sh: ShellCheck not found). That finding was approved (no --yes, no skip) on the strength of a manual run, which is separate evidence and not the pipeline's verdict. At 971194e5, in a clean clone, PATH=<pinned linters>:$PATH bin/fm-lint.sh exited 0 (ShellCheck 0.11.0, actionlint 1.7.12, 3 workflow files) and --list-files selected bin/fm-backlog-transition-lib.sh, bin/fm-bearings-snapshot.sh, bin/fm-fleet-snapshot.sh, bin/fm-fleet-view.sh and tests/fm-fleet-snapshot-view.test.sh. The same manual run exited 0 at 339cf840 and at the current head cacf2272.
  • Hold-reason evidence used the encoder fallback, not the real bin/fm-captain-hold.sh CLI. The installed tasks-axi is 0.2.5, below FM_TASKS_AXI_MIN 0.2.6, so fm-captain-hold.sh refuses to run. test_adapter_hold_reasons_decode_like_markdown stores the reason with the owner encoder (fm_hold_reason_encode) and the real tasks-axi hold on a real Beads home (it prints owner: encoder). The real owner route and the full real-owner hold lifecycle are untested on this host.
  • tests/fm-captain-hold-lifecycle.test.sh fails on this host. At 971194e5: exit 1, not ok - hold refused the reason for sample-reason-call, fm-captain-hold: compatible tasks-axi is required. The identical failure occurs on the unmodified upstream base 6af83310. That is baseline evidence only; it does not show the absence of a coexisting regression, because the suite cannot exercise this change here. Likewise tests/fm-contributions.test.sh fails on the base and on this change; its cause is not established by these notes.
  • Suites by head. 971194e5: fm-fleet-snapshot-view exit 0 (23 ok), fm-bearings-snapshot exit 0 (58 ok). 339cf840: fm-fleet-snapshot-view exit 0 (27 ok). cacf2272: fm-fleet-snapshot-view exit 0 (27 ok). fm-bearings-snapshot was not re-run after 971194e5.
  • CI-review rounds. 339cf840 fixed the inherited TASKS_AXI_FILE (adapter read and test fixtures), the incomplete empty response and | in an ambiguous link value, each with a regression test that fails on the previous code. cacf2272 fixes the "PR link mistaken for merge" finding: tasks-axi records no merge state (done --pr links a PR without checking it), so an adapter row closed with a PR link keeps its closed state, close date, PR link and raw data but is no longer labelled merged. The regression test_adapter_backlog_reaches_snapshot_view_and_bearings fails on 339cf840 code and passes on cacf2272; the Markdown control still reports an explicitly merged row as merged.
  • Known limitation, newly raised by Greptile on cacf2272 ("Shipped PRs disappear"). Because the landed selector requires a merged verb for rows with a PR link, ordinary adapter-backed shipped work (closed by fm-teardown with done --pr) does not appear in Recently Landed in the fleet snapshot and Bearings. This is the deliberate trade of limited truthful coverage over a false merge claim. A verified-merge signal for adapter rows (a tasks-axi field or a merge check at teardown) is not part of this change.
  • CI. The CI and Require no-mistakes workflow runs show action_required (fork-PR workflow approval by a maintainer); they have not run. No upstream merge is requested or implied.

KhalilouKarl and others added 7 commits October 2, 2026 01:30
…acklog owner

Add fm_backlog_rows_json beside fm_backlog_row_list: one bounded list read
with a count-driven re-read, a strict table decoder and the tasks-axi link
grammar, returning an error object instead of an empty inventory.
…view and bearings

A home whose tasks-axi backend is not markdown had its backlog read from the
empty data/backlog.md next to it, so the snapshot reported no work and a valid
inventory. The snapshot now reads the adapter through the shared reader, and an
unavailable, malformed or incomplete read is present:false with a diagnostic
that main_inventory reports instead of an empty valid backlog.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@greptile-apps

greptile-apps Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 4/5

[Medium risk] Adds support for reading backlog from a tasks-axi backend instead of markdown.

The PR does not appear ready to merge because verified ship completions disappear from Recently Landed on tasks-axi homes.

Reviews (3) · Last reviewed commit: "fix(fleet): do not label an adapter row ..."

Comment thread bin/fm-backlog-transition-lib.sh Outdated
Comment thread bin/fm-backlog-transition-lib.sh Outdated
Comment thread bin/fm-backlog-transition-lib.sh
Comment thread tests/fm-fleet-snapshot-view.test.sh
Comment thread bin/fm-fleet-view.sh Outdated
KhalilouKarl and others added 2 commits October 2, 2026 02:46
…mpty response, escape pipes

- fm_backlog_rows_list_once runs tasks-axi list with TASKS_AXI_FILE cleared, like bin/fm-tasks-axi.sh.
- The count: 0 branch accepts only the full captured empty response (tasks line plus help block).
- Fixture helpers unset TASKS_AXI_FILE so fixtures stay isolated.
- The fleet view escapes | in the raw ambiguous link value.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
tasks-axi done --pr links a PR without checking merge state, so a closed
row with a PR link proves closure and an artifact, not a merge. Keep the
row, link and close date; leave the completion verb unset so it is not
reported as landed. Explicit Markdown merged metadata is unchanged.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Comment thread bin/fm-backlog-transition-lib.sh
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