@farmslot/agent-runtime 0.17.0 → 0.17.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,18 @@
4
4
 
5
5
  - Active-development baseline; add user-facing changes here before release or package publication.
6
6
 
7
+ ## 0.17.2 - 2026-10-09
8
+
9
+ - The native worker launch digest ignores `GW_URL`, the gateway URL the gateway now injects. A native session saved before the node reported its URL, or reached through another URL for the same gateway, still resumes or parks. Any other launch setting change is still refused. A node built from main never reports its gateway URL, so a gateway with this change sends no `GW_URL` to it and digests match. Only a node built from an intermediate commit of this change, one that reports the URL with an older digest, could see a mismatch. The detached native host belongs to the node and is upgraded with it. A running host is reused (`native/client.ts`), so it must be restarted along with the node.
10
+ - The review launch handshake fails fast on any Codex selection screen it doesn't know (for example "Hooks need review", footer "enter confirm · esc skip") instead of waiting it out and reporting the launch as started.
11
+ - `scripts/review-terminal.cjs` answers Codex 0.162's "Folder access" screen for a review workspace with option 1, Open restricted, once per launch. Codex shows it on every launch in a folder declared untrusted and saves nothing when you choose it, so no config can skip it. Any other prompt, including Trust, or a changed screen fails the launch with the pane excerpt and no key is sent. The launch receipt carries `folderAccess: "restricted"` when it answered.
12
+ - Publish with protocol 0.35.1.
13
+
14
+ ## 0.17.1 - 2026-10-09
15
+
16
+ - `scripts/acceptance-ledger.cjs` is also called by `@farmslot/recipe-cli` `run`, which records a recipe's proof targets with `setAcceptanceVerdict`; its header now names both callers. No behavior change.
17
+ - Publish with protocol 0.35.0 so consumers share one protocol copy.
18
+
7
19
  ## 0.17.0 - 2026-10-04
8
20
 
9
21
  - Docs refer to the recipe runner package as `@farmslot/recipe-runner` (renamed from `@farmslot/recipe-harness`).
@@ -1 +1 @@
1
- {"version":3,"file":"worker-launch.d.ts","sourceRoot":"","sources":["../../src/native/worker-launch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"worker-launch.d.ts","sourceRoot":"","sources":["../../src/native/worker-launch.ts"],"names":[],"mappings":"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"}
@@ -98,6 +98,11 @@ export function decodeNativeWorkerLaunch(value) {
98
98
  environment: { set: set, unset },
99
99
  };
100
100
  }
101
+ /**
102
+ * Gateway routing, not a launch setting: the gateway sets it from the URL the
103
+ * node dials, which may change across a node redeploy or reconnect.
104
+ */
105
+ const ROUTING_ENVIRONMENT = new Set(['GW_URL']);
101
106
  /** Journals compare launch settings without retaining project environment values. */
102
107
  export function nativeWorkerLaunchDigest(launch) {
103
108
  return createHash('sha256')
@@ -108,7 +113,9 @@ export function nativeWorkerLaunchDigest(launch) {
108
113
  effort: launch.effort,
109
114
  ...(launch.filesystemPolicy ? { filesystemPolicy: launch.filesystemPolicy } : {}),
110
115
  environment: {
111
- set: Object.entries(launch.environment.set).sort(([a], [b]) => a.localeCompare(b)),
116
+ set: Object.entries(launch.environment.set)
117
+ .filter(([name]) => !ROUTING_ENVIRONMENT.has(name))
118
+ .sort(([a], [b]) => a.localeCompare(b)),
112
119
  unset: [...new Set(launch.environment.unset)].sort(),
113
120
  },
114
121
  }))
