Skip to content

feat(bin): add pre-dispatch admission gate for ship spawns - #2864

Open
pramendra wants to merge 7 commits into
kunchenguid:mainfrom
pramendra:fm/fleet-ws2-preflight-admission
Open

feat(bin): add pre-dispatch admission gate for ship spawns#2864
pramendra wants to merge 7 commits into
kunchenguid:mainfrom
pramendra:fm/fleet-ws2-preflight-admission

Conversation

@pramendra

Copy link
Copy Markdown

Intent

Build a pre-dispatch admission gate that fm-spawn.sh calls before launching a ship worker, refusing dispatch when any of four independently-proven preconditions fails: (1) push path reachable - the resolved push target (fork remote if configured, else origin) actually accepts a push from the authenticated GitHub identity; (2) delivery path completes end to end - the requested delivery mode (no-mistakes/direct-PR/local-only) is actually valid for this repo, e.g. direct-PR must be refused when a required CI workflow demands a no-mistakes-produced PR body, as on firstmate's own repo; (3) quota headroom measured - quota-axi reports a fresh, non-exhausted measurement for the resolved harness's provider, never assumed; (4) concurrency inside measured capacity - current host load average and available memory are inside a configured safe ceiling. The refusal must name exactly which precondition(s) failed, not a generic error, and a spawn must actually be refused by this gate in testing. Each check must be provably able to fail (mutation-tested), and any deliberately narrowed scope must be stated plainly rather than silently assumed to be complete.

