Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save arikon/91476f67e6a3a30dcb2f6ceae8e70802 to your computer and use it in GitHub Desktop.

Select an option

Save arikon/91476f67e6a3a30dcb2f6ceae8e70802 to your computer and use it in GitHub Desktop.
OMX #3354: realistic native Ultragoal receipt transport for Codex App (dev@73cb50c1..96bdd023)
diff --git a/docs/codex-native-hooks.md b/docs/codex-native-hooks.md
index 75f72bcc..3f95f503 100644
--- a/docs/codex-native-hooks.md
+++ b/docs/codex-native-hooks.md
@@ -120,8 +120,20 @@ while the Conductor boundary is active.
Planning boundaries (`ralplan`, `deep-interview`) remain fail-closed for mutation
transports: only their documented planning artifact paths and non-deactivating
-state operations are allowed. No assignment-backed grant, prompt-derived scope,
-or child-write allowance exists in this Option C implementation.
+state operations are allowed. They do not accept an Ultragoal assignment-backed
+grant, prompt-derived scope, or child-write allowance.
+
+Standalone Ultragoal on a native Codex surface outside tmux has three configured
+backends: `off`, `host`, and `local-experimental`. `off` preserves the no-owner
+activation block. `host` is the production-safe integration point, but it fails
+closed because Codex does not currently expose a documented host-issued native
+executor receipt API. `local-experimental` requires an ordered bootstrap:
+typed executor spawn, root authorization through
+`omx ultragoal native-bootstrap authorize`, then activation. The assignment is
+a short-lived same-user guardrail, not host authentication or an ADR 3212
+hostile-child boundary. See
+[`native-subagent-assignments.md`](native-subagent-assignments.md) for exact
+configuration, lifecycle, reconciliation, and recovery behavior.
### Exact direct-cancel recovery exception
diff --git a/docs/native-subagent-assignments.md b/docs/native-subagent-assignments.md
new file mode 100644
index 00000000..01445224
--- /dev/null
+++ b/docs/native-subagent-assignments.md
@@ -0,0 +1,211 @@
+# Native subagent assignments
+
+The Codex native hook keeps typed native children read-only unless the active
+root Conductor establishes an exact, session-scoped assignment. This transport
+does not grant Team-worker identity or authority.
+
+## Backends
+
+Configure the transport in `~/.omx/config.json`:
+
+```json
+{
+ "nativeUltragoal": {
+ "backend": "local-experimental",
+ "assignmentTtlSeconds": 900
+ }
+}
+```
+
+`assignmentTtlSeconds` accepts an integer from 30 through 3600 and defaults to
+900. `OMX_NATIVE_ULTRAGOAL_BACKEND` overrides the configured backend. The
+override is fail-closed: a present non-empty invalid value resolves to `off`
+instead of falling back to a configured authority backend. The
+legacy `OMX_NATIVE_SUBAGENT_ASSIGNMENTS=on` setting maps to
+`local-experimental` only when neither the new environment override nor an
+explicit configured backend is present.
+
+The available backends are:
+
+- `off` (default): native Ultragoal activation outside tmux remains blocked
+ because no authorized executor is available.
+- `host`: reserved for a documented, unforgeable receipt issued by the Codex
+ host. OMX has no such host receipt API today, so this backend fails closed
+ with `OMX-ULTRAGOAL-HOST-RECEIPT-UNAVAILABLE`.
+- `local-experimental`: enables short-lived local assignments after OMX checks
+ the native tracker. This is a bounded same-user workflow guardrail, not host
+ authentication and not an ADR 3212 hostile-child boundary.
+
+## Ordered bootstrap
+
+On Codex native surfaces outside tmux, a fresh standalone `$ultragoal`
+activation stays inactive until the executor assignment is ready. Use this
+order:
+
+1. Invoke `$ultragoal`. The hook verifies typed `spawn_agent` support, creates
+ a session bootstrap, and returns `OMX-ULTRAGOAL-BOOTSTRAP-REQUIRED` without
+ activating Conductor mode.
+2. Spawn one direct native child with `agent_type: "executor"` and retain its
+ canonical child ID.
+3. Authorize only the required paths and actions:
+
+ ```sh
+ omx ultragoal native-bootstrap authorize \
+ --session-id <session-id> \
+ --root-thread-id <root-thread-id> \
+ --bootstrap-generation <generation-from-bootstrap-required> \
+ --child-id <child-agent-id> \
+ --path-prefix <repo-relative-path> \
+ --json
+ ```
+
+ Repeat `--path-prefix` for additional scopes. Add `--path-write-only` to
+ omit `bash-write`. Use `--ttl-seconds <30-3600>` only when the configured
+ TTL is unsuitable. Every `native-bootstrap` action requires an explicit
+ `--session-id` equal to the canonical current runtime session; pointer-only
+ or cross-session commands fail closed. `--bootstrap-generation` is the exact
+ generation printed by the bootstrap-required response; stale commands cannot
+ authorize a replacement generation.
+4. Retry the canonical Ultragoal activation. `PreToolUse` moves the receipt to
+ `activating`; only a successful activation `PostToolUse` publishes `active`.
+ The hook proceeds only after the
+ bootstrap generation, assignment, tracker session, root thread, exact child
+ ID, direct parent, role, status, lifetime, and path scope all validate.
+
+The child remains read-only until activation is confirmed. A crash before the
+activation tool runs leaves `ready`; a rejected or interrupted activation leaves
+`activating`. Both are safe and retryable while the assignment and tracked
+executor remain valid. If the receipt is revoked, expires, or loses tracker
+authority before confirmation, the hook revokes the grant and terminalizes the
+new Ultragoal state as `failed` instead of leaving Conductor active without an
+executor.
+
+## Location
+
+The bootstrap for root session `<session-id>` is stored at:
+
+```text
+.omx/state/sessions/<session-id>/native-ultragoal-bootstrap.json
+```
+
+The assignment for child `<child-agent-id>` is stored at:
+
+```text
+.omx/state/sessions/<session-id>/native-assignments/<encodeURIComponent(child-agent-id)>.json
+```
+
+`omx ultragoal native-bootstrap authorize` is the supported writer. The native
+hook rejects the canonical command when a tracked child invokes it and rejects
+child writes to bootstrap or `native-assignments` paths, even when ordinary
+path scope would otherwise match. This is still a same-user experimental
+boundary: the CLI cannot authenticate an arbitrary local OS process as
+Main-root without a host-issued receipt.
+
+## Active assignment schema
+
+The JSON object must contain exactly these keys:
+
+```json
+{
+ "schema_version": 1,
+ "kind": "native-subagent-assignment",
+ "lifecycle": "active",
+ "root_session_id": "exact-root-session-id",
+ "root_thread_id": "exact-root-thread-id",
+ "child_agent_id": "exact-canonical-child-agent-id",
+ "agent_type": "executor",
+ "allowed_actions": ["path-write", "bash-write"],
+ "path_prefixes": ["tmp/native-probe"],
+ "issued_at": "2026-07-23T20:00:00.000Z",
+ "expires_at": "2026-07-23T20:10:00.000Z",
+ "bootstrap_generation": "exact-bootstrap-generation"
+}
+```
+
+The hook checks the root session and leader thread against the active session
+and native subagent tracker. The first version accepts only a directly attested
+`executor` child. Its tracker entry must be `kind: "subagent"`, carry
+`mode: "executor"`, `provenance_kind: "native_subagent"`, and exact
+`direct_child_parent_id` / `direct_child_root_id` bindings to Main-root; revoked
+reopen authority, completion, or a non-available explicit status fails closed.
+The live tool payload must independently provide one unambiguous top-level
+`executor` role through the native `agent_role`/`agent_type` aliases.
+Nested-only role evidence, missing tracker attestation, or conflicting aliases
+cannot authorize an assignment. The filename must encode that same canonical
+child ID, and `bootstrap_generation` must match the current session bootstrap.
+
+Assignments are fail-closed when unreadable, malformed, expired, issued too far
+in the future, longer than 24 hours, symlinked, hard-linked, larger than 64 KiB,
+or writable by group/other. Unknown keys, duplicate actions or prefixes,
+ambiguous paths, symlink traversal, `.omx`, and `.git` scopes are rejected.
+Deleting the file or changing `lifecycle` away from `active` revokes the grant.
+
+## Lifecycle, revocation, and recovery
+
+Inspect and reconcile the current bootstrap with:
+
+```sh
+omx ultragoal native-bootstrap status --session-id <session-id> --json
+```
+
+Status reconciliation returns readiness only while the exact assignment and
+tracked direct executor remain valid. An expired assignment cannot authorize a
+mutation. Reconciliation revokes an active assignment when the tracked child is
+missing, completed, unavailable, foreign to the root, or has the wrong role.
+Fresh activation also reconciles before it proceeds.
+
+All lifecycle mutations for one session are serialized by a session-scoped
+lock. Activation revalidates tracker authority, generation, file identity,
+schema, scope, and expiry under that lock and returns a positive receipt before
+the hook permits state activation. Concurrent revoke cannot be overwritten by
+a stale authorize or activation write. Revoked and expired generations require
+an explicit new bootstrap before another authorization; authorization never
+rotates a generation implicitly. An already-active receipt is idempotently
+revalidated so a rejected or interrupted state write can be retried safely.
+
+Explicitly revoke the bootstrap and its assignment with:
+
+```sh
+omx ultragoal native-bootstrap revoke \
+ --session-id <session-id> \
+ --child-id <child-agent-id> \
+ --reason <reason> \
+ --json
+```
+
+`--child-id` is optional when the bootstrap already records the child. After
+revocation, expiry, or tracker invalidation, the child returns to the normal
+read-only policy. Re-run `authorize` with the explicit current `--session-id`,
+root thread, and a live strictly tracked executor to renew or replace the lease;
+when standalone Ultragoal state is still active, the CLI restores bootstrap
+status to `active` only after revalidation. Terminal `Stop`, exact root
+cancellation, and a new fresh run revoke or rotate the old generation. An
+assignment from an older generation cannot be reused.
+
+## Actions
+
+- `path-write`: direct file-edit tools within `path_prefixes`.
+- `bash-write`: one statically analyzable shell mutation within
+ `path_prefixes`.
+
+Assignments never authorize VCS, PR, network, deployment, state, orchestration,
+goal, assignment, or Team-worker operations. A `"."` prefix still excludes
+`.git` and `.omx`. Shell substitution,
+unresolved arithmetic, dynamic nested execution, unsafe heredocs, unsafe
+nameref/allexport state, arbitrary PATH mutation, unresolved interpreter
+writes, and path/symlink escapes remain blocked.
+
+Without a valid assignment, typed native children continue to receive
+`OWNER_CONFIRMATION_REQUIRED`.
+
+## Root orchestration transports
+
+An active, session-bound Main-root Conductor may write the existing bounded
+metadata roots, including `.omx/state`, `.omx/ultragoal`, `.omx/ralph`,
+`.omx/team`, `.omx/mailbox`, `.omx/handoff`, `.omx/handoffs`, `.omx/goals`,
+`.omx/notepad`, `.omx/wiki`, and `.beads`.
+
+The hook structurally recognizes canonical `omx state read`, `omx state write`,
+`omx state clear`, and `omx ultragoal checkpoint` commands before generic shell
+mutation analysis. Exact session/cwd/mode binding and all existing injection,
+PATH, symlink, and protected-state-gate checks still apply.
diff --git a/plugins/oh-my-codex/skills/ultragoal/SKILL.md b/plugins/oh-my-codex/skills/ultragoal/SKILL.md
index 3a22a0ed..7010d328 100644
--- a/plugins/oh-my-codex/skills/ultragoal/SKILL.md
+++ b/plugins/oh-my-codex/skills/ultragoal/SKILL.md
@@ -24,6 +24,7 @@ Ultragoal is both a tracked workflow skill and the Autopilot durable-implementat
- **Standalone `$ultragoal` activation**: ensure `.omx/state[/sessions/<session>]/ultragoal-state.json` exists with `mode:"ultragoal"`, `active:true`, and a non-empty `current_phase` such as `planning` before or while goals are created. This state is a lightweight HUD/runtime declaration; `.omx/ultragoal/goals.json` and `ledger.jsonl` remain the durable goal source of truth.
- **During execution**: update `current_phase` to the smallest accurate phase (`planning`, `executing`, `verifying`, `reviewing`, `checkpointing`, or `blocked`) when the visible workflow phase changes.
+- **Codex App outside tmux**: `nativeUltragoal.backend` defaults to `off`. `host` remains fail-closed until Codex exposes a documented host-issued native executor receipt API. `local-experimental` is an explicit same-user guardrail, not host authentication or an ADR 3212 hostile-child boundary. When typed `spawn_agent` support is advertised, keep Ultragoal inactive while Main-root follows the ordered bootstrap: invoke `$ultragoal`, spawn one exact typed `executor`, run `omx ultragoal native-bootstrap authorize --session-id <session-id> --root-thread-id <root-thread-id> --bootstrap-generation <generation> --child-id <child-id> --path-prefix <repo-relative-path> --json`, then retry the canonical Ultragoal activation. Keep paths/actions minimal; use `omx ultragoal native-bootstrap status` to reconcile/recover and `omx ultragoal native-bootstrap revoke` when the executor is no longer needed. Follow `docs/native-subagent-assignments.md` for configuration and lifecycle details.
- **Inside active Autopilot**: keep `mode:"autopilot"` active and set the supervised phase to `current_phase:"ultragoal"`; do not start a peer Autopilot replacement. Ultragoal's own mode state may still exist as child-phase detail, but Autopilot owns the parent phase.
- **On handoff to code-review**: persist implementation/test/ledger evidence under Autopilot `handoff_artifacts.ultragoal`, then set Autopilot `current_phase:"code-review"`.
- **On completion/blocker**: set standalone Ultragoal `active:false,current_phase:"complete"` only when all durable goals are complete; otherwise keep it active with a blocker/review-blocked phase and ledger evidence.
diff --git a/skills/ultragoal/SKILL.md b/skills/ultragoal/SKILL.md
index 3a22a0ed..7010d328 100644
--- a/skills/ultragoal/SKILL.md
+++ b/skills/ultragoal/SKILL.md
@@ -24,6 +24,7 @@ Ultragoal is both a tracked workflow skill and the Autopilot durable-implementat
- **Standalone `$ultragoal` activation**: ensure `.omx/state[/sessions/<session>]/ultragoal-state.json` exists with `mode:"ultragoal"`, `active:true`, and a non-empty `current_phase` such as `planning` before or while goals are created. This state is a lightweight HUD/runtime declaration; `.omx/ultragoal/goals.json` and `ledger.jsonl` remain the durable goal source of truth.
- **During execution**: update `current_phase` to the smallest accurate phase (`planning`, `executing`, `verifying`, `reviewing`, `checkpointing`, or `blocked`) when the visible workflow phase changes.
+- **Codex App outside tmux**: `nativeUltragoal.backend` defaults to `off`. `host` remains fail-closed until Codex exposes a documented host-issued native executor receipt API. `local-experimental` is an explicit same-user guardrail, not host authentication or an ADR 3212 hostile-child boundary. When typed `spawn_agent` support is advertised, keep Ultragoal inactive while Main-root follows the ordered bootstrap: invoke `$ultragoal`, spawn one exact typed `executor`, run `omx ultragoal native-bootstrap authorize --session-id <session-id> --root-thread-id <root-thread-id> --bootstrap-generation <generation> --child-id <child-id> --path-prefix <repo-relative-path> --json`, then retry the canonical Ultragoal activation. Keep paths/actions minimal; use `omx ultragoal native-bootstrap status` to reconcile/recover and `omx ultragoal native-bootstrap revoke` when the executor is no longer needed. Follow `docs/native-subagent-assignments.md` for configuration and lifecycle details.
- **Inside active Autopilot**: keep `mode:"autopilot"` active and set the supervised phase to `current_phase:"ultragoal"`; do not start a peer Autopilot replacement. Ultragoal's own mode state may still exist as child-phase detail, but Autopilot owns the parent phase.
- **On handoff to code-review**: persist implementation/test/ledger evidence under Autopilot `handoff_artifacts.ultragoal`, then set Autopilot `current_phase:"code-review"`.
- **On completion/blocker**: set standalone Ultragoal `active:false,current_phase:"complete"` only when all durable goals are complete; otherwise keep it active with a blocker/review-blocked phase and ledger evidence.
diff --git a/src/cli/__tests__/ultragoal.test.ts b/src/cli/__tests__/ultragoal.test.ts
index 74c6d1f2..961c0a61 100644
--- a/src/cli/__tests__/ultragoal.test.ts
+++ b/src/cli/__tests__/ultragoal.test.ts
@@ -14,6 +14,10 @@ import {
NATIVE_SUBAGENT_ROLE_ROUTING_MARKER_FILE,
writeRoleRoutingMarker,
} from '../../subagents/role-routing-marker.js';
+import {
+ beginNativeUltragoalBootstrap,
+ nativeExecutorAssignmentPath,
+} from '../../ultragoal/native-bootstrap.js';
import { ultragoalCommand, ULTRAGOAL_HELP } from '../ultragoal.js';
async function withCwd<T>(run: (cwd: string) => Promise<T>): Promise<T> {
@@ -144,6 +148,7 @@ describe('cli/ultragoal', () => {
['next'],
['start-next'],
['checkpoint', '--goal-id', 'G001-first', '--status', 'complete', '--evidence', 'worker evidence'],
+ ['native-bootstrap', 'revoke', '--session-id', 'worker-session'],
];
const envCases: Array<[string, string]> = [
['OMX_TEAM_WORKER', 'display-team/worker-1'],
@@ -214,6 +219,127 @@ describe('cli/ultragoal', () => {
assert.match(ULTRAGOAL_HELP, /quality-gate-json/);
assert.match(ULTRAGOAL_HELP, /ai-slop-cleaner/);
assert.match(ULTRAGOAL_HELP, /code-review/);
+ assert.match(ULTRAGOAL_HELP, /native-bootstrap <authorize\|status\|revoke>/);
+ });
+
+ it('authorizes, reports, and revokes an experimental native executor bootstrap', async () => {
+ await withCwd(async (cwd) => {
+ const previousBackend = process.env.OMX_NATIVE_ULTRAGOAL_BACKEND;
+ process.env.OMX_NATIVE_ULTRAGOAL_BACKEND = 'local-experimental';
+ const stateDir = join(cwd, '.omx', 'state');
+ const sessionId = 'native-cli-session';
+ const rootThreadId = 'native-cli-root';
+ const childAgentId = 'native-cli-executor';
+ try {
+ await mkdir(stateDir, { recursive: true });
+ await writeFile(join(stateDir, 'session.json'), `${JSON.stringify({
+ session_id: sessionId,
+ native_session_id: rootThreadId,
+ cwd,
+ })}\n`);
+ await writeFile(join(stateDir, 'subagent-tracking.json'), `${JSON.stringify({
+ schemaVersion: 1,
+ sessions: {
+ [sessionId]: {
+ session_id: sessionId,
+ leader_thread_id: rootThreadId,
+ updated_at: new Date().toISOString(),
+ threads: {
+ [rootThreadId]: { thread_id: rootThreadId, kind: 'leader' },
+ [childAgentId]: {
+ thread_id: childAgentId,
+ kind: 'subagent',
+ mode: 'executor',
+ status: 'available',
+ provenance_kind: 'native_subagent',
+ direct_child_parent_id: rootThreadId,
+ direct_child_root_id: rootThreadId,
+ },
+ },
+ },
+ },
+ }, null, 2)}\n`);
+ const initialBootstrap = await beginNativeUltragoalBootstrap({
+ stateDir,
+ sessionId,
+ rootThreadId,
+ backend: 'local-experimental',
+ ttlSeconds: 900,
+ });
+
+ const crossSession = await capture(() => ultragoalCommand([
+ 'native-bootstrap', 'status', '--session-id', 'foreign-session', '--json',
+ ]));
+ assert.equal(crossSession.exitCode, 1);
+ assert.match(crossSession.stderr.join('\n'), /does not match the canonical current runtime session/);
+ const omittedSession = await capture(() => ultragoalCommand([
+ 'native-bootstrap', 'status', '--json',
+ ]));
+ assert.equal(omittedSession.exitCode, 1);
+ assert.match(omittedSession.stderr.join('\n'), /require an explicit --session-id/);
+
+ const authorized = await capture(() => ultragoalCommand([
+ 'native-bootstrap', 'authorize',
+ '--session-id', sessionId,
+ '--root-thread-id', rootThreadId,
+ '--child-id', childAgentId,
+ '--bootstrap-generation', initialBootstrap.generation,
+ '--path-prefix', 'src',
+ '--json',
+ ]));
+ assert.equal(authorized.exitCode, undefined);
+ assert.equal(JSON.parse(authorized.stdout.join('\n')).assignment.child_agent_id, childAgentId);
+ assert.equal(existsSync(nativeExecutorAssignmentPath(stateDir, sessionId, childAgentId)), true);
+
+ const status = await capture(() => ultragoalCommand([
+ 'native-bootstrap', 'status', '--session-id', sessionId, '--json',
+ ]));
+ const statusPayload = JSON.parse(status.stdout.join('\n')) as {
+ bootstrap: { status: string };
+ readiness: { ready: boolean };
+ };
+ assert.equal(statusPayload.bootstrap.status, 'ready');
+ assert.equal(statusPayload.readiness.ready, true);
+
+ const revoked = await capture(() => ultragoalCommand([
+ 'native-bootstrap', 'revoke', '--session-id', sessionId, '--json',
+ ]));
+ assert.equal(revoked.exitCode, undefined);
+ assert.equal(JSON.parse(revoked.stdout.join('\n')).status, 'revoked');
+
+ await mkdir(join(stateDir, 'sessions', sessionId), { recursive: true });
+ await writeFile(join(stateDir, 'sessions', sessionId, 'ultragoal-state.json'), `${JSON.stringify({
+ mode: 'ultragoal',
+ active: true,
+ current_phase: 'executing',
+ session_id: sessionId,
+ })}\n`);
+ const recoveryBootstrap = await beginNativeUltragoalBootstrap({
+ stateDir,
+ sessionId,
+ rootThreadId,
+ backend: 'local-experimental',
+ ttlSeconds: 900,
+ });
+ const recovered = await capture(() => ultragoalCommand([
+ 'native-bootstrap', 'authorize',
+ '--session-id', sessionId,
+ '--root-thread-id', rootThreadId,
+ '--child-id', childAgentId,
+ '--bootstrap-generation', recoveryBootstrap.generation,
+ '--path-prefix', 'src',
+ '--json',
+ ]));
+ assert.equal(recovered.exitCode, undefined);
+ const recoveredStatus = await capture(() => ultragoalCommand([
+ 'native-bootstrap', 'status', '--session-id', sessionId, '--json',
+ ]));
+ assert.equal(JSON.parse(recoveredStatus.stdout.join('\n')).bootstrap.status, 'active');
+ } finally {
+ if (typeof previousBackend === 'string') process.env.OMX_NATIVE_ULTRAGOAL_BACKEND = previousBackend;
+ else delete process.env.OMX_NATIVE_ULTRAGOAL_BACKEND;
+ }
+ });
});
it('creates and starts goals through the command surface', async () => {
diff --git a/src/cli/ultragoal.ts b/src/cli/ultragoal.ts
index 64d2e356..c781ed62 100644
--- a/src/cli/ultragoal.ts
+++ b/src/cli/ultragoal.ts
@@ -12,6 +12,7 @@ import {
resolveNativeSubagentSupportStatus,
} from '../leader/contract.js';
import { resolveRuntimeStateScope } from '../mcp/state-paths.js';
+import { resolveNativeUltragoalConfig } from '../config/native-ultragoal.js';
import { readRoleRoutingMarker } from '../subagents/role-routing-marker.js';
import {
addUltragoalGoal,
@@ -33,6 +34,31 @@ import {
ULTRAGOAL_STEERING_SOURCES,
UltragoalError,
} from '../ultragoal/artifacts.js';
+import {
+ issueLocalNativeExecutorAssignment,
+ markNativeUltragoalBootstrapActive,
+ prepareNativeUltragoalBootstrapActivation,
+ readNativeUltragoalBootstrap,
+ reconcileLocalNativeExecutorAssignments,
+ revokeLocalNativeExecutorAssignment,
+} from '../ultragoal/native-bootstrap.js';
+
+async function sessionHasActiveStandaloneUltragoal(stateDir: string, sessionId: string): Promise<boolean> {
+ try {
+ const parsed = JSON.parse(await readFile(
+ join(stateDir, 'sessions', sessionId, 'ultragoal-state.json'),
+ 'utf-8',
+ )) as Record<string, unknown>;
+ const phase = String(parsed.current_phase ?? parsed.currentPhase ?? '').trim().toLowerCase();
+ return parsed.mode === 'ultragoal'
+ && parsed.active === true
+ && parsed.session_id === sessionId
+ && phase !== ''
+ && !['complete', 'completed', 'cancelled', 'failed'].includes(phase);
+ } catch {
+ return false;
+ }
+}
export const ULTRAGOAL_HELP = `omx ultragoal - Durable repo-native multi-goal workflow over Codex goal mode
@@ -46,6 +72,7 @@ Usage:
omx ultragoal steer --directive-json <json-or-path> [--json]
omx ultragoal checkpoint --goal-id <id> --status <complete|failed|blocked> [--evidence <text>] [--codex-goal-json <json-or-path>] [--quality-gate-json <json-or-path>] [--json]
omx ultragoal status [--codex-goal-json <json-or-path>] [--json]
+ omx ultragoal native-bootstrap <authorize|status|revoke> [options] [--json]
Aliases:
create -> create-goals, complete|next|start-next -> complete-goals
@@ -336,6 +363,7 @@ const ULTRAGOAL_MUTATING_COMMANDS = new Set([
'next',
'start-next',
'checkpoint',
+ 'native-bootstrap',
]);
function readTeamWorkerIdentity(env: NodeJS.ProcessEnv = process.env): string | null {
@@ -374,6 +402,110 @@ export async function ultragoalCommand(args: string[], deps: UltragoalCommandDep
assertUltragoalMutationAllowedFromCurrentProcess(command);
+ if (command === 'native-bootstrap') {
+ const action = rest[0] ?? 'status';
+ const actionArgs = rest.slice(1);
+ const scope = await resolveRuntimeStateScope(cwd);
+ const config = resolveNativeUltragoalConfig();
+ const requestedSessionId = readValue(actionArgs, '--session-id');
+ if (!requestedSessionId) {
+ throw new UltragoalError('Native bootstrap commands require an explicit --session-id.');
+ }
+ if (!scope.sessionId) {
+ throw new UltragoalError('Native bootstrap requires a canonical current runtime session.');
+ }
+ if (requestedSessionId !== scope.sessionId) {
+ throw new UltragoalError('Requested --session-id does not match the canonical current runtime session.');
+ }
+ const sessionId = scope.sessionId;
+ const rootThreadId = readValue(actionArgs, '--root-thread-id');
+
+ if (action === 'authorize') {
+ if (config.backend !== 'local-experimental') {
+ throw new UltragoalError('native-bootstrap authorize requires nativeUltragoal.backend="local-experimental".');
+ }
+ const childAgentId = readValue(actionArgs, '--child-id');
+ const bootstrapGeneration = readValue(actionArgs, '--bootstrap-generation');
+ const pathPrefixes = readRepeated(actionArgs, '--path-prefix');
+ if (!rootThreadId) throw new UltragoalError('Missing --root-thread-id.');
+ if (!childAgentId) throw new UltragoalError('Missing --child-id.');
+ if (!bootstrapGeneration) throw new UltragoalError('Missing --bootstrap-generation.');
+ if (pathPrefixes.length === 0) throw new UltragoalError('Pass at least one --path-prefix.');
+ const ttlRaw = readValue(actionArgs, '--ttl-seconds');
+ const ttlSeconds = ttlRaw === undefined ? config.assignmentTtlSeconds : Number(ttlRaw);
+ try {
+ const assignment = await issueLocalNativeExecutorAssignment({
+ cwd: scope.cwd,
+ stateDir: scope.baseStateDir,
+ sessionId,
+ rootThreadId,
+ childAgentId,
+ expectedGeneration: bootstrapGeneration,
+ pathPrefixes,
+ ttlSeconds,
+ allowedActions: hasFlag(actionArgs, '--path-write-only')
+ ? ['path-write']
+ : ['path-write', 'bash-write'],
+ });
+ if (await sessionHasActiveStandaloneUltragoal(scope.baseStateDir, sessionId)) {
+ const currentBootstrap = await readNativeUltragoalBootstrap(scope.baseStateDir, sessionId);
+ if (currentBootstrap?.status !== 'active') {
+ const prepared = await prepareNativeUltragoalBootstrapActivation({
+ cwd: scope.cwd,
+ stateDir: scope.baseStateDir,
+ sessionId,
+ childAgentId,
+ });
+ if (!prepared.ok) throw new UltragoalError('native_ultragoal_activation_receipt_invalid');
+ const confirmed = await markNativeUltragoalBootstrapActive({
+ cwd: scope.cwd,
+ stateDir: scope.baseStateDir,
+ sessionId,
+ childAgentId,
+ });
+ if (!confirmed.ok) throw new UltragoalError('native_ultragoal_activation_receipt_invalid');
+ }
+ }
+ if (json) printJson({ ok: true, backend: config.backend, assignment });
+ else console.log(`native Ultragoal executor authorized: ${assignment.child_agent_id}`);
+ } catch (error) {
+ throw new UltragoalError(error instanceof Error ? error.message : String(error));
+ }
+ return;
+ }
+
+ if (action === 'revoke') {
+ await revokeLocalNativeExecutorAssignment({
+ stateDir: scope.baseStateDir,
+ sessionId,
+ childAgentId: readValue(actionArgs, '--child-id'),
+ reason: readValue(actionArgs, '--reason') ?? 'root_requested_revoke',
+ });
+ if (json) printJson({ ok: true, sessionId, status: 'revoked' });
+ else console.log(`native Ultragoal bootstrap revoked: ${sessionId}`);
+ return;
+ }
+
+ if (action === 'status') {
+ const bootstrap = await readNativeUltragoalBootstrap(scope.baseStateDir, sessionId);
+ const readiness = bootstrap?.root_thread_id
+ ? await reconcileLocalNativeExecutorAssignments({
+ cwd: scope.cwd,
+ stateDir: scope.baseStateDir,
+ sessionId,
+ rootThreadId: bootstrap.root_thread_id,
+ })
+ : { ready: false };
+ if (json) printJson({ backend: config.backend, bootstrap, readiness });
+ else console.log(bootstrap
+ ? `native Ultragoal bootstrap: ${bootstrap.status}${readiness.ready ? ' (ready)' : ''}`
+ : 'native Ultragoal bootstrap: absent');
+ return;
+ }
+
+ throw new UltragoalError('Invalid native-bootstrap action; expected authorize, status, or revoke.');
+ }
+
if (command === 'create' || command === 'create-goals') {
const briefFile = readValue(rest, '--brief-file');
const brief = readValue(rest, '--brief')
diff --git a/src/config/__tests__/native-ultragoal.test.ts b/src/config/__tests__/native-ultragoal.test.ts
new file mode 100644
index 00000000..e4bb6532
--- /dev/null
+++ b/src/config/__tests__/native-ultragoal.test.ts
@@ -0,0 +1,95 @@
+import assert from 'node:assert/strict';
+import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
+import { tmpdir } from 'node:os';
+import { join } from 'node:path';
+import { describe, it } from 'node:test';
+import { resolveNativeUltragoalConfig } from '../native-ultragoal.js';
+
+describe('native Ultragoal config', () => {
+ it('defaults off and reads the explicit global config', async () => {
+ const homeDir = await mkdtemp(join(tmpdir(), 'omx-native-ultragoal-config-'));
+ try {
+ assert.deepEqual(resolveNativeUltragoalConfig({ homeDir, env: {} }), {
+ backend: 'off',
+ assignmentTtlSeconds: 900,
+ source: 'default',
+ });
+ await mkdir(join(homeDir, '.omx'), { recursive: true });
+ await writeFile(join(homeDir, '.omx', 'config.json'), JSON.stringify({
+ nativeUltragoal: {
+ backend: 'local-experimental',
+ assignmentTtlSeconds: 300,
+ },
+ }));
+ assert.deepEqual(resolveNativeUltragoalConfig({ homeDir, env: {} }), {
+ backend: 'local-experimental',
+ assignmentTtlSeconds: 300,
+ source: 'config',
+ });
+ } finally {
+ await rm(homeDir, { recursive: true, force: true });
+ }
+ });
+
+ it('keeps invalid config fail-closed and preserves explicit env precedence', async () => {
+ const homeDir = await mkdtemp(join(tmpdir(), 'omx-native-ultragoal-config-invalid-'));
+ try {
+ await mkdir(join(homeDir, '.omx'), { recursive: true });
+ await writeFile(join(homeDir, '.omx', 'config.json'), JSON.stringify({
+ nativeUltragoal: { backend: 'local', assignmentTtlSeconds: 1 },
+ }));
+ assert.equal(resolveNativeUltragoalConfig({ homeDir, env: {} }).backend, 'off');
+ assert.deepEqual(resolveNativeUltragoalConfig({
+ homeDir,
+ env: { OMX_NATIVE_ULTRAGOAL_BACKEND: 'host' },
+ }), {
+ backend: 'host',
+ assignmentTtlSeconds: 900,
+ source: 'env',
+ });
+ assert.equal(resolveNativeUltragoalConfig({
+ homeDir,
+ env: { OMX_NATIVE_SUBAGENT_ASSIGNMENTS: 'on' },
+ }).backend, 'off');
+ await writeFile(join(homeDir, '.omx', 'config.json'), '{ malformed');
+ assert.deepEqual(resolveNativeUltragoalConfig({
+ homeDir,
+ env: { OMX_NATIVE_SUBAGENT_ASSIGNMENTS: 'on' },
+ }), {
+ backend: 'off',
+ assignmentTtlSeconds: 900,
+ source: 'config',
+ });
+ } finally {
+ await rm(homeDir, { recursive: true, force: true });
+ }
+ });
+
+ it('keeps explicit new config ahead of the legacy assignment opt-in', async () => {
+ const homeDir = await mkdtemp(join(tmpdir(), 'omx-native-ultragoal-config-legacy-'));
+ try {
+ await mkdir(join(homeDir, '.omx'), { recursive: true });
+ await writeFile(join(homeDir, '.omx', 'config.json'), JSON.stringify({
+ nativeUltragoal: { backend: 'host', assignmentTtlSeconds: 120 },
+ }));
+ assert.deepEqual(resolveNativeUltragoalConfig({
+ homeDir,
+ env: { OMX_NATIVE_SUBAGENT_ASSIGNMENTS: 'on' },
+ }), {
+ backend: 'host',
+ assignmentTtlSeconds: 120,
+ source: 'config',
+ });
+ assert.deepEqual(resolveNativeUltragoalConfig({
+ homeDir,
+ env: { OMX_NATIVE_ULTRAGOAL_BACKEND: 'local' },
+ }), {
+ backend: 'off',
+ assignmentTtlSeconds: 120,
+ source: 'env',
+ });
+ } finally {
+ await rm(homeDir, { recursive: true, force: true });
+ }
+ });
+});
diff --git a/src/config/native-ultragoal.ts b/src/config/native-ultragoal.ts
new file mode 100644
index 00000000..83da9374
--- /dev/null
+++ b/src/config/native-ultragoal.ts
@@ -0,0 +1,125 @@
+import { existsSync, readFileSync } from 'node:fs';
+import { homedir } from 'node:os';
+import { join } from 'node:path';
+
+export type NativeUltragoalBackend = 'off' | 'host' | 'local-experimental';
+
+export interface NativeUltragoalRuntimeConfig {
+ backend: NativeUltragoalBackend;
+ assignmentTtlSeconds: number;
+ source: 'default' | 'config' | 'env' | 'legacy-env';
+}
+
+interface NativeUltragoalConfigFile {
+ nativeUltragoal?: {
+ backend?: unknown;
+ assignmentTtlSeconds?: unknown;
+ };
+}
+
+const DEFAULT_ASSIGNMENT_TTL_SECONDS = 15 * 60;
+const MIN_ASSIGNMENT_TTL_SECONDS = 30;
+const MAX_ASSIGNMENT_TTL_SECONDS = 60 * 60;
+
+function normalizeBackend(value: unknown): NativeUltragoalBackend | null {
+ if (typeof value !== 'string') return null;
+ const normalized = value.trim().toLowerCase();
+ if (normalized === 'off' || normalized === 'host' || normalized === 'local-experimental') return normalized;
+ return null;
+}
+
+function normalizeAssignmentTtlSeconds(value: unknown): number | null {
+ if (typeof value !== 'number' || !Number.isInteger(value)) return null;
+ if (value < MIN_ASSIGNMENT_TTL_SECONDS || value > MAX_ASSIGNMENT_TTL_SECONDS) return null;
+ return value;
+}
+
+function readConfigFile(homeDir: string):
+ | { status: 'absent' }
+ | { status: 'invalid' }
+ | { status: 'valid'; value: NativeUltragoalConfigFile } {
+ const path = join(homeDir, '.omx', 'config.json');
+ if (!existsSync(path)) return { status: 'absent' };
+ try {
+ const parsed = JSON.parse(readFileSync(path, 'utf-8')) as unknown;
+ return parsed && typeof parsed === 'object' && !Array.isArray(parsed)
+ ? { status: 'valid', value: parsed as NativeUltragoalConfigFile }
+ : { status: 'invalid' };
+ } catch {
+ return { status: 'invalid' };
+ }
+}
+
+export function resolveNativeUltragoalConfig(options: {
+ homeDir?: string;
+ env?: NodeJS.ProcessEnv;
+} = {}): NativeUltragoalRuntimeConfig {
+ const env = options.env ?? process.env;
+ const configResult = readConfigFile(options.homeDir ?? homedir());
+ const config = configResult.status === 'valid' ? configResult.value : null;
+ const hasExplicitConfiguredBackend = config?.nativeUltragoal?.backend !== undefined;
+ const configuredBackend = normalizeBackend(config?.nativeUltragoal?.backend);
+ const assignmentTtlSeconds = normalizeAssignmentTtlSeconds(
+ config?.nativeUltragoal?.assignmentTtlSeconds,
+ ) ?? DEFAULT_ASSIGNMENT_TTL_SECONDS;
+ const rawEnvBackend = env.OMX_NATIVE_ULTRAGOAL_BACKEND;
+ const explicitEnvBackend = normalizeBackend(rawEnvBackend);
+ if (explicitEnvBackend) {
+ return {
+ backend: explicitEnvBackend,
+ assignmentTtlSeconds,
+ source: 'env',
+ };
+ }
+ if (typeof rawEnvBackend === 'string' && rawEnvBackend.trim() !== '') {
+ return {
+ backend: 'off',
+ assignmentTtlSeconds,
+ source: 'env',
+ };
+ }
+
+ if (configResult.status === 'invalid') {
+ return {
+ backend: 'off',
+ assignmentTtlSeconds,
+ source: 'config',
+ };
+ }
+
+ if (configuredBackend) {
+ return {
+ backend: configuredBackend,
+ assignmentTtlSeconds,
+ source: 'config',
+ };
+ }
+
+ if (hasExplicitConfiguredBackend) {
+ return {
+ backend: 'off',
+ assignmentTtlSeconds,
+ source: 'config',
+ };
+ }
+
+ if (String(env.OMX_NATIVE_SUBAGENT_ASSIGNMENTS ?? '').trim().toLowerCase() === 'on') {
+ return {
+ backend: 'local-experimental',
+ assignmentTtlSeconds,
+ source: 'legacy-env',
+ };
+ }
+
+ return {
+ backend: 'off',
+ assignmentTtlSeconds,
+ source: 'default',
+ };
+}
+
+export function nativeUltragoalBackendIsLocalExperimental(
+ options: Parameters<typeof resolveNativeUltragoalConfig>[0] = {},
+): boolean {
+ return resolveNativeUltragoalConfig(options).backend === 'local-experimental';
+}
diff --git a/src/scripts/__tests__/codex-native-assignment.test.ts b/src/scripts/__tests__/codex-native-assignment.test.ts
new file mode 100644
index 00000000..20c579dd
--- /dev/null
+++ b/src/scripts/__tests__/codex-native-assignment.test.ts
@@ -0,0 +1,461 @@
+import assert from "node:assert/strict";
+import { chmod, mkdir, mkdtemp, rm, symlink, writeFile } from "node:fs/promises";
+import { tmpdir } from "node:os";
+import { dirname, join, resolve } from "node:path";
+import { afterEach, beforeEach, describe, it } from "node:test";
+import { dispatchCodexNativeHook } from "../codex-native-hook.js";
+
+async function writeJson(path: string, value: unknown): Promise<void> {
+ await mkdir(dirname(path), { recursive: true });
+ await writeFile(path, `${JSON.stringify(value, null, 2)}\n`, "utf-8");
+}
+
+async function createActiveConductorFixture(phase = "executing"): Promise<{
+ cwd: string;
+ stateDir: string;
+ sessionId: string;
+ leaderThreadId: string;
+ childAgentId: string;
+}> {
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-assignment-"));
+ const stateDir = join(cwd, ".omx", "state");
+ const sessionId = "sess-native-assignment";
+ const leaderThreadId = "thread-native-assignment-leader";
+ const childAgentId = "agent-native-assignment-executor";
+ const now = new Date().toISOString();
+ const bootstrapGeneration = "bootstrap-generation-native-assignment";
+
+ await writeJson(join(stateDir, "session.json"), {
+ session_id: sessionId,
+ native_session_id: leaderThreadId,
+ cwd,
+ });
+ await writeJson(join(stateDir, "subagent-tracking.json"), {
+ schemaVersion: 1,
+ sessions: {
+ [sessionId]: {
+ session_id: sessionId,
+ leader_thread_id: leaderThreadId,
+ updated_at: now,
+ threads: {
+ [leaderThreadId]: {
+ thread_id: leaderThreadId,
+ kind: "leader",
+ first_seen_at: now,
+ last_seen_at: now,
+ turn_count: 1,
+ },
+ [childAgentId]: {
+ thread_id: childAgentId,
+ kind: "subagent",
+ mode: "executor",
+ status: "available",
+ provenance_kind: "native_subagent",
+ direct_child_parent_id: leaderThreadId,
+ direct_child_root_id: leaderThreadId,
+ leader_thread_id: leaderThreadId,
+ first_seen_at: now,
+ last_seen_at: now,
+ turn_count: 1,
+ },
+ },
+ },
+ },
+ });
+ await writeJson(join(stateDir, "sessions", sessionId, "skill-active-state.json"), {
+ active: true,
+ skill: "ultragoal",
+ phase,
+ session_id: sessionId,
+ active_skills: [
+ { skill: "ultragoal", phase, active: true, session_id: sessionId },
+ ],
+ });
+ await writeJson(join(stateDir, "sessions", sessionId, "ultragoal-state.json"), {
+ active: true,
+ mode: "ultragoal",
+ current_phase: phase,
+ session_id: sessionId,
+ });
+ await writeJson(join(stateDir, "sessions", sessionId, "native-ultragoal-bootstrap.json"), {
+ schema_version: 1,
+ kind: "native-ultragoal-bootstrap",
+ generation: bootstrapGeneration,
+ backend: "local-experimental",
+ status: "active",
+ session_id: sessionId,
+ root_thread_id: leaderThreadId,
+ child_agent_id: childAgentId,
+ created_at: now,
+ updated_at: now,
+ expires_at: new Date(Date.now() + 10 * 60_000).toISOString(),
+ });
+
+ return { cwd, stateDir, sessionId, leaderThreadId, childAgentId };
+}
+
+function preToolUse(
+ cwd: string,
+ sessionId: string,
+ identity: Record<string, unknown>,
+ toolName: string,
+ toolInput: Record<string, unknown>,
+) {
+ return dispatchCodexNativeHook({
+ hook_event_name: "PreToolUse",
+ cwd,
+ session_id: sessionId,
+ ...identity,
+ tool_name: toolName,
+ tool_input: toolInput,
+ }, { cwd });
+}
+
+describe("native Conductor assignment transport", () => {
+ const originalAssignmentOptIn = process.env.OMX_NATIVE_SUBAGENT_ASSIGNMENTS;
+
+ beforeEach(() => {
+ process.env.OMX_NATIVE_SUBAGENT_ASSIGNMENTS = "on";
+ });
+
+ afterEach(() => {
+ if (originalAssignmentOptIn === undefined) delete process.env.OMX_NATIVE_SUBAGENT_ASSIGNMENTS;
+ else process.env.OMX_NATIVE_SUBAGENT_ASSIGNMENTS = originalAssignmentOptIn;
+ });
+
+ it("requires typed tracker authority and rejects missing or conflicting role evidence", async () => {
+ const fixture = await createActiveConductorFixture();
+ const { cwd, stateDir, sessionId, leaderThreadId, childAgentId } = fixture;
+ const assignmentPath = join(
+ stateDir,
+ "sessions",
+ sessionId,
+ "native-assignments",
+ `${encodeURIComponent(childAgentId)}.json`,
+ );
+ const issuedAt = new Date();
+ const expiresAt = new Date(issuedAt.getTime() + 10 * 60_000);
+ const trackingPath = join(stateDir, "subagent-tracking.json");
+ const trackedChild = {
+ thread_id: childAgentId,
+ kind: "subagent",
+ leader_thread_id: leaderThreadId,
+ first_seen_at: issuedAt.toISOString(),
+ last_seen_at: issuedAt.toISOString(),
+ turn_count: 1,
+ };
+
+ try {
+ await writeJson(assignmentPath, {
+ schema_version: 1,
+ kind: "native-subagent-assignment",
+ lifecycle: "active",
+ root_session_id: sessionId,
+ root_thread_id: leaderThreadId,
+ child_agent_id: childAgentId,
+ agent_type: "executor",
+ allowed_actions: ["path-write"],
+ path_prefixes: ["src/assigned"],
+ issued_at: issuedAt.toISOString(),
+ expires_at: expiresAt.toISOString(),
+ bootstrap_generation: "bootstrap-generation-native-assignment",
+ });
+ await writeJson(trackingPath, {
+ schemaVersion: 1,
+ sessions: {
+ [sessionId]: {
+ session_id: sessionId,
+ leader_thread_id: leaderThreadId,
+ updated_at: issuedAt.toISOString(),
+ threads: {
+ [leaderThreadId]: { thread_id: leaderThreadId, kind: "leader" },
+ [childAgentId]: trackedChild,
+ },
+ },
+ },
+ });
+
+ const realTypedChild = await preToolUse(
+ cwd,
+ sessionId,
+ { agent_id: childAgentId, agent_type: "executor" },
+ "Write",
+ { file_path: "src/assigned/real-typed-child.txt", content: "ok\n" },
+ );
+ assert.equal(realTypedChild.outputJson?.decision, "block");
+ assert.match(String(realTypedChild.outputJson?.reason ?? ""), /OWNER_CONFIRMATION_REQUIRED/);
+
+ const missingTypedRole = await preToolUse(
+ cwd,
+ sessionId,
+ {
+ agent_id: childAgentId,
+ source: { subagent: { thread_spawn: { agent_role: "executor" } } },
+ },
+ "Write",
+ { file_path: "src/assigned/missing-role.txt", content: "must-not-write\n" },
+ );
+ assert.equal(missingTypedRole.outputJson?.decision, "block");
+ assert.match(String(missingTypedRole.outputJson?.reason ?? ""), /OWNER_CONFIRMATION_REQUIRED/);
+
+ const conflictingTypedAliases = await preToolUse(
+ cwd,
+ sessionId,
+ { agent_id: childAgentId, agent_role: "executor", agent_type: "writer" },
+ "Write",
+ { file_path: "src/assigned/conflicting-aliases.txt", content: "must-not-write\n" },
+ );
+ assert.equal(conflictingTypedAliases.outputJson?.decision, "block");
+ assert.match(String(conflictingTypedAliases.outputJson?.reason ?? ""), /OWNER_CONFIRMATION_REQUIRED/);
+
+ await writeJson(trackingPath, {
+ schemaVersion: 1,
+ sessions: {
+ [sessionId]: {
+ session_id: sessionId,
+ leader_thread_id: leaderThreadId,
+ updated_at: issuedAt.toISOString(),
+ threads: {
+ [leaderThreadId]: { thread_id: leaderThreadId, kind: "leader" },
+ [childAgentId]: { ...trackedChild, mode: "writer" },
+ },
+ },
+ },
+ });
+ const conflictingTrackerRole = await preToolUse(
+ cwd,
+ sessionId,
+ { agent_id: childAgentId, agent_role: "executor" },
+ "Write",
+ { file_path: "src/assigned/conflicting-role.txt", content: "must-not-write\n" },
+ );
+ assert.equal(conflictingTrackerRole.outputJson?.decision, "block");
+ assert.match(String(conflictingTrackerRole.outputJson?.reason ?? ""), /OWNER_CONFIRMATION_REQUIRED/);
+ } finally {
+ await rm(cwd, { recursive: true, force: true });
+ }
+ });
+
+ it("allows only an exact live typed-child path grant and keeps all negative contracts fail-closed", async () => {
+ const fixture = await createActiveConductorFixture();
+ const { cwd, stateDir, sessionId, leaderThreadId, childAgentId } = fixture;
+ const assignmentPath = join(
+ stateDir,
+ "sessions",
+ sessionId,
+ "native-assignments",
+ `${encodeURIComponent(childAgentId)}.json`,
+ );
+ const issuedAt = new Date();
+ const expiresAt = new Date(issuedAt.getTime() + 10 * 60_000);
+
+ try {
+ await writeJson(assignmentPath, {
+ schema_version: 1,
+ kind: "native-subagent-assignment",
+ lifecycle: "active",
+ root_session_id: sessionId,
+ root_thread_id: leaderThreadId,
+ child_agent_id: childAgentId,
+ agent_type: "executor",
+ allowed_actions: ["path-write"],
+ path_prefixes: ["src/assigned"],
+ issued_at: issuedAt.toISOString(),
+ expires_at: expiresAt.toISOString(),
+ bootstrap_generation: "bootstrap-generation-native-assignment",
+ });
+
+ const exactChild = { agent_id: childAgentId, agent_role: "executor" };
+ const allowed = await preToolUse(
+ cwd,
+ sessionId,
+ exactChild,
+ "Write",
+ { file_path: "src/assigned/result.txt", content: "ok\n" },
+ );
+ assert.equal(allowed.outputJson, null);
+
+ for (const [name, identity, filePath] of [
+ ["outside-scope", exactChild, "src/outside.txt"],
+ ["assignment-self-mutation", exactChild, assignmentPath],
+ ["foreign-child", { agent_id: "agent-native-assignment-foreign", agent_role: "executor" }, "src/assigned/result.txt"],
+ ["role-mismatch", { agent_id: childAgentId, agent_role: "writer" }, "src/assigned/result.txt"],
+ ["ungranted-writer", { agent_id: "agent-native-assignment-writer", agent_role: "writer" }, "src/assigned/result.txt"],
+ ] as const) {
+ const denied = await preToolUse(
+ cwd,
+ sessionId,
+ identity,
+ "Write",
+ { file_path: filePath, content: `${name}\n` },
+ );
+ assert.equal(denied.outputJson?.decision, "block", name);
+ assert.match(String(denied.outputJson?.reason ?? ""), /OWNER_CONFIRMATION_REQUIRED/, name);
+ }
+
+ await writeJson(assignmentPath, {
+ schema_version: 1,
+ kind: "native-subagent-assignment",
+ lifecycle: "active",
+ root_session_id: "foreign-session",
+ root_thread_id: leaderThreadId,
+ child_agent_id: childAgentId,
+ agent_type: "executor",
+ allowed_actions: ["path-write"],
+ path_prefixes: ["src/assigned"],
+ issued_at: issuedAt.toISOString(),
+ expires_at: expiresAt.toISOString(),
+ bootstrap_generation: "bootstrap-generation-native-assignment",
+ unexpected_scope_expansion: true,
+ });
+ const malformed = await preToolUse(
+ cwd,
+ sessionId,
+ exactChild,
+ "Write",
+ { file_path: "src/assigned/malformed.txt", content: "malformed\n" },
+ );
+ assert.equal(malformed.outputJson?.decision, "block");
+ assert.match(String(malformed.outputJson?.reason ?? ""), /OWNER_CONFIRMATION_REQUIRED/);
+
+ await mkdir(join(cwd, "src", "assigned"), { recursive: true });
+ const escapedTarget = await mkdtemp(join(tmpdir(), "omx-native-assignment-escape-"));
+ await symlink(escapedTarget, join(cwd, "src", "assigned", "link"));
+ await writeJson(assignmentPath, {
+ schema_version: 1,
+ kind: "native-subagent-assignment",
+ lifecycle: "active",
+ root_session_id: sessionId,
+ root_thread_id: leaderThreadId,
+ child_agent_id: childAgentId,
+ agent_type: "executor",
+ allowed_actions: ["path-write", "bash-write"],
+ path_prefixes: ["src/assigned"],
+ issued_at: issuedAt.toISOString(),
+ expires_at: expiresAt.toISOString(),
+ bootstrap_generation: "bootstrap-generation-native-assignment",
+ });
+ const allowedBash = await preToolUse(
+ cwd,
+ sessionId,
+ exactChild,
+ "Bash",
+ { command: "printf ok > src/assigned/bash.txt" },
+ );
+ assert.equal(allowedBash.outputJson, null);
+ for (const [name, command] of [
+ ["bash-outside-scope", "printf no > src/outside-bash.txt"],
+ ["bash-symlink-escape", "printf no > src/assigned/link/escaped.txt"],
+ ["bash-substitution-poison", "printf \"$(printf no)\" > src/assigned/poison.txt"],
+ ] as const) {
+ const denied = await preToolUse(cwd, sessionId, exactChild, "Bash", { command });
+ assert.equal(denied.outputJson?.decision, "block", name);
+ assert.match(String(denied.outputJson?.reason ?? ""), /OWNER_CONFIRMATION_REQUIRED/, name);
+ }
+ await rm(escapedTarget, { recursive: true, force: true });
+
+ await writeJson(assignmentPath, {
+ schema_version: 1,
+ kind: "native-subagent-assignment",
+ lifecycle: "active",
+ root_session_id: sessionId,
+ root_thread_id: leaderThreadId,
+ child_agent_id: childAgentId,
+ agent_type: "executor",
+ allowed_actions: ["path-write"],
+ path_prefixes: ["src/assigned"],
+ issued_at: new Date(issuedAt.getTime() - 20 * 60_000).toISOString(),
+ expires_at: new Date(issuedAt.getTime() - 10 * 60_000).toISOString(),
+ });
+ const stale = await preToolUse(
+ cwd,
+ sessionId,
+ exactChild,
+ "Write",
+ { file_path: "src/assigned/stale.txt", content: "stale\n" },
+ );
+ assert.equal(stale.outputJson?.decision, "block");
+ assert.match(String(stale.outputJson?.reason ?? ""), /OWNER_CONFIRMATION_REQUIRED/);
+
+ await writeJson(assignmentPath, {
+ schema_version: 1,
+ kind: "native-subagent-assignment",
+ lifecycle: "active",
+ root_session_id: sessionId,
+ root_thread_id: leaderThreadId,
+ child_agent_id: childAgentId,
+ agent_type: "executor",
+ allowed_actions: ["path-write", "bash-write"],
+ path_prefixes: ["."],
+ issued_at: issuedAt.toISOString(),
+ expires_at: expiresAt.toISOString(),
+ bootstrap_generation: "bootstrap-generation-native-assignment",
+ });
+ for (const [name, toolName, toolInput] of [
+ ["git-path", "Write", { file_path: ".git/config", content: "must-not-write\n" }],
+ ["omx-goal-path", "Write", { file_path: ".omx/ultragoal/goals.json", content: "{}\n" }],
+ ["git-bash", "Bash", { command: "printf no > .git/config" }],
+ ["omx-goal-bash", "Bash", { command: "printf no > .omx/ultragoal/goals.json" }],
+ ] as const) {
+ const denied = await preToolUse(cwd, sessionId, exactChild, toolName, toolInput);
+ assert.equal(denied.outputJson?.decision, "block", name);
+ assert.match(String(denied.outputJson?.reason ?? ""), /OWNER_CONFIRMATION_REQUIRED/, name);
+ }
+
+ await writeJson(assignmentPath, {
+ schema_version: 1,
+ kind: "native-subagent-assignment",
+ lifecycle: "active",
+ root_session_id: sessionId,
+ root_thread_id: leaderThreadId,
+ child_agent_id: childAgentId,
+ agent_type: "executor",
+ allowed_actions: ["path-write"],
+ path_prefixes: ["src/assigned"],
+ issued_at: issuedAt.toISOString(),
+ expires_at: expiresAt.toISOString(),
+ });
+ await chmod(assignmentPath, 0o666);
+ const writableByOthers = await preToolUse(
+ cwd,
+ sessionId,
+ exactChild,
+ "Write",
+ { file_path: "src/assigned/world-writable-grant.txt", content: "must-not-write\n" },
+ );
+ assert.equal(writableByOthers.outputJson?.decision, "block");
+ assert.match(String(writableByOthers.outputJson?.reason ?? ""), /OWNER_CONFIRMATION_REQUIRED/);
+ } finally {
+ await rm(cwd, { recursive: true, force: true });
+ }
+ });
+
+ it("allows only Main-root to issue an assignment in the exact active session scope", async () => {
+ const fixture = await createActiveConductorFixture();
+ const { cwd, sessionId, leaderThreadId } = fixture;
+
+ try {
+ const root = { agent_id: leaderThreadId, thread_id: leaderThreadId };
+
+ const rootAssignment = await preToolUse(cwd, sessionId, root, "Write", {
+ file_path: `.omx/state/sessions/${sessionId}/native-assignments/root-created.json`,
+ content: "{}\n",
+ });
+ assert.equal(rootAssignment.outputJson, null, "root-assignment-create");
+ const foreignSessionAssignment = await preToolUse(cwd, sessionId, root, "Write", {
+ file_path: ".omx/state/sessions/foreign-session/native-assignments/root-created.json",
+ content: "{}\n",
+ });
+ assert.equal(foreignSessionAssignment.outputJson?.decision, "block", "foreign-session-assignment");
+ const protectedGate = await preToolUse(cwd, sessionId, root, "Write", {
+ file_path: `.omx/state/sessions/${sessionId}/ultragoal-state.json`,
+ content: "{}\n",
+ });
+ assert.equal(protectedGate.outputJson?.decision, "block", "protected-state-gate");
+
+ } finally {
+ await rm(cwd, { recursive: true, force: true });
+ }
+ });
+
+});
diff --git a/src/scripts/__tests__/issue-3311-ultragoal-native-outside-tmux.test.ts b/src/scripts/__tests__/issue-3311-ultragoal-native-outside-tmux.test.ts
index bc832ed9..feb42459 100644
--- a/src/scripts/__tests__/issue-3311-ultragoal-native-outside-tmux.test.ts
+++ b/src/scripts/__tests__/issue-3311-ultragoal-native-outside-tmux.test.ts
@@ -5,14 +5,19 @@ import { tmpdir } from "node:os";
import { dirname, join } from "node:path";
import { afterEach, describe, it } from "node:test";
import { dispatchCodexNativeHook } from "../codex-native-hook.js";
+import {
+ issueLocalNativeExecutorAssignment,
+ readNativeUltragoalBootstrap,
+ revokeLocalNativeExecutorAssignment,
+} from "../../ultragoal/native-bootstrap.js";
// Regression coverage for OMX #3311: on native Codex App / native-hook
// surfaces outside tmux, standalone Ultragoal must not activate an
// execution-blocking Main-root Conductor state when no authorized executor
-// will ever be reachable (Team is tmux-only; native child/descendant
-// provenance intentionally grants no write authority per #3127). The guard
-// under test refuses the *activation* write itself; it must never affect
-// already-active sessions, non-ultragoal modes, non-native launchers, or
+// will ever be reachable. Team is tmux-only; native child/descendant provenance
+// grants no write authority unless the root issues an exact scoped assignment.
+// The guard under test refuses the *activation* write itself; it must never
+// affect already-active sessions, non-ultragoal modes, non-native launchers, or
// attached-tmux transport.
async function writeJson(path: string, value: unknown): Promise<void> {
@@ -35,6 +40,8 @@ async function writeLeaderSessionFixture(
await writeJson(join(stateDir, "session.json"), {
session_id: sessionId,
native_session_id: leaderThreadId,
+ owner_codex_session_id: sessionId,
+ target_session_id: sessionId,
cwd,
});
await writeJson(join(stateDir, "subagent-tracking.json"), {
@@ -53,10 +60,13 @@ async function writeLeaderSessionFixture(
describe("issue-3311: standalone Ultragoal native-App outside-tmux activation guard", () => {
const originalTmux = process.env.TMUX;
+ const originalAssignmentOptIn = process.env.OMX_NATIVE_SUBAGENT_ASSIGNMENTS;
afterEach(() => {
if (originalTmux === undefined) delete process.env.TMUX;
else process.env.TMUX = originalTmux;
+ if (originalAssignmentOptIn === undefined) delete process.env.OMX_NATIVE_SUBAGENT_ASSIGNMENTS;
+ else process.env.OMX_NATIVE_SUBAGENT_ASSIGNMENTS = originalAssignmentOptIn;
});
it("blocks fresh standalone-ultragoal Conductor activation on native App outside tmux (Bash state write)", async () => {
@@ -88,8 +98,71 @@ describe("issue-3311: standalone Ultragoal native-App outside-tmux activation gu
(result.outputJson as { hookSpecificOutput?: { additionalContext?: string } } | null)
?.hookSpecificOutput?.additionalContext || "",
);
- assert.match(context, /native child\/descendant provenance does not grant write authority/);
- assert.doesNotMatch(context, /write-assignment|assignment-backed|scoped native .*grant/i);
+ assert.match(context, /typed native spawn surface backed by scoped write assignments/);
+ } finally {
+ await rm(cwd, { recursive: true, force: true });
+ }
+ });
+
+ it("keeps fresh activation inactive until the advertised executor is authorized", async () => {
+ delete process.env.TMUX;
+ process.env.OMX_NATIVE_SUBAGENT_ASSIGNMENTS = "on";
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-3319-supported-bash-"));
+ try {
+ const stateDir = join(cwd, ".omx", "state");
+ const sessionId = "sess-3319-supported-bash";
+ const leaderThreadId = "thread-3319-supported-bash";
+ await writeLeaderSessionFixture(stateDir, sessionId, leaderThreadId, cwd);
+
+ const result = await dispatchCodexNativeHook(
+ {
+ hook_event_name: "PreToolUse",
+ cwd,
+ session_id: sessionId,
+ thread_id: leaderThreadId,
+ agent_id: leaderThreadId,
+ source: "native",
+ available_tools: ["collaboration.spawn_agent"],
+ tool_name: "Bash",
+ tool_input: { command: `omx state write --input '${ACTIVATION_INPUT}' --json` },
+ },
+ { cwd },
+ );
+
+ assert.equal(result.outputJson?.decision, "block");
+ assert.match(String(result.outputJson?.reason ?? ""), /OMX-ULTRAGOAL-BOOTSTRAP-REQUIRED/);
+ } finally {
+ await rm(cwd, { recursive: true, force: true });
+ }
+ });
+
+ it("keeps fresh activation blocked when native subagents are advertised without typed role routing", async () => {
+ delete process.env.TMUX;
+ process.env.OMX_NATIVE_SUBAGENT_ASSIGNMENTS = "on";
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-3319-untyped-bash-"));
+ try {
+ const stateDir = join(cwd, ".omx", "state");
+ const sessionId = "sess-3319-untyped-bash";
+ const leaderThreadId = "thread-3319-untyped-bash";
+ await writeLeaderSessionFixture(stateDir, sessionId, leaderThreadId, cwd);
+
+ const result = await dispatchCodexNativeHook(
+ {
+ hook_event_name: "PreToolUse",
+ cwd,
+ session_id: sessionId,
+ thread_id: leaderThreadId,
+ agent_id: leaderThreadId,
+ source: "native",
+ capabilities: { native_subagents: true },
+ tool_name: "Bash",
+ tool_input: { command: `omx state write --input '${ACTIVATION_INPUT}' --json` },
+ },
+ { cwd },
+ );
+
+ assert.equal(result.outputJson?.decision, "block");
+ assert.match(String(result.outputJson?.reason ?? ""), /OMX-ULTRAGOAL-(?:NO-OWNER|BOOTSTRAP-REQUIRED)/);
} finally {
await rm(cwd, { recursive: true, force: true });
}
@@ -124,8 +197,7 @@ describe("issue-3311: standalone Ultragoal native-App outside-tmux activation gu
(result.outputJson as { hookSpecificOutput?: { additionalContext?: string } } | null)
?.hookSpecificOutput?.additionalContext || "",
);
- assert.match(context, /native child\/descendant provenance does not grant write authority/);
- assert.doesNotMatch(context, /write-assignment|assignment-backed|scoped native .*grant/i);
+ assert.match(context, /typed native spawn surface backed by scoped write assignments/);
} finally {
await rm(cwd, { recursive: true, force: true });
}
@@ -163,8 +235,7 @@ describe("issue-3311: standalone Ultragoal native-App outside-tmux activation gu
(result.outputJson as { hookSpecificOutput?: { additionalContext?: string } } | null)
?.hookSpecificOutput?.additionalContext || "",
);
- assert.match(context, /native child\/descendant provenance does not grant write authority/);
- assert.doesNotMatch(context, /write-assignment|assignment-backed|scoped native .*grant/i);
+ assert.match(context, /typed native spawn surface backed by scoped write assignments/);
} finally {
await rm(cwd, { recursive: true, force: true });
}
@@ -336,6 +407,129 @@ describe("issue-3311: standalone Ultragoal native-App outside-tmux activation gu
}
});
+ it("does not let a tracked native child authorize its own bootstrap assignment", async () => {
+ delete process.env.TMUX;
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-bootstrap-self-auth-"));
+ try {
+ const stateDir = join(cwd, ".omx", "state");
+ const sessionId = "sess-bootstrap-self-auth";
+ const leaderThreadId = "thread-bootstrap-self-auth-root";
+ const childThreadId = "thread-bootstrap-self-auth-child";
+ await writeLeaderSessionFixture(stateDir, sessionId, leaderThreadId, cwd);
+ await writeJson(join(stateDir, "subagent-tracking.json"), {
+ schemaVersion: 1,
+ sessions: {
+ [sessionId]: {
+ session_id: sessionId,
+ leader_thread_id: leaderThreadId,
+ threads: {
+ [leaderThreadId]: { thread_id: leaderThreadId, kind: "leader" },
+ [childThreadId]: {
+ thread_id: childThreadId,
+ kind: "subagent",
+ mode: "executor",
+ status: "available",
+ provenance_kind: "native_subagent",
+ direct_child_parent_id: leaderThreadId,
+ direct_child_root_id: leaderThreadId,
+ },
+ },
+ },
+ },
+ });
+
+ const result = await dispatchCodexNativeHook(
+ {
+ hook_event_name: "PreToolUse",
+ cwd,
+ session_id: sessionId,
+ thread_id: childThreadId,
+ agent_id: childThreadId,
+ agent_type: "executor",
+ source: "native",
+ tool_name: "Bash",
+ tool_input: {
+ command: `omx ultragoal native-bootstrap authorize --session-id ${sessionId} --root-thread-id ${leaderThreadId} --child-id ${childThreadId} --path-prefix src`,
+ },
+ },
+ { cwd },
+ );
+
+ assert.equal(result.outputJson?.decision, "block");
+ assert.match(String(result.outputJson?.reason ?? ""), /OWNER_CONFIRMATION_REQUIRED/);
+ assert.match(String(result.outputJson?.reason ?? ""), /root-owned/);
+ } finally {
+ await rm(cwd, { recursive: true, force: true });
+ }
+ });
+
+ it("keeps the spawned executor read-only while the bootstrap is awaiting authorization", async () => {
+ delete process.env.TMUX;
+ process.env.OMX_NATIVE_SUBAGENT_ASSIGNMENTS = "on";
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-bootstrap-pending-child-"));
+ try {
+ const stateDir = join(cwd, ".omx", "state");
+ const sessionId = "sess-bootstrap-pending-child";
+ const leaderThreadId = "thread-bootstrap-pending-root";
+ const childThreadId = "thread-bootstrap-pending-child";
+ await writeLeaderSessionFixture(stateDir, sessionId, leaderThreadId, cwd);
+ await dispatchCodexNativeHook(
+ {
+ hook_event_name: "UserPromptSubmit",
+ cwd,
+ session_id: sessionId,
+ thread_id: leaderThreadId,
+ source: "native",
+ available_tools: ["collaboration.spawn_agent"],
+ prompt: "$ultragoal execute this plan",
+ },
+ { cwd },
+ );
+ await writeJson(join(stateDir, "subagent-tracking.json"), {
+ schemaVersion: 1,
+ sessions: {
+ [sessionId]: {
+ session_id: sessionId,
+ leader_thread_id: leaderThreadId,
+ threads: {
+ [leaderThreadId]: { thread_id: leaderThreadId, kind: "leader" },
+ [childThreadId]: {
+ thread_id: childThreadId,
+ kind: "subagent",
+ mode: "executor",
+ status: "available",
+ provenance_kind: "native_subagent",
+ direct_child_parent_id: leaderThreadId,
+ direct_child_root_id: leaderThreadId,
+ },
+ },
+ },
+ },
+ });
+
+ const result = await dispatchCodexNativeHook(
+ {
+ hook_event_name: "PreToolUse",
+ cwd,
+ session_id: sessionId,
+ thread_id: childThreadId,
+ agent_id: childThreadId,
+ agent_type: "executor",
+ source: "native",
+ tool_name: "Write",
+ tool_input: { file_path: join(cwd, "src", "pending-write.ts"), content: "blocked" },
+ },
+ { cwd },
+ );
+
+ assert.equal(result.outputJson?.decision, "block");
+ assert.match(String(result.outputJson?.reason ?? ""), /bootstrap is not active/);
+ assert.match(String(result.outputJson?.reason ?? ""), /remain read-only/);
+ } finally {
+ await rm(cwd, { recursive: true, force: true });
+ }
+ });
+
it("does not block autopilot-supervised ultragoal activation (mode is autopilot, not standalone ultragoal)", async () => {
delete process.env.TMUX;
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-3311-autopilot-"));
@@ -427,6 +621,271 @@ describe("issue-3311: standalone Ultragoal native-App outside-tmux activation gu
}
});
+ it("keeps '$ultragoal' prompt activation inactive until the advertised executor is authorized", async () => {
+ delete process.env.TMUX;
+ process.env.OMX_NATIVE_SUBAGENT_ASSIGNMENTS = "on";
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-3319-supported-prompt-"));
+ try {
+ await mkdir(join(cwd, ".omx", "state"), { recursive: true });
+ const result = await dispatchCodexNativeHook(
+ {
+ hook_event_name: "UserPromptSubmit",
+ cwd,
+ session_id: "sess-3319-supported-prompt",
+ thread_id: "thread-3319-supported-prompt",
+ turn_id: "turn-3319-supported-prompt",
+ source: "native",
+ available_tools: ["collaboration.spawn_agent"],
+ prompt: "$ultragoal split this launch into durable goals",
+ },
+ { cwd },
+ );
+
+ assert.notEqual(result.skillState?.initialized_mode, "ultragoal");
+ assert.match(String(result.skillState?.transition_error ?? result.outputJson?.reason ?? ""), /BOOTSTRAP|inactive|authorization/i);
+ assert.equal(
+ existsSync(join(cwd, ".omx", "state", "sessions", "sess-3319-supported-prompt", "ultragoal-state.json")),
+ false,
+ );
+ } finally {
+ await rm(cwd, { recursive: true, force: true });
+ }
+ });
+
+ it("completes prompt bootstrap through typed assignment, activation, and scoped executor write", async () => {
+ delete process.env.TMUX;
+ process.env.OMX_NATIVE_SUBAGENT_ASSIGNMENTS = "on";
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-bootstrap-e2e-"));
+ try {
+ const stateDir = join(cwd, ".omx", "state");
+ const sessionId = "sess-bootstrap-e2e";
+ const rootThreadId = "thread-bootstrap-e2e-root";
+ const childThreadId = "thread-bootstrap-e2e-child";
+ await writeLeaderSessionFixture(stateDir, sessionId, rootThreadId, cwd);
+ const firstPrompt = await dispatchCodexNativeHook(
+ {
+ hook_event_name: "UserPromptSubmit",
+ cwd,
+ session_id: sessionId,
+ thread_id: rootThreadId,
+ source: "native",
+ available_tools: ["collaboration.spawn_agent"],
+ prompt: "$ultragoal execute the durable plan",
+ },
+ { cwd },
+ );
+ assert.equal(firstPrompt.skillState?.active, false);
+ const bootstrap = await readNativeUltragoalBootstrap(stateDir, sessionId);
+ assert.ok(bootstrap);
+
+ await writeJson(join(stateDir, "subagent-tracking.json"), {
+ schemaVersion: 1,
+ sessions: {
+ [sessionId]: {
+ session_id: sessionId,
+ leader_thread_id: rootThreadId,
+ threads: {
+ [rootThreadId]: { thread_id: rootThreadId, kind: "leader" },
+ [childThreadId]: {
+ thread_id: childThreadId,
+ kind: "subagent",
+ mode: "executor",
+ status: "available",
+ provenance_kind: "native_subagent",
+ direct_child_parent_id: rootThreadId,
+ direct_child_root_id: rootThreadId,
+ },
+ },
+ },
+ },
+ });
+ await issueLocalNativeExecutorAssignment({
+ cwd,
+ stateDir,
+ sessionId,
+ rootThreadId,
+ childAgentId: childThreadId,
+ expectedGeneration: bootstrap.generation,
+ pathPrefixes: ["src/native-flow"],
+ ttlSeconds: 300,
+ });
+
+ const activated = await dispatchCodexNativeHook(
+ {
+ hook_event_name: "UserPromptSubmit",
+ cwd,
+ session_id: sessionId,
+ thread_id: rootThreadId,
+ source: "native",
+ available_tools: ["collaboration.spawn_agent"],
+ prompt: "$ultragoal execute the durable plan",
+ },
+ { cwd },
+ );
+ assert.equal(activated.skillState?.active, true);
+ assert.equal(activated.skillState?.initialized_mode, "ultragoal");
+
+ const write = await dispatchCodexNativeHook(
+ {
+ hook_event_name: "PreToolUse",
+ cwd,
+ session_id: sessionId,
+ thread_id: childThreadId,
+ agent_id: childThreadId,
+ agent_type: "executor",
+ source: "native",
+ tool_name: "Write",
+ tool_input: { file_path: join(cwd, "src", "native-flow", "result.ts"), content: "ok" },
+ },
+ { cwd },
+ );
+ assert.equal(write.outputJson, null);
+
+ await writeJson(join(stateDir, "sessions", sessionId, "ultragoal-state.json"), {
+ mode: "ultragoal",
+ active: false,
+ current_phase: "complete",
+ session_id: sessionId,
+ });
+ const terminalWrite = await dispatchCodexNativeHook(
+ {
+ hook_event_name: "PreToolUse",
+ cwd,
+ session_id: sessionId,
+ thread_id: childThreadId,
+ agent_id: childThreadId,
+ agent_type: "executor",
+ source: "native",
+ tool_name: "Write",
+ tool_input: { file_path: join(cwd, "src", "native-flow", "late.ts"), content: "no" },
+ },
+ { cwd },
+ );
+ assert.equal(terminalWrite.outputJson?.decision, "block");
+ assert.equal((await readNativeUltragoalBootstrap(stateDir, sessionId))?.status, "revoked");
+ await dispatchCodexNativeHook(
+ {
+ hook_event_name: "Stop",
+ cwd,
+ session_id: sessionId,
+ thread_id: rootThreadId,
+ source: "native",
+ },
+ { cwd },
+ );
+ assert.equal((await readNativeUltragoalBootstrap(stateDir, sessionId))?.status, "revoked");
+ } finally {
+ await rm(cwd, { recursive: true, force: true });
+ }
+ });
+
+ it("keeps the executor read-only until successful activation PostToolUse", async () => {
+ delete process.env.TMUX;
+ process.env.OMX_NATIVE_SUBAGENT_ASSIGNMENTS = "on";
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-bootstrap-two-phase-"));
+ try {
+ const stateDir = join(cwd, ".omx", "state");
+ const sessionId = "sess-bootstrap-two-phase";
+ const rootThreadId = "thread-bootstrap-two-phase-root";
+ const childThreadId = "thread-bootstrap-two-phase-child";
+ await writeLeaderSessionFixture(stateDir, sessionId, rootThreadId, cwd);
+ const activationPayload = {
+ cwd,
+ session_id: sessionId,
+ thread_id: rootThreadId,
+ agent_id: rootThreadId,
+ source: "native",
+ available_tools: ["collaboration.spawn_agent"],
+ tool_name: "Bash",
+ tool_input: { command: `omx state write --input '${ACTIVATION_INPUT}' --json` },
+ };
+ await dispatchCodexNativeHook({ hook_event_name: "PreToolUse", ...activationPayload }, { cwd });
+ const bootstrap = await readNativeUltragoalBootstrap(stateDir, sessionId);
+ assert.ok(bootstrap);
+ await writeJson(join(stateDir, "subagent-tracking.json"), {
+ schemaVersion: 1,
+ sessions: {
+ [sessionId]: {
+ session_id: sessionId,
+ leader_thread_id: rootThreadId,
+ threads: {
+ [rootThreadId]: { thread_id: rootThreadId, kind: "leader" },
+ [childThreadId]: {
+ thread_id: childThreadId,
+ kind: "subagent",
+ mode: "executor",
+ status: "available",
+ provenance_kind: "native_subagent",
+ direct_child_parent_id: rootThreadId,
+ direct_child_root_id: rootThreadId,
+ },
+ },
+ },
+ },
+ });
+ await issueLocalNativeExecutorAssignment({
+ cwd,
+ stateDir,
+ sessionId,
+ rootThreadId,
+ childAgentId: childThreadId,
+ expectedGeneration: bootstrap.generation,
+ pathPrefixes: ["src/native-flow"],
+ ttlSeconds: 300,
+ });
+
+ const prepared = await dispatchCodexNativeHook(
+ { hook_event_name: "PreToolUse", ...activationPayload },
+ { cwd },
+ );
+ assert.equal(prepared.outputJson, null);
+ assert.equal((await readNativeUltragoalBootstrap(stateDir, sessionId))?.status, "activating");
+ const prematureWrite = await dispatchCodexNativeHook({
+ hook_event_name: "PreToolUse",
+ cwd,
+ session_id: sessionId,
+ thread_id: childThreadId,
+ agent_id: childThreadId,
+ agent_type: "executor",
+ source: "native",
+ tool_name: "Write",
+ tool_input: { file_path: join(cwd, "src", "native-flow", "premature.ts"), content: "no" },
+ }, { cwd });
+ assert.equal(prematureWrite.outputJson?.decision, "block");
+
+ await writeJson(join(stateDir, "sessions", sessionId, "ultragoal-state.json"), {
+ mode: "ultragoal",
+ active: true,
+ current_phase: "executing",
+ session_id: sessionId,
+ });
+ await dispatchCodexNativeHook({ hook_event_name: "PostToolUse", ...activationPayload }, { cwd });
+ assert.equal((await readNativeUltragoalBootstrap(stateDir, sessionId))?.status, "active");
+
+ await revokeLocalNativeExecutorAssignment({
+ stateDir,
+ sessionId,
+ reason: "activation_receipt_race",
+ });
+ await writeJson(join(stateDir, "sessions", sessionId, "ultragoal-state.json"), {
+ mode: "ultragoal",
+ active: true,
+ current_phase: "executing",
+ session_id: sessionId,
+ });
+ await dispatchCodexNativeHook({ hook_event_name: "PostToolUse", ...activationPayload }, { cwd });
+ const failedState = JSON.parse(readFileSync(
+ join(stateDir, "sessions", sessionId, "ultragoal-state.json"),
+ "utf-8",
+ )) as { active: boolean; current_phase: string; error?: string };
+ assert.equal(failedState.active, false);
+ assert.equal(failedState.current_phase, "failed");
+ assert.equal(failedState.error, "native_ultragoal_activation_receipt_invalid");
+ } finally {
+ await rm(cwd, { recursive: true, force: true });
+ }
+ });
+
it("allows the primary '$ultragoal' UserPromptSubmit activation when attached to tmux (Team is reachable)", async () => {
process.env.TMUX = "/tmp/tmux-3311-prompt,12345,0";
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-3311-prompt-tmux-"));
@@ -588,4 +1047,62 @@ describe("issue-3311: standalone Ultragoal native-App outside-tmux activation gu
await rm(cwd, { recursive: true, force: true });
}
});
+
+ it("keeps a completed standalone Ralplan to Ultragoal handoff inactive until executor authorization", async () => {
+ delete process.env.TMUX;
+ process.env.OMX_NATIVE_SUBAGENT_ASSIGNMENTS = "on";
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-ralplan-ultragoal-bootstrap-"));
+ try {
+ const stateDir = join(cwd, ".omx", "state");
+ const sessionId = "sess-ralplan-ultragoal-bootstrap";
+ const threadId = "thread-ralplan-ultragoal-bootstrap";
+ await writeLeaderSessionFixture(stateDir, sessionId, threadId, cwd);
+ await writeJson(join(stateDir, "sessions", sessionId, "skill-active-state.json"), {
+ active: false,
+ skill: "ralplan",
+ phase: "complete",
+ session_id: sessionId,
+ owner_codex_session_id: sessionId,
+ target_session_id: sessionId,
+ active_skills: [{
+ skill: "ralplan",
+ phase: "complete",
+ active: false,
+ session_id: sessionId,
+ owner_codex_session_id: sessionId,
+ }],
+ });
+ await writeJson(join(stateDir, "sessions", sessionId, "ralplan-state.json"), {
+ active: false,
+ mode: "ralplan",
+ current_phase: "complete",
+ session_id: sessionId,
+ owner_codex_session_id: sessionId,
+ target_session_id: sessionId,
+ });
+
+ const result = await dispatchCodexNativeHook(
+ {
+ hook_event_name: "UserPromptSubmit",
+ cwd,
+ session_id: sessionId,
+ thread_id: threadId,
+ source: "native",
+ available_tools: ["collaboration.spawn_agent"],
+ prompt: "$ultragoal execute the approved plan",
+ },
+ { cwd },
+ );
+
+ assert.equal(result.skillState?.active, false);
+ assert.equal(result.skillState?.skill, "ultragoal");
+ assert.match(String(result.skillState?.transition_error ?? ""), /OMX-ULTRAGOAL-BOOTSTRAP-REQUIRED/);
+ assert.equal(
+ existsSync(join(stateDir, "sessions", sessionId, "ultragoal-state.json")),
+ false,
+ );
+ } finally {
+ await rm(cwd, { recursive: true, force: true });
+ }
+ });
});
diff --git a/src/scripts/codex-native-hook.ts b/src/scripts/codex-native-hook.ts
index 8c74a5d4..a40aa6a8 100644
--- a/src/scripts/codex-native-hook.ts
+++ b/src/scripts/codex-native-hook.ts
@@ -97,6 +97,7 @@ import {
} from "../hooks/keyword-detector.js";
import { buildDeepInterviewConfigInstruction } from "../hooks/deep-interview-config-instruction.js";
import { readTeamModeConfig } from "../config/team-mode.js";
+import { resolveNativeUltragoalConfig } from "../config/native-ultragoal.js";
import {
detectNativeStopStallPattern,
loadAutoNudgeConfig,
@@ -165,6 +166,19 @@ import {
steerUltragoal,
type UltragoalSteeringProposal,
} from "../ultragoal/artifacts.js";
+import {
+ beginNativeUltragoalBootstrap,
+ DOCUMENTED_HOST_RECEIPT_UNAVAILABLE,
+ findReadyLocalNativeExecutorAssignment,
+ markNativeUltragoalBootstrapActive,
+ NATIVE_ASSIGNMENT_DIRECTORY,
+ nativeExecutorAssignmentFileIsSafe,
+ parseActiveLocalNativeExecutorAssignment,
+ prepareNativeUltragoalBootstrapActivation,
+ readNativeUltragoalBootstrap,
+ reconcileLocalNativeExecutorAssignments,
+ revokeLocalNativeExecutorAssignment,
+} from "../ultragoal/native-bootstrap.js";
import { triagePrompt } from "../hooks/triage-heuristic.js";
import { readTriageConfig } from "../hooks/triage-config.js";
import {
@@ -2661,6 +2675,28 @@ function buildNativeOutsideTmuxTeamPromptBlockState(
// of an already-active standalone Ultragoal session) are left untouched, so
// resumption, prior-plan continuation, and non-standalone Ultragoal remain
// exactly as before.
+function nativeSubagentAssignmentsOptedIn(): boolean {
+ return resolveNativeUltragoalConfig().backend === "local-experimental";
+}
+
+function payloadAdvertisesTypedNativeSpawn(payload: CodexHookPayload): boolean {
+ const capabilities = safeObject(payload.omx_runtime_capabilities ?? payload.capabilities);
+ const nativeSubagents = capabilities?.native_subagents ?? capabilities?.nativeSubagents;
+ const multiAgent = capabilities?.multi_agent_v1 ?? capabilities?.multiAgentV1;
+ const roleRouting = capabilities?.role_routing ?? capabilities?.roleRouting;
+ if (roleRouting === true && (nativeSubagents === true || multiAgent === true)) return true;
+
+ const availableTools = payload.available_tools ?? payload.availableTools ?? payload.tools;
+ if (!Array.isArray(availableTools)) return false;
+ return availableTools.some((tool) => {
+ const record = safeObject(tool);
+ const name = typeof tool === "string"
+ ? tool
+ : safeString(record?.name ?? record?.tool_name ?? record?.toolName).trim();
+ return isNativeSubagentSpawnToolName(name);
+ });
+}
+
async function buildNativeOutsideTmuxUltragoalPromptBlockState(
classification: KeywordInputClassification,
cwd: string,
@@ -2686,12 +2722,85 @@ async function buildNativeOutsideTmuxUltragoalPromptBlockState(
// planning guards). Fall through unchanged to recordSkillActivation's own
// transition/continuation/supervision logic.
const canonicalState = await readVisibleSkillActiveStateForStateDir(stateDir, sessionId);
- const hasAnyActiveTrackedSkill = canonicalState
- ? listActiveSkills(canonicalState).some((entry) => (
+ const activeTrackedSkills = canonicalState
+ ? listActiveSkills(canonicalState).filter((entry) => (
matchesSkillStopContext(entry, canonicalState, sessionId, threadId ?? "")
))
- : false;
- if (hasAnyActiveTrackedSkill) return null;
+ : [];
+ if (activeTrackedSkills.length > 0) return null;
+
+ const rootThreadId = safeString(threadId ?? readPayloadThreadId(payload)).trim();
+ const nativeConfig = resolveNativeUltragoalConfig();
+ const nativeSupport = resolveNativeSubagentSupportStatus({
+ payload,
+ persistedSupportBlocker: await readJsonIfExists(nativeSubagentSupportBlockerPath(stateDir)),
+ persistedRoleRoutingMarker: readRoleRoutingMarker(stateDir, { cwd, sessionId }),
+ persistedCapacityBlocker: await readJsonIfExists(nativeSubagentCapacityBlockerPath(stateDir)),
+ cwd,
+ sessionId,
+ });
+ if (nativeConfig.backend === "local-experimental" && rootThreadId) {
+ const ready = await reconcileLocalNativeExecutorAssignments({
+ cwd,
+ stateDir,
+ sessionId,
+ rootThreadId,
+ });
+ if (ready.ready && ready.childAgentId) return null;
+ if (nativeSupport.status === "supported" && payloadAdvertisesTypedNativeSpawn(payload)) {
+ const bootstrap = await beginNativeUltragoalBootstrap({
+ stateDir,
+ sessionId,
+ rootThreadId,
+ backend: nativeConfig.backend,
+ ttlSeconds: nativeConfig.assignmentTtlSeconds,
+ });
+ const nowIso = new Date().toISOString();
+ return {
+ version: 1,
+ active: false,
+ skill: "ultragoal",
+ keyword: match.keyword,
+ phase: "bootstrap",
+ activated_at: nowIso,
+ updated_at: nowIso,
+ source: "keyword-detector",
+ session_id: sessionId,
+ thread_id: rootThreadId,
+ turn_id: turnId,
+ active_skills: [],
+ transition_error: buildNativeUltragoalBootstrapRequiredReason(
+ sessionId,
+ rootThreadId,
+ bootstrap.generation,
+ ),
+ };
+ }
+ } else if (nativeConfig.backend === "host" && rootThreadId) {
+ await beginNativeUltragoalBootstrap({
+ stateDir,
+ sessionId,
+ rootThreadId,
+ backend: nativeConfig.backend,
+ ttlSeconds: nativeConfig.assignmentTtlSeconds,
+ });
+ const nowIso = new Date().toISOString();
+ return {
+ version: 1,
+ active: false,
+ skill: "ultragoal",
+ keyword: match.keyword,
+ phase: "bootstrap",
+ activated_at: nowIso,
+ updated_at: nowIso,
+ source: "keyword-detector",
+ session_id: sessionId,
+ thread_id: rootThreadId,
+ turn_id: turnId,
+ active_skills: [],
+ transition_error: ULTRAGOAL_HOST_RECEIPT_UNAVAILABLE_REASON,
+ };
+ }
const nowIso = new Date().toISOString();
return {
@@ -2711,6 +2820,40 @@ async function buildNativeOutsideTmuxUltragoalPromptBlockState(
};
}
+async function revokeTerminalNativeUltragoalBootstrap(
+ cwd: string,
+ stateDir: string,
+ sessionId: string,
+): Promise<void> {
+ if (!sessionId) return;
+ const bootstrap = await readNativeUltragoalBootstrap(stateDir, sessionId);
+ if (!bootstrap || bootstrap.status === "revoked") return;
+ const state = await readStopSessionPinnedState("ultragoal-state.json", cwd, sessionId, stateDir);
+ const phase = safeString(state?.current_phase ?? state?.currentPhase).trim().toLowerCase();
+ if (state?.active === false || TERMINAL_MODE_PHASES.has(phase)) {
+ await revokeLocalNativeExecutorAssignment({
+ stateDir,
+ sessionId,
+ reason: `ultragoal_${phase || "inactive"}`,
+ });
+ }
+}
+
+async function failNativeUltragoalActivation(
+ cwd: string,
+ stateDir: string,
+ sessionId: string,
+ reason: string,
+): Promise<void> {
+ await revokeLocalNativeExecutorAssignment({ stateDir, sessionId, reason });
+ await updateModeState("ultragoal", {
+ active: false,
+ current_phase: "failed",
+ error: reason,
+ last_turn_at: new Date().toISOString(),
+ }, cwd, sessionId);
+}
+
function buildSkillStateCliInstruction(mode: string, statePath: string): string {
return `skill: ${mode} activated and initial state initialized at ${statePath}; use CLI-first state updates via \`omx state write/read/clear --input '<json>' --json\`; use omx_state MCP only when explicit MCP compatibility is enabled.`;
}
@@ -4049,6 +4192,15 @@ function resolveConductorPolicyRoot(stateDir: string, fallbackCwd: string): Cond
return { cwd: canonicalFallback, valid: !statePresent, statePresent, externalStateRoot: statePresent };
}
+function readDirectPayloadAgentRole(payload: CodexHookPayload): string {
+ const roles = [...new Set([
+ "agent_role",
+ "agentRole",
+ "agent_type",
+ "agentType",
+ ].map((key) => safeString(payload[key]).trim().toLowerCase()).filter(Boolean))];
+ return roles.length === 1 ? roles[0] ?? "" : "";
+}
function readPayloadAgentRole(payload: CodexHookPayload): string {
const directRole = safeString(
@@ -5487,7 +5639,6 @@ function classifyPreToolUseMutationTransport(
return "goal-lifecycle";
}
const canonicalToolName = canonicalizeNativeCollaborationToolName(toolName);
-
if (
CONDUCTOR_ORCHESTRATION_TOOL_NAMES.has(canonicalToolName)
|| canonicalToolName.startsWith("collaboration.")
@@ -10528,15 +10679,26 @@ async function buildRalplanPreToolUseBoundaryOutput(
};
}
-function buildRawProtectedWorkflowStatePathOutput(
+async function buildRawProtectedWorkflowStatePathOutput(
payload: CodexHookPayload,
cwd: string,
stateDir: string,
-): Record<string, unknown> | null {
+ authoritativeSessionId = "",
+ activeConductor = false,
+): Promise<Record<string, unknown> | null> {
const toolName = safeString(payload.tool_name).trim();
if (classifyPreToolUseMutationTransport(payload, toolName, cwd) !== "path") return null;
const candidates = collectImplementationToolPathCandidates(payload, toolName, readPreToolUsePathCandidates(payload));
- const protectedPath = candidates.find((candidate) => isRawProtectedPlanningStateCandidate(stateDir, cwd, candidate));
+ const protectedCandidates = candidates.filter((candidate) => isRawProtectedPlanningStateCandidate(stateDir, cwd, candidate));
+ if (
+ nativeSubagentAssignmentsOptedIn()
+ && activeConductor
+ && authoritativeSessionId
+ && protectedCandidates.length > 0
+ && protectedCandidates.every((candidate) => isSessionBoundNativeAssignmentPath(cwd, candidate, authoritativeSessionId))
+ && await resolvePreToolUseWriteActor(payload, cwd, stateDir, authoritativeSessionId) === "main-root"
+ ) return null;
+ const protectedPath = protectedCandidates[0];
if (protectedPath === undefined) return null;
return {
decision: "block",
@@ -10799,6 +10961,104 @@ interface ActiveConductorState {
type PreToolUseWriteActor = "main-root" | "native-child" | "provenance-conflict" | "team-worker";
+type NativeAssignmentAction = "path-write" | "bash-write";
+
+interface NativeSubagentAssignment {
+ schema_version: 1;
+ kind: "native-subagent-assignment";
+ lifecycle: "active";
+ root_session_id: string;
+ root_thread_id: string;
+ child_agent_id: string;
+ agent_type: string;
+ allowed_actions: NativeAssignmentAction[];
+ path_prefixes: string[];
+ issued_at: string;
+ expires_at: string;
+ bootstrap_generation: string;
+}
+
+
+function nativeAssignmentPath(stateDir: string, sessionId: string, childAgentId: string): string {
+ return join(
+ stateDir,
+ "sessions",
+ sessionId,
+ NATIVE_ASSIGNMENT_DIRECTORY,
+ `${encodeURIComponent(childAgentId)}.json`,
+ );
+}
+
+function isNativeAssignmentPath(stateDir: string, rawPath: string, executionCwd: string): boolean {
+ const absolute = isAbsolute(rawPath) ? resolve(rawPath) : resolve(executionCwd, rawPath);
+ const assignmentRoot = resolve(stateDir, "sessions");
+ const relativePath = relative(assignmentRoot, absolute).replace(/\\/g, "/");
+ return relativePath !== ""
+ && !relativePath.startsWith("../")
+ && /^.+\/native-assignments(?:\/|$)/.test(relativePath);
+}
+
+async function readNativeSubagentAssignment(
+ payload: CodexHookPayload,
+ cwd: string,
+ stateDir: string,
+ sessionId: string,
+): Promise<NativeSubagentAssignment | null> {
+ if (!nativeSubagentAssignmentsOptedIn()) return null;
+ const childAgentId = readPayloadAgentId(payload);
+ const agentType = readDirectPayloadAgentRole(payload);
+ if (!childAgentId || !agentType || resolveInstalledRoleName(agentType, undefined, cwd) === null) return null;
+
+ const trackingState = await readSubagentTrackingState(cwd).catch(() => null);
+ const trackedSession = safeObject(trackingState?.sessions?.[sessionId]);
+ const leaderThreadId = safeString(trackedSession?.leader_thread_id).trim();
+ const trackedThreads = safeObject(trackedSession?.threads);
+ const trackedChild = safeObject(trackedThreads?.[childAgentId]);
+ const trackedAgentType = safeString(trackedChild?.mode).trim().toLowerCase();
+ const trackedParentId = safeString(
+ trackedChild?.direct_child_parent_id ?? trackedChild?.parent_thread_id,
+ ).trim();
+ const trackedRootId = safeString(trackedChild?.direct_child_root_id).trim();
+ const trackedStatus = safeString(trackedChild?.status).trim().toLowerCase();
+ if (
+ !leaderThreadId
+ || safeString(trackedChild?.kind).trim() !== "subagent"
+ || (trackedAgentType !== "" && trackedAgentType !== agentType)
+ || (trackedParentId !== "" && trackedParentId !== leaderThreadId)
+ || (trackedRootId !== "" && trackedRootId !== leaderThreadId)
+ || (trackedStatus !== "" && trackedStatus !== "available")
+ ) return null;
+
+ const path = nativeAssignmentPath(stateDir, sessionId, childAgentId);
+ if (!await nativeExecutorAssignmentFileIsSafe(stateDir, path)) return null;
+ let raw: Record<string, unknown> | null = null;
+ try {
+ raw = safeObject(JSON.parse(readFileSync(path, "utf-8")));
+ } catch {
+ return null;
+ }
+ const assignment = await parseActiveLocalNativeExecutorAssignment(raw, {
+ cwd,
+ sessionId,
+ rootThreadId: leaderThreadId,
+ childAgentId,
+ agentType,
+ });
+ if (!assignment) return null;
+ const ready = await findReadyLocalNativeExecutorAssignment({
+ cwd,
+ stateDir,
+ sessionId,
+ rootThreadId: leaderThreadId,
+ });
+ if (
+ !ready
+ || ready.child_agent_id !== assignment.child_agent_id
+ || ready.bootstrap_generation !== assignment.bootstrap_generation
+ ) return null;
+ return assignment;
+}
+
function hasSubagentThreadSpawnProvenance(payload: CodexHookPayload): boolean {
const source = payload.source;
if (!source || typeof source !== "object") return false;
@@ -10930,6 +11190,23 @@ const ULTRAGOAL_NO_OWNER_DENY_REASON =
+ "is tmux-only, and native child/descendant provenance intentionally does not grant write authority (see #3127). "
+ "Activating Conductor mode here would deadlock with only `omx cancel` reachable.";
+const ULTRAGOAL_HOST_RECEIPT_UNAVAILABLE_REASON =
+ `OMX-ULTRAGOAL-HOST-RECEIPT-UNAVAILABLE: ${DOCUMENTED_HOST_RECEIPT_UNAVAILABLE}. `
+ + "Host-backed native executor authority remains fail-closed until Codex exposes a documented receipt verifier.";
+
+function buildNativeUltragoalBootstrapRequiredReason(
+ sessionId: string,
+ rootThreadId: string,
+ generation: string,
+): string {
+ return "OMX-ULTRAGOAL-BOOTSTRAP-REQUIRED: typed native execution is available, but Ultragoal activation remains "
+ + "inactive until an exact executor is spawned and authorized. Spawn one typed `executor`, then run "
+ + "`omx ultragoal native-bootstrap authorize "
+ + `--session-id ${JSON.stringify(sessionId)} --root-thread-id ${JSON.stringify(rootThreadId)} `
+ + `--bootstrap-generation ${JSON.stringify(generation)} `
+ + "--child-id <spawned-child-id> --path-prefix . --json`, then retry the canonical Ultragoal state activation. ";
+}
+
function collectUltragoalActivationCandidatePayloads(
payload: CodexHookPayload,
toolName: string,
@@ -10996,21 +11273,154 @@ async function buildUltragoalNoOwnerActivationGuardOutput(
});
if (executionSurface.launcher !== "native" || executionSurface.transport !== "outside-tmux") return null;
+ const rootThreadId = readPayloadThreadId(payload);
+ const nativeConfig = resolveNativeUltragoalConfig();
+ if (nativeConfig.backend === "host") {
+ return {
+ decision: "block",
+ reason: ULTRAGOAL_HOST_RECEIPT_UNAVAILABLE_REASON,
+ hookSpecificOutput: {
+ hookEventName: "PreToolUse",
+ additionalContext: ULTRAGOAL_HOST_RECEIPT_UNAVAILABLE_REASON,
+ },
+ };
+ }
+ if (nativeConfig.backend === "local-experimental" && rootThreadId) {
+ let bootstrap = await readNativeUltragoalBootstrap(stateDir, sessionId);
+ if (!bootstrap) {
+ const nativeSupport = resolveNativeSubagentSupportStatus({
+ payload,
+ persistedSupportBlocker: await readJsonIfExists(nativeSubagentSupportBlockerPath(stateDir)),
+ persistedRoleRoutingMarker: readRoleRoutingMarker(stateDir, { cwd, sessionId }),
+ persistedCapacityBlocker: await readJsonIfExists(nativeSubagentCapacityBlockerPath(stateDir)),
+ cwd,
+ sessionId,
+ });
+ if (nativeSupport.status === "supported" && payloadAdvertisesTypedNativeSpawn(payload)) {
+ bootstrap = await beginNativeUltragoalBootstrap({
+ stateDir,
+ sessionId,
+ rootThreadId,
+ backend: nativeConfig.backend,
+ ttlSeconds: nativeConfig.assignmentTtlSeconds,
+ });
+ }
+ }
+ const ready = await findReadyLocalNativeExecutorAssignment({
+ cwd: policyCwd,
+ stateDir,
+ sessionId,
+ rootThreadId,
+ });
+ if (ready) {
+ const activation = await prepareNativeUltragoalBootstrapActivation({
+ cwd: policyCwd,
+ stateDir,
+ sessionId,
+ childAgentId: ready.child_agent_id,
+ });
+ if (activation.ok) return null;
+ }
+ const reason = bootstrap
+ ? buildNativeUltragoalBootstrapRequiredReason(sessionId, rootThreadId, bootstrap.generation)
+ : ULTRAGOAL_NO_OWNER_DENY_REASON;
+ return {
+ decision: "block",
+ reason,
+ hookSpecificOutput: {
+ hookEventName: "PreToolUse",
+ additionalContext: reason,
+ },
+ };
+ }
+
return {
decision: "block",
reason: ULTRAGOAL_NO_OWNER_DENY_REASON,
hookSpecificOutput: {
hookEventName: "PreToolUse",
additionalContext:
- "Standalone Ultragoal Conductor mode requires an attached tmux session (Team execution) on native Codex App "
- + "outside tmux; native child/descendant provenance does not grant write authority. Do not set ultragoal "
- + "active/current_phase here. Proceed with direct bounded implementation for this task without "
+ "Standalone Ultragoal Conductor mode requires either an attached tmux session (Team execution) or a positively "
+ + "advertised typed native spawn surface backed by scoped write assignments; neither is proven on this native "
+ + "Codex App outside-tmux event. Do not set "
+ + "ultragoal active/current_phase here. Proceed with direct bounded implementation for this task without "
+ "entering Ultragoal's Conductor-gated planning mode, or re-run from an attached tmux OMX CLI shell so "
+ "`omx team` is available. `omx cancel` remains available if a stuck Conductor state already exists.",
},
};
}
+async function buildNativeUltragoalBootstrapMutationGuardOutput(
+ payload: CodexHookPayload,
+ cwd: string,
+ stateDir: string,
+ sessionId: string,
+): Promise<Record<string, unknown> | null> {
+ if (safeString(payload.tool_name).trim() !== "Bash") return null;
+ const command = readPreToolUseCommand(payload);
+ if (!/\bomx\s+ultragoal\s+native-bootstrap\b/.test(command)) return null;
+ const actor = await resolvePreToolUseWriteActor(payload, cwd, stateDir, sessionId);
+ if (actor === "main-root") return null;
+ const reason = actor === "native-child"
+ ? "OWNER_CONFIRMATION_REQUIRED: native Ultragoal bootstrap metadata is root-owned; a native child cannot authorize, revoke, or reconcile its own assignment."
+ : "PROVENANCE_DENIED: native Ultragoal bootstrap mutation requires exact Main-root session provenance.";
+ return {
+ decision: "block",
+ reason,
+ hookSpecificOutput: {
+ hookEventName: "PreToolUse",
+ additionalContext: reason,
+ },
+ };
+}
+
+function isExactNativeUltragoalBootstrapCommand(command: string): boolean {
+ if (nativeAssignedBashHasUnsafeStructure(".", command)) return false;
+ const words = tokenizeConductorShellWords(command).map(shellWordLiteral);
+ return words.length >= 4
+ && basename(words[0] ?? "") === "omx"
+ && words[1] === "ultragoal"
+ && words[2] === "native-bootstrap"
+ && ["authorize", "status", "revoke"].includes(words[3] ?? "");
+}
+
+async function buildPendingNativeUltragoalExecutorGuardOutput(
+ payload: CodexHookPayload,
+ cwd: string,
+ stateDir: string,
+ sessionId: string,
+): Promise<Record<string, unknown> | null> {
+ if (!sessionId) return null;
+ let bootstrap = await readNativeUltragoalBootstrap(stateDir, sessionId);
+ if (!bootstrap || bootstrap.status === "revoked" || bootstrap.status === "expired") {
+ return null;
+ }
+ if (bootstrap.status === "active") {
+ const state = await readStopSessionPinnedState("ultragoal-state.json", cwd, sessionId, stateDir);
+ if (isActiveConductorModeState(state, "ultragoal", sessionId)) return null;
+ await revokeLocalNativeExecutorAssignment({
+ stateDir,
+ sessionId,
+ reason: "ultragoal_state_not_active",
+ });
+ bootstrap = await readNativeUltragoalBootstrap(stateDir, sessionId);
+ }
+ const actor = await resolvePreToolUseWriteActor(payload, cwd, stateDir, sessionId);
+ if (actor !== "native-child") return null;
+ const toolName = safeString(payload.tool_name).trim();
+ if (classifyPreToolUseMutationTransport(payload, toolName, cwd) === "read-only") return null;
+ if (await resolveAuthorizedSendMessageChildToLeader(payload, toolName, cwd, sessionId)) return null;
+ const reason = "OWNER_CONFIRMATION_REQUIRED: native Ultragoal bootstrap is not active; spawned executors remain read-only until the exact assignment/receipt validates and Main-root completes activation.";
+ return {
+ decision: "block",
+ reason,
+ hookSpecificOutput: {
+ hookEventName: "PreToolUse",
+ additionalContext: reason,
+ },
+ };
+}
+
function normalizeRepoRelativePath(cwd: string, rawPath: string): string | null {
const candidate = rawPath.trim();
if (!candidate || isUnresolvedVariableTarget(candidate)) return null;
@@ -11071,6 +11481,14 @@ function conductorPathTraversesLink(cwd: string, relativePath: string): boolean
return false;
}
+function isSessionBoundNativeAssignmentPath(cwd: string, rawPath: string, sessionId: string): boolean {
+ const relativePath = normalizeRepoRelativePath(cwd, rawPath);
+ const match = relativePath
+ ? /^\.omx\/state\/sessions\/([^/]+)\/native-assignments\/[^/]+\.json$/.exec(relativePath)
+ : null;
+ return sessionId !== "" && match?.[1] === sessionId;
+}
+
function isAllowedConductorMetadataPath(cwd: string, rawPath: string): boolean {
const relativePath = normalizeRepoRelativePath(cwd, rawPath);
if (!relativePath || conductorPathnameExpansionIsAmbiguous(relativePath)) return false;
@@ -19822,6 +20240,85 @@ function conductorStatePayloadPreservesActiveGuard(
return phase !== "" && isNonTerminalPhase(phase);
}
+function nativeAssignmentTargetIsWithinScope(
+ cwd: string,
+ rawTarget: string,
+ pathPrefixes: readonly string[],
+): boolean {
+ const relativeTarget = normalizePlanningArtifactRelativePath(cwd, rawTarget);
+ if (!relativeTarget || conductorPathnameExpansionIsAmbiguous(relativeTarget)) return false;
+ if (conductorPathTraversesLink(cwd, relativeTarget)) return false;
+ if (
+ relativeTarget === ".git"
+ || relativeTarget.startsWith(".git/")
+ || relativeTarget === ".omx"
+ || relativeTarget.startsWith(".omx/")
+ ) return false;
+ return pathPrefixes.some((prefix) => (
+ prefix === "."
+ || relativeTarget === prefix
+ || relativeTarget.startsWith(`${prefix}/`)
+ ));
+}
+
+function nativeAssignedBashHasUnsafeStructure(cwd: string, command: string): boolean {
+ const normalized = normalizeShellLineContinuations(command);
+ if (
+ splitConductorShellSegments(stripHeredocBodiesForCommandScan(normalized)).length !== 1
+ || hasUnresolvedShellArithmeticExpansion(normalized)
+ || hasUnquotedShellSubstitution(normalized)
+ || hasDynamicNestedShellExecution(normalized)
+ || hasUnsafeUnquotedHeredocExpansion(normalized)
+ || commandHasUnsafeConductorShellState(normalized, cwd)
+ || conductorCommandMayMutatePathResolution(normalized)
+ ) return true;
+ const interpreterWrites = extractConductorInterpreterWrites(normalized);
+ return interpreterWrites.some((write) => write.unresolved || write.targets.length === 0);
+}
+
+async function nativeChildAssignmentAllowsMutation(
+ payload: CodexHookPayload,
+ cwd: string,
+ stateDir: string,
+ sessionId: string,
+ toolName: string,
+ mutationTransport: PreToolUseMutationTransport,
+): Promise<boolean> {
+ if (
+ mutationTransport === "state"
+ || mutationTransport === "orchestration"
+ || mutationTransport === "goal-lifecycle"
+ || mutationTransport === "unknown"
+ ) {
+ return false;
+ }
+ const assignment = await readNativeSubagentAssignment(payload, cwd, stateDir, sessionId);
+ if (!assignment) return false;
+
+ if (mutationTransport === "path") {
+ if (!assignment.allowed_actions.includes("path-write")) return false;
+ const candidates = collectImplementationToolPathCandidates(
+ payload,
+ toolName,
+ readPreToolUsePathCandidates(payload),
+ );
+ return candidates.length > 0
+ && candidates.every((candidate) => (
+ !isNativeAssignmentPath(stateDir, candidate, cwd)
+ && nativeAssignmentTargetIsWithinScope(cwd, candidate, assignment.path_prefixes)
+ ));
+ }
+ if (mutationTransport !== "bash") return false;
+
+ const command = readPreToolUseCommand(payload);
+ if (nativeAssignedBashHasUnsafeStructure(cwd, command)) return false;
+ if (!assignment.allowed_actions.includes("bash-write")) return false;
+ const targets = extractDeepInterviewCommandWriteTargets(command, cwd, cwd);
+ if (targets.some((target) => isNativeAssignmentPath(stateDir, target, cwd))) return false;
+ return targets.length > 0 && targets.every((target) => (
+ nativeAssignmentTargetIsWithinScope(cwd, target, assignment.path_prefixes)
+ ));
+}
function buildConductorSessionProvenanceDeny(
activeState: ActiveConductorState,
@@ -19872,6 +20369,12 @@ export async function buildConductorPreToolUseWriteGuardOutput(
const pathCandidates = readPreToolUsePathCandidates(payload);
const mutationTransport = classifyPreToolUseMutationTransport(payload, toolName, cwd);
+ if (
+ writeActor === "main-root"
+ && toolName === "Bash"
+ && isExactNativeUltragoalBootstrapCommand(command)
+ ) return null;
+
let blocked = false;
let blockedDetail = "Main-root Conductor write is not delegated";
let nativeChildMutationAttempt = false;
@@ -19925,7 +20428,10 @@ export async function buildConductorPreToolUseWriteGuardOutput(
blocked = true;
blockedDetail = describeConductorBlockedWrite(toolName, undefined, toolPathCandidates.length);
} else {
- const blockedPath = toolPathCandidates.find((candidate) => !isAllowedConductorMetadataExecutionPath(cwd, policyCwd, candidate));
+ const blockedPath = toolPathCandidates.find((candidate) => (
+ !isSessionBoundNativeAssignmentPath(policyCwd, candidate, sessionId)
+ && !isAllowedConductorMetadataExecutionPath(cwd, policyCwd, candidate)
+ ));
blocked = blockedPath !== undefined;
if (blockedPath !== undefined) {
blockedDetail = describeConductorBlockedWrite(toolName, blockedPath, toolPathCandidates.length);
@@ -19945,11 +20451,23 @@ export async function buildConductorPreToolUseWriteGuardOutput(
stateDir,
policyCwd,
);
- if (writeActor === "team-worker" && !teamWorkerProtectedStateTarget) return null;
+ if (writeActor === "team-worker" && mutationTransport !== "goal-lifecycle" && !teamWorkerProtectedStateTarget) return null;
if (writeActor === "team-worker" && teamWorkerProtectedStateTarget && !blocked) {
blocked = true;
blockedDetail = "Bash targets protected workflow state outside authorized Team-worker scope";
}
+ if (
+ writeActor === "native-child"
+ && nativeChildMutationAttempt
+ && await nativeChildAssignmentAllowsMutation(
+ payload,
+ policyCwd,
+ stateDir,
+ sessionId,
+ toolName,
+ mutationTransport,
+ )
+ ) return null;
if (!blocked && (writeActor !== "native-child" || !nativeChildMutationAttempt)) return null;
if (!blocked && nativeChildMutationAttempt && writeActor === "native-child") {
blockedDetail = toolName === "Bash"
@@ -21963,6 +22481,28 @@ export async function dispatchCodexNativeHook(
},
});
}
+ if (
+ skillState?.active === true
+ && skillState.initialized_mode === "ultragoal"
+ && sessionIdForState
+ ) {
+ const bootstrap = await readNativeUltragoalBootstrap(stateDir, sessionIdForState);
+ let receiptConfirmed = bootstrap?.status === "active";
+ if (bootstrap && ["ready", "activating"].includes(bootstrap.status) && bootstrap.child_agent_id) {
+ const confirmed = await markNativeUltragoalBootstrapActive({
+ cwd,
+ stateDir,
+ sessionId: sessionIdForState,
+ childAgentId: bootstrap.child_agent_id,
+ });
+ receiptConfirmed = confirmed.ok;
+ }
+ if (!receiptConfirmed && resolveNativeUltragoalConfig().backend === "local-experimental") {
+ const reason = "native_ultragoal_activation_receipt_invalid";
+ await failNativeUltragoalActivation(cwd, stateDir, sessionIdForState, reason);
+ skillState = { ...skillState, active: false, transition_error: reason };
+ }
+ }
// --- Triage classifier (advisory-only, non-keyword prompts) ---
if (
prompt
@@ -22204,7 +22744,16 @@ export async function dispatchCodexNativeHook(
? (await readStopSessionPinnedState("autopilot-state.json", policyCwd, sessionBinding.canonicalSessionId, stateDir) ?? {})
: {},
});
- if (directCancel.kind !== "not-direct-cancel") outputJson = directCancel.output;
+ if (directCancel.kind !== "not-direct-cancel") {
+ if (directCancel.kind === "handled" && sessionBinding.canonicalSessionId) {
+ await revokeLocalNativeExecutorAssignment({
+ stateDir,
+ sessionId: sessionBinding.canonicalSessionId,
+ reason: "root_cancelled",
+ });
+ }
+ outputJson = directCancel.output;
+ }
}
if (!outputJson && !policyRoot.valid && policyRoot.statePresent && mutationTransport !== "read-only") {
outputJson = buildConductorSessionProvenanceDeny(
@@ -22326,6 +22875,12 @@ export async function dispatchCodexNativeHook(
})();
outputJson = nativePreToolUseSpecificDeny
?? buildNativeUnknownRolePreToolUseOutput(payload, policyCwd)
+ ?? await buildPendingNativeUltragoalExecutorGuardOutput(
+ payload,
+ policyCwd,
+ stateDir,
+ preToolUseSessionId,
+ )
?? await buildDeepInterviewPreToolUseBoundaryOutput(
payload,
policyCwd,
@@ -22346,6 +22901,12 @@ export async function dispatchCodexNativeHook(
stateDir,
rootPointerConflict,
)
+ ?? await buildNativeUltragoalBootstrapMutationGuardOutput(
+ payload,
+ policyCwd,
+ stateDir,
+ preToolUseSessionId,
+ )
?? await buildUltragoalNoOwnerActivationGuardOutput(
payload,
cwd,
@@ -22360,7 +22921,13 @@ export async function dispatchCodexNativeHook(
preToolUseSessionId,
policyCwd,
)
- ?? buildRawProtectedWorkflowStatePathOutput(payload, policyCwd, stateDir)
+ ?? await buildRawProtectedWorkflowStatePathOutput(
+ payload,
+ policyCwd,
+ stateDir,
+ preToolUseSessionId,
+ guardedConductorState !== null,
+ )
?? await buildNativeSubagentCapacityCloseGuardOutput(payload, policyCwd, stateDir)
?? buildMalformedPreToolUseBlockTestOutput(payload)
?? buildNativePreToolUseOutput(payload);
@@ -22375,6 +22942,34 @@ export async function dispatchCodexNativeHook(
}
await handleTeamWorkerPostToolUseSuccess(payload, cwd);
}
+ if (canonicalSessionId) {
+ const toolName = safeString(payload.tool_name).trim();
+ const activationCandidates = collectUltragoalActivationCandidatePayloads(payload, toolName, cwd);
+ if (activationCandidates.some((candidate) => isUltragoalConductorActivationPayload(candidate))) {
+ const bootstrap = await readNativeUltragoalBootstrap(stateDir, canonicalSessionId);
+ const state = await readStopSessionPinnedState("ultragoal-state.json", cwd, canonicalSessionId, stateDir);
+ if (isActiveConductorModeState(state, "ultragoal", canonicalSessionId)) {
+ let receiptConfirmed = bootstrap?.status === "active";
+ if (bootstrap?.status === "activating" && bootstrap.child_agent_id) {
+ const confirmed = await markNativeUltragoalBootstrapActive({
+ cwd,
+ stateDir,
+ sessionId: canonicalSessionId,
+ childAgentId: bootstrap.child_agent_id,
+ });
+ receiptConfirmed = confirmed.ok;
+ }
+ if (!receiptConfirmed && resolveNativeUltragoalConfig().backend === "local-experimental") {
+ await failNativeUltragoalActivation(
+ cwd,
+ stateDir,
+ canonicalSessionId,
+ "native_ultragoal_activation_receipt_invalid",
+ );
+ }
+ }
+ }
+ }
outputJson = buildNativePostToolUseOutput(payload);
} else if (hookEventName === "Stop") {
if (declaredTeamWorkerStopOnly) {
@@ -22413,6 +23008,9 @@ export async function dispatchCodexNativeHook(
};
}
}
+ if (!declaredTeamWorkerStopOnly && canonicalSessionId) {
+ await revokeTerminalNativeUltragoalBootstrap(policyCwd, stateDir, canonicalSessionId);
+ }
}
return {
diff --git a/src/subagents/__tests__/tracker.test.ts b/src/subagents/__tests__/tracker.test.ts
index f5ace531..bedb9e6b 100644
--- a/src/subagents/__tests__/tracker.test.ts
+++ b/src/subagents/__tests__/tracker.test.ts
@@ -5,7 +5,7 @@ import { mkdtemp, mkdir, rm, writeFile } from 'node:fs/promises';
import { hostname, tmpdir } from 'node:os';
import { join } from 'node:path';
import { describe, it } from 'node:test';
-import { __setCrossProcessPublishBarrierForTest, __setCrossProcessQuarantineBarrierForTest, consumeDirectChildReopenContext, CrossProcessLockLostError, buildSubagentResumeLedger, CROSS_PROCESS_LOCK_ARTIFACT_SWEEP_CAP, CROSS_PROCESS_LOCK_LEASE_MS, createSubagentTrackingState, crossProcessLockPath, DESCRIPTIVE_ADAPTED_PROVENANCE, fenceNativeSubagentAuthorities, forceGlobalAuthorityDenial, recordNativeSubagentAuthorityObservation, recordSubagentTurn, recordSubagentTurnForSession, NATIVE_SUBAGENT_PROVENANCE, readProcessStartIdentity, readSubagentTrackingState, readSubagentTrackingStateStrict, repairPersistedRootIdentity, revokeNativeSubagentAuthorities, selectReusableSubagentEntry, subagentTrackingPath, summarizeSubagentSession, withCrossProcessFileLockSync, writeSubagentTrackingState } from '../tracker.js';
+import { acquireCrossProcessFileLock, __setCrossProcessPublishBarrierForTest, __setCrossProcessQuarantineBarrierForTest, consumeDirectChildReopenContext, CrossProcessLockLostError, buildSubagentResumeLedger, CROSS_PROCESS_LOCK_ARTIFACT_SWEEP_CAP, CROSS_PROCESS_LOCK_LEASE_MS, createSubagentTrackingState, crossProcessLockPath, DESCRIPTIVE_ADAPTED_PROVENANCE, fenceNativeSubagentAuthorities, forceGlobalAuthorityDenial, recordNativeSubagentAuthorityObservation, recordSubagentTurn, recordSubagentTurnForSession, NATIVE_SUBAGENT_PROVENANCE, readProcessStartIdentity, readSubagentTrackingState, readSubagentTrackingStateStrict, repairPersistedRootIdentity, revokeNativeSubagentAuthorities, selectReusableSubagentEntry, subagentTrackingPath, summarizeSubagentSession, withCrossProcessFileLockSync, writeSubagentTrackingState } from '../tracker.js';
import { NATIVE_SUBAGENT_ROLE_ROUTING_MARKER_FILE, readRoleRoutingMarker, writeRoleRoutingMarker } from '../role-routing-marker.js';
const CROSS_PROCESS_LOCK_HOLDER_SOURCE = `
@@ -1880,6 +1880,31 @@ describe('subagents/tracker', () => {
}
});
+ it('can preserve a live local async owner beyond the legacy lease', async () => {
+ const cwd = await mkdtemp(join(tmpdir(), 'omx-subagent-tracker-'));
+ const resourcePath = join(cwd, 'lock-resource');
+ const lockPath = crossProcessLockPath(resourcePath);
+ try {
+ const liveClaim = crossProcessLockClaim(
+ 'live-async-owner',
+ process.pid,
+ Date.now() - CROSS_PROCESS_LOCK_LEASE_MS - 1,
+ );
+ await writeFile(lockPath, liveClaim);
+ await assert.rejects(
+ acquireCrossProcessFileLock(resourcePath, {
+ maxAttempts: 1,
+ retryMs: 1,
+ preserveLiveLocalOwner: true,
+ }),
+ /Timed out waiting for cross-process lock/,
+ );
+ assert.equal(readFileSync(lockPath, 'utf-8'), liveClaim);
+ } finally {
+ await rm(cwd, { recursive: true, force: true });
+ }
+ });
+
it('does not steal a live same-host identity-matched claim after its lease or mistake its token for ours', async () => {
const cwd = await mkdtemp(join(tmpdir(), 'omx-subagent-tracker-'));
const resourcePath = join(cwd, 'lock-resource');
diff --git a/src/subagents/tracker.ts b/src/subagents/tracker.ts
index 7823b252..986516cd 100644
--- a/src/subagents/tracker.ts
+++ b/src/subagents/tracker.ts
@@ -567,12 +567,16 @@ function isCrossProcessLockOlderThanLease(acquiredAtMs: number, nowMs: number):
return acquiredAtMs < nowMs - CROSS_PROCESS_LOCK_LEASE_MS;
}
-function isCrossProcessLockReclaimable(claim: CrossProcessLockClaim): boolean {
+function isCrossProcessLockReclaimable(
+ claim: CrossProcessLockClaim,
+ options: { preserveLiveLocalOwner?: boolean } = {},
+): boolean {
if (claim.host !== hostname()) return isCrossProcessLockOlderThanLease(claim.acquiredAtMs, Date.now());
if (isCrossProcessLockOwnerDead(claim.pid)) return true;
const currentPidStartId = readProcessStartIdentity(claim.pid);
if (claim.pidStartId && currentPidStartId) return currentPidStartId !== claim.pidStartId;
+ if (options.preserveLiveLocalOwner) return false;
return isCrossProcessLockOlderThanLease(claim.acquiredAtMs, Date.now());
}
@@ -624,9 +628,13 @@ function restoreQuarantinedCrossProcessLock(lockPath: string, quarantinedPath: s
removeCrossProcessLockFile(quarantinedPath);
}
-function recoverCrossProcessFileLock(lockPath: string, observed: CrossProcessLockState): boolean {
+function recoverCrossProcessFileLock(
+ lockPath: string,
+ observed: CrossProcessLockState,
+ options: { preserveLiveLocalOwner?: boolean } = {},
+): boolean {
if (observed.kind === 'missing') return true;
- if (observed.kind === 'claim' && !isCrossProcessLockReclaimable(observed.claim)) return false;
+ if (observed.kind === 'claim' && !isCrossProcessLockReclaimable(observed.claim, options)) return false;
const quarantinedPath = `${lockPath}.${Date.now()}.${randomUUID()}.quarantine`;
try {
@@ -644,7 +652,11 @@ function recoverCrossProcessFileLock(lockPath: string, observed: CrossProcessLoc
&& captured.kind === 'claim'
&& captured.claim.token === observed.claim.token;
const capturedRecoverable = captured.kind === 'malformed'
- || (capturedExpectedClaim && captured.kind === 'claim' && isCrossProcessLockReclaimable(captured.claim));
+ || (
+ capturedExpectedClaim
+ && captured.kind === 'claim'
+ && isCrossProcessLockReclaimable(captured.claim, options)
+ );
if (!capturedRecoverable) {
restoreQuarantinedCrossProcessLock(lockPath, quarantinedPath);
return true;
@@ -742,6 +754,47 @@ export function __setCrossProcessQuarantineBarrierForTest(
crossProcessQuarantineBarrier = barrier;
}
+export type CrossProcessFileLockHandle = {
+ assertOwnership(): void;
+ release(): void;
+};
+
+/** Acquire the shared recoverable lock for an async caller that owns its writes. */
+export async function acquireCrossProcessFileLock(
+ resourcePath: string,
+ options: { maxAttempts?: number; retryMs?: number; preserveLiveLocalOwner?: boolean } = {},
+): Promise<CrossProcessFileLockHandle> {
+ const lockPath = crossProcessLockPath(resourcePath);
+ const maxAttempts = typeof options.maxAttempts === 'number' && Number.isFinite(options.maxAttempts)
+ ? Math.max(1, Math.floor(options.maxAttempts))
+ : DEFAULT_CROSS_PROCESS_LOCK_MAX_ATTEMPTS;
+ const retryMs = typeof options.retryMs === 'number' && Number.isFinite(options.retryMs)
+ ? Math.max(1, Math.floor(options.retryMs))
+ : DEFAULT_CROSS_PROCESS_LOCK_RETRY_MS;
+ mkdirSync(dirname(lockPath), { recursive: true });
+ const token = randomUUID();
+ for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
+ if (
+ tryAcquireCrossProcessFileLock(lockPath, token)
+ || (
+ recoverCrossProcessFileLock(lockPath, readCrossProcessLockState(lockPath), options)
+ && tryAcquireCrossProcessFileLock(lockPath, token)
+ )
+ ) {
+ return {
+ assertOwnership: () => assertCrossProcessFileLockOwnership(lockPath, token),
+ release: () => releaseCrossProcessFileLock(lockPath, token),
+ };
+ }
+ if (attempt < maxAttempts - 1) {
+ await new Promise((resolveDelay) => {
+ setTimeout(resolveDelay, Math.min(25, retryMs * 2 ** Math.min(attempt, 4)));
+ });
+ }
+ }
+ throw new Error(`Timed out waiting for cross-process lock at ${lockPath}`);
+}
+
export function withCrossProcessFileLockSync<T>(
resourcePath: string,
operation: (context: CrossProcessFileLockContext) => T,
@@ -1182,6 +1235,12 @@ function readAuthorityFence(cwd: string): { ok: boolean; ids: Set<string> } {
}
}
+/** True when durable authority state requires fail-closed denial for this child. */
+export function isNativeSubagentAuthorityFenced(cwd: string, childThreadId: string): boolean {
+ const fence = readAuthorityFence(cwd);
+ return !fence.ok || fence.ids.has(childThreadId.trim());
+}
+
/** Upper bound on fenced ids, so repeated failures cannot grow the fence without limit. */
export const AUTHORITY_FENCE_MAX_IDS = 512;
diff --git a/src/ultragoal/__tests__/native-bootstrap.test.ts b/src/ultragoal/__tests__/native-bootstrap.test.ts
new file mode 100644
index 00000000..e25ac483
--- /dev/null
+++ b/src/ultragoal/__tests__/native-bootstrap.test.ts
@@ -0,0 +1,454 @@
+import assert from 'node:assert/strict';
+import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
+import { tmpdir } from 'node:os';
+import { dirname, join } from 'node:path';
+import { describe, it } from 'node:test';
+import {
+ beginNativeUltragoalBootstrap,
+ DOCUMENTED_HOST_RECEIPT_UNAVAILABLE,
+ findReadyLocalNativeExecutorAssignment,
+ issueLocalNativeExecutorAssignment,
+ markNativeUltragoalBootstrapActive,
+ nativeExecutorAssignmentPath,
+ prepareNativeUltragoalBootstrapActivation,
+ readNativeUltragoalBootstrap,
+ reconcileLocalNativeExecutorAssignments,
+ revokeLocalNativeExecutorAssignment,
+ unavailableHostNativeExecutorReceiptVerifier,
+} from '../native-bootstrap.js';
+
+async function writeJson(path: string, value: unknown): Promise<void> {
+ await mkdir(dirname(path), { recursive: true });
+ await writeFile(path, `${JSON.stringify(value, null, 2)}\n`);
+}
+
+async function fixture() {
+ const cwd = await mkdtemp(join(tmpdir(), 'omx-native-bootstrap-'));
+ const stateDir = join(cwd, '.omx', 'state');
+ const sessionId = 'session-native-bootstrap';
+ const rootThreadId = 'root-native-bootstrap';
+ const childAgentId = 'child-native-bootstrap';
+ const now = new Date('2026-07-28T12:00:00.000Z');
+ await writeJson(join(stateDir, 'subagent-tracking.json'), {
+ schemaVersion: 1,
+ sessions: {
+ [sessionId]: {
+ session_id: sessionId,
+ leader_thread_id: rootThreadId,
+ updated_at: now.toISOString(),
+ threads: {
+ [rootThreadId]: {
+ thread_id: rootThreadId,
+ kind: 'leader',
+ first_seen_at: now.toISOString(),
+ last_seen_at: now.toISOString(),
+ turn_count: 1,
+ },
+ [childAgentId]: {
+ thread_id: childAgentId,
+ kind: 'subagent',
+ mode: 'executor',
+ status: 'available',
+ provenance_kind: 'native_subagent',
+ direct_child_parent_id: rootThreadId,
+ direct_child_root_id: rootThreadId,
+ first_seen_at: now.toISOString(),
+ last_seen_at: now.toISOString(),
+ turn_count: 1,
+ },
+ },
+ },
+ },
+ });
+ return { cwd, stateDir, sessionId, rootThreadId, childAgentId, now };
+}
+
+describe('native Ultragoal bootstrap', () => {
+ it('keeps the host backend explicitly unavailable without a documented verifier', async () => {
+ const f = await fixture();
+ try {
+ const state = await beginNativeUltragoalBootstrap({
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ rootThreadId: f.rootThreadId,
+ backend: 'host',
+ ttlSeconds: 300,
+ now: f.now,
+ });
+ assert.equal(state.status, 'host-receipt-unavailable');
+ assert.equal(state.reason, DOCUMENTED_HOST_RECEIPT_UNAVAILABLE);
+ assert.deepEqual(await unavailableHostNativeExecutorReceiptVerifier.verifyActivationReceipt({
+ cwd: f.cwd,
+ sessionId: f.sessionId,
+ rootThreadId: f.rootThreadId,
+ }), { ok: false, reason: DOCUMENTED_HOST_RECEIPT_UNAVAILABLE });
+ } finally {
+ await rm(f.cwd, { recursive: true, force: true });
+ }
+ });
+
+ it('orders local bootstrap before assignment and activation', async () => {
+ const f = await fixture();
+ try {
+ const bootstrap = await beginNativeUltragoalBootstrap({
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ rootThreadId: f.rootThreadId,
+ backend: 'local-experimental',
+ ttlSeconds: 900,
+ now: f.now,
+ });
+ assert.equal(bootstrap.status, 'awaiting-executor');
+ assert.equal(await findReadyLocalNativeExecutorAssignment({
+ cwd: f.cwd,
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ rootThreadId: f.rootThreadId,
+ now: f.now,
+ }), null);
+
+ await assert.rejects(
+ issueLocalNativeExecutorAssignment({
+ cwd: f.cwd,
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ rootThreadId: f.rootThreadId,
+ childAgentId: f.childAgentId,
+ expectedGeneration: bootstrap.generation,
+ pathPrefixes: ['$UNRESOLVED/*'],
+ ttlSeconds: 300,
+ now: f.now,
+ }),
+ /invalid_native_assignment_path_prefixes/,
+ );
+
+ const assignment = await issueLocalNativeExecutorAssignment({
+ cwd: f.cwd,
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ rootThreadId: f.rootThreadId,
+ childAgentId: f.childAgentId,
+ expectedGeneration: bootstrap.generation,
+ pathPrefixes: ['src', 'tests'],
+ ttlSeconds: 300,
+ now: f.now,
+ });
+ assert.equal(assignment.bootstrap_generation, bootstrap.generation);
+ assert.equal((await readNativeUltragoalBootstrap(f.stateDir, f.sessionId))?.status, 'ready');
+ assert.equal((await findReadyLocalNativeExecutorAssignment({
+ cwd: f.cwd,
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ rootThreadId: f.rootThreadId,
+ now: f.now,
+ }))?.child_agent_id, f.childAgentId);
+
+ const prepared = await prepareNativeUltragoalBootstrapActivation({
+ cwd: f.cwd,
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ childAgentId: f.childAgentId,
+ now: f.now,
+ });
+ assert.equal(prepared.ok, true);
+ assert.equal((await readNativeUltragoalBootstrap(f.stateDir, f.sessionId))?.status, 'activating');
+ const activation = await markNativeUltragoalBootstrapActive({
+ cwd: f.cwd,
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ childAgentId: f.childAgentId,
+ now: f.now,
+ });
+ assert.equal(activation.ok, true);
+ assert.equal((await readNativeUltragoalBootstrap(f.stateDir, f.sessionId))?.status, 'active');
+ assert.equal((await markNativeUltragoalBootstrapActive({
+ cwd: f.cwd,
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ childAgentId: f.childAgentId,
+ now: f.now,
+ })).ok, true);
+
+ const renewed = await issueLocalNativeExecutorAssignment({
+ cwd: f.cwd,
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ rootThreadId: f.rootThreadId,
+ childAgentId: f.childAgentId,
+ expectedGeneration: bootstrap.generation,
+ pathPrefixes: ['src'],
+ ttlSeconds: 600,
+ now: new Date(f.now.getTime() + 60_000),
+ });
+ assert.equal(renewed.bootstrap_generation, bootstrap.generation);
+ assert.equal((await readNativeUltragoalBootstrap(f.stateDir, f.sessionId))?.status, 'active');
+ } finally {
+ await rm(f.cwd, { recursive: true, force: true });
+ }
+ });
+
+ it('revokes a local lease when tracker lifecycle closes and supports explicit revoke', async () => {
+ const f = await fixture();
+ try {
+ const bootstrap = await beginNativeUltragoalBootstrap({
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ rootThreadId: f.rootThreadId,
+ backend: 'local-experimental',
+ ttlSeconds: 900,
+ now: f.now,
+ });
+ await issueLocalNativeExecutorAssignment({
+ cwd: f.cwd,
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ rootThreadId: f.rootThreadId,
+ childAgentId: f.childAgentId,
+ expectedGeneration: bootstrap.generation,
+ pathPrefixes: ['src'],
+ ttlSeconds: 300,
+ now: f.now,
+ });
+ const trackerPath = join(f.stateDir, 'subagent-tracking.json');
+ const tracker = JSON.parse(await readFile(trackerPath, 'utf-8')) as {
+ sessions: Record<string, { threads: Record<string, { status: string }> }>;
+ };
+ tracker.sessions[f.sessionId].threads[f.childAgentId].status = 'closed';
+ await writeJson(trackerPath, tracker);
+ assert.deepEqual(await reconcileLocalNativeExecutorAssignments({
+ cwd: f.cwd,
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ rootThreadId: f.rootThreadId,
+ now: f.now,
+ }), { ready: false });
+ const assignment = JSON.parse(await readFile(
+ nativeExecutorAssignmentPath(f.stateDir, f.sessionId, f.childAgentId),
+ 'utf-8',
+ )) as { lifecycle: string; revoke_reason?: string };
+ assert.equal(assignment.lifecycle, 'revoked');
+ assert.equal(assignment.revoke_reason, 'child_closed');
+
+ await revokeLocalNativeExecutorAssignment({
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ reason: 'root_cancelled',
+ now: f.now,
+ });
+ assert.equal((await readNativeUltragoalBootstrap(f.stateDir, f.sessionId))?.status, 'revoked');
+ } finally {
+ await rm(f.cwd, { recursive: true, force: true });
+ }
+ });
+
+ it('denies explicit and fail-closed durable authority fences', async () => {
+ const f = await fixture();
+ try {
+ const bootstrap = await beginNativeUltragoalBootstrap({
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ rootThreadId: f.rootThreadId,
+ backend: 'local-experimental',
+ ttlSeconds: 900,
+ now: f.now,
+ });
+ const fencePath = join(f.stateDir, 'subagent-tracking.json.authority-fence.json');
+ await writeJson(fencePath, { ids: [f.childAgentId] });
+ await assert.rejects(issueLocalNativeExecutorAssignment({
+ cwd: f.cwd,
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ rootThreadId: f.rootThreadId,
+ childAgentId: f.childAgentId,
+ expectedGeneration: bootstrap.generation,
+ pathPrefixes: ['src'],
+ ttlSeconds: 300,
+ now: f.now,
+ }), /child_authority_fenced/);
+
+ await writeFile(fencePath, '{ malformed');
+ await assert.rejects(issueLocalNativeExecutorAssignment({
+ cwd: f.cwd,
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ rootThreadId: f.rootThreadId,
+ childAgentId: f.childAgentId,
+ expectedGeneration: bootstrap.generation,
+ pathPrefixes: ['src'],
+ ttlSeconds: 300,
+ now: f.now,
+ }), /child_authority_fenced/);
+ } finally {
+ await rm(f.cwd, { recursive: true, force: true });
+ }
+ });
+
+ it('rotates expired bootstrap generations and cannot activate without the exact assignment file', async () => {
+ const f = await fixture();
+ try {
+ const first = await beginNativeUltragoalBootstrap({
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ rootThreadId: f.rootThreadId,
+ backend: 'local-experimental',
+ ttlSeconds: 30,
+ now: f.now,
+ });
+ await issueLocalNativeExecutorAssignment({
+ cwd: f.cwd,
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ rootThreadId: f.rootThreadId,
+ childAgentId: f.childAgentId,
+ expectedGeneration: first.generation,
+ pathPrefixes: ['src'],
+ ttlSeconds: 30,
+ now: f.now,
+ });
+ const assignmentPath = nativeExecutorAssignmentPath(f.stateDir, f.sessionId, f.childAgentId);
+ await rm(assignmentPath);
+ const missingAssignmentActivation = await markNativeUltragoalBootstrapActive({
+ cwd: f.cwd,
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ childAgentId: f.childAgentId,
+ now: f.now,
+ });
+ assert.equal(missingAssignmentActivation.ok, false);
+ assert.equal((await readNativeUltragoalBootstrap(f.stateDir, f.sessionId))?.status, 'ready');
+
+ const second = await beginNativeUltragoalBootstrap({
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ rootThreadId: f.rootThreadId,
+ backend: 'local-experimental',
+ ttlSeconds: 30,
+ now: new Date(f.now.getTime() + 31_000),
+ });
+ assert.notEqual(second.generation, first.generation);
+ assert.equal(second.status, 'awaiting-executor');
+ } finally {
+ await rm(f.cwd, { recursive: true, force: true });
+ }
+ });
+
+ it('serializes authorize before revoke so stale readiness cannot resurrect authority', async () => {
+ const f = await fixture();
+ try {
+ const bootstrap = await beginNativeUltragoalBootstrap({
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ rootThreadId: f.rootThreadId,
+ backend: 'local-experimental',
+ ttlSeconds: 900,
+ now: f.now,
+ });
+ const concurrent = await Promise.allSettled([
+ issueLocalNativeExecutorAssignment({
+ cwd: f.cwd,
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ rootThreadId: f.rootThreadId,
+ childAgentId: f.childAgentId,
+ expectedGeneration: bootstrap.generation,
+ pathPrefixes: ['src'],
+ ttlSeconds: 300,
+ now: f.now,
+ }),
+ revokeLocalNativeExecutorAssignment({
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ reason: 'concurrent_root_revoke',
+ now: f.now,
+ }),
+ ]);
+ if (concurrent[0].status === 'rejected') {
+ assert.match(String(concurrent[0].reason), /native_ultragoal_bootstrap_not_ready/);
+ }
+ assert.equal(concurrent[1].status, 'fulfilled');
+ assert.equal((await readNativeUltragoalBootstrap(f.stateDir, f.sessionId))?.status, 'revoked');
+ const assignmentPath = nativeExecutorAssignmentPath(f.stateDir, f.sessionId, f.childAgentId);
+ if (concurrent[0].status === 'fulfilled') {
+ const assignment = JSON.parse(await readFile(assignmentPath, 'utf-8')) as {
+ lifecycle: string;
+ revoke_reason?: string;
+ };
+ assert.equal(assignment.lifecycle, 'revoked');
+ assert.equal(assignment.revoke_reason, 'concurrent_root_revoke');
+ } else {
+ await assert.rejects(readFile(assignmentPath), /ENOENT/);
+ }
+ const replacement = await beginNativeUltragoalBootstrap({
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ rootThreadId: f.rootThreadId,
+ backend: 'local-experimental',
+ ttlSeconds: 900,
+ now: f.now,
+ });
+ await assert.rejects(issueLocalNativeExecutorAssignment({
+ cwd: f.cwd,
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ rootThreadId: f.rootThreadId,
+ childAgentId: f.childAgentId,
+ expectedGeneration: bootstrap.generation,
+ pathPrefixes: ['src'],
+ ttlSeconds: 300,
+ now: f.now,
+ }), /native_ultragoal_bootstrap_not_ready/);
+ assert.notEqual(replacement.generation, bootstrap.generation);
+ } finally {
+ await rm(f.cwd, { recursive: true, force: true });
+ }
+ });
+
+ it('recovers one dead lifecycle lock without letting concurrent mutations overlap', async () => {
+ const f = await fixture();
+ try {
+ const bootstrap = await beginNativeUltragoalBootstrap({
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ rootThreadId: f.rootThreadId,
+ backend: 'local-experimental',
+ ttlSeconds: 900,
+ now: f.now,
+ });
+ const lockPath = join(
+ f.stateDir,
+ 'sessions',
+ f.sessionId,
+ 'native-ultragoal-bootstrap.json.lock',
+ );
+ await writeJson(lockPath, { pid: 2_147_483_647, token: 'dead-owner' });
+ const concurrent = await Promise.allSettled([
+ issueLocalNativeExecutorAssignment({
+ cwd: f.cwd,
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ rootThreadId: f.rootThreadId,
+ childAgentId: f.childAgentId,
+ expectedGeneration: bootstrap.generation,
+ pathPrefixes: ['src'],
+ ttlSeconds: 300,
+ now: f.now,
+ }),
+ revokeLocalNativeExecutorAssignment({
+ stateDir: f.stateDir,
+ sessionId: f.sessionId,
+ reason: 'dead_lock_concurrent_revoke',
+ now: f.now,
+ }),
+ ]);
+ if (concurrent[0].status === 'rejected') {
+ assert.match(String(concurrent[0].reason), /native_ultragoal_bootstrap_not_ready/);
+ }
+ assert.equal(concurrent[1].status, 'fulfilled');
+ assert.equal((await readNativeUltragoalBootstrap(f.stateDir, f.sessionId))?.status, 'revoked');
+ await assert.rejects(readFile(lockPath), /ENOENT/);
+ await assert.rejects(readFile(`${lockPath}.reaper`), /ENOENT/);
+ } finally {
+ await rm(f.cwd, { recursive: true, force: true });
+ }
+ });
+});
diff --git a/src/ultragoal/native-bootstrap.ts b/src/ultragoal/native-bootstrap.ts
new file mode 100644
index 00000000..b9324f7f
--- /dev/null
+++ b/src/ultragoal/native-bootstrap.ts
@@ -0,0 +1,757 @@
+import { randomUUID } from 'node:crypto';
+import { constants as fsConstants } from 'node:fs';
+import { access, chmod, lstat, mkdir, readFile, readdir, rename, unlink, writeFile } from 'node:fs/promises';
+import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
+import {
+ acquireCrossProcessFileLock,
+ isNativeSubagentAuthorityFenced,
+ NATIVE_SUBAGENT_PROVENANCE,
+ readSubagentTrackingState,
+} from '../subagents/tracker.js';
+import type { NativeUltragoalBackend } from '../config/native-ultragoal.js';
+
+export const NATIVE_ULTRAGOAL_BOOTSTRAP_FILE = 'native-ultragoal-bootstrap.json';
+export const NATIVE_ASSIGNMENT_DIRECTORY = 'native-assignments';
+export const DOCUMENTED_HOST_RECEIPT_UNAVAILABLE = 'documented_host_native_executor_receipt_unavailable';
+
+export type NativeUltragoalBootstrapStatus =
+ | 'awaiting-executor'
+ | 'ready'
+ | 'activating'
+ | 'active'
+ | 'revoked'
+ | 'expired'
+ | 'host-receipt-unavailable';
+
+export interface NativeUltragoalBootstrapState {
+ schema_version: 1;
+ kind: 'native-ultragoal-bootstrap';
+ generation: string;
+ backend: NativeUltragoalBackend;
+ status: NativeUltragoalBootstrapStatus;
+ session_id: string;
+ root_thread_id: string;
+ child_agent_id?: string;
+ created_at: string;
+ updated_at: string;
+ expires_at: string;
+ reason?: string;
+}
+
+export interface LocalNativeExecutorAssignment {
+ schema_version: 1;
+ kind: 'native-subagent-assignment';
+ lifecycle: 'active' | 'revoked' | 'expired';
+ root_session_id: string;
+ root_thread_id: string;
+ child_agent_id: string;
+ agent_type: 'executor';
+ allowed_actions: Array<'path-write' | 'bash-write'>;
+ path_prefixes: string[];
+ issued_at: string;
+ expires_at: string;
+ bootstrap_generation: string;
+ revoked_at?: string;
+ revoke_reason?: string;
+}
+
+export interface HostNativeExecutorReceiptVerifier {
+ readonly available: boolean;
+ verifyActivationReceipt(input: {
+ cwd: string;
+ sessionId: string;
+ rootThreadId: string;
+ }): Promise<{ ok: true; childAgentId: string } | { ok: false; reason: string }>;
+}
+
+const ACTIVE_ASSIGNMENT_SCHEMA_KEYS = new Set([
+ 'schema_version',
+ 'kind',
+ 'lifecycle',
+ 'root_session_id',
+ 'root_thread_id',
+ 'child_agent_id',
+ 'agent_type',
+ 'allowed_actions',
+ 'path_prefixes',
+ 'issued_at',
+ 'expires_at',
+ 'bootstrap_generation',
+]);
+const MAX_ASSIGNMENT_LIFETIME_MS = 24 * 60 * 60 * 1000;
+
+export const unavailableHostNativeExecutorReceiptVerifier: HostNativeExecutorReceiptVerifier = {
+ available: false,
+ async verifyActivationReceipt() {
+ return { ok: false, reason: DOCUMENTED_HOST_RECEIPT_UNAVAILABLE };
+ },
+};
+
+function bootstrapPath(stateDir: string, sessionId: string): string {
+ return join(stateDir, 'sessions', sessionId, NATIVE_ULTRAGOAL_BOOTSTRAP_FILE);
+}
+
+async function withNativeUltragoalLifecycleLock<T>(
+ stateDir: string,
+ sessionId: string,
+ operation: () => Promise<T>,
+): Promise<T> {
+ const handle = await acquireCrossProcessFileLock(bootstrapPath(stateDir, sessionId), {
+ maxAttempts: 200,
+ retryMs: 25,
+ preserveLiveLocalOwner: true,
+ });
+ try {
+ const result = await operation();
+ handle.assertOwnership();
+ return result;
+ } finally {
+ handle.release();
+ }
+}
+
+export function nativeExecutorAssignmentPath(stateDir: string, sessionId: string, childAgentId: string): string {
+ return join(
+ stateDir,
+ 'sessions',
+ sessionId,
+ NATIVE_ASSIGNMENT_DIRECTORY,
+ `${encodeURIComponent(childAgentId)}.json`,
+ );
+}
+
+async function writeJsonAtomic(path: string, value: unknown, mode = 0o600): Promise<void> {
+ await mkdir(dirname(path), { recursive: true, mode: 0o700 });
+ const tmpPath = `${path}.tmp.${process.pid}.${Date.now()}.${randomUUID()}`;
+ await writeFile(tmpPath, `${JSON.stringify(value, null, 2)}\n`, { encoding: 'utf-8', mode });
+ try {
+ await chmod(tmpPath, mode);
+ await rename(tmpPath, path);
+ } catch (error) {
+ await unlink(tmpPath).catch(() => {});
+ throw error;
+ }
+}
+
+async function readJsonObject(path: string): Promise<Record<string, unknown> | null> {
+ try {
+ const parsed = JSON.parse(await readFile(path, 'utf-8')) as unknown;
+ return parsed && typeof parsed === 'object' && !Array.isArray(parsed)
+ ? parsed as Record<string, unknown>
+ : null;
+ } catch {
+ return null;
+ }
+}
+
+function readString(value: unknown): string {
+ return typeof value === 'string' ? value.trim() : '';
+}
+
+function normalizePrefix(cwd: string, rawPrefix: string): string | null {
+ const trimmed = rawPrefix.trim().replace(/\\/g, '/');
+ if (trimmed === '.') return '.';
+ if (!trimmed || isAbsolute(trimmed) || trimmed.includes('\0') || /[$`*?\[\]{}]/.test(trimmed)) return null;
+ const absolute = resolve(cwd, trimmed);
+ const normalized = relative(cwd, absolute).replace(/\\/g, '/');
+ if (!normalized || normalized === '..' || normalized.startsWith('../')) return null;
+ if (
+ normalized === '.git'
+ || normalized.startsWith('.git/')
+ || normalized === '.omx'
+ || normalized.startsWith('.omx/')
+ ) return null;
+ return normalized;
+}
+
+async function pathPrefixTraversesUnsafeLink(cwd: string, relativePath: string): Promise<boolean> {
+ if (relativePath === '.') return false;
+ let current = resolve(cwd);
+ for (const segment of relativePath.split('/').filter(Boolean)) {
+ current = join(current, segment);
+ try {
+ const metadata = await lstat(current);
+ if (metadata.isSymbolicLink() || (!metadata.isDirectory() && metadata.nlink > 1)) return true;
+ } catch (error) {
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') continue;
+ return true;
+ }
+ }
+ return false;
+}
+
+export async function parseActiveLocalNativeExecutorAssignment(
+ raw: Record<string, unknown> | null,
+ input: {
+ cwd: string;
+ sessionId: string;
+ rootThreadId: string;
+ childAgentId: string;
+ agentType: string;
+ nowMs?: number;
+ },
+): Promise<(LocalNativeExecutorAssignment & { lifecycle: 'active' }) | null> {
+ if (!raw || Object.keys(raw).some((key) => !ACTIVE_ASSIGNMENT_SCHEMA_KEYS.has(key))) return null;
+ if (
+ raw.schema_version !== 1
+ || raw.kind !== 'native-subagent-assignment'
+ || raw.lifecycle !== 'active'
+ || readString(raw.root_session_id) !== input.sessionId
+ || readString(raw.root_thread_id) !== input.rootThreadId
+ || readString(raw.child_agent_id) !== input.childAgentId
+ || readString(raw.agent_type).toLowerCase() !== 'executor'
+ || input.agentType.trim().toLowerCase() !== 'executor'
+ || !readString(raw.bootstrap_generation)
+ ) return null;
+
+ const nowMs = input.nowMs ?? Date.now();
+ const issuedAt = Date.parse(readString(raw.issued_at));
+ const expiresAt = Date.parse(readString(raw.expires_at));
+ if (
+ !Number.isFinite(issuedAt)
+ || !Number.isFinite(expiresAt)
+ || issuedAt > nowMs + 30_000
+ || expiresAt <= nowMs
+ || expiresAt <= issuedAt
+ || expiresAt - issuedAt > MAX_ASSIGNMENT_LIFETIME_MS
+ ) return null;
+
+ const allowedActions = Array.isArray(raw.allowed_actions)
+ ? raw.allowed_actions.map((value) => readString(value))
+ : [];
+ if (
+ allowedActions.length === 0
+ || allowedActions.length > 2
+ || new Set(allowedActions).size !== allowedActions.length
+ || allowedActions.some((action) => action !== 'path-write' && action !== 'bash-write')
+ ) return null;
+
+ const pathPrefixes = Array.isArray(raw.path_prefixes)
+ ? raw.path_prefixes.map((value) => normalizePrefix(input.cwd, readString(value)))
+ : [];
+ if (
+ pathPrefixes.length === 0
+ || pathPrefixes.length > 32
+ || pathPrefixes.some((prefix) => prefix === null)
+ || new Set(pathPrefixes).size !== pathPrefixes.length
+ ) return null;
+ for (const prefix of pathPrefixes as string[]) {
+ if (await pathPrefixTraversesUnsafeLink(input.cwd, prefix)) return null;
+ }
+
+ return {
+ schema_version: 1,
+ kind: 'native-subagent-assignment',
+ lifecycle: 'active',
+ root_session_id: input.sessionId,
+ root_thread_id: input.rootThreadId,
+ child_agent_id: input.childAgentId,
+ agent_type: 'executor',
+ allowed_actions: allowedActions as Array<'path-write' | 'bash-write'>,
+ path_prefixes: pathPrefixes as string[],
+ issued_at: new Date(issuedAt).toISOString(),
+ expires_at: new Date(expiresAt).toISOString(),
+ bootstrap_generation: readString(raw.bootstrap_generation),
+ };
+}
+
+function parseBootstrap(raw: Record<string, unknown> | null): NativeUltragoalBootstrapState | null {
+ if (
+ raw?.schema_version !== 1
+ || raw.kind !== 'native-ultragoal-bootstrap'
+ || !readString(raw.generation)
+ || !['off', 'host', 'local-experimental'].includes(readString(raw.backend))
+ || ![
+ 'awaiting-executor', 'ready', 'activating', 'active', 'revoked', 'expired', 'host-receipt-unavailable',
+ ].includes(readString(raw.status))
+ || !readString(raw.session_id)
+ || !readString(raw.root_thread_id)
+ || !readString(raw.created_at)
+ || !readString(raw.updated_at)
+ || !readString(raw.expires_at)
+ || !Number.isFinite(Date.parse(readString(raw.expires_at)))
+ ) return null;
+ return raw as unknown as NativeUltragoalBootstrapState;
+}
+
+function parseAssignment(raw: Record<string, unknown> | null): LocalNativeExecutorAssignment | null {
+ if (
+ raw?.schema_version !== 1
+ || raw.kind !== 'native-subagent-assignment'
+ || !['active', 'revoked', 'expired'].includes(readString(raw.lifecycle))
+ || raw.agent_type !== 'executor'
+ || !Array.isArray(raw.allowed_actions)
+ || !Array.isArray(raw.path_prefixes)
+ || !readString(raw.root_session_id)
+ || !readString(raw.root_thread_id)
+ || !readString(raw.child_agent_id)
+ || !readString(raw.issued_at)
+ || !readString(raw.expires_at)
+ || !readString(raw.bootstrap_generation)
+ || !Number.isFinite(Date.parse(readString(raw.expires_at)))
+ ) return null;
+ return raw as unknown as LocalNativeExecutorAssignment;
+}
+
+async function beginNativeUltragoalBootstrapUnlocked(input: {
+ stateDir: string;
+ sessionId: string;
+ rootThreadId: string;
+ backend: NativeUltragoalBackend;
+ ttlSeconds: number;
+ now?: Date;
+}): Promise<NativeUltragoalBootstrapState> {
+ const now = input.now ?? new Date();
+ const existing = parseBootstrap(await readJsonObject(bootstrapPath(input.stateDir, input.sessionId)));
+ if (
+ existing
+ && existing.session_id === input.sessionId
+ && existing.root_thread_id === input.rootThreadId
+ && existing.backend === input.backend
+ && Date.parse(existing.expires_at) > now.getTime()
+ && ['awaiting-executor', 'ready', 'activating', 'active'].includes(existing.status)
+ ) return existing;
+
+ if (existing?.child_agent_id) {
+ const staleAssignmentPath = nativeExecutorAssignmentPath(
+ input.stateDir,
+ input.sessionId,
+ existing.child_agent_id,
+ );
+ const staleAssignment = parseAssignment(await readJsonObject(staleAssignmentPath));
+ if (staleAssignment?.lifecycle === 'active') {
+ await transitionAssignment(
+ staleAssignmentPath,
+ staleAssignment,
+ Date.parse(existing.expires_at) <= now.getTime() ? 'expired' : 'revoked',
+ 'bootstrap_replaced',
+ now,
+ );
+ }
+ }
+
+ const state: NativeUltragoalBootstrapState = {
+ schema_version: 1,
+ kind: 'native-ultragoal-bootstrap',
+ generation: randomUUID(),
+ backend: input.backend,
+ status: input.backend === 'host' ? 'host-receipt-unavailable' : 'awaiting-executor',
+ session_id: input.sessionId,
+ root_thread_id: input.rootThreadId,
+ created_at: now.toISOString(),
+ updated_at: now.toISOString(),
+ expires_at: new Date(now.getTime() + input.ttlSeconds * 1000).toISOString(),
+ ...(input.backend === 'host' ? { reason: DOCUMENTED_HOST_RECEIPT_UNAVAILABLE } : {}),
+ };
+ await writeJsonAtomic(bootstrapPath(input.stateDir, input.sessionId), state);
+ return state;
+}
+
+export async function beginNativeUltragoalBootstrap(
+ input: Parameters<typeof beginNativeUltragoalBootstrapUnlocked>[0],
+): Promise<NativeUltragoalBootstrapState> {
+ return withNativeUltragoalLifecycleLock(input.stateDir, input.sessionId, () => (
+ beginNativeUltragoalBootstrapUnlocked(input)
+ ));
+}
+
+export async function readNativeUltragoalBootstrap(
+ stateDir: string,
+ sessionId: string,
+): Promise<NativeUltragoalBootstrapState | null> {
+ return parseBootstrap(await readJsonObject(bootstrapPath(stateDir, sessionId)));
+}
+
+async function validateTrackedExecutor(input: {
+ cwd: string;
+ sessionId: string;
+ rootThreadId: string;
+ childAgentId: string;
+}): Promise<{ ok: true } | { ok: false; reason: string }> {
+ const tracking = await readSubagentTrackingState(input.cwd).catch(() => null);
+ const session = tracking?.sessions?.[input.sessionId];
+ const child = session?.threads?.[input.childAgentId];
+ if (!session || session.leader_thread_id !== input.rootThreadId) {
+ return { ok: false, reason: 'leader_session_mismatch' };
+ }
+ if (isNativeSubagentAuthorityFenced(input.cwd, input.childAgentId)) {
+ return { ok: false, reason: 'child_authority_fenced' };
+ }
+ if (!child || child.kind !== 'subagent') return { ok: false, reason: 'child_not_tracked' };
+ const role = readString(child.mode || child.role).toLowerCase();
+ if (role !== 'executor') return { ok: false, reason: 'child_role_mismatch' };
+ if (child.provenance_kind !== NATIVE_SUBAGENT_PROVENANCE) {
+ return { ok: false, reason: 'child_native_authority_unproven' };
+ }
+ if (child.reopen_authority_revoked === true) return { ok: false, reason: 'child_authority_revoked' };
+ if (child.status && child.status !== 'available') return { ok: false, reason: `child_${child.status}` };
+ if (child.completed_at) return { ok: false, reason: 'child_completed' };
+ if (child.direct_child_parent_id !== input.rootThreadId) {
+ return { ok: false, reason: 'child_parent_mismatch' };
+ }
+ if (child.direct_child_root_id !== input.rootThreadId) {
+ return { ok: false, reason: 'child_root_mismatch' };
+ }
+ return { ok: true };
+}
+
+async function issueLocalNativeExecutorAssignmentUnlocked(input: {
+ cwd: string;
+ stateDir: string;
+ sessionId: string;
+ rootThreadId: string;
+ childAgentId: string;
+ expectedGeneration: string;
+ pathPrefixes: string[];
+ ttlSeconds: number;
+ allowedActions?: Array<'path-write' | 'bash-write'>;
+ now?: Date;
+}): Promise<LocalNativeExecutorAssignment> {
+ const now = input.now ?? new Date();
+ if (!Number.isInteger(input.ttlSeconds) || input.ttlSeconds < 30 || input.ttlSeconds > 3600) {
+ throw new Error('invalid_native_assignment_ttl');
+ }
+ let bootstrap = await readNativeUltragoalBootstrap(input.stateDir, input.sessionId);
+ const wasActive = bootstrap?.status === 'active';
+ if (
+ !bootstrap
+ || bootstrap.backend !== 'local-experimental'
+ || bootstrap.session_id !== input.sessionId
+ || bootstrap.root_thread_id !== input.rootThreadId
+ || bootstrap.generation !== input.expectedGeneration
+ || !['awaiting-executor', 'ready', 'active'].includes(bootstrap.status)
+ || Date.parse(bootstrap.expires_at) <= now.getTime()
+ ) throw new Error('native_ultragoal_bootstrap_not_ready');
+
+ const tracked = await validateTrackedExecutor(input);
+ if (!tracked.ok) throw new Error(tracked.reason);
+ const normalizedPrefixes = input.pathPrefixes.map((prefix) => normalizePrefix(input.cwd, prefix));
+ if (
+ normalizedPrefixes.length === 0
+ || normalizedPrefixes.length > 32
+ || normalizedPrefixes.some((prefix) => prefix === null)
+ || new Set(normalizedPrefixes).size !== normalizedPrefixes.length
+ ) throw new Error('invalid_native_assignment_path_prefixes');
+ for (const prefix of normalizedPrefixes as string[]) {
+ if (await pathPrefixTraversesUnsafeLink(input.cwd, prefix)) {
+ throw new Error('invalid_native_assignment_path_prefixes');
+ }
+ }
+ const actions = input.allowedActions ?? ['path-write', 'bash-write'];
+ if (
+ actions.length === 0
+ || actions.length > 2
+ || new Set(actions).size !== actions.length
+ || actions.some((action) => action !== 'path-write' && action !== 'bash-write')
+ ) throw new Error('invalid_native_assignment_actions');
+ const requestedExpiry = now.getTime() + input.ttlSeconds * 1000;
+ const expiresAt = wasActive
+ ? requestedExpiry
+ : Math.min(requestedExpiry, Date.parse(bootstrap.expires_at));
+ const assignment: LocalNativeExecutorAssignment = {
+ schema_version: 1,
+ kind: 'native-subagent-assignment',
+ lifecycle: 'active',
+ root_session_id: input.sessionId,
+ root_thread_id: input.rootThreadId,
+ child_agent_id: input.childAgentId,
+ agent_type: 'executor',
+ allowed_actions: actions,
+ path_prefixes: normalizedPrefixes as string[],
+ issued_at: now.toISOString(),
+ expires_at: new Date(expiresAt).toISOString(),
+ bootstrap_generation: bootstrap.generation,
+ };
+ await writeJsonAtomic(
+ nativeExecutorAssignmentPath(input.stateDir, input.sessionId, input.childAgentId),
+ assignment,
+ );
+ await writeJsonAtomic(bootstrapPath(input.stateDir, input.sessionId), {
+ ...bootstrap,
+ status: wasActive ? 'active' : 'ready',
+ child_agent_id: input.childAgentId,
+ updated_at: now.toISOString(),
+ ...(wasActive ? { expires_at: new Date(expiresAt).toISOString(), reason: undefined } : {}),
+ });
+ return assignment;
+}
+
+export async function issueLocalNativeExecutorAssignment(
+ input: Parameters<typeof issueLocalNativeExecutorAssignmentUnlocked>[0],
+): Promise<LocalNativeExecutorAssignment> {
+ return withNativeUltragoalLifecycleLock(input.stateDir, input.sessionId, () => (
+ issueLocalNativeExecutorAssignmentUnlocked(input)
+ ));
+}
+
+export async function nativeExecutorAssignmentFileIsSafe(stateDir: string, path: string): Promise<boolean> {
+ try {
+ const relativePath = relative(resolve(stateDir), resolve(path)).replace(/\\/g, '/');
+ if (!relativePath || relativePath === '..' || relativePath.startsWith('../')) return false;
+ let current = resolve(stateDir);
+ for (const segment of relativePath.split('/').filter(Boolean)) {
+ current = join(current, segment);
+ const metadata = await lstat(current);
+ if (metadata.isSymbolicLink()) return false;
+ if (current === resolve(path)) {
+ if (!metadata.isFile() || metadata.nlink !== 1 || (metadata.mode & 0o022) !== 0 || metadata.size > 64 * 1024) {
+ return false;
+ }
+ } else if (!metadata.isDirectory()) return false;
+ }
+ await access(path, fsConstants.R_OK);
+ return true;
+ } catch {
+ return false;
+ }
+}
+
+async function transitionAssignment(
+ path: string,
+ assignment: LocalNativeExecutorAssignment,
+ lifecycle: 'revoked' | 'expired',
+ reason: string,
+ now = new Date(),
+): Promise<LocalNativeExecutorAssignment> {
+ const next: LocalNativeExecutorAssignment = {
+ ...assignment,
+ lifecycle,
+ revoked_at: now.toISOString(),
+ revoke_reason: reason,
+ };
+ await writeJsonAtomic(path, next);
+ return next;
+}
+
+async function findReadyLocalNativeExecutorAssignmentUnlocked(input: {
+ cwd: string;
+ stateDir: string;
+ sessionId: string;
+ rootThreadId: string;
+ now?: Date;
+}): Promise<LocalNativeExecutorAssignment | null> {
+ const now = input.now ?? new Date();
+ const bootstrap = await readNativeUltragoalBootstrap(input.stateDir, input.sessionId);
+ if (
+ !bootstrap
+ || bootstrap.backend !== 'local-experimental'
+ || bootstrap.root_thread_id !== input.rootThreadId
+ || !bootstrap.child_agent_id
+ || !['ready', 'activating', 'active'].includes(bootstrap.status)
+ || Date.parse(bootstrap.expires_at) <= now.getTime()
+ ) return null;
+ const path = nativeExecutorAssignmentPath(input.stateDir, input.sessionId, bootstrap.child_agent_id);
+ if (!await nativeExecutorAssignmentFileIsSafe(input.stateDir, path)) return null;
+ const rawAssignment = await readJsonObject(path);
+ const transitionableAssignment = parseAssignment(rawAssignment);
+ if (
+ transitionableAssignment?.lifecycle === 'active'
+ && Date.parse(transitionableAssignment.expires_at) <= now.getTime()
+ ) {
+ await transitionAssignment(path, transitionableAssignment, 'expired', 'assignment_expired', now);
+ return null;
+ }
+ const assignment = await parseActiveLocalNativeExecutorAssignment(rawAssignment, {
+ cwd: input.cwd,
+ sessionId: input.sessionId,
+ rootThreadId: input.rootThreadId,
+ childAgentId: bootstrap.child_agent_id,
+ agentType: 'executor',
+ nowMs: now.getTime(),
+ });
+ if (!assignment || assignment.bootstrap_generation !== bootstrap.generation) return null;
+ const tracked = await validateTrackedExecutor({
+ cwd: input.cwd,
+ sessionId: input.sessionId,
+ rootThreadId: input.rootThreadId,
+ childAgentId: assignment.child_agent_id,
+ });
+ if (!tracked.ok) {
+ await transitionAssignment(path, assignment, 'revoked', tracked.reason, now);
+ return null;
+ }
+ return assignment;
+}
+
+export async function findReadyLocalNativeExecutorAssignment(
+ input: Parameters<typeof findReadyLocalNativeExecutorAssignmentUnlocked>[0],
+): Promise<LocalNativeExecutorAssignment | null> {
+ return withNativeUltragoalLifecycleLock(input.stateDir, input.sessionId, () => (
+ findReadyLocalNativeExecutorAssignmentUnlocked(input)
+ ));
+}
+
+async function validateNativeUltragoalActivationReceipt(input: {
+ cwd: string;
+ stateDir: string;
+ sessionId: string;
+ childAgentId: string;
+ now?: Date;
+}, allowedStatuses: NativeUltragoalBootstrapStatus[]): Promise<{
+ ok: true;
+ assignment: LocalNativeExecutorAssignment;
+ bootstrap: NativeUltragoalBootstrapState;
+} | { ok: false }> {
+ const bootstrap = await readNativeUltragoalBootstrap(input.stateDir, input.sessionId);
+ if (
+ !bootstrap
+ || !allowedStatuses.includes(bootstrap.status)
+ || bootstrap.child_agent_id !== input.childAgentId
+ ) return { ok: false };
+ const now = input.now ?? new Date();
+ if (Date.parse(bootstrap.expires_at) <= now.getTime()) return { ok: false };
+ const assignmentPath = nativeExecutorAssignmentPath(input.stateDir, input.sessionId, input.childAgentId);
+ if (!await nativeExecutorAssignmentFileIsSafe(input.stateDir, assignmentPath)) return { ok: false };
+ const assignment = await parseActiveLocalNativeExecutorAssignment(await readJsonObject(assignmentPath), {
+ cwd: input.cwd,
+ sessionId: input.sessionId,
+ rootThreadId: bootstrap.root_thread_id,
+ childAgentId: input.childAgentId,
+ agentType: 'executor',
+ nowMs: now.getTime(),
+ });
+ if (
+ !assignment
+ || assignment.bootstrap_generation !== bootstrap.generation
+ ) return { ok: false };
+ const tracked = await validateTrackedExecutor({
+ cwd: input.cwd,
+ sessionId: input.sessionId,
+ rootThreadId: bootstrap.root_thread_id,
+ childAgentId: input.childAgentId,
+ });
+ if (!tracked.ok) return { ok: false };
+ return { ok: true, assignment, bootstrap };
+}
+
+async function prepareNativeUltragoalBootstrapActivationUnlocked(input: {
+ cwd: string;
+ stateDir: string;
+ sessionId: string;
+ childAgentId: string;
+ now?: Date;
+}): Promise<{ ok: true; assignment: LocalNativeExecutorAssignment } | { ok: false }> {
+ const validated = await validateNativeUltragoalActivationReceipt(input, ['ready', 'activating']);
+ if (!validated.ok) return validated;
+ const { assignment, bootstrap } = validated;
+ if (bootstrap.status !== 'activating') {
+ await writeJsonAtomic(bootstrapPath(input.stateDir, input.sessionId), {
+ ...bootstrap,
+ status: 'activating',
+ updated_at: (input.now ?? new Date()).toISOString(),
+ });
+ }
+ return { ok: true, assignment };
+}
+
+export async function prepareNativeUltragoalBootstrapActivation(
+ input: Parameters<typeof prepareNativeUltragoalBootstrapActivationUnlocked>[0],
+): Promise<{ ok: true; assignment: LocalNativeExecutorAssignment } | { ok: false }> {
+ return withNativeUltragoalLifecycleLock(input.stateDir, input.sessionId, () => (
+ prepareNativeUltragoalBootstrapActivationUnlocked(input)
+ ));
+}
+
+async function markNativeUltragoalBootstrapActiveUnlocked(
+ input: Parameters<typeof prepareNativeUltragoalBootstrapActivationUnlocked>[0],
+): Promise<{ ok: true; assignment: LocalNativeExecutorAssignment } | { ok: false }> {
+ const validated = await validateNativeUltragoalActivationReceipt(input, ['ready', 'activating', 'active']);
+ if (!validated.ok) return validated;
+ const { assignment, bootstrap } = validated;
+ if (bootstrap.status !== 'active') {
+ await writeJsonAtomic(bootstrapPath(input.stateDir, input.sessionId), {
+ ...bootstrap,
+ status: 'active',
+ updated_at: (input.now ?? new Date()).toISOString(),
+ });
+ }
+ return { ok: true, assignment };
+}
+
+export async function markNativeUltragoalBootstrapActive(
+ input: Parameters<typeof markNativeUltragoalBootstrapActiveUnlocked>[0],
+): Promise<{ ok: true; assignment: LocalNativeExecutorAssignment } | { ok: false }> {
+ return withNativeUltragoalLifecycleLock(input.stateDir, input.sessionId, () => (
+ markNativeUltragoalBootstrapActiveUnlocked(input)
+ ));
+}
+
+async function revokeLocalNativeExecutorAssignmentUnlocked(input: {
+ stateDir: string;
+ sessionId: string;
+ childAgentId?: string;
+ reason: string;
+ now?: Date;
+}): Promise<void> {
+ const now = input.now ?? new Date();
+ const bootstrap = await readNativeUltragoalBootstrap(input.stateDir, input.sessionId);
+ const childAgentId = input.childAgentId ?? bootstrap?.child_agent_id;
+ if (childAgentId) {
+ const path = nativeExecutorAssignmentPath(input.stateDir, input.sessionId, childAgentId);
+ const assignment = parseAssignment(await readJsonObject(path));
+ if (assignment?.lifecycle === 'active') {
+ await transitionAssignment(path, assignment, 'revoked', input.reason, now);
+ }
+ }
+ if (bootstrap) {
+ await writeJsonAtomic(bootstrapPath(input.stateDir, input.sessionId), {
+ ...bootstrap,
+ status: 'revoked',
+ updated_at: now.toISOString(),
+ reason: input.reason,
+ });
+ }
+}
+
+export async function revokeLocalNativeExecutorAssignment(
+ input: Parameters<typeof revokeLocalNativeExecutorAssignmentUnlocked>[0],
+): Promise<void> {
+ return withNativeUltragoalLifecycleLock(input.stateDir, input.sessionId, () => (
+ revokeLocalNativeExecutorAssignmentUnlocked(input)
+ ));
+}
+
+async function reconcileLocalNativeExecutorAssignmentsUnlocked(input: {
+ cwd: string;
+ stateDir: string;
+ sessionId: string;
+ rootThreadId: string;
+ now?: Date;
+}): Promise<{ ready: boolean; childAgentId?: string }> {
+ const bootstrap = await readNativeUltragoalBootstrap(input.stateDir, input.sessionId);
+ const directory = join(input.stateDir, 'sessions', input.sessionId, NATIVE_ASSIGNMENT_DIRECTORY);
+ const entries = await readdir(directory).catch(() => []);
+ for (const entry of entries) {
+ if (!entry.endsWith('.json')) continue;
+ const path = join(directory, entry);
+ const assignment = parseAssignment(await readJsonObject(path));
+ if (!assignment || assignment.lifecycle !== 'active') continue;
+ if (
+ !bootstrap
+ || assignment.bootstrap_generation !== bootstrap.generation
+ || assignment.child_agent_id !== bootstrap.child_agent_id
+ ) {
+ await transitionAssignment(path, assignment, 'revoked', 'bootstrap_replaced', input.now);
+ continue;
+ }
+ const tracked = await validateTrackedExecutor({
+ cwd: input.cwd,
+ sessionId: input.sessionId,
+ rootThreadId: input.rootThreadId,
+ childAgentId: assignment.child_agent_id,
+ });
+ if (!tracked.ok) await transitionAssignment(path, assignment, 'revoked', tracked.reason, input.now);
+ }
+ const assignment = await findReadyLocalNativeExecutorAssignmentUnlocked(input);
+ return assignment
+ ? { ready: true, childAgentId: assignment.child_agent_id }
+ : { ready: false };
+}
+
+export async function reconcileLocalNativeExecutorAssignments(
+ input: Parameters<typeof reconcileLocalNativeExecutorAssignmentsUnlocked>[0],
+): Promise<{ ready: boolean; childAgentId?: string }> {
+ return withNativeUltragoalLifecycleLock(input.stateDir, input.sessionId, () => (
+ reconcileLocalNativeExecutorAssignmentsUnlocked(input)
+ ));
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment