Skip to content

fix(bin): keep the fleet view working past the per-argument cap - #46

Merged
sbracewell64 merged 1 commit into
mainfrom
fork-land/fleet-view
Aug 6, 2026
Merged

fix(bin): keep the fleet view working past the per-argument cap#46
sbracewell64 merged 1 commit into
mainfrom
fork-land/fleet-view

Conversation

@sbracewell64

Copy link
Copy Markdown
Owner

Intent

Repair the structured fleet view, which failed once the backlog grew past a size the fleet had already reached. Defect repair only: the output format and what the view reports are unchanged.

Defect 1 - the per-argument cap. bin/fm-fleet-snapshot.sh handed the whole backlog and task inventory to jq as --argjson command-line arguments. Linux caps a single argv entry at MAX_ARG_STRLEN (131072 bytes), independent of the much larger ARG_MAX total (2097152 here, which is why the total-size intuition misleads), so the snapshot died with Argument list too long.

Bulk JSON now travels on stdin: json_envelope assembles the value with shell builtins and pipes it into jq -n, whose filter reads it back with input. stdin was chosen over a temp file or a process substitution because this command is read-only and must stay that way - there is no file to create, secure, or leave behind when an interrupted read abandons it, and unlike --slurpfile the filter receives the value itself rather than a one-element array to unwrap. Every unbounded --argjson in the file is converted, not only the one that was failing.

Defect 2 - the fail-opens. task_json_lines built one row per task in a loop piped into jq -s, so a row that could not be serialized was dropped while jq -s slurped the survivors and exited 0. A task vanished from a snapshot that still reported success. scout_report_lines had the same shape and its caller checked no status at all, and bin/fm-fleet-view.sh rendered a snapshot that produced no output as a healthy empty fleet at exit 0. A genuine failure now exits nonzero and names what failed; an empty fleet remains a complete snapshot at exit 0.

Relationship to upstream PR 1612

Upstream kunchenguid/firstmate#1612 is open against the same task and its head (a53f8b4) is untouched by this branch. The two overlap and are not equivalent:

upstream 1612 this branch
Per-argument cap fixed, via json_inputs + successive input reads fixed, via json_envelope + one envelope
Task row fails closed fixed, per-row guard with return 1 fixed, scoped pipefail
bin/fm-fleet-view.sh empty-snapshot guard not addressed - file untouched fixed

The distinct contribution here is the renderer: 1612 does not modify bin/fm-fleet-view.sh, so a snapshot that exits 0 having produced nothing still renders there as a healthy empty fleet. Both approaches to the cap are sound; this is not a claim that 1612's snapshot work is wrong.

Delivery and verification status

This is a direct-PR, not a no-mistakes delivery. It carries no no-mistakes attestation marker and did not run that pipeline, so the Require no-mistakes check is expected to fail. That red is authorized for this PR and is not evidence of a defect in the change. Nothing here should be read as no-mistakes-verified; the evidence below is what was actually run.

Test evidence

Run on this branch at base aef7a6d (current fork trunk):

  • tests/fm-fleet-snapshot-view.test.sh - 20 assertions, exit 0
  • tests/fm-bearings-snapshot.test.sh - 41 assertions, exit 0
  • tests/fm-secondmate-safety.test.sh - 70 assertions, exit 0
  • shellcheck --norc --external-sources on both changed scripts - clean at the pinned 0.11.0

Negative controls, run against the unfixed code before any change, since this defect is precisely a false success:

  • oversized backlog - red, Argument list too long, exit 1
  • oversized task row - red, and the failure named the defect exactly: ["small-task"] where two tasks existed, from a snapshot that exited 0
  • failed/empty snapshot at the renderer - red, no error surfaced
  • empty fleet - green before and after, guarding against over-correction

The pre-fix code was also confirmed to fail against the real 141848-byte, 126-record backlog; the fixed code renders it at exit 0. Both oversized fixtures are generated programmatically and assert their own size exceeds the cap, so neither can go quietly vacuous.

Disclosed pre-existing failure: tests/fm-decision-hold-lifecycle.test.sh fails locally with fm-decision-hold: compatible tasks-axi is required against installed tasks-axi 0.2.3. This was confirmed to fail identically on unmodified HEAD via a clean git archive tree, so it is an environment version floor and is not caused by this change.

Merge

Do not merge. Raised for review only.

fm-fleet-snapshot.sh handed the whole backlog and task inventory to jq as
--argjson command-line arguments. Linux caps a single argv entry at
MAX_ARG_STRLEN (131072 bytes) independent of the much larger ARG_MAX total,
so the snapshot died with "Argument list too long" once the backlog crossed
that cap - a size the fleet had already reached.

Bulk JSON now travels on stdin: json_envelope assembles the value with shell
builtins and pipes it into `jq -n`, whose filter reads it back with `input`.
stdin was chosen over a temp file or a process substitution because this
command is read-only and must stay that way - there is no file to create,
secure, or leave behind when an interrupted read abandons it. Every unbounded
--argjson in the file is converted, not only the one that was failing.

The more serious half was a fail-open. task_json_lines built one row per task
in a loop piped into `jq -s`, so a row that could not be serialized was
dropped while `jq -s` slurped the survivors and exited 0 - a task vanished
from a snapshot that still reported success, and a supervisor reviewing the
fleet would see a task that does not exist. scout_report_lines had the same
shape and its caller checked no status at all, and fm-fleet-view.sh rendered
a snapshot that produced no output as a healthy empty fleet at exit 0. A
genuine failure now exits nonzero and names what failed, while an empty fleet
remains a complete snapshot at exit 0.

Tests generate the oversized backlog and the oversized task row
programmatically, assert both render in full, and assert that neither a
failed snapshot nor an empty one is ever reported as success.

The macOS stock-Bash job asserts an exact fleet-view test count, so its
expected value moves from 15 to 20 in the same commit as the five new tests
to keep the guard and the suite from drifting. The sibling Bearings
assertion stays at 41: that suite is unchanged.
@sbracewell64
sbracewell64 force-pushed the fork-land/fleet-view branch from 1ef77e2 to eed857d Compare August 6, 2026 03:15
@sbracewell64
sbracewell64 merged commit 561f0bb into main Aug 6, 2026
12 of 14 checks passed
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