@@ -1 +1 @@
1
- {"version":3,"file":"worker-launch.js","sourceRoot":"","sources":["../../src/native/worker-launch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"worker-launch.js","sourceRoot":"","sources":["../../src/native/worker-launch.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farmslot/agent-runtime",
3
- "version": "0.17.0",
3
+ "version": "0.17.2",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -45,7 +45,7 @@
45
45
  "prepublishOnly": "node ../../scripts/quality/check-farmslot-package-readiness.mjs --publish --packages @farmslot/agent-runtime"
46
46
  },
47
47
  "dependencies": {
48
- "@farmslot/protocol": "0.34.0"
48
+ "@farmslot/protocol": "0.35.1"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@types/node": "^22.0.0",
@@ -6,9 +6,11 @@ const { atomicWrite, readJson } = require('./mark-io.cjs');
6
6
  // Acceptance-criteria ledger (ADR-060; contract in docs/reference/agent-runtime.md
7
7
  // and docs/reference/task-directory-contract.md).
8
8
  //
9
- // `farmslot-agent ac` is the only writer of artifacts/acceptance-status.json, the
10
- // way `mark` is the only writer of SIGNAL.json. The ids come from task init, which
11
- // records the criteria in inputs/handoff.json; this module never invents one.
9
+ // This module is the only writer of artifacts/acceptance-status.json, the way
10
+ // `mark` is the only writer of SIGNAL.json. Two commands call it: `farmslot-agent ac`
11
+ // and a recipe run with a task dir, which records its proof targets
12
+ // (@farmslot/recipe-cli). The ids come from task init, which records the criteria in
13
+ // inputs/handoff.json; this module never invents one.
12
14
  //
13
15
  // The constants and the validate/summarize/render helpers are a behavioral mirror
14
16
  // of @farmslot/protocol/contracts/acceptance (see test/acceptance-ledger-sync.test.mjs).
@@ -0,0 +1,110 @@
1
+ // Codex (0.162+) asks "Folder access" on every interactive launch in a folder
2
+ // declared untrusted, and choosing "Open restricted" saves nothing, so no
3
+ // pre-launch config can skip it. A review terminal answers that one screen with
4
+ // option 1 (Open restricted) once. Any other prompt, or a changed screen, fails
5
+ // the launch instead of pressing keys blindly. The only key ever sent is Enter on
6
+ // the already-selected option 1, so Trust can't be chosen: keep it that way and
7
+ // don't add a path that moves the selection.
8
+
9
+ const BODY =
10
+ 'Config, hooks, and exec policies from untrusted folders stay disabled. ' +
11
+ 'Trusted project folders can still contribute settings. Skills still load, ' +
12
+ 'and tools follow your permission settings. Opening will not change saved trust.';
13
+ // Option 2 and the footer differ when Codex runs under its app-server daemon.
14
+ const ENDINGS = [
15
+ '› 1. Open restricted 2. Quit enter continue · esc quit',
16
+ '› 1. Open restricted 2. Back to Agent Command Center enter continue · esc back',
17
+ ];
18
+ // Any Codex selection screen ends in an "enter …" / "esc …" footer, e.g. "Hooks
19
+ // need review" (enter confirm · esc skip); unknown ones must fail, not wait out.
20
+ const PROMPT_MARKERS =
21
+ /folder access|open restricted|trust this folder|trust and continue|trust all|hooks need review|update available|enter continue|enter confirm|esc quit|esc back|esc skip|press enter|\(y\/n\)/i;
22
+ const WORKING = /esc to interrupt/;
23
+ const COMPOSER = /\? for shortcuts/;
24
+ // The boot splash, and a header frame right after it, already paint the composer
25
+ // footer before Folder access appears, so an idle composer only counts as ready
26
+ // once it has held this long.
27
+ const LOADING = /OpenAI Codex \(v[^)]*\) loading/;
28
+ const IDLE_READY_MS = 1_500;
29
+
30
+ const collapse = (text) => text.replace(/\s+/g, ' ').trim();
31
+
32
+ /**
33
+ * Classify a captured Codex pane: the exact Folder access screen for one of
34
+ * `folders`, any other prompt, a working turn, an idle composer, or starting.
35
+ */
36
+ function classifyCodexLaunchScreen(pane, folders) {
37
+ const text = collapse(pane);
38
+ for (const ending of ENDINGS) {
39
+ const tail = ` ${BODY} ${ending}`;
40
+ if (!text.startsWith('Folder access ') || !text.endsWith(tail)) continue;
41
+ // The folder line wraps at the pane width, so compare it without whitespace.
42
+ const shown = text.slice('Folder access '.length, -tail.length).replace(/\s+/g, '');
43
+ if (folders.some((folder) => folder.replace(/\s+/g, '') === shown))
44
+ return { kind: 'folder-access' };
45
+ }
46
+ if (PROMPT_MARKERS.test(text)) return { kind: 'prompt' };
47
+ if (WORKING.test(text)) return { kind: 'working' };
48
+ if (!LOADING.test(text) && COMPOSER.test(text)) return { kind: 'idle' };
49
+ return { kind: 'starting' };
50
+ }
51
+
52
+ const excerpt = (pane) =>
53
+ pane
54
+ .split('\n')
55
+ .filter((line) => line.trim())
56
+ .slice(-8)
57
+ .join('\n');
58
+
59
+ /**
60
+ * Watch a freshly launched Codex pane until it is working on the prompt, or idle
61
+ * at its composer for IDLE_READY_MS. Returns 'restricted' when it answered the
62
+ * Folder access screen, null otherwise. Throws on any other prompt, or when the
63
+ * screen is still there after its one answer. `claimAnswer` must atomically claim
64
+ * the launch's single answer (false when another watcher of the same launch, or
65
+ * an earlier interrupted one, already holds it); without the claim Folder access
66
+ * is only waited out.
67
+ */
68
+ async function answerCodexFolderAccess({
69
+ capture,
70
+ sendEnter,
71
+ claimAnswer = () => true,
72
+ folders,
73
+ timeoutMs = 15_000,
74
+ settleMs = 2_000,
75
+ pollMs = 250,
76
+ now = Date.now,
77
+ sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
78
+ }) {
79
+ const deadline = now() + timeoutMs;
80
+ let answeredAt = null;
81
+ let idleSince = null;
82
+ while (now() < deadline) {
83
+ await sleep(pollMs);
84
+ const pane = capture();
85
+ // The session ended; the run monitor reports a dead reviewer.
86
+ if (pane === null) break;
87
+ const screen = classifyCodexLaunchScreen(pane, folders);
88
+ if (screen.kind === 'working') break;
89
+ if (screen.kind === 'idle') {
90
+ idleSince ??= now();
91
+ if (now() - idleSince >= IDLE_READY_MS) break;
92
+ continue;
93
+ }
94
+ idleSince = null;
95
+ if (screen.kind === 'prompt')
96
+ throw new Error(`Codex showed an unexpected launch prompt:\n${excerpt(pane)}`);
97
+ if (screen.kind !== 'folder-access') continue;
98
+ if (answeredAt === null) {
99
+ if (claimAnswer()) sendEnter();
100
+ answeredAt = now();
101
+ } else if (now() - answeredAt >= settleMs) {
102
+ throw new Error(
103
+ `Codex still shows Folder access after Open restricted was chosen once:\n${excerpt(pane)}`,
104
+ );
105
+ }
106
+ }
107
+ return answeredAt === null ? null : 'restricted';
108
+ }
109
+
110
+ module.exports = { answerCodexFolderAccess, classifyCodexLaunchScreen };
@@ -3,6 +3,7 @@ const fs = require('node:fs'),
3
3
  path = require('node:path'),
4
4
  cp = require('node:child_process');
5
5
  const { sandbox } = require('./review-filesystem.cjs');
6
+ const { answerCodexFolderAccess } = require('./review-codex-folder-access.cjs');
6
7
  const input = JSON.parse(process.argv[2]);
7
8
  const quote = (s) => "'" + s.replaceAll("'", "'\\''") + "'";
8
9
  const tmux = (args) => cp.spawnSync('tmux', args, { encoding: 'utf8' });
@@ -12,6 +13,45 @@ const check = (result) => {
12
13
  return result.stdout.trim();
13
14
  };
14
15
  const target = input.session;
16
+
17
+ /**
18
+ * Answer Codex's Folder access screen for a launch record. The one Enter per
19
+ * launch is claimed by creating `claim` exclusively, so overlapping or replayed
20
+ * helpers (a gateway restart can leave the first one running) never send two.
21
+ * The marker goes `watching` → `done`; a replay of an unfinished one resumes here.
22
+ */
23
+ async function codexHandshake(marker, claim, record, folders) {
24
+ try {
25
+ await answerCodexFolderAccess({
26
+ capture: () => {
27
+ const pane = tmux(['capture-pane', '-p', '-t', target]);
28
+ return pane.status === 0 ? pane.stdout : null;
29
+ },
30
+ claimAnswer: () => {
31
+ try {
32
+ fs.writeFileSync(claim, record.runId, { mode: 0o600, flag: 'wx' });
33
+ return true;
34
+ } catch (error) {
35
+ if (error.code === 'EEXIST') return false;
36
+ throw error;
37
+ }
38
+ },
39
+ sendEnter: () => check(tmux(['send-keys', '-t', target, 'Enter'])),
40
+ folders,
41
+ });
42
+ } catch (error) {
43
+ tmux(['kill-session', '-t', target]);
44
+ throw error;
45
+ }
46
+ if (fs.existsSync(claim)) record.folderAccess = 'restricted';
47
+ record.codexHandshake = 'done';
48
+ // Replace, never truncate in place: a helper killed mid-write must not leave a
49
+ // marker every replay then fails to parse. Per-process name: helpers can overlap.
50
+ const temporary = `${marker}.${process.pid}.tmp`;
51
+ fs.writeFileSync(temporary, JSON.stringify(record), { mode: 0o600 });
52
+ fs.renameSync(temporary, marker);
53
+ }
54
+
15
55
  async function main() {
16
56
  if (!['launch', 'inspect', 'stop'].includes(input.action))
17
57
  throw Error('Unknown review terminal action');
@@ -31,6 +71,7 @@ async function main() {
31
71
  throw Error('Invalid review terminal identity');
32
72
  const marker = path.join(input.task, '.terminal-launch.json');
33
73
  const cancelled = path.join(input.task, '.terminal-cancelled');
74
+ const claim = path.join(input.task, '.terminal-folder-access-claim');
34
75
  const existing = fs.existsSync(marker) ? JSON.parse(fs.readFileSync(marker, 'utf8')) : undefined;
35
76
  if (
36
77
  existing &&
@@ -64,6 +105,8 @@ async function main() {
64
105
  'Review terminal receipt does not match the requested runner and model; request a new review',
65
106
  );
66
107
  if (has.status !== 0) throw Error('Review terminal exited; explicit retry required');
108
+ if (existing.codexHandshake && existing.codexHandshake !== 'done')
109
+ await codexHandshake(marker, claim, existing, [input.cwd, fs.realpathSync(input.cwd)]);
67
110
  process.stdout.write(JSON.stringify(existing));
68
111
  return;
69
112
  }
@@ -118,6 +161,7 @@ async function main() {
118
161
  model: input.model,
119
162
  startedAt: new Date().toISOString(),
120
163
  signalAttemptId: environment.FARMSLOT_SIGNAL_ATTEMPT_ID,
164
+ ...(input.runner === 'codex' ? { codexHandshake: 'watching' } : {}),
121
165
  };
122
166
  const launch = `const cp=require('node:child_process');const env={...process.env};for(const key of ['FARMSLOT_NODE_TOKEN','FARMSLOT_GATEWAY_TOKEN','FARMSLOT_GATEWAY_PASSWORD','CLAUDECODE'])delete env[key];const r=cp.spawnSync(${JSON.stringify(guard.sandbox.executable)},${JSON.stringify([...guard.sandbox.args, '/bin/sh', '-c', input.command])},{cwd:${JSON.stringify(cwd)},env,stdio:'inherit'});process.exit(r.status??1);`;
123
167
  fs.writeFileSync(commandFile, launch, { mode: 0o600 });
@@ -147,6 +191,7 @@ async function main() {
147
191
  check(tmux(['kill-session', '-t', target]));
148
192
  throw new Error('Review terminal launch was cancelled');
149
193
  }
194
+ if (record.codexHandshake) await codexHandshake(marker, claim, record, [input.cwd, cwd]);
150
195
  process.stdout.write(JSON.stringify(record));
151
196
  }
152
197
  main().catch((error) => {