Conversation
0f49ccb to
f4e778f
Compare
|
Thanks for the PR! This branch currently has a merge conflict with the base branch. When you get a chance, please rebase onto (or merge) the latest base branch, resolve the conflict, and push. After that, checks will re-run and the PR will get looked at again. Noted for firstmate#529 at |
f4e778f to
a5a7923
Compare
|
Thanks for the PR! This branch currently has a merge conflict with the base branch. When you get a chance, please rebase onto (or merge) the latest base branch, resolve the conflict, and push. After that, checks will re-run and the PR will get looked at again. Noted for firstmate#529 at |
9dbc1a1 to
3806c04
Compare
|
Automated reminder: thanks for the PR! This branch currently has a merge conflict with the base branch. When you get a chance, please rebase onto (or merge) the latest base branch, resolve the conflict, and push. After that, checks will re-run and the PR will get looked at again. Noted for firstmate#529 at |
3806c04 to
8a01b6b
Compare
8a01b6b to
bdc0e16
Compare
|
Automated reminder: thanks for the PR! This branch currently has a merge conflict with the base branch. When you get a chance, please rebase onto (or merge) the latest base branch, resolve the conflict, and push. After that, checks will re-run and the PR will get looked at again. Noted for firstmate#529 at |
bdc0e16 to
0ff0b98
Compare
This comment was marked as resolved.
This comment was marked as resolved.
5ddb00b to
163dd63
Compare
|
Automated reminder: thanks for the PR! This branch currently has a merge conflict with the base branch. When you get a chance, please rebase onto (or merge) the latest base branch, resolve the conflict, and push. After that, checks will re-run and the PR will get looked at again. Noted for firstmate#529 at |
163dd63 to
a367435
Compare
Adds OMP (Oh My Pi) as a firstmate primary and crew harness. OMP is a Pi fork with a Pi-compatible extension API but was previously unusable: fm-harness.sh misdetected it as claude (OMP sets CLAUDECODE=1), and OMP auto-loads .omp/extensions/, never .pi/extensions/. Rebased on upstream main, including kunchenguid#397 (fix(pi): restore primary watcher supervision lifecycle). The .omp/ supervisors are kept in lockstep with the kunchenguid#397 Pi supervisors: guardFollowupActive one-shot skip, void markLoaded, awaited follow-up delivery, stopArm() + a one-shot process.once("exit") cleanup, ctx.ui.notify command handler, and the fm_watch_arm_omp tool (label + text content + structured details) as the primary arm path with /fm-watch-arm-omp as the human fallback. OMP adaptations from the Pi source: - the turn-end guard listens for `turn_end` (OMP has no `agent_settled` event, which is Pi 0.80.5-only); - the tool schema uses pi.zod.object({}) (OMP-canonical), not typebox, and omits promptSnippet/promptGuidelines (not in OMP's ToolDefinition); - Promise.withResolvers + in/typeof narrowing + typed ChildProcess per this repo's TS lint. Files: fm-harness.sh (detect OMPCODE before CLAUDECODE), .omp/extensions/* (turn-end guard + PreToolUse seatbelt, watcher bridge), fm-spawn.sh (omp launch template + model/effort flags + crew turn-end hook), fm-session-start.sh (extension-loaded check), fm-supervision-instructions.sh + docs/supervision-protocols/omp.md (supervision block), fm-watch.sh / fm-tmux-lib.sh (busy signature), tests/fm-omp-primary-types.test.sh (strict typecheck mirroring fm-pi-primary-types), plus docs + harness-adapters skill. Verified: rebased clean; tsc --strict --noEmit clean against @oh-my-pi/pi-coding-agent types; shellcheck -x clean; fm-{supervision-instructions,session-start,turnend-guard,secondmate-harness,spawn-batch,spawn-dispatch-profile} tests pass. Live in a herdr pane: omp -p -e <exts> returned OMP_DONE_EXIT=0, bin/fm-harness.sh returned omp from the omp child, and both extension-loaded markers were written by the running extensions. PENDING: the full multi-turn guarded-wake / re-arm loop and the exact busy signature / exit / interrupt keys still want a longer live co-primary session; the harness-adapters entry stays PENDING LIVE VERIFICATION until then.
Live run on 2026-07-10 (omp v16.3.15, herdr backend): a fresh omp became the first mate (root AGENTS.md loaded via agents-md), detection via bin/fm-harness.sh AND bin/fm-lock.sh resolved omp, both .omp/extensions/ loaded (markers written), the turn-end guard fired on a real multi-turn primary ("TURN WOULD END BLIND ... 2 task(s) in flight, no live watcher") and the primary re-armed the watcher instead of ending blind, and two omp crewmates (fm-webull-broker-w7, fm-finnhub-free-f3) ran autonomously under --auto-approve in treehouse worktrees and shipped two green PRs.
Promoted the PENDING LIVE VERIFICATION markers to VERIFIED across the harness-adapters skill (heading + guard/watcher + launch-profile row + a live validation record), docs/supervision-protocols/omp.md, docs/turnend-guard.md, and docs/arm-pretool-check.md.
Kept honest (not yet exercised): a seatbelt {block:true} deny of an arm anti-pattern, the tmux-backend busy signature (this run used herdr's native busy-state), and the exit/interrupt keys.
Adds tests/fm-omp-primary-live-e2e.test.sh, the OMP counterpart to fm-pi-primary-live-e2e.test.sh, so the VERIFIED omp adapter is backed by a repeatable regression like the author's pi/grok adapters (deviation from the verified-harness pattern, closed).
The test (opt-in, FM_OMP_LIVE_E2E=1) launches omp on a private tmux socket with the tracked .omp/extensions via -e, drives bash/read turns, triggers the turn-end guard, arms fm_watch_arm_omp, delivers a watcher wake, drains + re-arms, and asserts: one-or-more guard injections, no foreground bin/fm-watch-arm.sh arm, a live re-armed watcher pid, and a clean /quit (OMP_EXIT=0) that reaps both the watcher and arm children. Passes on omp v16.4.0.
OMP adaptations vs the pi e2e: no PI_OFFLINE stub model (drives a real model turn, hence opt-in); uses the default authed agent dir because a fresh PI_CODING_AGENT_DIR triggers omp's blocking first-run setup wizard; and it asserts >=1 guard injection (not exactly 1) because omp's guard listens for turn_end (no agent_settled), so it re-nags on each blind turn until armed - the run saw 3 injections before the model armed the watcher.
Reconciled the docs to this stronger, honest state: Exit (/quit) is now VERIFIED (clean exit + child cleanup), the guard 'once per run' claim is corrected to the per-turn re-nag, and the still-unexercised items are narrowed to a seatbelt {block:true} deny, the tmux busy-footer regex, and the interrupt (Escape) key.
…nds kunchenguid#432) omp (Oh My Pi) exports OMPCODE=1 (and CLAUDECODE=1) into child shells and fm-harness.sh detect_own checks OMPCODE first, so running the suite from an omp session leaks OMPCODE past the suites' harness pins - flipping detection to omp and breaking cases that CI (no ambient marker) keeps green. Extends kunchenguid#432's ambient-marker isolation to OMPCODE: - fm-session-start: add OMPCODE to run_session_start's env -u neutralization. - fm-secondmate-harness / fm-turnend-guard / fm-x-mode: drop ambient OMPCODE at the top so their CLAUDECODE=1 harness pins stay authoritative. (fm-watcher-lock's ambient failure was a pre-existing flaky restart timeout, status 124 - unrelated to omp, left untouched.)
commands.test iterates the full tests/*.test.sh suite to mirror ci.yml, which runs with no ambient harness/backend markers. A contributor gating from inside an omp/herdr session, though, leaks OMPCODE/CLAUDECODE/HERDR_ENV/TMUX into the run: HERDR_ENV routes fm-bootstrap.sh into the EXPERIMENTAL herdr backend (a deterministic FLEET_SYNC timeout-scaling failure) and OMPCODE/CLAUDECODE flip detect_own harness detection. Strip those per test so the gate matches CI's clean env regardless of the shell it runs from.
Upstream kunchenguid#483 (feat: guard primary shells from persistent cd commands) refactored the Pi turnend-guard's runPretoolCheck into a generic runChecker(script, command) and wired a cd-guard check before the watcher-arm check. Port the same change to the OMP twin: - .omp/extensions/fm-primary-turnend-guard.ts: replace runPretoolCheck with runChecker, run fm-cd-pretool-check.sh then fm-arm-pretool-check.sh in the tool_call handler (cd-guard deny short-circuits before the arm check, matching Pi's order). Wrappers inlined per the ts-no-tiny-functions lint rule (single-return, one call site each). - docs/cd-guard.md: add OMP row to the harness wiring table. - tests/fm-cd-pretool-check.test.sh: add test_omp_wiring parallel to test_pi_wiring, asserting the OMP extension runs both seatbelts.
Upstream kunchenguid#658 (agent secret injection) wraps every launch template with $agent_secrets_prefix but its coverage loop omitted omp. The rebase resolution added the prefix to the omp template (mirroring pi); extend the test's baselines and both harness loops so the omp ship/secondmate launch commands and their prefix wrapping are verified, not just eyeballed.
detect_own's bare-interpreter args globs (`*" omp "*|*/omp`, `*" pi "*|*/pi`) only matched a trailing `/omp` or a space-delimited ` omp `, so the real launched form `bun /…/omp --auto-approve …` (a live omp runs as bun with the harness at a path-final component followed by flags) fell through to `unknown`, diverging from fm-lock.sh's `(^|/| )name( |$)` word boundary. Align both globs to that boundary. Detection is layered (OMPCODE=1 catches native omp first), so this hardens the fallback rather than fixing an observed failure. Verified live 2026-07-17: a live omp tmux pane reports pane_current_command=bun with foreground child `bun /Users/…/.bun/bin/omp`. docs/tmux-backend.md records that capture (removing the pending-verification caveat) and its liveness-gap summary now names omp's generic `bun` alongside pi's `node`; `bun` still cannot join the alive-glob without misclassifying unrelated bun processes. Add tests/fm-harness-detect.test.sh covering the launched-form match and guarding against false positives (omp workers, unrelated bun/node sessions).
a7a00a7 to
28be797
Compare
|
Automated reminder: thanks for the PR! This branch currently has a merge conflict with the base branch. When you get a chance, please rebase onto (or merge) the latest base branch, resolve the conflict, and push. After that, checks will re-run and the PR will get looked at again. Noted for firstmate#529 at |
|
It would be nice to get this merged |
|
Speaking as Kun's firstmate: closing this as stale. It has been waiting on a contributor update for 14+ days with no author push or comment. Reopen if you want to pick it back up. |
Intent
Add Oh My Pi (
omp) as a first-class firstmate harness adapter (primary or crew) alongside claude/codex/opencode/pi/grok, faithfully mirroring the verified pi adapter. Adds the omp backend tofm-harness.sh(detectOMPCODEbeforeCLAUDECODE), anfm-spawn.shlaunch template, a turnend-guard + watch extension under.omp/extensionsmirroring.pi/extensions, an intent reader, lock detection via thebuninterpreter, and the fixed harness allowlists (bootstrap,AGENTS.mdverified list, spawn header). Ports the cd-guard seatbelt to OMP'sturn_endevent; omp behaves like pi for gate-instruction neutralization.The omp crewmate launch is an interactive positional session wrapped in the agent-secrets prefix like every sibling adapter:
omp --auto-approve <flags> -e <ext> "$(cat <brief>)"(ship/scout) /... -e <turnend> -e <watch> ...(secondmate). There is no-p/--mode json/--no-sessioninvocation.Rebased onto latest upstream
mainthrough #658 (local agent secret injection); the omp launch template adopts the$agent_secrets_prefixwrapping exactly like pi so omp crewmates also receive 1Password secret injection.What Changed
omp) as a first-class firstmate harness backend:fm-harness.shdetectsOMPCODEahead ofCLAUDECODE,fm-spawn.shgrows an omp launch template (ship/scout and secondmate) wrapped in$agent_secrets_prefix,fm-lock.shrecognizes omp via itsbuninterpreter,fm-teardown.shcleans state-resident omp extensions, and tmux/watch busy-state regexes gain omp indicators..omp/extensions/fm-primary-turnend-guard.tsandfm-primary-omp-watch.tsmirroring the.piextensions, porting the cd-guard seatbelt onto OMP'sturn_endevent and writing the turn-end signal.AGENTS.mdverified list, spawn header, skill/architecture/configuration docs), add adocs/supervision-protocols/omp.mdprotocol page, and add live-e2e, extension-types, and ambient-OMPCODE-isolation test coverage.detect_own's bare-interpreter ancestry match: the args globs now mirrorfm-lock.sh's(^|/| )name( |$)word boundary so the real launched formbun /…/omp --auto-approve …resolves (previously fell through tounknown); applied to both omp and pi, withtests/fm-harness-detect.test.shcovering it. Live-verified 2026-07-17 that a live omp reportscomm=bun/pane_current_command=bun;docs/tmux-backend.mdrecords that capture and its liveness-gap summary now names omp'sbunalongside pi'snode.Risk Assessment
✅ Low: additive, well-bounded port that faithfully mirrors the already-verified pi adapter across every touched script, with matching unit tests, an opt-in live e2e, a detection regression test, and docs. No functional defects; the detection hardening is verified live and covered by a test.
Testing
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
bin/fm-spawn.sh:362- User intent states fm-spawn's omp invocation uses-p --mode json --no-session, but the actual launch template uses an interactive positional session:omp --auto-approve __MODELFLAG____EFFORTFLAG__-e __OMPEXT__ "$(cat __BRIEF__)"(crewmate) /... -e __OMPTURNEND__ -e __OMPWATCH__ ...(secondmate). No-p/--mode json/--no-sessionomp invocation exists anywhere in bin/. The interactive launch is almost certainly the correct choice — supervised crewmates run in a watched tmux pane and every sibling adapter (claude/pi/grok) launches interactively; a-pprint-mode one-shot could not be supervised or steered. Surfacing so the author can confirm the intent text was just imprecise shorthand and no non-interactive path was dropped..agents/skills/firstmate-orca/SKILL.md:16- This change addedompto the harness enumeration in docs/orca-backend.md but left the parallel list in .agents/skills/firstmate-orca/SKILL.md line 16 (claude,codex,opencode,pi, orgrok) unchanged, so the orca skill doc now under-documents the supported harness set and could read as omp not being orca-compatible. Mechanical parity edit to match the sibling doc that was updated.⏭️ **Test** - skipped
Step was skipped.
docs/tmux-backend.md:106- docs/tmux-backend.md secondmate-liveness 'Known gap' section names onlypias the interpreter-based harness the tmux agent-liveness classifier (fm_backend_tmux_agent_alive) cannot confidently classify. omp now runs underbun, and backends/tmux.sh was NOT changed by this branch (its deliberate-unknown interpreter set is still node/python/python3, andbunfalls into the generic 'unknown' bucket), so an omp secondmate shares pi's inconclusive-liveness gap. The doc still accurately describes the unchanged code, so I left it untouched; but omp's arrival as a verified adapter makes the gap section incomplete. Out of scope here because a real fix touches liveness classification behavior, not just prose. Worth a follow-up to either wire omp/bun into the classifier or add omp alongside pi in the gap note.✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.