@inetafrica/open-claudia 3.4.5 → 3.4.6
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 +6 -0
- package/core/providers/codex-hook.js +7 -5
- package/docs/permissions-audit-2026-07.md +3 -1
- package/package.json +1 -1
- package/test-fixtures/fake-agent-cli.js +1 -2
- package/test-provider-boot-matrix.js +1 -1
- package/test-provider-language.js +8 -1
- package/test-provider-tool-hooks.js +8 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v3.4.6 — Codex runs again: the gate stopped asking for the impossible
|
|
4
|
+
|
|
5
|
+
- **Every Codex turn since Codex CLI 0.153.x failed with `OpenAI Codex is incompatible: Codex rejected the isolated PreToolUse configuration or could not disable uncovered tool transports`.** The mandatory tool-hook gate ran `codex features list` with our overrides and required `unified_exec` to read `false`. Codex 0.153.2, 0.153.3 and 0.153.4 all ignore `-c features.unified_exec=false` (the feature is locked on and `codex features list` reports `unified_exec stable true` regardless), so the gate refused the provider on every turn — the failure Sumeet hit right after switching to gpt-6-astra on 3.4.5.
|
|
6
|
+
- **Why it is safe to stop requiring it off.** Probed live on 0.153.4 (2026-09-05): a shell command run through unified exec still arrives at the PreToolUse hook as tool_name `Bash` with `tool_input.command`, and the real deny gate caught the probe command (deny audited, marker file never written). Unified exec is a covered transport, not an uncovered one. Plugins stay forced off and hooks stay forced on; project trust stays untrusted.
|
|
7
|
+
- **What changed.** `core/providers/codex-hook.js` no longer emits the `features.unified_exec=false` override nor checks its state. Fixtures and the tool-hook tests now model Codex as it is (`unified_exec stable true`) and assert no unified_exec override is generated. Fleet pods are affected identically (the 3.4.4 and 3.4.5 images carry Codex 0.153.x), so Codex on pods works only from this release onward.
|
|
8
|
+
|
|
3
9
|
## v3.4.5 — Astra on the picker, two shortcuts fewer
|
|
4
10
|
|
|
5
11
|
- **gpt-6-astra is offered by the codex provider.** OpenAI rolled GPT-6 (Astra) out to ChatGPT-plan Codex accounts on 2026-09-05 — the earlier 400 (`not supported when using Codex with a ChatGPT account`) was a staged rollout, not client staleness. It sits first in `CODEX_MODELS`, so it appears as a `/model` button; the typed form `/model gpt-6-astra` already worked because the typed path never validated against the list. The default model is unchanged (`gpt-5.6-sol` unless `CODEX_MODEL` is set).
|
|
@@ -38,7 +38,12 @@ function buildCodexHookOverrides({ cwd, nodePath, cliPath } = {}) {
|
|
|
38
38
|
return Object.freeze({
|
|
39
39
|
featuresHooks: "features.hooks=true",
|
|
40
40
|
featuresPlugins: "features.plugins=false",
|
|
41
|
-
|
|
41
|
+
// unified_exec is deliberately NOT forced off. Probed live 2026-09-05 on
|
|
42
|
+
// Codex 0.153.4 (0.153.2 and 0.153.3 behave the same): `-c
|
|
43
|
+
// features.unified_exec=false` is silently ignored — the feature is locked
|
|
44
|
+
// on — while unified-exec shell calls still reach PreToolUse as tool_name
|
|
45
|
+
// "Bash" (the deny gate observed the probe command, marker not executed).
|
|
46
|
+
// Requiring it off made every Codex turn fail MANDATORY_TOOL_HOOK_UNAVAILABLE.
|
|
42
47
|
// A path is a dynamic TOML map key. Current Codex `-c` parsing rejects a
|
|
43
48
|
// quoted path inside dotted-key notation, so replace the isolated projects
|
|
44
49
|
// table with one explicit inline table (user config is ignored below).
|
|
@@ -58,7 +63,6 @@ function hookArgs(overrides) {
|
|
|
58
63
|
"--strict-config",
|
|
59
64
|
"-c", overrides.featuresHooks,
|
|
60
65
|
"-c", overrides.featuresPlugins,
|
|
61
|
-
"-c", overrides.featuresUnifiedExec,
|
|
62
66
|
"-c", overrides.projectTrust,
|
|
63
67
|
"-c", overrides.preToolUse,
|
|
64
68
|
"--dangerously-bypass-hook-trust",
|
|
@@ -150,15 +154,13 @@ function checkCodexHookCompatibility({ binary, runCommand, env, cwd, prepared =
|
|
|
150
154
|
"features",
|
|
151
155
|
"-c", o.featuresHooks,
|
|
152
156
|
"-c", o.featuresPlugins,
|
|
153
|
-
"-c", o.featuresUnifiedExec,
|
|
154
157
|
"-c", o.projectTrust,
|
|
155
158
|
"-c", o.preToolUse,
|
|
156
159
|
"list",
|
|
157
160
|
], opts);
|
|
158
161
|
const configured = features.ok
|
|
159
162
|
&& featureState(features.output, "hooks", true)
|
|
160
|
-
&& featureState(features.output, "plugins", false)
|
|
161
|
-
&& featureState(features.output, "unified_exec", false);
|
|
163
|
+
&& featureState(features.output, "plugins", false);
|
|
162
164
|
result = configured
|
|
163
165
|
? { ok: true, code: null, reason: null }
|
|
164
166
|
: {
|
|
@@ -246,7 +246,9 @@ Verified-OK pathways (no change needed): scheduler re-runs stamp
|
|
|
246
246
|
`OC_CHANNEL_USER_ID` (file gate stays live on approved external re-runs);
|
|
247
247
|
Spaces turns flow through the common router (triage covered); sub-agents
|
|
248
248
|
spawn read-only and inherit channel env; codex transport confinement
|
|
249
|
-
(hooks on, plugins
|
|
249
|
+
(hooks on, plugins off, untrusted trust) is mandatory-or-refuse. unified_exec is
|
|
250
|
+
no longer forced off (2026-09-05): Codex 0.153.x locks it on and its shell calls
|
|
251
|
+
still reach the PreToolUse hook as "Bash".
|
|
250
252
|
|
|
251
253
|
G3 closed with P3 (test-approval-cards.js pins the `apr:` handler). `tool run`
|
|
252
254
|
remains the one authorised channel reachable on external turns — by design:
|
package/package.json
CHANGED
|
@@ -143,7 +143,7 @@ function handleCompatibilityCommand() {
|
|
|
143
143
|
process.stdout.write([
|
|
144
144
|
`hooks stable ${overrides.includes("features.hooks=true")}`,
|
|
145
145
|
`plugins stable ${!overrides.includes("features.plugins=false")}`,
|
|
146
|
-
|
|
146
|
+
"unified_exec stable true",
|
|
147
147
|
].join("\n") + "\n");
|
|
148
148
|
return true;
|
|
149
149
|
}
|
|
@@ -160,7 +160,6 @@ function runHookProbe() {
|
|
|
160
160
|
&& !argv.includes("--profile")
|
|
161
161
|
&& overrides.includes("features.hooks=true")
|
|
162
162
|
&& overrides.includes("features.plugins=false")
|
|
163
|
-
&& overrides.includes("features.unified_exec=false")
|
|
164
163
|
&& overrides.some((value) => /^projects=\{.+trust_level="untrusted".+\}$/.test(value))
|
|
165
164
|
&& hookOverrides.length === 1
|
|
166
165
|
&& /matcher\s*=\s*"\^\(Bash\|apply_patch\)\$"/.test(hookOverrides[0]);
|
|
@@ -34,7 +34,7 @@ if (same("--version")) {
|
|
|
34
34
|
? "--config --json --sandbox --model --skip-git-repo-check --strict-config --ignore-user-config --dangerously-bypass-hook-trust\n"
|
|
35
35
|
: "--config --json --sandbox --image --model --skip-git-repo-check --strict-config --ignore-user-config --dangerously-bypass-hook-trust\n")});
|
|
36
36
|
} else if (${JSON.stringify(kind)} === "codex" && args[0] === "features" && args.at(-1) === "list") {
|
|
37
|
-
process.stdout.write("hooks stable true\\nplugins stable false\\nunified_exec stable
|
|
37
|
+
process.stdout.write("hooks stable true\\nplugins stable false\\nunified_exec stable true\\n");
|
|
38
38
|
} else if (${JSON.stringify(kind)} === "codex" && same("login", "status")) {
|
|
39
39
|
if (${JSON.stringify(mode)} === "unauthenticated") {
|
|
40
40
|
process.stderr.write("not logged in\\n");
|
|
@@ -456,7 +456,14 @@ assert.match(pkg.description, /provider-agnostic coding-agent harness/i);
|
|
|
456
456
|
// joins CODEX_MODELS first; the /claude and /codex shortcuts go — /backend and
|
|
457
457
|
// the /model picker already switch providers; Codex CLI bumped to 0.153.4 on
|
|
458
458
|
// the operator host and the image (unpinned install) picks it up at build.
|
|
459
|
-
|
|
459
|
+
// 3.4.6 prepared 2026-09-05 after Sumeet sent a screenshot of the first Codex
|
|
460
|
+
// turn on 3.4.5 failing ("Codex rejected the isolated PreToolUse configuration
|
|
461
|
+
// or could not disable uncovered tool transports"): Codex 0.153.x ignores
|
|
462
|
+
// `-c features.unified_exec=false` (locked on), so the hook gate refused every
|
|
463
|
+
// Codex turn. Live probe: unified-exec shell calls still reach PreToolUse as
|
|
464
|
+
// tool_name "Bash" and the deny gate caught the probe, so the gate no longer
|
|
465
|
+
// requires unified_exec off. Push approved by Sumeet before release.
|
|
466
|
+
assert.strictEqual(pkg.version, "3.4.6", "release version must remain unchanged without explicit approval");
|
|
460
467
|
for (const keyword of ["claude", "codex", "coding-agent", "provider-agnostic"]) {
|
|
461
468
|
assert.ok(pkg.keywords.includes(keyword), `package keyword missing: ${keyword}`);
|
|
462
469
|
}
|
|
@@ -59,7 +59,7 @@ function compatibleCodexCommand(_binary, args) {
|
|
|
59
59
|
output: [
|
|
60
60
|
"hooks stable true",
|
|
61
61
|
"plugins stable false",
|
|
62
|
-
"unified_exec stable
|
|
62
|
+
"unified_exec stable true",
|
|
63
63
|
].join("\n"),
|
|
64
64
|
code: 0,
|
|
65
65
|
};
|
|
@@ -137,12 +137,15 @@ try {
|
|
|
137
137
|
assert.ok(defaultClaudeInvocation.args.includes("--settings"), "Claude factories enforce the generated hook by default");
|
|
138
138
|
|
|
139
139
|
// Codex uses only transient, generated CLI overrides. User config is ignored,
|
|
140
|
-
// the current project is explicitly untrusted, plugin hooks and
|
|
141
|
-
//
|
|
140
|
+
// the current project is explicitly untrusted, plugin hooks are disabled, and
|
|
141
|
+
// hook trust is bypassed only after exact verification. unified_exec is NOT
|
|
142
|
+
// forced off: Codex 0.153.x ignores the override (locked on) and its shell
|
|
143
|
+
// calls still arrive as tool_name "Bash" (probed live 2026-09-05).
|
|
142
144
|
const overrides = buildCodexHookOverrides({ cwd: projectDir });
|
|
143
145
|
assert.strictEqual(overrides.featuresHooks, "features.hooks=true");
|
|
144
146
|
assert.strictEqual(overrides.featuresPlugins, "features.plugins=false");
|
|
145
|
-
assert.strictEqual(overrides.featuresUnifiedExec, "
|
|
147
|
+
assert.strictEqual(overrides.featuresUnifiedExec, undefined, "unified_exec is no longer forced off (Codex ignores it)");
|
|
148
|
+
assert.ok(!Object.values(overrides).some((value) => String(value).includes("unified_exec")), "no unified_exec override is generated");
|
|
146
149
|
assert.match(overrides.projectTrust, /^projects=\{.+trust_level="untrusted".+\}$/);
|
|
147
150
|
assert.match(overrides.preToolUse, /^hooks\.PreToolUse=/);
|
|
148
151
|
assert.match(overrides.preToolUse, /deny-gate-hook/);
|
|
@@ -158,6 +161,7 @@ try {
|
|
|
158
161
|
assert.ok(prepared.args.includes("--ignore-user-config"));
|
|
159
162
|
assert.ok(prepared.args.includes("--strict-config"));
|
|
160
163
|
assert.ok(prepared.args.includes("--dangerously-bypass-hook-trust"));
|
|
164
|
+
assert.ok(!prepared.args.some((value) => String(value).includes("features.unified_exec")), "argv carries no unified_exec override");
|
|
161
165
|
assert.ok(!prepared.args.includes("--profile"), "a merging Codex profile is never trusted");
|
|
162
166
|
const tampered = Object.freeze({ ...prepared, args: Object.freeze([...prepared.args, "--profile", "project-hooks"]) });
|
|
163
167
|
assert.strictEqual(verifyPreparedCodexHook(tampered), false, "trust bypass rejects non-generated argv");
|