@mrciphersmith/keryx 0.3.41 → 0.3.42
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/README.md +10 -6
- package/dist/cli.js +61 -20
- package/package.json +1 -1
- package/src/gdskills/contracts/subagent-dispatch.schema.json +1 -1
package/README.md
CHANGED
|
@@ -487,7 +487,7 @@ What is in it today:
|
|
|
487
487
|
bounded parallel scheduling, and an offline fleet report over a recorded event
|
|
488
488
|
log (`keryx agents monitor <events-file>`).
|
|
489
489
|
- **Vendor CLIs as child agents — off by default.** keryx can hand a bounded,
|
|
490
|
-
**read-only** task (or, for `claude-cli`
|
|
490
|
+
**read-only** task (or, for `claude-cli` and `codex-cli`, a reviewed write — see below)
|
|
491
491
|
to a coding CLI you already have installed (`codex exec`,
|
|
492
492
|
`claude -p`, or Google's Antigravity CLI, `agy -p --output-format
|
|
493
493
|
stream-json`) and host it as a child of the same harness: a disposable git
|
|
@@ -509,16 +509,20 @@ What is in it today:
|
|
|
509
509
|
- **A write from an external agent you review before it lands.**
|
|
510
510
|
`keryx agents external run claude-cli --task "…" --write` runs `claude` in a
|
|
511
511
|
throwaway worktree with only `Read Grep Glob Edit Write` (no shell, no network,
|
|
512
|
-
no MCP)
|
|
512
|
+
no MCP); `codex-cli --write` runs `codex` in the same kind of worktree under an
|
|
513
|
+
OS sandbox (as measured: writes outside the worktree fail, a DNS lookup fails, `.git` read-only)
|
|
514
|
+
that still leaves it a shell able to read files your account can read, so review
|
|
515
|
+
its output too. Its diff is captured, secret-redacted, hashed and stored as a pending
|
|
513
516
|
review — nothing reaches your checkout. `keryx agents external review <run-id>`
|
|
514
517
|
shows it; `apply <run-id>` needs a real terminal, shows the diff and asks you to
|
|
515
518
|
type the first 12 hex digits of the patch hash, then creates a NEW local branch
|
|
516
519
|
`external/<run-id>` with one commit. Your current branch and working tree are
|
|
517
520
|
never touched, nothing is pushed and no pull request is opened;
|
|
518
521
|
`discard <run-id>` drops it. There is no flag that skips the confirmation. Only
|
|
519
|
-
`claude-cli`
|
|
520
|
-
review is a human reading the diff (a model review is not built), and
|
|
521
|
-
|
|
522
|
+
`claude-cli` and `codex-cli` can write (`antigravity-cli` refuses `--write`), the
|
|
523
|
+
review is a human reading the diff (a model review is not built), and neither
|
|
524
|
+
has a long live history (`codex` was verified in a scratch repository on
|
|
525
|
+
`codex` 0.159.2; versions outside 0.159.2 up to 0.160.0 are refused). In the TUI: `/external-diff` and a
|
|
522
526
|
sidebar row while a diff waits. See the [external agent write
|
|
523
527
|
guide](docs/docs/guides/external-agent-write.md).
|
|
524
528
|
- **Completion you can audit.** The completion gate blocks on missing evidence: a
|
|
@@ -948,7 +952,7 @@ untouched.
|
|
|
948
952
|
| No bundled embedding runtime | No semantic ranking in memory search | Lexical memory search remains fully available |
|
|
949
953
|
| ripgrep is external | `keryx ctx rg` needs `rg` on `PATH` | Install ripgrep, or let the agent read files directly |
|
|
950
954
|
| Model commands need a credential | Four of the five commands above exit non-zero without one; `wiki enrich` exits `0` and marks the affected pages skipped | Everything else runs deterministically offline |
|
|
951
|
-
| External agents are read-only, except `claude-cli` write mode, which
|
|
955
|
+
| External agents are read-only, except `claude-cli` and `codex-cli` write mode, which have no long live history | A delegated CLI can read and search; only `claude-cli` and `codex-cli` can write, and only as a stored diff a human reviews (`keryx agents external review\|apply\|discard`) that lands as a new local branch — never on your checkout, never pushed. `claude` is confined by a tool allow-list (no shell, no network); `codex` by an OS sandbox that still leaves it a shell that can read files your user can read (it cannot send them, but they can show up in the run output), and is refused when older than 0.159.0 — live-verified in a scratch repository on `codex` 0.159.0. `antigravity-cli` refuses `--write`. A model review is not built. The parent gets the child's result and nothing before it — supervision of a running external child is not implemented. `claude` and `agy` read-only runs are live-verified | Use keryx's own child agents for work that must mutate the tree, or the [external agent write guide](docs/docs/guides/external-agent-write.md) for a reviewed `claude-cli` or `codex-cli` diff |
|
|
952
956
|
| A dispatched `flow-next` task is "done" by checks, not review | `task done` means normal end + a commit on the trigger branch + `keryx health gate` passing in the worktree; nobody has read the diff | Review and merge the `trigger/<flow>-<task>` branch yourself |
|
|
953
957
|
| `trust` dispatch needs Linux + a working bubblewrap | The hardened unattended sandbox (network off, home hidden, allow-listed env) is bwrap-only; without it — or on macOS — a `trust` dispatch refuses before starting | Use `permissionMode: "ask"` (read-only), or run triggers on a Linux host with bwrap |
|
|
954
958
|
| `dispatch.network: true` is the host's full network | The agent's commands then reach the internet and every host loopback service; the model call never needs it (it is made outside the sandbox) | Leave `network` off; review the `trigger/*` branch before installing or building it |
|
package/dist/cli.js
CHANGED
|
@@ -14119,7 +14119,7 @@ var package_default;
|
|
|
14119
14119
|
var init_package = __esm(() => {
|
|
14120
14120
|
package_default = {
|
|
14121
14121
|
name: "@mrciphersmith/keryx",
|
|
14122
|
-
version: "0.3.
|
|
14122
|
+
version: "0.3.42",
|
|
14123
14123
|
description: "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
14124
14124
|
private: false,
|
|
14125
14125
|
publishConfig: {
|
|
@@ -51368,13 +51368,15 @@ permission bridge.
|
|
|
51368
51368
|
A line-stream agent (\`claude-cli\`, \`codex-cli\`) is a DIFFERENT thing:
|
|
51369
51369
|
\`run\` refuses it outright ("speaks the one-way line stream. Delegate to it
|
|
51370
51370
|
from \`keryx shell\` with /delegate"). There is no ACP permission bridge and
|
|
51371
|
-
no patch capture for it
|
|
51372
|
-
ACP transport
|
|
51373
|
-
|
|
51374
|
-
|
|
51375
|
-
\`runtime\` block, and
|
|
51376
|
-
|
|
51377
|
-
|
|
51371
|
+
no patch capture for it in those paths \u2014 \`worktree-write\` is implemented for
|
|
51372
|
+
the ACP transport, and for \`claude-cli\` and \`codex-cli\` only through the
|
|
51373
|
+
operator's own \`keryx agents external run <id> --write\`, which captures the
|
|
51374
|
+
diff for human review. A dispatch that asks for \`worktree-write\` on a
|
|
51375
|
+
line-stream agent anywhere else (the internal \`runtime\` block, and
|
|
51376
|
+
\`keryx shell\`'s /delegate) is REFUSED fail-closed with a distinguishable
|
|
51377
|
+
\`not-implemented\` reason \u2014 never silently accepted and its writes
|
|
51378
|
+
discarded. There it stays \`read-only\`, contained by the same disposable
|
|
51379
|
+
worktree as every external run.
|
|
51378
51380
|
|
|
51379
51381
|
See \`docs/docs/guides/acp-client.md\` for the full ACP contract, including the
|
|
51380
51382
|
output size bounds (a stderr-only flood and an output flood both end the run
|
|
@@ -85139,14 +85141,14 @@ var init_registry3 = __esm(() => {
|
|
|
85139
85141
|
label: "Codex",
|
|
85140
85142
|
binary: "codex",
|
|
85141
85143
|
detect: ["--version"],
|
|
85142
|
-
versionPattern: "codex-cli (\\d+\\.\\d+\\.\\d+)",
|
|
85144
|
+
versionPattern: "codex-cli (\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.]+)?)",
|
|
85143
85145
|
knownGoodRange: { min: "0.147.0" },
|
|
85144
85146
|
sandboxModes: ["read-only", "worktree-write"],
|
|
85145
85147
|
streamingInput: false,
|
|
85146
85148
|
resumable: true,
|
|
85147
85149
|
reportsCost: false,
|
|
85148
85150
|
budgetFlag: false,
|
|
85149
|
-
notes: "Resume requires NOT passing `--ephemeral`: an ephemeral thread fails resume with " + "`no rollout found for thread id \u2026 (code -32600)`. `codex exec resume` also takes a " + "narrower flag set than `codex exec` \u2014 no `-s`, no `-C` \u2014 so
|
|
85151
|
+
notes: "Resume requires NOT passing `--ephemeral`: an ephemeral thread fails resume with " + "`no rollout found for thread id \u2026 (code -32600)`. `codex exec resume` also takes a " + "narrower flag set than `codex exec` \u2014 no `-s`, no `-C` \u2014 so a read-only resume inherits " + "its sandbox, a write run re-asserts its confinement as `-c` overrides, and it must be " + "spawned with cwd already set to the worktree. Write mode needs codex 0.159.2 up to, but not including, 0.160.0."
|
|
85150
85152
|
},
|
|
85151
85153
|
{
|
|
85152
85154
|
id: "claude-cli",
|
|
@@ -85196,10 +85198,27 @@ var init_registry3 = __esm(() => {
|
|
|
85196
85198
|
});
|
|
85197
85199
|
|
|
85198
85200
|
// src/harness/external/dispatch.ts
|
|
85201
|
+
function codecWriteVersionRefusal(entry, version) {
|
|
85202
|
+
const verified = CODEC_WRITE_VERIFIED_VERSIONS[entry.id];
|
|
85203
|
+
if (verified === undefined)
|
|
85204
|
+
return;
|
|
85205
|
+
const range = `\`${entry.binary}\` ${verified.min} up to, but not including, ${verified.before}`;
|
|
85206
|
+
const prefix = `${entry.label} write mode needs ${range}, the versions whose sandbox confinement was measured; `;
|
|
85207
|
+
if (version === undefined)
|
|
85208
|
+
return `${prefix}the installed version could not be read`;
|
|
85209
|
+
if (!/^\d+\.\d+\.\d+$/.test(version))
|
|
85210
|
+
return `${prefix}found ${version}, a pre-release`;
|
|
85211
|
+
if (compareVersions(version, verified.min) < 0)
|
|
85212
|
+
return `${prefix}found ${version}, which is older`;
|
|
85213
|
+
if (compareVersions(version, verified.before) >= 0) {
|
|
85214
|
+
return `${prefix}found ${version}, which is newer and not yet verified: update keryx, or use \`--task\` without \`--write\``;
|
|
85215
|
+
}
|
|
85216
|
+
return;
|
|
85217
|
+
}
|
|
85199
85218
|
function implementedSandboxModesFor(entry, options = {}) {
|
|
85200
85219
|
if (transportOf(entry) === "acp")
|
|
85201
85220
|
return IMPLEMENTED_ACP_SANDBOX_MODES;
|
|
85202
|
-
return entry.id
|
|
85221
|
+
return CODEC_WRITE_AGENT_IDS.includes(entry.id) && options.ownsWriteCapture === true ? IMPLEMENTED_ACP_SANDBOX_MODES : IMPLEMENTED_SANDBOX_MODES;
|
|
85203
85222
|
}
|
|
85204
85223
|
function validateRuntimeBlock(runtime, allowedActions, options = {}) {
|
|
85205
85224
|
if (runtime === undefined || runtime.kind === "keryx") {
|
|
@@ -85241,7 +85260,7 @@ function validateRuntimeBlock(runtime, allowedActions, options = {}) {
|
|
|
85241
85260
|
return {
|
|
85242
85261
|
ok: false,
|
|
85243
85262
|
code: "not-implemented",
|
|
85244
|
-
reason: `sandbox "${sandbox}" is not implemented in this release; only ${implemented.join(", ")} is available` + (sandbox === "worktree-write" && transportOf(entry) !== "acp" ? `; write mode is
|
|
85263
|
+
reason: `sandbox "${sandbox}" is not implemented in this release; only ${implemented.join(", ")} is available` + (sandbox === "worktree-write" && transportOf(entry) !== "acp" ? `; write mode is available for ${CODEC_WRITE_AGENT_IDS.join(", ")} only` + (entry.id === "antigravity-cli" ? ": antigravity-cli's edit tool writes outside the worktree" : "") : "")
|
|
85245
85264
|
};
|
|
85246
85265
|
}
|
|
85247
85266
|
if (sandbox === "read-only") {
|
|
@@ -85267,12 +85286,16 @@ function readRuntimeBlock(dispatch) {
|
|
|
85267
85286
|
return;
|
|
85268
85287
|
return raw;
|
|
85269
85288
|
}
|
|
85270
|
-
var READ_ONLY_FORBIDDEN_ACTIONS, IMPLEMENTED_SANDBOX_MODES, IMPLEMENTED_ACP_SANDBOX_MODES,
|
|
85289
|
+
var READ_ONLY_FORBIDDEN_ACTIONS, IMPLEMENTED_SANDBOX_MODES, IMPLEMENTED_ACP_SANDBOX_MODES, CODEC_WRITE_AGENT_IDS, CODEC_WRITE_VERIFIED_VERSIONS;
|
|
85271
85290
|
var init_dispatch = __esm(() => {
|
|
85272
85291
|
init_registry3();
|
|
85273
85292
|
READ_ONLY_FORBIDDEN_ACTIONS = ["write", "network", "spawn-subagent"];
|
|
85274
85293
|
IMPLEMENTED_SANDBOX_MODES = ["read-only"];
|
|
85275
85294
|
IMPLEMENTED_ACP_SANDBOX_MODES = ["read-only", "worktree-write"];
|
|
85295
|
+
CODEC_WRITE_AGENT_IDS = ["claude-cli", "codex-cli"];
|
|
85296
|
+
CODEC_WRITE_VERIFIED_VERSIONS = {
|
|
85297
|
+
"codex-cli": { min: "0.159.2", before: "0.160.0" }
|
|
85298
|
+
};
|
|
85276
85299
|
});
|
|
85277
85300
|
|
|
85278
85301
|
// src/harness/external/env-deny.ts
|
|
@@ -85806,7 +85829,7 @@ var init_prompt2 = __esm(() => {
|
|
|
85806
85829
|
EXTERNAL_WRITE_RUNTIME_DIRECTIVE = [
|
|
85807
85830
|
"# Runtime directive",
|
|
85808
85831
|
"",
|
|
85809
|
-
"You are running non-interactively as a bounded child agent. Produce the work itself as " + "your final message, in the requested output schema. Do not ask questions, do not offer a " + "choice of modes, do not route to another skill, orchestrator, or flow, do not delegate to " + "another agent. You may create and modify files, only inside your current working " + "directory, using
|
|
85832
|
+
"You are running non-interactively as a bounded child agent. Produce the work itself as " + "your final message, in the requested output schema. Do not ask questions, do not offer a " + "choice of modes, do not route to another skill, orchestrator, or flow, do not delegate to " + "another agent. You may create and modify files, only inside your current working " + "directory, using your file reading, searching and editing tools. Do not use a shell to reach " + "outside it. Do not touch .git, .github, .claude or .metaproject. Your changes are captured as a patch that a " + "human reviews before anything lands, so summarise what you changed in the final message."
|
|
85810
85833
|
].join(`
|
|
85811
85834
|
`);
|
|
85812
85835
|
DIFF_INTRO_COMPLETE = "The operator's uncommitted changes are below. Your worktree is checked out at HEAD and " + "does not contain them, so this diff is the only place they exist for you.";
|
|
@@ -88338,6 +88361,8 @@ function buildCodexArgv(input) {
|
|
|
88338
88361
|
"--ignore-user-config",
|
|
88339
88362
|
"--skip-git-repo-check"
|
|
88340
88363
|
];
|
|
88364
|
+
if (input.sandbox === "worktree-write")
|
|
88365
|
+
argv.push(...CODEX_WRITE_CONFINEMENT_FLAGS);
|
|
88341
88366
|
if (input.resultSchemaPath !== undefined)
|
|
88342
88367
|
argv.push("--output-schema", input.resultSchemaPath);
|
|
88343
88368
|
if (input.model !== undefined)
|
|
@@ -88345,8 +88370,9 @@ function buildCodexArgv(input) {
|
|
|
88345
88370
|
argv.push(input.prompt);
|
|
88346
88371
|
return argv;
|
|
88347
88372
|
}
|
|
88348
|
-
function buildCodexResumeArgv(sessionRef, message) {
|
|
88349
|
-
|
|
88373
|
+
function buildCodexResumeArgv(sessionRef, message, input) {
|
|
88374
|
+
const confinement = input?.sandbox === "worktree-write" ? ["-c", `sandbox_mode="${CODEX_SANDBOX_MODES["worktree-write"]}"`, ...CODEX_WRITE_CONFINEMENT_FLAGS] : [];
|
|
88375
|
+
return ["codex", "exec", "resume", sessionRef, "--json", "--ignore-user-config", "--skip-git-repo-check", ...confinement, message];
|
|
88350
88376
|
}
|
|
88351
88377
|
function parseCodexEvents(line) {
|
|
88352
88378
|
const record = readJsonObject2(line);
|
|
@@ -88501,12 +88527,21 @@ function brief2(text, max = 200) {
|
|
|
88501
88527
|
const flat = text.replace(/\s+/g, " ").trim();
|
|
88502
88528
|
return flat.length <= max ? flat : `${flat.slice(0, max - 1)}\u2026`;
|
|
88503
88529
|
}
|
|
88504
|
-
var CODEX_SANDBOX_MODES, RECOGNISED_TYPES, NARRATED_FAILURE_LINE, CLI_USAGE_PATTERNS, AUTH_PATTERNS2, LIMIT_PATTERNS2, codexCliCodec;
|
|
88530
|
+
var CODEX_SANDBOX_MODES, CODEX_WRITE_CONFINEMENT_FLAGS, RECOGNISED_TYPES, NARRATED_FAILURE_LINE, CLI_USAGE_PATTERNS, AUTH_PATTERNS2, LIMIT_PATTERNS2, codexCliCodec;
|
|
88505
88531
|
var init_codex_cli = __esm(() => {
|
|
88506
88532
|
CODEX_SANDBOX_MODES = {
|
|
88507
88533
|
"read-only": "read-only",
|
|
88508
88534
|
"worktree-write": "workspace-write"
|
|
88509
88535
|
};
|
|
88536
|
+
CODEX_WRITE_CONFINEMENT_FLAGS = [
|
|
88537
|
+
"--ignore-rules",
|
|
88538
|
+
"-c",
|
|
88539
|
+
"sandbox_workspace_write.exclude_slash_tmp=true",
|
|
88540
|
+
"-c",
|
|
88541
|
+
"sandbox_workspace_write.exclude_tmpdir_env_var=true",
|
|
88542
|
+
"-c",
|
|
88543
|
+
"sandbox_workspace_write.network_access=false"
|
|
88544
|
+
];
|
|
88510
88545
|
RECOGNISED_TYPES = new Set([
|
|
88511
88546
|
"thread.started",
|
|
88512
88547
|
"turn.started",
|
|
@@ -88536,7 +88571,7 @@ var init_codex_cli = __esm(() => {
|
|
|
88536
88571
|
parseLine: parseCodexLine,
|
|
88537
88572
|
parseEvents: parseCodexEvents,
|
|
88538
88573
|
classifyFailure: classifyCodexFailure,
|
|
88539
|
-
buildResumeArgv:
|
|
88574
|
+
buildResumeArgv: buildCodexResumeArgv,
|
|
88540
88575
|
isRecognisedLine: isRecognisedCodexLine
|
|
88541
88576
|
};
|
|
88542
88577
|
});
|
|
@@ -88650,15 +88685,21 @@ async function runExternalChild(input, deps) {
|
|
|
88650
88685
|
if (!isAcp && codec === undefined) {
|
|
88651
88686
|
return refuse2("Error", `no codec is registered for external agent "${entry.id}"`);
|
|
88652
88687
|
}
|
|
88688
|
+
let detectedVersion;
|
|
88653
88689
|
if (deps.detect !== undefined) {
|
|
88654
88690
|
const availability = resolveAvailability(entry, await deps.detect(entry.binary, entry.detect));
|
|
88655
88691
|
if (availability.state === "binary-missing") {
|
|
88656
88692
|
return refuse2("Denied", `${entry.label} is not installed (\`${entry.binary}\` not on PATH)`);
|
|
88657
88693
|
}
|
|
88694
|
+
if (availability.state === "available")
|
|
88695
|
+
detectedVersion = availability.version;
|
|
88658
88696
|
if (availability.state === "available" && availability.verdict.state !== "in-range") {
|
|
88659
88697
|
deps.onWarning?.(`${entry.label} version ${availability.version ?? "unknown"} is outside the range this build's fixtures were recorded against`);
|
|
88660
88698
|
}
|
|
88661
88699
|
}
|
|
88700
|
+
const versionRefusal = sandbox === "worktree-write" ? codecWriteVersionRefusal(entry, detectedVersion) : undefined;
|
|
88701
|
+
if (versionRefusal !== undefined)
|
|
88702
|
+
return refuse2("Denied", versionRefusal);
|
|
88662
88703
|
const schemaPrep = await prepareResultSchema();
|
|
88663
88704
|
if (!schemaPrep.ok)
|
|
88664
88705
|
return refuse2("Error", schemaPrep.reason);
|
|
@@ -179443,7 +179484,7 @@ async function runCommand4(args, deps, log) {
|
|
|
179443
179484
|
maxExternalDepth: DEFAULT_MAX_EXTERNAL_DEPTH,
|
|
179444
179485
|
onWarning: (warning) => console.error(`warning: ${plain(warning)}`)
|
|
179445
179486
|
};
|
|
179446
|
-
if (write && id
|
|
179487
|
+
if (write && CODEC_WRITE_AGENT_IDS.includes(id)) {
|
|
179447
179488
|
let handle;
|
|
179448
179489
|
let interrupted = false;
|
|
179449
179490
|
const onSigint = () => {
|
|
@@ -179717,7 +179758,7 @@ function printExternalHelp() {
|
|
|
179717
179758
|
{ flag: "--no-probe", desc: "Skip detection entirely; every entry reports `not-probed`." },
|
|
179718
179759
|
{ flag: "--task", desc: "run: what the agent should do. It runs in a disposable worktree; your tree is never touched." },
|
|
179719
179760
|
{ flag: "--unattended", desc: "run: refuse every permission that would need a human (also implied without a TTY)." },
|
|
179720
|
-
{ flag: "--write", desc: "run: writes land in the disposable worktree and leave as a never-applied patch. An ACP agent advertises fs.writeTextFile; for a line-stream agent only claude
|
|
179761
|
+
{ flag: "--write", desc: "run: writes land in the disposable worktree and leave as a never-applied patch. An ACP agent advertises fs.writeTextFile; for a line-stream agent only claude-cli and codex-cli are supported. claude gets Edit and Write inside the worktree and no shell; codex runs under its OS sandbox (writes confined to the worktree, network closed as far as measured) and keeps a shell that can read any file you can read. codex needs version 0.159.2 or newer but older than 0.160.0. antigravity-cli is refused: its edit tool writes outside the worktree." },
|
|
179721
179762
|
{ flag: "--timeout", desc: "run: wall-clock ceiling in ms (default: externalAgents.defaultTimeoutMs)." }
|
|
179722
179763
|
]);
|
|
179723
179764
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrciphersmith/keryx",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.42",
|
|
4
4
|
"description": "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|
|
@@ -165,7 +165,7 @@
|
|
|
165
165
|
"minLength": 1
|
|
166
166
|
},
|
|
167
167
|
"sandbox": {
|
|
168
|
-
"description": "Permission level for the external child. `worktree-write` is schema-valid but refused at runtime
|
|
168
|
+
"description": "Permission level for the external child. `worktree-write` is schema-valid but refused at runtime except for an ACP agent and, through the operator's `--write` command only, `claude-cli` and `codex-cli`, with a reason distinguishable from an unsupported-by-this-agent refusal.",
|
|
169
169
|
"type": "string",
|
|
170
170
|
"enum": ["read-only", "worktree-write"]
|
|
171
171
|
},
|