Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions .agents/skills/harness-adapters/references/harness/omp.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Cross-harness provider and credential identity is owned by `references/common/mo
| Fact | Value |
|---|---|
| Binary | `omp`, a single Bun-compiled executable resolved from `PATH` by `../../../bin/fm-spawn.sh`; a missing binary refuses the spawn. |
| Launch | Foreign markers cleared (`CLAUDECODE`, `PI_CODING_AGENT`, `GROK_AGENT`, `FM_PI_HARNESS`, `GEMINI_CLI`, Cursor's), `FM_OMP_HARNESS=omp OMP_SKIP_SETUP=1`, then `omp --config <.omp/fm-worker-overlay.yml> --auto-approve --cwd <worktree> [--model] [--thinking] -e state/<id>.omp-ext.ts <one positional brief>`; a secondmate passes no `-e` and relies on auto-discovery. |
| Launch | [`fm-spawn.sh --help`](../../../../../bin/fm-spawn.sh) owns launch flags, session posture, worker memory scope, and secondmate extension loading. |
| Busy state | `../../../bin/fm-busy-lib.sh` source `omp-ext`: the per-task extension marks busy at `agent_start` and idle at `agent_end` only when `willContinue` is not true; `ctx.isIdle()` is deliberately not consulted because it reads false at a natural TUI `agent_end` (`session_stop` is awaited before settle). |
| Exit command | `/quit` (`/exit` and `/q` are aliases). |
| Interrupt | Single Escape; the composer is left empty, no clear key. |
Expand All @@ -18,8 +18,8 @@ Cross-harness provider and credential identity is owned by `references/common/mo
| Effort flag | `--thinking <off\|minimal\|low\|medium\|high\|xhigh\|max\|auto>`, a superset of the shared vocabulary, so every level including `max` maps straight across. |
| Model discovery | `omp models [--json]` lists built-in and auto-discovered providers only; extension-registered providers such as `claude-bridge` never appear, so those models pass through the spawn unvalidated with a stderr notice. `omp usage` shows provider windows; `quota-axi` covers the `claude` provider when the bridge is in use. |
| Marker | None of omp's own (verified: `PI_CODING_AGENT` absent from the binary, no `PI_CODING_AGENT_DIR` or `OMP_PROFILE` in the default profile). `FM_OMP_HARNESS=omp` is Firstmate's launch marker; ancestry matches the exact process name `omp`. |
| Composer | Pinned to `composer.shape: borderless` by the overlay, a bare `❯` (U+276F) row the shared classifier already reads; busy text is `Working…` (U+2026), the only spelling the omp busy regex accepts (the three-dot form its headless `-p` mode writes never reaches a supervised pane), with the status row's braille spinner plus elapsed cell as the second signal. |
| Autonomy | `--auto-approve` owns approval (omp forces `tools.approvalMode: yolo` for the session under it); the overlay pins `plan.defaultOnStartup: false`, `prewalk.enabled: false`, `retry.usageReservePolicy: auto`. |
| Composer | See [`fm-spawn.sh --help`](../../../../../bin/fm-spawn.sh) for the composer posture pin; busy text is `Working…` (U+2026), the only spelling the omp busy regex accepts (the three-dot form its headless `-p` mode writes never reaches a supervised pane), with the status row's braille spinner plus elapsed cell as the second signal. |
| Autonomy | Approval and unattended-session posture are owned by [`fm-spawn.sh --help`](../../../../../bin/fm-spawn.sh). |
| Trust | No project-trust gate at all; a fresh profile shows a provider-login wizard instead, suppressed by `OMP_SKIP_SETUP=1`. |
| Resume | `-c/--continue` and `-r/--resume` exist but carry no verified pane-resume contract; use deterministic relaunch. |

Expand All @@ -34,10 +34,9 @@ The omp template in `../../../bin/fm-spawn.sh` clears every foreign marker at it
`../../../bin/fm-session-lock-lib.sh` matches the same anchored name for session-lock ownership, and `../../../bin/backends/tmux.sh` classifies it `agent` for liveness.
The optional claude-bridge extension runs a nested executable literally named `claude` as a sibling of tool execution, never an ancestor of it, so omp's own tool calls detect as omp; that subtree is never walked by a Firstmate script.

## Worker posture overlay
## Launch posture