What Changed

  • Add bin/fm-preflight-gate.sh, a new admission gate invoked before fm-spawn.sh creates a worktree or launches a ship worker. It independently proves four preconditions — reachable push path (fork remote if configured, else origin, via gh-axi api .../permissions.push), a delivery mode that can actually complete for the repo (no-mistakes init state, or a structural scan of .github/workflows/*.yml for a pull_request-triggered workflow requiring a no-mistakes-produced PR body when mode is direct-PR), fresh non-exhausted quota headroom from quota-axi --json for the resolved harness's provider, and host load average/free memory inside configurable ceilings — and refuses with one refused [<check>]: <reason> line per failed check (exit 4), or an admitted: ... line on success (exit 0).
  • Wire the gate into bin/fm-spawn.sh's ship-spawn path: it now shells out to fm-preflight-gate.sh with the resolved project dir, mode, and harness, and aborts the spawn (exit 4) on refusal, unless FM_PREFLIGHT_GATE_BYPASS=1 is set.
  • Add tests/fm-preflight-gate.test.sh covering admission and each of the four refusal paths, export FM_PREFLIGHT_GATE_BYPASS=1 from tests/lib.sh so existing hermetic fm-spawn suites (which fake tmux/git but not gh-axi/quota-axi/no-mistakes) aren't refused by checks they don't exercise, document the gate in docs/architecture.md and docs/scripts.md, and add a .serena/ project config/gitignore.

Risk Assessment

✅ Low: The change is additive and self-contained (a new bin/fm-preflight-gate.sh plus a 9-line call site in fm-spawn.sh gated behind a test-only bypass); every failure mode in the four checks fails closed (refuses rather than silently admitting), all four required preconditions from the intent are implemented and named on refusal, the scope narrowing (github.com-only push check, structural grep for the no-mistakes PR-body marker, quota-axi-mapped harnesses only, host-wide rather than per-task concurrency) is disclosed plainly in the script's own header exactly as the intent requires, and the new test suite exercises real refuse/pass behavior per check plus two live fm-spawn.sh integration tests rather than asserting on source text.

Testing

All four admission preconditions (push-path, delivery-path, quota-headroom, concurrency) are covered by refuse-case and pass-case tests plus a combined-failure naming test and two live fm-spawn.sh integration tests that demonstrate real refusal (exit 4, worktree/metadata/launch never created) and real admission (normal launch path unchanged); the full new suite (17/17) and four pre-existing fm-spawn ship-path suites all pass with no regressions, and a manual mutation of the push-path check confirmed the suite actually detects a broken precondition, satisfying the "provably able to fail" requirement.

Evidence: fm-preflight-gate.test.sh full run (17/17 passing)
ok - push-path refuses when origin denies push and no fork remote exists (the exact incident this workstream targets)
ok - push-path passes when a pushable fork remote is configured
ok - push-path refuses (not silently passes) on a remote it has no permissions API for
ok - push-path and delivery-path are no-ops for local-only (nothing is ever pushed)
ok - delivery-path refuses no-mistakes mode when the repo has no gate
ok - delivery-path refuses direct-PR against the exact convention that blocked it on firstmate's own repo
ok - delivery-path passes direct-PR when no workflow requires the no-mistakes marker
ok - quota-headroom refuses on a stale/keychain-required measurement (the real, currently-observed claude state)
ok - quota-headroom refuses on a fresh-but-exhausted measurement (the real, currently-observed codex state)
ok - quota-headroom passes on a fresh, non-exhausted measurement
ok - quota-headroom skips (not refuses) a harness quota-axi has no provider for
ok - concurrency refuses when host load average is mutated past the safe ceiling
ok - concurrency refuses when host available memory is mutated below the safe floor
ok - concurrency passes when host load/memory are within the safe ceiling
ok - a spawn failing two preconditions at once gets both named, not just the first
ok - fm-spawn.sh wiring: a failed admission check refuses before any endpoint or metadata is created
ok - fm-spawn.sh wiring: a fully healthy admission launches exactly as it did before this gate existed
Evidence: Mutation check: disabling push-path is caught by the suite
not ok - no push access and no fork remote should refuse: expected exit 4, got 0
(after restoring bin/fm-preflight-gate.sh: git status --short shows no diff)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

✅ **Review** - passed

✅ No issues found.

✅ **Test** - passed

✅ No issues found.

  • bash tests/fm-preflight-gate.test.sh (17/17 passing)
  • bash tests/fm-spawn-batch.test.sh
  • bash tests/fm-spawn-dispatch-profile.test.sh
  • bash tests/fm-spawn-pool-base-freshen.test.sh
  • bash tests/fm-spawn-worktree-settle.test.sh
  • Manual mutation test: neutered fm_preflight_check_push_path to always return 0, reran the suite, confirmed the push-path refusal test failed as expected, then restored the original file and verified git status --short shows no diff
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

Your Name added 2 commits August 23, 2026 20:04
Refuse a ship spawn before any worktree or endpoint exists unless push
path, delivery mode, quota headroom, and host concurrency are each
independently proven rather than assumed (fleet-engineering-plan
workstream 2, closes A + E). Wired into fm-spawn.sh's ship-spawn path;
hermetic ship-spawn suites opt out via FM_PREFLIGHT_GATE_BYPASS
(tests/lib.sh), mirroring FM_GATE_REFUSE_BYPASS's precedent.
@greptile-apps

greptile-apps Bot commented Aug 23, 2026

Copy link
Copy Markdown

Confidence Score: 3/5

The PR is not yet safe to merge because valid workflow syntax can bypass the direct-PR delivery admission check and launch work whose PR will be rejected.

The workflow scanner misses both valid commented or flow-style pull-request triggers and ordinary shell-variable indirection from the PR body, so the gate can admit delivery paths that cannot complete.

Files Needing Attention: bin/fm-preflight-gate.sh

Reviews (6): Last reviewed commit: "no-mistakes: apply CI fixes" | Re-trigger Greptile

Comment thread bin/fm-preflight-gate.sh Outdated
Comment thread bin/fm-preflight-gate.sh Outdated
Comment thread bin/fm-preflight-gate.sh Outdated
Comment thread bin/fm-preflight-gate.sh Outdated
Comment thread bin/fm-preflight-gate.sh Outdated
Comment thread bin/fm-preflight-gate.sh
Comment thread bin/fm-preflight-gate.sh
Comment on lines +240 to +243
/^on:[[:space:]]*pull_request[[:space:]]*$/ { found = 1; next }
/^on:[[:space:]]*$/ { in_on = 1; next }
in_on && /^[^[:space:]]/ { in_on = 0 }
in_on && /^[[:space:]]+pull_request:([[:space:]]|$)/ { found = 1 }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Valid pull-request triggers are missed

When a workflow declares on: pull_request # comment, places a comment after on:, or uses a flow mapping such as on: {pull_request: {types: [opened]}}, these patterns do not recognize the valid pull_request trigger. The delivery gate therefore admits a direct-PR spawn whose resulting PR is rejected by the required workflow.

Comment thread bin/fm-preflight-gate.sh
Comment on lines +267 to +269
if (trimmed ~ /^[A-Za-z_][A-Za-z0-9_]*:[[:space:]]*\$\{\{.*pull_request\.body.*\}\}/) {
name = trimmed; sub(/:.*/, "", name); body_vars[name] = 1
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Shell-assigned PR bodies go untracked

When a workflow assigns body="${{ github.event.pull_request.body }}" inside a run script and later compares $body with the no-mistakes marker, this YAML-only assignment pattern never records body as PR-body-derived. The comparison is missed, so the gate admits a direct-PR spawn whose resulting PR cannot satisfy the workflow.

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