agent-control-plane-core 0.2.2 → 0.2.3
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/package.json +1 -1
- package/src/adapters/codex.mjs +11 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-control-plane-core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Vendor-neutral control-plane contract for coding agents: a normalized ToolCallEvent/Verdict schema with per-agent adapters (Claude Code, Codex) and a conformance suite.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
package/src/adapters/codex.mjs
CHANGED
|
@@ -58,6 +58,10 @@ export const MIN_ENFORCING_VERSION = Object.freeze([0, 135]);
|
|
|
58
58
|
// Both native events gate a tool call; PermissionRequest is the ask-tier veto.
|
|
59
59
|
const GATING_EVENTS = new Set(["PreToolUse", "PermissionRequest"]);
|
|
60
60
|
|
|
61
|
+
// Codex drops an enforced deny that carries no (or an empty) reason and runs the
|
|
62
|
+
// tool, so a reasonless enforced deny still renders a non-empty one.
|
|
63
|
+
const DEFAULT_DENY_REASON = "blocked by monitor";
|
|
64
|
+
|
|
61
65
|
const CONSUMED = new Set([
|
|
62
66
|
"hook_event_name",
|
|
63
67
|
"session_id",
|
|
@@ -163,6 +167,13 @@ export function render(verdict, event, { soleGate = false } = {}) {
|
|
|
163
167
|
body.permissionDecision = vd.decision;
|
|
164
168
|
if (vd.reason !== undefined) body.permissionDecisionReason = vd.reason;
|
|
165
169
|
}
|
|
170
|
+
// Codex FAILS OPEN on an enforced deny whose permissionDecisionReason is missing
|
|
171
|
+
// or empty: its PreToolUse output parser drops the block (block_reason = None)
|
|
172
|
+
// and runs the tool. Unlike Claude, which honours a bare deny, Codex needs a
|
|
173
|
+
// non-empty reason for the block to bite — so guarantee one on every enforced
|
|
174
|
+
// deny, whatever the judge supplied.
|
|
175
|
+
if (enforced && !body.permissionDecisionReason)
|
|
176
|
+
body.permissionDecisionReason = DEFAULT_DENY_REASON;
|
|
166
177
|
if (vd.mutated_input !== undefined) body.updatedInput = vd.mutated_input;
|
|
167
178
|
|
|
168
179
|
return nativeResponse({
|