The captain's own `~/.omp/agent/config.yml` is never written; the tracked `.omp/fm-worker-overlay.yml` is passed with `--config` for the one session and pins only the settings whose captain-level values would park an unattended worker on a prompt, change its pinned model, or make its composer unreadable.
`../../../bin/fm-spawn.sh`'s header owns the exact list and the reason for each pin.
[`fm-spawn.sh --help`](../../../../../bin/fm-spawn.sh) owns session posture, worker-only memory scope, and the invariant that the captain's own configuration is never written.

## Extension loading

Expand Down
27 changes: 27 additions & 0 deletions .omp/fm-session-overlay.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Firstmate session posture for omp (Oh My Pi), passed as `--config` on every
# Firstmate-launched omp session (crewmate, scout, and secondmate alike) by
# bin/fm-spawn.sh, whose header owns why the launch carries it. It is the omp
# analogue of the Pi adapter's `--tui-mode regular` pin: a per-launch overlay,
# never a write to the captain's own ~/.omp/agent/config.yml, which stays
# exactly as the captain set it (model roles, theme, providers, compaction).
# Each key below pins one setting whose captain-facing value would park an
# unattended worker on an interactive prompt, change its pinned model under it,
# or make its composer unreadable to bin/fm-composer-lib.sh. Verified against
# omp 18.1.11's own settings schema (`omp config list`).
composer:
# Renders a bare `❯` (U+276F) row, a glyph the shared composer classifier
# already reads; the shipped default `band` and six other shapes are not in
# its catalogue, and the shape is otherwise a captain-level setting.
shape: borderless
plan:
# `plan.defaultOnStartup: true` opens every session read-only; a worker that
# cannot edit files sits on its brief forever.
defaultOnStartup: false
prewalk:
# Prewalk swaps the active model for the `smol` role after the first edit, so
# a worker pinned with --model would silently change model mid-task.
enabled: false
retry:
# `confirm` pops a dialog when a usage window runs low; `auto` lets omp fall
# through the captain's own fallback chain without a keystroke.
usageReservePolicy: auto
34 changes: 7 additions & 27 deletions .omp/fm-worker-overlay.yml
Original file line number Diff line number Diff line change
@@ -1,27 +1,7 @@
# Firstmate worker posture for omp (Oh My Pi), passed as `--config` on every
# Firstmate-launched omp session (crewmate, scout, and secondmate alike) by
# bin/fm-spawn.sh, whose header owns why the launch carries it. It is the omp
# analogue of the Pi adapter's `--tui-mode regular` pin: a per-launch overlay,
# never a write to the captain's own ~/.omp/agent/config.yml, which stays
# exactly as the captain set it (model roles, theme, providers, compaction).
# Each key below pins one setting whose captain-facing value would park an
# unattended worker on an interactive prompt, change its pinned model under it,
# or make its composer unreadable to bin/fm-composer-lib.sh. Verified against
# omp 18.1.11's own settings schema (`omp config list`).
composer:
# Renders a bare `❯` (U+276F) row, a glyph the shared composer classifier
# already reads; the shipped default `band` and six other shapes are not in
# its catalogue, and the shape is otherwise a captain-level setting.
shape: borderless
plan:
# `plan.defaultOnStartup: true` opens every session read-only; a worker that
# cannot edit files sits on its brief forever.
defaultOnStartup: false
prewalk:
# Prewalk swaps the active model for the `smol` role after the first edit, so
# a worker pinned with --model would silently change model mid-task.
enabled: false
retry:
# `confirm` pops a dialog when a usage window runs low; `auto` lets omp fall
# through the captain's own fallback chain without a keystroke.
usageReservePolicy: auto
# Mnemopi text-only recall; bin/fm-spawn.sh's header owns launch scope.
# Each local embedding helper loads one copy of the model per session (about
# 1 GB); retain memory with text-only recall until upstream shares the model:
# https://github.com/can1357/oh-my-pi/issues/9908
# Verified against omp 18.6.3 (`omp config list --json`).
mnemopi:
noEmbeddings: true
31 changes: 21 additions & 10 deletions bin/fm-spawn.sh
Original file line number Diff line number Diff line change
Expand Up @@ -199,12 +199,15 @@
# markers (omp publishes none of its own), sets the Firstmate-owned
# FM_OMP_HARNESS=omp detection marker, suppresses the first-run provider
# wizard with OMP_SKIP_SETUP=1, forces --auto-approve, pins the working
# directory with --cwd, and passes the tracked worker posture overlay
# .omp/fm-worker-overlay.yml through --config. That overlay pins composer
# directory with --cwd, and passes the tracked session posture overlay
# .omp/fm-session-overlay.yml through --config. That overlay pins composer
# shape, plan mode off, prewalk off, and the non-interactive usage-reserve
# policy for the one session only (--auto-approve alone owns approval); the
# captain's own ~/.omp/agent/config.yml (model roles, providers, theme) is
# never written.
# policy for the one session only (--auto-approve alone owns approval,
# forcing tools.approvalMode: yolo for the session).
# Crewmates and scouts also layer .omp/fm-worker-overlay.yml to keep Mnemopi
# text-only recall without loading a separate embedding model per session.
# Secondmate lanes keep their memory settings; the captain's own
# ~/.omp/agent/config.yml (model roles, providers, theme) is never written.
# A model written as <provider>/<id> is validated against `omp models --json`
# only when that provider appears in the listing; a provider absent from the
# listing (an extension-registered provider such as claude-bridge, which omp
Expand Down Expand Up @@ -369,7 +372,8 @@
# __OMPEXT__ absolute path to state/<task-id>.omp-ext.ts (omp busy-state and
# turn-end extension, written by this script; outside the worktree so
# omp's cwd-only auto-discovery cannot load it a second time)
# __OMPWORKERCFG__ absolute path to the tracked .omp/fm-worker-overlay.yml posture overlay
# __OMPSESSIONCFG__ absolute path to the tracked .omp/fm-session-overlay.yml posture overlay
# __OMPWORKERCFG__ absolute path to the tracked .omp/fm-worker-overlay.yml memory overlay
# __OPINPUT__ absolute path to the canonical operational-input encoder
# __BRIEFDOORBELL__ quoted printable doorbell naming the launch-brief record this
# script published into the receiving home's operational inbox
Expand Down Expand Up @@ -2074,11 +2078,11 @@ launch_template() {
# naming them with -e as well loads each twice (verified), doubling every
# session_stop continuation.
omp)
printf '%s' 'env -u CLAUDECODE -u PI_CODING_AGENT -u GROK_AGENT -u FM_PI_HARNESS -u GEMINI_CLI -u CURSOR_AGENT -u CURSOR_INVOKED_AS FM_OMP_HARNESS=omp OMP_SKIP_SETUP=1 __OMPBIN__ --config __OMPWORKERCFG__ --auto-approve --cwd __WORKTREE__'
printf '%s' 'env -u CLAUDECODE -u PI_CODING_AGENT -u GROK_AGENT -u FM_PI_HARNESS -u GEMINI_CLI -u CURSOR_AGENT -u CURSOR_INVOKED_AS FM_OMP_HARNESS=omp OMP_SKIP_SETUP=1 __OMPBIN__ --config __OMPSESSIONCFG__ --auto-approve --cwd __WORKTREE__'
if [ "$kind" = secondmate ]; then
printf '%s' ' __MODELFLAG____EFFORTFLAG__"$(__OPINPUT__ encode launch-brief < __BRIEF__)"'
else
printf '%s' ' __MODELFLAG____EFFORTFLAG__-e __OMPEXT__ "$(__OPINPUT__ encode launch-brief < __BRIEF__)"'
printf '%s' ' --config __OMPWORKERCFG__ __MODELFLAG____EFFORTFLAG__-e __OMPEXT__ "$(__OPINPUT__ encode launch-brief < __BRIEF__)"'
fi
;;
# agy (Antigravity CLI): --prompt-interactive "<brief>" starts the supervised
Expand Down Expand Up @@ -2355,11 +2359,16 @@ omp)
echo "error: omp executable not found on PATH; install Oh My Pi or select a different verified harness" >&2
exit 1
}
OMP_SESSION_CFG="$FM_ROOT/.omp/fm-session-overlay.yml"
OMP_WORKER_CFG="$FM_ROOT/.omp/fm-worker-overlay.yml"
[ -f "$OMP_WORKER_CFG" ] || {
echo "error: omp worker posture overlay missing at $OMP_WORKER_CFG; a worker launched without it can park on the captain's own approval or plan-mode settings" >&2
[ -f "$OMP_SESSION_CFG" ] || {
echo "error: omp session posture overlay missing at $OMP_SESSION_CFG; a session launched without it can park on the captain's own approval or plan-mode settings" >&2
exit 1
}
if [ "$KIND" != secondmate ] && [ ! -f "$OMP_WORKER_CFG" ]; then
echo "error: omp worker memory overlay missing at $OMP_WORKER_CFG" >&2
exit 1
fi
;;
agy)
AGY_BIN=$(resolve_pi_executable agy) || {
Expand Down Expand Up @@ -5128,6 +5137,7 @@ sq_piturnend=$(shell_quote "$PROJ_ABS/.pi/extensions/fm-primary-turnend-guard.ts
sq_piwatch=$(shell_quote "$PROJ_ABS/.pi/extensions/fm-primary-pi-watch.ts")
sq_ompext=$(shell_quote "$STATE/$ID.omp-ext.ts")
sq_ompcfg=$(shell_quote "${OMP_WORKER_CFG:-$FM_ROOT/.omp/fm-worker-overlay.yml}")
sq_ompsessioncfg=$(shell_quote "${OMP_SESSION_CFG:-$FM_ROOT/.omp/fm-session-overlay.yml}")
sq_opinput=$(shell_quote "$FM_ROOT/bin/fm-operational-input.sh")
sq_worktree=$(shell_quote "$WT")
MODELFLAG=$(model_flag_for_harness "$HARNESS" "$MODEL")
Expand Down Expand Up @@ -5180,6 +5190,7 @@ LAUNCH=${LAUNCH//__PITURNEND__/$sq_piturnend}
LAUNCH=${LAUNCH//__PIWATCH__/$sq_piwatch}
LAUNCH=${LAUNCH//__OMPEXT__/$sq_ompext}
LAUNCH=${LAUNCH//__OMPWORKERCFG__/$sq_ompcfg}
LAUNCH=${LAUNCH//__OMPSESSIONCFG__/$sq_ompsessioncfg}
LAUNCH=${LAUNCH//__OPINPUT__/$sq_opinput}
case "$HARNESS" in
pi | pi-signed) LAUNCH=${LAUNCH//__PIBIN__/"$(shell_quote "$PI_BIN")"} ;;
Expand Down
2 changes: 1 addition & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -791,7 +791,7 @@ The Kimi installer requires an existing regular non-symlink `~/.kimi-code/config
Its `remove` action excises only the marker-delimited Firstmate region and removes Firstmate's hook files.
For Pi and pi-signed secondmate launches, `fm-spawn.sh` starts the selected executable with `-e` pointed at the secondmate home's own tracked `.pi/extensions/fm-primary-pi-watch.ts` and `.pi/extensions/fm-primary-turnend-guard.ts`, both already present from the secondmate home's git worktree.

For omp secondmate launches, `fm-spawn.sh` passes no `-e` at all: omp auto-discovers the home's tracked `.omp/extensions/` with no trust gate, and naming a discovered file with `-e` as well loads it twice; every omp launch instead carries the tracked `.omp/fm-worker-overlay.yml` posture overlay through `--config`, which [`fm-spawn.sh --help`](../bin/fm-spawn.sh) owns.
For omp session posture, worker-only memory scope, and safe secondmate extension loading, see the authoritative [`fm-spawn.sh --help`](../bin/fm-spawn.sh) contract.

## Claude permission mode (config/claude-permission-mode)

Expand Down
23 changes: 23 additions & 0 deletions docs/verification/runtime-backends.md
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,29 @@ skip-runner: pi-signed is not installed, so its pin check was not exercised

The guard submits no prompt and spends no tokens, so it runs by default wherever a runner is installed; rerun it after every Claude or Pi upgrade.

## omp worker memory posture

Verified 2026-10-06 on macOS arm64 with omp 18.6.3.
`omp config list --json` reports `mnemopi.noEmbeddings` as a boolean forcing deterministic FTS-only recall, with `memory.backend` still `mnemopi`.
Real RPC sessions using `google-antigravity/gemini-3.1-flash-lite` received `{"type":"prompt","message":"Reply exactly OK. Do not use tools."}` and completed their turns.
The common launch arguments were:

```sh
OMP_SKIP_SETUP=1 omp --mode rpc --no-session --no-extensions --no-rules \
--no-skills --no-title --no-tools \
--model google-antigravity/gemini-3.1-flash-lite --thinking low \
--cwd <isolated-smoke-directory> --config <overlay>
```

`ps -axo pid=,ppid=,rss=,command=` supplied the process tree, restricted recursively to each smoke session's descendants.
The pre-change posture overlay produced an embedding helper with RSS 753456 KiB at the first 15-second sample.
The worker launch, layering `--config .omp/fm-session-overlay.yml --config .omp/fm-worker-overlay.yml`, produced zero embedding helpers in 30 one-second samples, including after `prompt_result` reported `status=completed` and `sessionSettled=true`.
The lane launch, using only `--config .omp/fm-session-overlay.yml`, produced an embedding helper with RSS 1134320 KiB at 15 seconds.
RSS is not physical footprint; these samples prove helper presence and scope rather than a fixed per-session saving.
Refresh this measurement after an omp upgrade by repeating both overlay combinations and submitting the RPC prompt above.
`bash bin/fm-test-run.sh tests/fm-omp-harness.test.sh` checks worker/scout versus secondmate overlay routing without model credentials.
[`fm-spawn.sh --help`](../../bin/fm-spawn.sh) owns launch routing and memory scope.

## Codex hook trust

Verified 2026-09-16 on codex-cli 0.151.0, macOS arm64, in a fresh linked worktree of this repository.
Expand Down
7 changes: 4 additions & 3 deletions tests/fm-omp-harness.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ test_spawn_launch_line_and_worker_wiring() {
launch=$(cat "$LAUNCH_LOG")
assert_contains "$launch" "env -u CLAUDECODE -u PI_CODING_AGENT -u GROK_AGENT -u FM_PI_HARNESS -u GEMINI_CLI -u CURSOR_AGENT -u CURSOR_INVOKED_AS FM_OMP_HARNESS=omp OMP_SKIP_SETUP=1 '$FAKEBIN_DIR/omp'" \
"omp launch did not clear foreign markers and establish its own at the launch boundary"
assert_contains "$launch" "--config '$ROOT/.omp/fm-worker-overlay.yml' --auto-approve --cwd '$WT_DIR'" \
"omp launch did not carry the tracked posture overlay, --auto-approve, and the pinned working directory"
assert_contains "$launch" "--config '$ROOT/.omp/fm-session-overlay.yml' --auto-approve --cwd '$WT_DIR' --config '$ROOT/.omp/fm-worker-overlay.yml'" \
"omp scout launch did not carry shared posture and worker-only memory overlays"
assert_contains "$launch" "--model 'openai-codex/gpt-6-astra' --thinking 'medium' -e '$state/$id.omp-ext.ts'" \
"omp launch did not pass the model, thinking level, and the state-resident worker extension"
assert_contains "$launch" "encode launch-brief < '$HOME_DIR/data/$id/launch-brief.md'" "omp launch lost the canonical typed launch-brief envelope"
Expand Down Expand Up @@ -241,7 +241,8 @@ test_secondmate_launch_relies_on_discovery() {
case "$launch" in
*" -e "*) fail "an omp secondmate launch must name no -e: omp auto-discovers .omp/extensions and a file named both ways loads twice: $launch" ;;
esac
assert_contains "$launch" "--config '$ROOT/.omp/fm-worker-overlay.yml' --auto-approve --cwd '$home'" "secondmate launch lost the posture overlay or the pinned home directory: $launch"
assert_contains "$launch" "--config '$ROOT/.omp/fm-session-overlay.yml' --auto-approve --cwd '$home'" "secondmate launch lost the posture overlay or the pinned home directory: $launch"
assert_not_contains "$launch" "fm-worker-overlay.yml" "secondmate launch must preserve the lane's memory settings"
assert_contains "$launch" "FM_OMP_HARNESS=omp OMP_SKIP_SETUP=1 '$fakebin/omp'" "secondmate launch lost the omp marker or executable"
assert_contains "$launch" "FM_SUPERVISION_MODEL=extension" "an omp secondmate must run the extension supervision model"
assert_absent "$world/home/state/sm.omp-ext.ts" "a secondmate must not receive a per-task worker extension"
Expand Down
2 changes: 1 addition & 1 deletion tests/fm-omp-primary-live-e2e.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ mkfifo "$RPC_IN" || fail "could not create the rpc fifo"
-u FM_HOME -u FM_ROOT_OVERRIDE -u FM_STATE_OVERRIDE -u FM_CONFIG_OVERRIDE -u FM_DATA_OVERRIDE \
FM_OMP_HARNESS=omp OMP_SKIP_SETUP=1 FM_POLL=1 FM_SIGNAL_GRACE=0 FM_HEARTBEAT=600 \
FM_GUARD_GRACE="$GUARD_GRACE" \
omp --mode rpc --no-session --cwd "$PROJECT" --config "$PROJECT/.omp/fm-worker-overlay.yml" --auto-approve \
omp --mode rpc --no-session --cwd "$PROJECT" --config "$PROJECT/.omp/fm-session-overlay.yml" --auto-approve \
--model "$MODEL" --thinking low < "$RPC_IN" > "$RPC_LOG" 2> "$RPC_ERR"
) &
OMP_PID=$!
Expand Down
Loading