diff --git a/.agents/skills/harness-adapters/SKILL.md b/.agents/skills/harness-adapters/SKILL.md
index 19e41c8346..866b92e76e 100644
--- a/.agents/skills/harness-adapters/SKILL.md
+++ b/.agents/skills/harness-adapters/SKILL.md
@@ -328,6 +328,17 @@ The extension reports `session_start` readiness, acknowledges the initial instru
Firstmate waits for the first `turn_start` acknowledgement before reporting a successful spawn.
OMP workers keep their sessions under the task temp root so recovery can resume the exact conversation and ordinary cleanup can remove the session files with the rest of the task temp.
+**Native orchestration opt-in.** OMP activates its built-in multi-agent orchestration mode when the exact lowercase keyword `orchestrate` appears in the initial user message; `magicKeywords.enabled` and `magicKeywords.orchestrate` (both default true) then append a hidden `orchestrate-notice` system instruction that directs the worker to decompose, dispatch `task` subagents, integrate, and verify.
+The matcher is a Unicode word-boundary scan of the message that starts the turn, case-sensitive, with fenced code, inline code spans, comments, and balanced tags masked out: `orchestrate`, `orchestrate,` and `path:orchestrate` fire; `Orchestrate`, `orchestration`, `orchestrate.ts`, `path/orchestrate`, `foo::orchestrate`, `orchestrate()`, and backtick-quoted forms do not.
+The OMP launch message is an encoded instruction to read the original brief at its absolute path (`fm-operational-input.sh encode launch-brief` emits `FIRSTMATE_OP: v1 launch-brief:
` as the positional argument). File reads mid-session are tool results and are never scanned for keywords.
+`bin/fm-brief.sh --orchestrate` records the opt-in for an ordinary ship task as a generated YAML front-matter marker (`---\norchestration: enabled\n---`) at the very top of the brief. `bin/fm-spawn.sh` reads only that front-matter, so task prose, acceptance criteria, quoted examples, or code blocks that happen to contain the same line cannot spoof the opt-in.
+For an opted-in OMP launch, `bin/fm-spawn.sh` passes a single message: the standalone `orchestrate` keyword followed by an instruction to read the original brief at its absolute path before doing any work. For an ordinary (non-opted) OMP launch it passes only the instruction to read the original brief. The full original task text is read from the brief file in a tool result, which is never scanned for keywords.
+Marked briefs refuse raw launch commands before endpoint creation, so the verified OMP launch template cannot be bypassed and silently lose the opt-in keyword.
+Any other harness or task kind is refused before launch.
+Nested `task` subagents stay inside the task worktree as implementation helpers owned by the crewmate; they do not become independent Firstmate workers and do not gain merge or production authority, so Firstmate's registered-crewmate supervision, production/merge authority, receipt contract, and No-Mistakes branch custody are unchanged.
+Use the opt-in only for tasks with genuinely independent workstreams inside the same worktree: ordinary and sequential tasks launch unchanged, `orchestrate` and `workflowz` are never combined, and the keyword is never added by default or forced onto trivial work.
+The activation boundary was verified on OMP 18.1.14 (2026-09-10); `docs/verification/runtime-backends.md` owns the live commands and bounded output.
+
[The tmux backend guide](../../../docs/tmux-backend.md#current-behavior-and-safety) owns OMP's launch identity, supported canonical paths, composer geometry, submission, and recovery behavior.
[The Herdr backend guide](../../../docs/herdr-backend.md#composer-and-injection-safety) owns OMP's native identity, composer, busy steering, normal exit, and blocked-injection behavior on Herdr.
OMP is verified only on tmux and Herdr; the backend applicability rationale and inspection evidence live in [runtime-backends verification](../../../docs/verification/runtime-backends.md#omp-applicability-outside-tmux-and-herdr).
diff --git a/bin/fm-brief.sh b/bin/fm-brief.sh
index cff2117691..ddc46bc049 100755
--- a/bin/fm-brief.sh
+++ b/bin/fm-brief.sh
@@ -6,7 +6,7 @@
# placeholder with the task description, concrete outcomes, and context, and may adjust other sections
# when the task genuinely deviates (e.g. working an existing external PR instead
# of shipping a new one).
-# Usage: fm-brief.sh --mode [--herdr-lab]
+# Usage: fm-brief.sh --mode [--herdr-lab] [--orchestrate]
# fm-brief.sh --scout [--herdr-lab]
# fm-brief.sh --secondmate {...|--no-projects}
# fm-brief.sh --render-ship-delivery
@@ -17,6 +17,11 @@
# tells the main firstmate when to route work there; routine churn stays in its own home;
# captain-relevant escalations and marked from-firstmate replies append to this
# home's status file.
+# --orchestrate opts an ordinary ship task into native OMP orchestration: it
+# records the `orchestration: enabled` marker as front-matter at the top of the
+# brief and lets bin/fm-spawn.sh carry the exact lowercase `orchestrate` keyword
+# as a separate OMP launch message before the unchanged encoded brief. It is
+# refused on scout and secondmate briefs, which are not ship tasks.
# --no-projects writes a project-less charter for a domain whose subject is the
# firstmate repo itself (its home is a firstmate worktree, its crews take pooled
# worktrees of the same repo). It is mutually exclusive with a project list, and
@@ -186,6 +191,7 @@ fi
KIND=ship
HERDR_LAB=0
NO_PROJECTS=0
+ORCHESTRATE=0
MODE=
MODE_SET=0
POS=()
@@ -206,6 +212,7 @@ for a in "$@"; do
--scout) KIND=scout ;;
--secondmate) KIND=secondmate ;;
--herdr-lab) HERDR_LAB=1 ;;
+ --orchestrate) ORCHESTRATE=1 ;;
--no-projects) NO_PROJECTS=1 ;;
--mode) want_value=mode ;;
--mode=*) MODE=${a#--mode=}; MODE_SET=1 ;;
@@ -243,6 +250,11 @@ if [ "$KIND" = secondmate ] && [ "$HERDR_LAB" -eq 1 ]; then
exit 1
fi
+if [ "$ORCHESTRATE" -eq 1 ] && [ "$KIND" != ship ]; then
+ echo "error: --orchestrate applies only to ship briefs; a scout delivers a report and a secondmate is not a delivery task" >&2
+ exit 1
+fi
+
if [ "$NO_PROJECTS" -eq 1 ] && [ "$KIND" != secondmate ]; then
echo "error: --no-projects applies only to --secondmate charters" >&2
exit 1
@@ -492,8 +504,24 @@ case "$MODE" in
esac
DOD=$(render_ship_delivery "$ID" "$MODE")
+ORCHESTRATION_FRONTMATTER=""
+ORCHESTRATION_SECTION=""
+if [ "$ORCHESTRATE" -eq 1 ]; then
+ IFS= read -r -d '' ORCHESTRATION_FRONTMATTER <<'EOF' || true
+---
+orchestration: enabled
+---
+
+EOF
+ IFS= read -r -d '' ORCHESTRATION_SECTION <<'EOF' || true
+# Orchestration
+This task may use native `task` subagents for independent workstreams; you remain accountable for integrating and verifying their output.
+
+EOF
+fi
+
IFS= read -r -d '' SHIP_BRIEF <` fragment from config/omp-max-time
+# __OMPMESSAGE__ OMP-only initial positional message: the encoded launch brief, or the `orchestrate` keyword plus the brief path when the brief opts in
# __PITURNEND__ absolute path to .pi/extensions/fm-primary-turnend-guard.ts in a pi secondmate home
# __PIWATCH__ absolute path to .pi/extensions/fm-primary-pi-watch.ts in a pi secondmate home
# __HERMESBIN__ absolute resolved Hermes executable (PATH first, then $HOME/.local/bin/hermes)
@@ -1322,9 +1323,9 @@ launch_template() {
if [ "$kind" = secondmate ]; then
# The explicit path is the exact same tracked file native project discovery sees.
# OMP 17.1.8's discoverExtensionPaths path-resolves and deduplicates before loading, so this guarantees the integration without registering it twice.
- printf '%s' '__OMPENV____OMPBIN__ --session-dir __OMPSESSIONDIR__ __OMPRESUMEFLAG__--auto-approve __OMPMAXTIME____MODELFLAG____EFFORTFLAG____PREWALKFLAG__-e __OMPPRIMARY__ "$(__OPINPUT__ encode launch-brief < __BRIEF__)"'
+ printf '%s' '__OMPENV____OMPBIN__ --session-dir __OMPSESSIONDIR__ __OMPRESUMEFLAG__--auto-approve __OMPMAXTIME____MODELFLAG____EFFORTFLAG____PREWALKFLAG__-e __OMPPRIMARY__ __OMPMESSAGE__'
else
- printf '%s' '__OMPENV____OMPBIN__ --session-dir __OMPSESSIONDIR__ --auto-approve __OMPMAXTIME____MODELFLAG____EFFORTFLAG____PREWALKFLAG__-e __OMPEXT__ "$(__OPINPUT__ encode launch-brief < __BRIEF__)"'
+ printf '%s' '__OMPENV____OMPBIN__ --session-dir __OMPSESSIONDIR__ --auto-approve __OMPMAXTIME____MODELFLAG____EFFORTFLAG____PREWALKFLAG__-e __OMPEXT__ __OMPMESSAGE__'
fi
;;
# grok (Grok Build TUI): a positional prompt starts the supervised interactive
@@ -2833,6 +2834,27 @@ else
fi
[ -f "$BRIEF" ] || { echo "error: no brief at $BRIEF" >&2; exit 1; }
+# Orchestration opt-in is explicit task data, never a keyword scan of prose:
+# fm-brief.sh --orchestrate records a front-matter marker `orchestration: enabled`
+# at the very top of the generated brief, and a ship task launched with
+# harness=omp then carries the exact `orchestrate` keyword in its launch message
+# while every other combination refuses before any endpoint exists.
+# The marker is only honored when it is the literal first three lines of the
+# brief, so ordinary task text, acceptance criteria, quoted examples, or code
+# blocks that happen to contain the words cannot spoof the opt-in.
+ORCHESTRATE_BRIEF=0
+if [ "$(head -n 3 "$BRIEF" 2>/dev/null)" = $'---\norchestration: enabled\n---' ]; then
+ ORCHESTRATE_BRIEF=1
+fi
+if [ "$ORCHESTRATE_BRIEF" -eq 1 ]; then
+ [ "$KIND" = ship ] || { echo "error: orchestration applies only to ordinary ship tasks; the brief at $BRIEF records it but this spawn is kind=$KIND" >&2; exit 1; }
+ if [ "$RAW_LAUNCH" -eq 1 ]; then
+ echo "error: orchestration requires the verified OMP launch template; this spawn is a raw launch command for a marked brief at $BRIEF. Pass --harness omp and a project or worktree path, not a raw command" >&2
+ exit 1
+ fi
+ [ "$HARNESS" = omp ] || { echo "error: orchestration requires harness=omp; the brief at $BRIEF records it but this spawn resolved harness=$HARNESS" >&2; exit 1; }
+fi
+
if [ "$HARNESS" = omp ] && [ "$KIND" = secondmate ]; then
validate_omp_prewalk_for_launch_dir "$PROJ_ABS"
omp_project_extension_preflight "$PROJ_ABS" || exit 1
@@ -4288,6 +4310,19 @@ HERMESRESUMEFLAG=
LAUNCH=${LAUNCH//__MODELFLAG__/$MODELFLAG}
LAUNCH=${LAUNCH//__EFFORTFLAG__/$EFFORTFLAG}
LAUNCH=${LAUNCH//__PREWALKFLAG__/$PREWALKFLAG}
+if [ "$HARNESS" = omp ]; then
+ # shellcheck disable=SC2016
+ # Placeholders __BRIEF__ and __OPINPUT__ are substituted after shell-quoting;
+ # single quotes here keep the pane-side command literal. The launch message is
+ # a single task-bearing instruction to read the original brief before working;
+ # opted-in launches prepend the standalone `orchestrate` keyword.
+ if [ "$ORCHESTRATE_BRIEF" -eq 1 ]; then
+ OMP_MESSAGE='"$(printf '"'"'orchestrate\n\nRead the brief at %s and follow it exactly.'"'"' __BRIEF__ | __OPINPUT__ encode launch-brief)"'
+ else
+ OMP_MESSAGE='"$(printf '"'"'Read the brief at %s and follow it exactly.'"'"' __BRIEF__ | __OPINPUT__ encode launch-brief)"'
+ fi
+ LAUNCH=${LAUNCH//__OMPMESSAGE__/$OMP_MESSAGE}
+fi
LAUNCH=${LAUNCH//__BRIEF__/$sq_brief}
LAUNCH=${LAUNCH//__TURNEND_SIGNAL__/$sq_turnend_signal}
LAUNCH=${LAUNCH//__STATE__/$sq_state}
diff --git a/docs/verification/runtime-backends.md b/docs/verification/runtime-backends.md
index e8e8c03fbc..2f20a539eb 100644
--- a/docs/verification/runtime-backends.md
+++ b/docs/verification/runtime-backends.md
@@ -381,6 +381,31 @@ Raw-launch OMP refusals and direct non-OMP compatibility are covered by `tests/f
The secondmate integration checks reran on 2026-08-27 and prove that the exact Firstmate primary and fleet-hook extensions remain permitted in the persistent home without allowing modified or unrelated tracked extension code.
Live firing of the fleet hook's `tool_result`, `todo_reminder`, and `session.compacting` handlers is PENDING firstmate scratch OMP verification before merge; deterministic extension and spawn tests do not claim OMP event delivery.
+### OMP native orchestration opt-in
+
+The agent-runtime launch and activation contract is owned by the [harness-adapters skill](../../.agents/skills/harness-adapters/SKILL.md); this page records its verification evidence without restating that contract.
+
+The activation boundary was verified on 2026-09-10 against OMP 18.1.14. The live proof used an isolated `FM_HOME`, a disposable project, a private tmux socket, and the `tests/fm-omp-worker-tmux-live-e2e.test.sh` fixture shape:
+
+```sh
+omp --version
+FM_HOME="$fixture_home" bin/fm-brief.sh --mode local-only --orchestrate
+FM_HOME="$fixture_home" FM_BACKEND=tmux bin/fm-spawn.sh \
+ --mode local-only --yolo off --harness omp --model openai-codex/gpt-5.6-luna --effort low
+```
+
+Observed bounded output:
+
+```text
+omp/18.1.14
+spawned orch-live-worker harness=omp kind=ship mode=local-only yolo=off
+status: done: ready in branch fm/orch-live-worker
+session: orchestrate-notice injected; task toolCall dispatched CalcImplementation + GreetImplementation
+subagent sessions: CalcImplementation.jsonl, GreetImplementation.jsonl
+combined verification: python3 -m pytest tests/ 5 passed
+```
+
+The session file records one `orchestrate-notice` custom message, one `task` toolCall whose `tasks` array named two subagents (`CalcImplementation`, `GreetImplementation`), and the two corresponding `agent="task"` completion results. The worktree contains the committed `lib/calc.py` and `lib/greet.py` implementations, and the combined pytest suite passed.
The Herdr role matrix required each expected turn-end or routed-reply notification to reach the durable queue or the primary follow-up transcript before the fixture drained it.
The deterministic composer, tmux, and Herdr fixtures reran on 2026-08-26 and proved that the backend typed-submit primitive for an already-busy OMP target returns internal `queued-unconfirmed` only after Enter transport succeeds and the composer either clears or remains proven pending while native state is still working.
diff --git a/tests/fm-brief.test.sh b/tests/fm-brief.test.sh
index 504cc6249a..141d2a3bb0 100755
--- a/tests/fm-brief.test.sh
+++ b/tests/fm-brief.test.sh
@@ -312,8 +312,42 @@ yolo on a ship brief|brief-refused-b1 some-proj --mode direct-PR --yolo on|--yol
yolo=value form on a ship brief|brief-refused-b2 some-proj --mode direct-PR --yolo=off|--yolo is not a brief input
mode on a scout brief|brief-refused-b3 some-proj --scout --mode direct-PR|--mode applies only to ship briefs
mode on a secondmate charter|brief-refused-b4 --secondmate --no-projects --mode no-mistakes|--mode applies only to ship briefs
+orchestrate on a scout brief|brief-refused-b5 some-proj --scout --orchestrate|--orchestrate applies only to ship briefs
+orchestrate on a secondmate charter|brief-refused-b6 --secondmate --no-projects --orchestrate|--orchestrate applies only to ship briefs
ROWS
- pass "fm-brief.sh: --yolo and scout/secondmate --mode are refused, never silently dropped"
+ pass "fm-brief.sh: --yolo, scout/secondmate --mode, and non-ship --orchestrate are refused, never silently dropped"
+}
+
+# The opt-in marker is explicit task data: a ship brief carries
+# `orchestration: enabled` only when --orchestrate was passed, and the same
+# scaffold without the flag stays byte-free of the marker.
+test_orchestrate_opt_in_adds_marker_only_on_ship() {
+ local home brief out status
+ home="$TMP_ROOT/orchestrate-home"
+ mkdir -p "$home/data"
+
+ out=$(FM_HOME="$home" "$ROOT/bin/fm-brief.sh" brief-orch-c1 some-proj --mode direct-PR --orchestrate 2>&1)
+ status=$?
+ expect_code 0 "$status" "fm-brief.sh ship --orchestrate should exit 0"
+ assert_contains "$out" "replace {TASK} and every {ACCEPTANCE CRITERION}" \
+ "orchestrate scaffold success omitted required placeholder replacements"
+ brief="$home/data/brief-orch-c1/brief.md"
+ assert_present "$brief" "orchestrate brief was not scaffolded"
+ assert_grep "# Orchestration" "$brief" "orchestrate brief missing the Orchestration section"
+ [ "$(head -n 3 "$brief")" = $'---\norchestration: enabled\n---' ] \
+ || fail "orchestrate brief did not record the front-matter orchestration marker"
+ # shellcheck disable=SC2016
+ assert_grep 'native `task` subagents' "$brief" \
+ "orchestrate brief missing the native subagent boundary statement"
+
+ FM_HOME="$home" "$ROOT/bin/fm-brief.sh" brief-plain-c2 some-proj --mode direct-PR >/dev/null 2>&1 \
+ || fail "plain ship brief should scaffold"
+ brief="$home/data/brief-plain-c2/brief.md"
+ assert_no_grep "orchestration: enabled" "$brief" "plain ship brief leaked the orchestration marker"
+ assert_no_grep "# Orchestration" "$brief" "plain ship brief leaked the Orchestration section"
+ assert_no_grep "subagents" "$brief" "plain ship brief leaked the orchestration subagent statement"
+
+ pass "fm-brief.sh: --orchestrate adds the ship marker only when opted in"
}
test_faster_paths_use_configured_authority_without_stacked_review() {
@@ -860,6 +894,7 @@ test_ship_modes_generate_clean_briefs
test_ship_mode_is_required_and_closed_set
test_ship_mode_is_explicit_not_registry
test_delivery_flags_are_refused_where_they_do_not_apply
+test_orchestrate_opt_in_adds_marker_only_on_ship
test_faster_paths_use_configured_authority_without_stacked_review
test_no_mistakes_dod_wording
test_ship_project_memory_wording
diff --git a/tests/fm-omp-harness.test.sh b/tests/fm-omp-harness.test.sh
index a73168f2a8..d2e94fb56c 100755
--- a/tests/fm-omp-harness.test.sh
+++ b/tests/fm-omp-harness.test.sh
@@ -408,6 +408,67 @@ test_capability_probe_never_falls_back_when_omp_is_missing() {
pass "selected OMP refuses instead of falling back to another harness"
}
+# An orchestrate opt-in is brief-level data, not a spawn flag. It must fail before
+# any endpoint exists if the selected harness is not OMP, so the keyword can never
+# be forced onto a different runtime.
+test_orchestrate_marker_refuses_non_omp_harness() {
+ local home proj id out status
+ home="$TMP_ROOT/orchestrate-refuse-home"
+ mkdir -p "$home/data" "$home/state" "$home/config" "$home/projects"
+ proj="$home/project"
+ fm_git_init_commit "$proj" || fail "could not create project for orchestrate refusal"
+ id="brief-orch-refuse"
+ out=$(FM_HOME="$home" "$ROOT/bin/fm-brief.sh" "$id" "$(basename "$proj")" --mode direct-PR --orchestrate 2>&1)
+ status=$?
+ expect_code 0 "$status" "orchestrate ship brief should scaffold"
+ out=$(FM_HOME="$home" "$ROOT/bin/fm-spawn.sh" "$id" "$proj" --mode direct-PR --yolo off --harness claude --backend tmux 2>&1)
+ status=$?
+ expect_code 1 "$status" "orchestration marker with a non-omp harness should refuse"
+ assert_contains "$out" "orchestration requires harness=omp" "non-omp harness refusal did not explain the required harness"
+ pass "fm-spawn: orchestration marker refuses non-omp harnesses"
+}
+
+# An orchestrate opt-in is brief-level data. The verified OMP template is the only
+# launch path that injects the exact `orchestrate` keyword; a raw launch command
+# bypasses that template and must refuse a marked brief before endpoint creation.
+test_orchestrate_marker_refuses_raw_launch_command() {
+ local home proj id out status
+ home="$TMP_ROOT/orchestrate-raw-refuse-home"
+ mkdir -p "$home/data" "$home/state" "$home/config" "$home/projects"
+ proj="$home/project"
+ fm_git_init_commit "$proj" || fail "could not create project for raw launch refusal"
+ id="brief-orch-raw"
+ out=$(FM_HOME="$home" "$ROOT/bin/fm-brief.sh" "$id" "$(basename "$proj")" --mode direct-PR --orchestrate 2>&1)
+ status=$?
+ expect_code 0 "$status" "orchestrate ship brief should scaffold"
+ out=$(FM_HOME="$home" "$ROOT/bin/fm-spawn.sh" "$id" "$proj" "cat /dev/null" --mode direct-PR --yolo off --backend tmux 2>&1)
+ status=$?
+ expect_code 1 "$status" "orchestration marker with a raw launch command should refuse"
+ assert_contains "$out" "orchestration requires the verified OMP launch template" "raw launch refusal did not explain the required template"
+ pass "fm-spawn: orchestration marker refuses raw launch commands"
+}
+
+test_task_text_marker_does_not_opt_in() {
+ local home proj brief out status
+ home="$TMP_ROOT/task-text-marker-home"
+ mkdir -p "$home/data" "$home/state" "$home/config" "$home/projects"
+ proj="$home/project"
+ fm_git_init_commit "$proj" || fail "could not create project for task marker regression"
+ out=$(FM_HOME="$home" "$ROOT/bin/fm-brief.sh" brief-task-marker some-proj --mode direct-PR 2>&1)
+ status=$?
+ expect_code 0 "$status" "plain ship brief should scaffold for task marker regression"
+ brief="$home/data/brief-task-marker/brief.md"
+ sed -i '/^# Task$/a orchestration: enabled' "$brief"
+ sed -i 's/{TASK}/Complete the requested work/; s/{ACCEPTANCE CRITERION}/The task completes successfully/' "$brief"
+ out=$(FM_HOME="$home" "$ROOT/bin/fm-spawn.sh" brief-task-marker "$proj" --mode direct-PR --yolo off --harness claude --backend tmux 2>&1)
+ status=$?
+ case "$out" in
+ *"orchestration requires harness=omp"*) fail "task prose marker was misclassified as orchestration opt-in" ;;
+ esac
+ [ "$status" -ne 0 ] || fail "task marker regression unexpectedly launched a worker"
+ pass "fm-spawn: task prose marker does not opt into orchestration"
+}
+
test_launch_boundary_marker_preserves_exact_omp_identity
test_standalone_worker_uses_bound_identity
test_standalone_primary_survives_executable_replacement
@@ -420,3 +481,6 @@ test_capability_probe_rejects_non_bun_entrypoint
test_capability_probe_reports_every_missing_requirement
test_capability_probe_scopes_exact_max_time_to_bounded_launches
test_capability_probe_never_falls_back_when_omp_is_missing
+test_orchestrate_marker_refuses_non_omp_harness
+test_orchestrate_marker_refuses_raw_launch_command
+test_task_text_marker_does_not_opt_in