Add support for omp (Oh My Pi) as a primary harness - #2503
Open
EvanAgee wants to merge 3 commits into
Open
Conversation
Firstmate was misidentifying omp as Claude Code because omp sets both OMPCODE=1 and CLAUDECODE=1. This made firstmate use the wrong command surface for every downstream branch. Fix: detect omp by its own OMPCODE marker before CLAUDECODE, with the same precedence logic cursor uses (unambiguous marker checked first). Add omp to the ancestry fallback for marker-clean processes. Port the Pi adapter's two extensions to omp's extension API: - Watcher: session_switch (new/resume/fork/handoff) replaces Pi's combined session_shutdown+session_start; everything else is 1:1 (arm child, sendWake, retry, lock, fm_watch_arm_omp tool) - Guard: session_stop replaces Pi's agent_settled as the settle hook; tool_call seatbelt, session_compact digest, and session_start/switch digest injection are 1:1 Add omp launch branch to fm-spawn.sh: explicit -e for both extensions (omp does not auto-discover project .pi/extensions), per-task .omp-ext.ts sidecar using omp event names, binary resolution, and placeholder substitutions. Add docs/supervision-protocols/omp.md, README adapter list, detection test, event probe fixture, and clear OMPCODE in the shared test lib so existing tests don't inherit the parent omp process's marker.
fm-session-lock-lib.sh did not know about omp. The harness regex (FM_HARNESS_RE) omitted omp, the harness names list omitted omp, and the bare-interpreter case (which handles bun, omp's runtime) did not extract the script path to find the harness name. When the model ran bin/fm-session-start.sh under omp, the lock resolver could not find the omp process in the ancestry and failed with 'cannot locate harness process in ancestry'. The session lock stayed stale and fm_watch_arm_omp refused to arm. Fix: add omp to FM_HARNESS_RE and FM_HARNESS_NAMES, add bun to the bare-interpreter case, and extract the script path from the interpreter args so fm_harness_path_name can find the omp component.
The omp detection test's crew-resolution case read the operator's real config/crew-harness, so it returned the pinned adapter instead of testing the 'default mirrors own' path. Point detect_with at an empty config dir so the matrix tests detection logic, not local config. Add tests/fm-omp-primary-types.test.sh mirroring the Pi types test: it strict-typechecks both omp extensions (fm-primary-omp-watch.ts, fm-primary-omp-turnend-guard.ts) against the installed @oh-my-pi/pi-coding-agent package, so a type break is caught in CI without a live omp run.
EvanAgee
force-pushed
the
feat/omp-adapter
branch
from
August 17, 2026 12:55
3a37df9 to
663b97c
Compare
|
There are 8 other PRs about adding |
Author
|
Thanks for the heads up. Have you tried any of them personally? Any of them that allow things to run smoothly in firstmate? |
I'm trying this one since yesterday https://github.com/Boxyboxy/firstmate.git branch: |
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.
What this does
Firstmate was misidentifying omp (Oh My Pi) as Claude Code. omp sets both
OMPCODE=1andCLAUDECODE=1on its child processes (verified omp 17.3.3 and 17.3.5), and firstmate checkedCLAUDECODEbefore any omp-specific marker. So every omp session got the Claude command surface — wrong hooks, wrong launch flags, wrong protocol doc — and the Pi-family extension supervision never engaged.The fix
Detection (
bin/fm-harness.sh): checkOMPCODE=1beforeCLAUDECODE=1, with the same precedence logic cursor uses (unambiguous marker first). Addompto the ancestry fallback. omp is now correctly identified asomp, notclaude. Precedence is now: cursor > grok > omp > claude > pi.Watcher extension (
.pi/extensions/fm-primary-omp-watch.ts): ported from the Pi watcher. The key change: omp firessession_switch(reason: new/resume/fork/handoff) for same-process replacements where Pi firedsession_shutdown+session_start. Everything else is 1:1 — arm child lifecycle,sendUserMessage({deliverAs:"followUp"})wake, retry/recovery, lock ownership, thefm_watch_arm_omptool and/fm-watch-arm-ompcommand.Turn-end guard (
.pi/extensions/fm-primary-omp-turnend-guard.ts): ported from the Pi guard. The key change: omp'ssession_stopevent replaces Pi'sagent_settledas the "turn about to settle" hook.session_stopcarriesstop_hook_active(matching whatfm-turnend-guard.shexpects) and can natively request a continuation turn. Thetool_callseatbelt (arm-pretool + cd-pretool),session_compactdigest injection, and session-start digest are 1:1.Spawn (
bin/fm-spawn.sh): omp launch branch passes-efor both extensions explicitly (omp does not auto-discover project.pi/extensions), plus a per-task.omp-ext.tssidecar using omp event names (agent_start/agent_endwithwillContinueguard instead of Pi'sagent_settled+isIdle).Lock resolver (
bin/fm-session-lock-lib.sh): resolves the session lock correctly for omp.Docs:
docs/supervision-protocols/omp.mdmirrorspi.mdwith omp event semantics. README adapter list updated.Verification
Live-verified against real omp 17.3.5
-psession. The full event sequence fires:session_start -> agent_start -> turn_start -> turn_end -> session_stop(stop_hook_active=false) -> agent_end -> session_shutdown. Both load markers (.omp-watch-extension-loaded,.omp-turnend-extension-loaded) write. Session lock and wake queue established.fm_watch_arm_omptool; watcher armed with fresh beacon (beacon_age=0);.watch-cycle-exits.logshowsorigin=started exit_code=0 successor=started;.last-watcher-beatwritten.bash .../fm-watch-arm.sh(a protected command). Thetool_callhandler returned{block: true}; omp honored it —tool_execution_endshowsisError: truewith the deny reason[watcher-nested]. The command did NOT execute. The cd-guard deny ([persistent-cd]) is proven at the checker level and uses the identical block path.fm-turnend-guard.sh(exit 2), and the extension injected aturn-end-guard: TURN WOULD END BLINDfollowUp viasendUserMessage({deliverAs:"followUp"}), driving a continuation turn. With no supervision needed, the guard exits 0 and the session settles cleanly (proven in 4A).willContinuecontinuations,session_stopfires only at the final settle — never between turns — so the guard cannot fire during a retry. (Auto-retry is non-deterministic; theauto_retry_start/auto_retry_endevents were observed in an earlier run but not captured alongsidesession_stopin the same run.)Static-verified
tests/fm-omp-harness.test.sh— all 8 cases green (env markers plus crew resolution, config-isolated).tests/fm-omp-primary-types.test.sh— both extensions pass strict no-emit typecheck against omp 17.3.5.Not yet live-verified (honest gaps)
These three cases from the verification plan (
docs/omp-adapter-verification.md) could not be driven in this environment:session_switchfires only on interactive same-process/resume,/new,/fork— not reproducible in-pprint mode. The generation start/stop logic is typechecked and the start/shutdown endpoints are live-proven, but the switch-retirement path itself was not driven live.session_compactevent deterministically. The handler reusesinjectSessionstart(proven live in 4A/4D), but the compact event path was not live-triggered.fm-spawnhardcodes thefirstmatetmux session name (bin/backends/tmux.sh:69, no override), which is the live fleet session on this machine. The spawn omp branch and launch string are verified by code inspection and typecheck, but a live crew run was not driven to avoid interfering with the running fleet.The deeper automated test files (
fm-omp-watch-extension,fm-omp-turnend-guard,fm-omp-primary-live-e2e) are tracked as follow-up in the verification doc.Test files
tests/fm-omp-harness.test.sh— detection matrix (mirrors cursor/grok tests), config-isolatedtests/fm-omp-primary-types.test.sh— strict typecheck of both extensions against the installed omp packagetests/fixtures/omp-event-probe.ts— test-only event probe for live verificationdocs/omp-adapter-verification.md— full testing and verification plan