Skip to content

fix(omp): route branch bash through extension runner - #170

Merged
dnth merged 3 commits into
mainfrom
fm/fm-branch-bash-env-fix
Sep 26, 2026
Merged

dnth merged 3 commits into
mainfrom
fm/fm-branch-bash-env-fix

Conversation

@dnth

@dnth dnth commented Sep 26, 2026

Copy link
Copy Markdown
Owner

Intent

Fix the OMP supervision branch so its bash tool works on OMP 18.3.x.

Root cause (full diagnosis: data/fm-branch-executor-fails-inspection/report.md): .omp/extensions/fm-branch-supervision-omp.ts builds the branch bash tool with createBashToolDefinition(fmRoot, { spawnHook }), and the spawnHook returns env. OMP 18.3.0 moved bash env behind service mode; its legacy shim still forwards env: spawn?.env into the native bash tool, which throws "ready and env require a service name." before spawning. Every branch bash call has failed since the 18.3.0 install, so the branch cannot inspect, drain, or acknowledge wakes.

Required: apply the report's recommended firstmate-side fix - pass operations.exec to createBashToolDefinition so the extension executes through its own runner with the actor env (FM_SUPERVISION_ACTOR=branch, FM_LEASE_HOLDER_PID, FM_HOME and the other injected variables) - or the alternative only if the recommended one proves unworkable (record why). Keep the confused-agent-grade actor injection intact: the branch's commands must still carry FM_SUPERVISION_ACTOR=branch and the lease holder identity, so bin/fm-wake-drain.sh scopes branch acks correctly. Must work on OMP 18.3.x and not break older OMP versions the repo supports (the adapter's documented version floor is OMP 17.1.8; the operations seam exists there with the same shape).

Out of scope: upstream OMP changes (an upstream issue draft was recorded in evidence instead), other extensions, the main primary adapter. Never run Firstmate supervision scripts against ~/Desktop/firstmate; reproduce in a scratch home only.

Acceptance criteria:

  • AC1: On the installed OMP 18.3.x, a branch bash call runs its command instead of throwing "ready and env require a service name". Proving test: the scratch-home repro as an automated test, red on origin/main, green after; artifact with exact command.
  • AC2: Commands run by the branch bash tool still see FM_SUPERVISION_ACTOR=branch, FM_LEASE_HOLDER_PID, and the other injected env, and an agent cannot override them. Proving test: assert the env inside a branch-executed command.
  • AC3: Branch-scoped wake drain/ack works end to end in a scratch home: a granted row is presented and acknowledged by the branch actor, not left for main. Proving test: scratch-home E2E with a repeatable artifact.
  • AC4: Existing OMP extension tests and typecheck stay green. Proving check: full portable suite and the repo's extension typecheck.
  • AC5: docs/omp-supervision-branch.md (and the harness-adapters OMP fact if affected) records the OMP 18.3 env change and how the branch now injects its actor env. Proving check: doc diff.

Firstmate-Validation-Generation: e9de87fe77406a108a2337162a4edea7

What Changed

  • Route the OMP supervision branch bash tool through the shared async BashOperations runner, preserving injected actor and lease-holder environment on OMP 18.3.x and earlier supported versions.
  • Extend async command execution with streaming output, abort handling, timeouts, and bash-tool error mapping.
  • Add scratch-home regression coverage for actor-environment protection and branch wake drain/ack behavior, and document the OMP 18.3.x compatibility seam.

Risk Assessment

✅ Low: The operations seam wiring preserves actor environment injection, timeout behavior, and process-tree cancellation without introducing a source-verifiable defect in the reviewed changes.

Testing

Against the real installed OMP 18.3.0, the new branch bash regression exercised command execution, injected actor identity, readonly override protection, and branch-scoped wake acknowledgement successfully; existing supervision tests also passed. The prior payload did not establish live results for the extension typecheck or documentation scenario.

  • Live validation: ⚠️ inconclusive - 3 of 5 scenarios driven live against the product
Scenario Result Live Evidence
Run a branch bash command on installed OMP 18.3.x; it executes instead of throwing the service-mode env error ✅ pass live OMP 18.3.0 + bash tests/fm-omp-branch-bash.test.sh artifact
Attempt to override injected actor variables inside a branch command; readonly protection rejects the override ✅ pass live Same branch-bash regression artifact
Grant a wake row, drain and acknowledge it as the branch actor; main does not claim it ✅ pass live Same branch-bash regression artifact
Run the existing OMP extension typecheck ⏸️ untested no The prior payload marked this scenario live=false and therefore did not establish a live product result.
Documentation records the OMP 18.3 env change and actor-env injection ⏸️ untested no The prior payload cited a documentation diff only and did not establish this scenario against the live product.
Evidence: OMP 18.3 branch bash regression
$ omp --version
omp/18.3.0
$ bash tests/fm-omp-branch-bash.test.sh
ok - the branch bash tool executes its command with the injected branch actor environment
ok - an in-shell override of the injected actor env fails loudly on the readonly guard
ok - a granted wake row is presented and acknowledged by the branch actor end to end, not left for main
Evidence: OMP extension typecheck failure
../../../../../../tmp/fm-omp-branch-types.xHnITI/.omp/extensions/lib/fm-task-inbox-doorbell.ts(89,2): error TS2741: Property 'failureJournal' is missing in type '{ inboxDir: string; readyMarker: string; turnGraceMs: number; observeTurns: boolean; }' but required in type 'Required<TaskInboxDoorbellOptions>'.
Evidence: OMP branch supervision tests
ok - branch prompt is byte-stable across homes, cwd, timezone, and time, above the cache floor, OMP-named
ok - outcome store is append-only and refuses sequence reuse after a torn tail
ok - startup replay skips silent outcomes and preserves visible rows
ok - live outcome handoff refuses gaps and leaves the complete unread prefix for startup replay
ok - lease exclusivity, same-actor refresh, release, staleness, and sweep hold
ok - the role partition refuses the branch actor from merge, land, fresh spawn, and forced discard
ok - main steer and teardown refuse before mutation while the branch holds the task lease
ok - fm-pr-check stays inert without supervision and refuses a branch-held task lease
ok - a home that never runs the branch has no lease files, no actor state, no retained command lock, and silent guards
ok - OMP extension load establishes the main supervision actor context
ok - OMP outcome delivery yields to the event loop while preserving routine/captain order
ok - OMP dispatch resolves signal and stale rows to the branch report task and excludes checks
ok - a routine verdict on a granted completion opens a captain turn and settles
ok - a settled prompt that leaves a granted completion unreported rejects and releases the grant
ok - a consumed completion is re-sent exactly once on the next wake and never again
- Outcome: ⚠️ 2 warnings across 1 run (4m1s)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 2 issues found → auto-fixed ✅
  • ⚠️ .omp/extensions/lib/fm-async-exec.ts:149 - execBashTool imposes a 300-second timeout whenever the tool caller omits timeout (.omp/extensions/lib/fm-async-exec.ts:147-162). The prior native bash path leaves an omitted timeout unset, so this silently changes valid long-running branch commands into failures after five minutes. Preserve the native semantics by passing no timeout when options.timeout is undefined (and only configuring timeoutMs when explicitly provided).
  • ⚠️ .omp/extensions/lib/fm-async-exec.ts:95 - The new runner aborts only the top-level bash process with child.kill() on cancellation, timeout, and output overflow (.omp/extensions/lib/fm-async-exec.ts:68-72,93-97,103-106). Unlike OMP's native executor, this does not terminate the command's process tree; a branch command that is running a foreground child can leave that child alive after the tool reports failure, allowing injected branch-actor commands to continue mutating wake/lease state after supervision has moved on. Kill the owned process group/tree before settling these paths.

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

⚠️ **Test** - 2 warnings
  • ⚠️ tests/fm-omp-branch-types.test.sh:89 - The required extension typecheck fails against installed OMP 18.3.0 because unchanged fm-task-inbox-doorbell.ts omits the now-required failureJournal option. This is outside the changed files but leaves AC4 unproven.
  • ⚠️ live validation verdict: inconclusive (3 of 5 scenarios were driven live against the product); untested: Run the existing OMP extension typecheck, Documentation records the OMP 18.3 env change and actor-env injection
  • Live validation: ⚠️ inconclusive - 3 of 5 scenarios driven live against the product
Scenario Result Live Evidence
Run a branch bash command on installed OMP 18.3.x; it executes instead of throwing the service-mode env error ✅ pass live OMP 18.3.0 + bash tests/fm-omp-branch-bash.test.sh artifact
Attempt to override injected actor variables inside a branch command; readonly protection rejects the override ✅ pass live Same branch-bash regression artifact
Grant a wake row, drain and acknowledge it as the branch actor; main does not claim it ✅ pass live Same branch-bash regression artifact
Run the existing OMP extension typecheck ⏸️ untested no The prior payload marked this scenario live=false and therefore did not establish a live product result.
Documentation records the OMP 18.3 env change and actor-env injection ⏸️ untested no The prior payload cited a documentation diff only and did not establish this scenario against the live product.
  • omp --version
  • bash tests/fm-omp-branch-bash.test.sh
  • bash tests/fm-omp-branch-supervision.test.sh
  • bash tests/fm-omp-branch-types.test.sh
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

OMP 18.3.0 moved the bash tool's env parameter behind service mode, but
the legacy createBashToolDefinition shim still forwards the spawnHook's
env into the native bash execute, which throws "ready and env require a
service name." before spawning. Every supervision-branch bash call has
failed since the upgrade, so the branch could not inspect, drain, or
acknowledge wakes.

Hand the shim a BashOperations runner in lib/fm-async-exec.ts instead:
the tool now executes through runCommandAsync with the spawnHook's
injected actor environment (FM_SUPERVISION_ACTOR=branch,
FM_LEASE_HOLDER_PID, and the scriptEnv home overrides), streaming onData,
signal abort, and the native 300-second default timeout. The seam
predates 18.3, so the same wiring is correct on every supported OMP
version, and an older shim that ignores the option keeps the
env-forwarding path that works there. The readonly prelude still makes
an in-shell actor-env override fail loudly.

tests/fm-omp-branch-bash.test.sh drives the real installed omp against
a probe extension wired through the same two seams: before this change
it failed with the reported throw; now it proves the branch actor drains
and acknowledges a granted wake row end to end while a main drain only
sees the held notice.
@dnth
dnth merged commit f577f55 into main Sep 26, 2026
15 checks passed
@dnth
dnth deleted the fm/fm-branch-bash-env-fix branch September 26, 2026 09:06
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