@weave_protocol/adapter-codex 0.0.0-stage → 0.1.0

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 CHANGED
@@ -1,3 +1,69 @@
1
- # Temporary Holding Version
1
+ # 🛡️ @weave_protocol/adapter-codex
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ > Enforce [WARD.md](https://github.com/Tyox-all/Weave_Protocol/tree/main/ward) in **OpenAI Codex CLI** with its `PreToolUse` hook. Every shell command, file edit and MCP call is checked against your policy before it runs.
4
+
5
+ [![npm](https://img.shields.io/npm/v/@weave_protocol/adapter-codex?color=000&style=flat-square)](https://www.npmjs.com/package/@weave_protocol/adapter-codex)
6
+
7
+ The same WARD.md you use with Claude Code, Antigravity, Microsoft Agent Framework and Gemini CLI.
8
+
9
+ ## Quick start
10
+
11
+ ```bash
12
+ npm i -g @weave_protocol/adapter-codex
13
+ weave-ward-codex init # adds the hook to ~/.codex/hooks.json
14
+ ```
15
+
16
+ Then, in Codex, run **`/hooks`** and trust **"Weave: checking WARD.md"**. Codex skips new or changed hooks until you trust them. Add a `WARD.md` to your project (`npx @weave_protocol/ward init`), or a user-wide one at `~/.codex/WARD.md`.
17
+
18
+ The command is `weave-ward-codex`, not `weave-codex`. The `weave-codex` npm name belongs to W&B Weave's Codex integration, which is a different product.
19
+
20
+ ## What it checks
21
+
22
+ The hook uses Ward's shared evaluator (`evaluateToolCall`), so the rules match the other adapters exactly:
23
+
24
+ - **Shell commands** (`Bash`, including unified exec): the `shell_exec` capability, plus every URL and every absolute or `~` path in the command.
25
+ - **File edits** (`apply_patch`): the files the patch touches, read from its `*** Add File`, `*** Update File`, `*** Move to` and `*** Delete File` lines. Adds, updates and moves are writes; deletes are deletes. Text inside the patch is never treated as a target.
26
+ - **MCP tools** (`mcp__<server>__<tool>`): by name, plus their path and URL arguments.
27
+ - **`update_plan`** uses the `task_planning` capability, the same one the Gemini CLI adapter uses for planning tools.
28
+
29
+ Codex's hosted tools, such as web search, don't go through `PreToolUse`. Neither do some specialized paths, as Codex's docs note. Treat the hook as a guardrail, and combine it with Codex's own sandbox and approval settings.
30
+
31
+ ## Decisions
32
+
33
+ | WARD decision | What Codex sees |
34
+ |---|---|
35
+ | allow | nothing: the call continues, and Codex's own approvals still apply |
36
+ | deny | `permissionDecision: "deny"` with the WARD reason, which the model sees |
37
+ | require_approval | a deny whose reason says approval is needed (Codex hooks don't support "ask") |
38
+
39
+ **Failure modes:**
40
+ - **An invalid WARD.md always denies**, so a typo can't silently switch enforcement off.
41
+ - **No WARD.md anywhere means no enforcement.**
42
+ - **Malformed payloads and evaluator errors** allow by default. `init --fail-closed` makes them deny.
43
+
44
+ WARD.md is looked up in this order:
45
+ 1. `$WEAVE_WARD_PATH`
46
+ 2. `<project>/WARD.md`
47
+ 3. `<project>/.codex/WARD.md`
48
+ 4. `<project>/.weave/WARD.md`
49
+ 5. `$CODEX_HOME/WARD.md` (default `~/.codex/WARD.md`)
50
+
51
+ ## Commands
52
+
53
+ ```bash
54
+ weave-ward-codex init [--matcher=REGEX] [--timeout=SECONDS] [--fail-closed]
55
+ weave-ward-codex disable
56
+ weave-ward-codex status
57
+ weave-ward-codex test Bash --input='{"command":"cat secrets/key"}' # dry run
58
+ weave-ward-codex hook pre-tool-use # what Codex runs
59
+ ```
60
+
61
+ `init` writes to `$CODEX_HOME/hooks.json` (default `~/.codex/hooks.json`). It backs the file up, edits it atomically, and finds its own entry by its status message, so your other hooks are untouched.
62
+
63
+ ## Verified
64
+
65
+ Built against Codex's [hooks documentation](https://developers.openai.com/codex/hooks): the `PreToolUse` payload, deny output, `apply_patch` and MCP tool naming. 12 fixture tests.
66
+
67
+ ## License
68
+
69
+ Apache-2.0
package/dist/cli.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * weave-ward-codex CLI
4
+ *
5
+ * weave-ward-codex init [--matcher=REGEX] [--timeout=SECONDS] [--fail-closed] Install the WARD hook
6
+ * weave-ward-codex disable Remove it
7
+ * weave-ward-codex status Hook + active WARD.md
8
+ * weave-ward-codex test <tool> [--input=JSON] Dry-run a tool call
9
+ * weave-ward-codex hook pre-tool-use [--fail-closed] Hook handler (run by Codex)
10
+ *
11
+ * (Not "weave-codex": that npm name belongs to W&B Weave's Codex integration.)
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;GAUG"}
package/dist/cli.js ADDED
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * weave-ward-codex CLI
4
+ *
5
+ * weave-ward-codex init [--matcher=REGEX] [--timeout=SECONDS] [--fail-closed] Install the WARD hook
6
+ * weave-ward-codex disable Remove it
7
+ * weave-ward-codex status Hook + active WARD.md
8
+ * weave-ward-codex test <tool> [--input=JSON] Dry-run a tool call
9
+ * weave-ward-codex hook pre-tool-use [--fail-closed] Hook handler (run by Codex)
10
+ *
11
+ * (Not "weave-codex": that npm name belongs to W&B Weave's Codex integration.)
12
+ */
13
+ import { installHook, removeHook, isHookInstalled, readHooks, hooksJsonPath, userWardPath } from './config.js';
14
+ import { resolveWardForCwd, evaluateCall, runPreToolUseHook } from './hook.js';
15
+ const tty = process.stderr.isTTY && !process.env.NO_COLOR;
16
+ const c = {
17
+ reset: tty ? '\x1b[0m' : '', bold: tty ? '\x1b[1m' : '', red: tty ? '\x1b[31m' : '',
18
+ green: tty ? '\x1b[32m' : '', yellow: tty ? '\x1b[33m' : '', cyan: tty ? '\x1b[36m' : '', gray: tty ? '\x1b[90m' : '',
19
+ };
20
+ const say = (s = '') => console.error(s);
21
+ const flag = (args, name) => args.includes(`--${name}`);
22
+ const option = (args, name) => args.find((a) => a.startsWith(`--${name}=`))?.slice(name.length + 3);
23
+ function help() {
24
+ say(`\n${c.cyan}${c.bold}🛡️ weave-ward-codex${c.reset} ${c.gray}WARD.md enforcement for OpenAI Codex CLI${c.reset}\n`);
25
+ say(`${c.bold}Commands:${c.reset}`);
26
+ say(` ${c.cyan}init${c.reset} ${c.gray}[--matcher=REGEX] [--timeout=SECONDS] [--fail-closed]${c.reset} Install the PreToolUse hook in ~/.codex/hooks.json`);
27
+ say(` ${c.cyan}disable${c.reset} Remove the hook`);
28
+ say(` ${c.cyan}status${c.reset} Show the hook and the active WARD.md`);
29
+ say(` ${c.cyan}test${c.reset} ${c.gray}<tool> [--input=JSON]${c.reset} Dry-run a tool call against WARD.md`);
30
+ say(` ${c.cyan}hook pre-tool-use${c.reset} ${c.gray}[--fail-closed]${c.reset} Hook handler (Codex runs this)\n`);
31
+ return 0;
32
+ }
33
+ function init(args) {
34
+ const timeout = option(args, 'timeout');
35
+ installHook({
36
+ matcher: option(args, 'matcher'),
37
+ timeoutSeconds: timeout ? Number(timeout) : undefined,
38
+ failClosed: flag(args, 'fail-closed'),
39
+ });
40
+ say(`${c.green}✓${c.reset} WARD hook installed in ${hooksJsonPath()}`);
41
+ say(`${c.yellow}!${c.reset} Codex skips new hooks until you trust them: run ${c.bold}/hooks${c.reset} in Codex and trust "${'Weave: checking WARD.md'}".`);
42
+ const ward = safeResolve(process.cwd());
43
+ if (!ward) {
44
+ say(`${c.yellow}!${c.reset} No WARD.md found here or at ${userWardPath()}; calls are allowed until you add one.`);
45
+ }
46
+ return 0;
47
+ }
48
+ function disable() {
49
+ const { removed } = removeHook();
50
+ say(removed ? `${c.green}✓${c.reset} Removed the WARD hook from ${hooksJsonPath()}` : 'No WARD hook was installed.');
51
+ return 0;
52
+ }
53
+ function safeResolve(cwd) {
54
+ try {
55
+ return resolveWardForCwd(cwd);
56
+ }
57
+ catch (err) {
58
+ say(`${c.red}✗${c.reset} ${err instanceof Error ? err.message : String(err)}`);
59
+ return null;
60
+ }
61
+ }
62
+ function status() {
63
+ const installed = isHookInstalled(readHooks());
64
+ say(`Hook: ${installed ? `${c.green}installed${c.reset}` : `${c.yellow}not installed${c.reset}`} (${hooksJsonPath()})`);
65
+ const ward = safeResolve(process.cwd());
66
+ say(`WARD.md: ${ward ? ward.source : `${c.yellow}none found${c.reset}`}`);
67
+ return installed && ward ? 0 : 1;
68
+ }
69
+ function test(args) {
70
+ const tool = args.find((a) => !a.startsWith('--'));
71
+ if (!tool) {
72
+ say('Usage: weave-ward-codex test <tool> [--input=JSON]');
73
+ return 2;
74
+ }
75
+ const ward = safeResolve(process.cwd());
76
+ if (!ward) {
77
+ say('No WARD.md found; nothing to test against.');
78
+ return 2;
79
+ }
80
+ const input = JSON.parse(option(args, 'input') ?? '{}');
81
+ const result = evaluateCall(ward.policy, tool, input, process.cwd());
82
+ const color = result.decision === 'allow' ? c.green : result.decision === 'deny' ? c.red : c.yellow;
83
+ say(`${color}${result.decision}${c.reset} ${tool}`);
84
+ for (const r of result.reasons)
85
+ say(` ${c.gray}${r}${c.reset}`);
86
+ return result.decision === 'allow' ? 0 : 1;
87
+ }
88
+ async function main() {
89
+ const [cmd, ...rest] = process.argv.slice(2);
90
+ switch (cmd) {
91
+ case 'init': return init(rest);
92
+ case 'disable':
93
+ case 'uninstall': return disable();
94
+ case 'status': return status();
95
+ case 'test': return test(rest);
96
+ case 'hook':
97
+ if (rest[0] === 'pre-tool-use' || !rest[0])
98
+ return runPreToolUseHook(flag(rest, 'fail-closed'));
99
+ // Other events: print nothing, so the call continues
100
+ return 0;
101
+ default: return help();
102
+ }
103
+ }
104
+ main().then((code) => process.exit(code), (err) => {
105
+ say(`weave-ward-codex: ${err instanceof Error ? err.message : String(err)}`);
106
+ process.exit(1);
107
+ });
108
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Manage $CODEX_HOME/hooks.json (default ~/.codex/hooks.json) — install,
3
+ * remove, inspect the WARD hook.
4
+ *
5
+ * Safety rules:
6
+ * - Back up hooks.json before changing it, and write atomically
7
+ * - Idempotent: init twice leaves one entry
8
+ * - Our entry is found by its statusMessage; other hooks are untouched
9
+ *
10
+ * Codex skips new or changed hooks until they are trusted: after init, run
11
+ * /hooks in Codex and trust the Weave hook.
12
+ */
13
+ import type { CodexHookGroup } from './types.js';
14
+ export declare const STATUS_MESSAGE = "Weave: checking WARD.md";
15
+ export declare function codexHome(): string;
16
+ export declare function hooksJsonPath(): string;
17
+ /** User-global WARD.md, used when a project has none. */
18
+ export declare function userWardPath(): string;
19
+ export interface HooksFile {
20
+ description?: string;
21
+ hooks?: {
22
+ PreToolUse?: CodexHookGroup[];
23
+ [event: string]: CodexHookGroup[] | undefined;
24
+ };
25
+ [other: string]: unknown;
26
+ }
27
+ export declare function readHooks(path?: string): HooksFile;
28
+ export declare function writeHooks(file: HooksFile, path?: string): void;
29
+ export interface InstallOptions {
30
+ /** Command that runs this CLI. Default: "weave-ward-codex" */
31
+ binary?: string;
32
+ /** Regex of tool names to gate. Default: every tool */
33
+ matcher?: string;
34
+ /** Hook timeout in seconds (Codex's unit). Default 10 */
35
+ timeoutSeconds?: number;
36
+ /** Deny on malformed payloads and evaluator errors. Default: allow */
37
+ failClosed?: boolean;
38
+ }
39
+ export declare function isHookInstalled(file?: HooksFile): boolean;
40
+ export declare function installHook(opts?: InstallOptions): HooksFile;
41
+ export declare function removeHook(): {
42
+ removed: number;
43
+ file: HooksFile;
44
+ };
45
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,eAAO,MAAM,cAAc,4BAA4B,CAAC;AAExD,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,yDAAyD;AACzD,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,MAAM,WAAW,SAAS;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE;QACN,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;QAC9B,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,EAAE,GAAG,SAAS,CAAC;KAC/C,CAAC;IACF,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED,wBAAgB,SAAS,CAAC,IAAI,SAAkB,GAAG,SAAS,CAS3D;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,SAAkB,GAAG,IAAI,CAMxE;AAED,MAAM,WAAW,cAAc;IAC7B,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sEAAsE;IACtE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAID,wBAAgB,eAAe,CAAC,IAAI,GAAE,SAAuB,GAAG,OAAO,CAEtE;AAED,wBAAgB,WAAW,CAAC,IAAI,GAAE,cAAmB,GAAG,SAAS,CAWhE;AAED,wBAAgB,UAAU,IAAI;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,SAAS,CAAA;CAAE,CAWjE"}
package/dist/config.js ADDED
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Manage $CODEX_HOME/hooks.json (default ~/.codex/hooks.json) — install,
3
+ * remove, inspect the WARD hook.
4
+ *
5
+ * Safety rules:
6
+ * - Back up hooks.json before changing it, and write atomically
7
+ * - Idempotent: init twice leaves one entry
8
+ * - Our entry is found by its statusMessage; other hooks are untouched
9
+ *
10
+ * Codex skips new or changed hooks until they are trusted: after init, run
11
+ * /hooks in Codex and trust the Weave hook.
12
+ */
13
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, renameSync, copyFileSync } from 'node:fs';
14
+ import { dirname, join, resolve } from 'node:path';
15
+ import { homedir } from 'node:os';
16
+ export const STATUS_MESSAGE = 'Weave: checking WARD.md';
17
+ export function codexHome() {
18
+ return process.env.CODEX_HOME ? resolve(process.env.CODEX_HOME) : join(homedir(), '.codex');
19
+ }
20
+ export function hooksJsonPath() {
21
+ return join(codexHome(), 'hooks.json');
22
+ }
23
+ /** User-global WARD.md, used when a project has none. */
24
+ export function userWardPath() {
25
+ return join(codexHome(), 'WARD.md');
26
+ }
27
+ export function readHooks(path = hooksJsonPath()) {
28
+ if (!existsSync(path))
29
+ return {};
30
+ try {
31
+ return JSON.parse(readFileSync(path, 'utf8'));
32
+ }
33
+ catch (err) {
34
+ throw new Error(`Failed to parse ${path}; fix the JSON or move it aside and re-run. ${err instanceof Error ? err.message : String(err)}`);
35
+ }
36
+ }
37
+ export function writeHooks(file, path = hooksJsonPath()) {
38
+ mkdirSync(dirname(path), { recursive: true });
39
+ if (existsSync(path))
40
+ copyFileSync(path, `${path}.weave-backup`);
41
+ const tmp = `${path}.tmp`;
42
+ writeFileSync(tmp, JSON.stringify(file, null, 2) + '\n', 'utf8');
43
+ renameSync(tmp, path);
44
+ }
45
+ const ours = (g) => g.hooks?.some((h) => h.statusMessage === STATUS_MESSAGE);
46
+ export function isHookInstalled(file = readHooks()) {
47
+ return (file.hooks?.PreToolUse ?? []).some(ours);
48
+ }
49
+ export function installHook(opts = {}) {
50
+ const file = readHooks();
51
+ const command = `${opts.binary ?? 'weave-ward-codex'} hook pre-tool-use${opts.failClosed ? ' --fail-closed' : ''}`;
52
+ const group = {
53
+ matcher: opts.matcher ?? '*',
54
+ hooks: [{ type: 'command', command, timeout: opts.timeoutSeconds ?? 10, statusMessage: STATUS_MESSAGE }],
55
+ };
56
+ const hooks = (file.hooks ??= {});
57
+ hooks.PreToolUse = [...(hooks.PreToolUse ?? []).filter((g) => !ours(g)), group];
58
+ writeHooks(file);
59
+ return file;
60
+ }
61
+ export function removeHook() {
62
+ const file = readHooks();
63
+ const before = file.hooks?.PreToolUse ?? [];
64
+ const after = before.filter((g) => !ours(g));
65
+ const removed = before.length - after.length;
66
+ if (removed > 0 && file.hooks) {
67
+ if (after.length)
68
+ file.hooks.PreToolUse = after;
69
+ else
70
+ delete file.hooks.PreToolUse;
71
+ writeHooks(file);
72
+ }
73
+ return { removed, file };
74
+ }
75
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/hook.d.ts ADDED
@@ -0,0 +1,35 @@
1
+ /**
2
+ * PreToolUse hook handler: reads Codex's payload from stdin, finds the
3
+ * active WARD.md, decides with Ward's shared evaluator, and prints a deny or
4
+ * nothing.
5
+ *
6
+ * WARD.md resolution (cwd = the payload's cwd):
7
+ * 1. $WEAVE_WARD_PATH
8
+ * 2. <cwd>/WARD.md
9
+ * 3. <cwd>/.codex/WARD.md
10
+ * 4. <cwd>/.weave/WARD.md
11
+ * 5. $CODEX_HOME/WARD.md (default ~/.codex/WARD.md)
12
+ *
13
+ * Failure modes:
14
+ * - A WARD.md that exists but is invalid always denies: a typo must not
15
+ * silently switch enforcement off.
16
+ * - Malformed payloads and evaluator errors allow by default (with a note
17
+ * on stderr); --fail-closed denies instead.
18
+ */
19
+ import { type WardPolicy } from '@weave_protocol/ward';
20
+ import { type CodexHookOutput } from './types.js';
21
+ export interface ResolvedWard {
22
+ policy: WardPolicy;
23
+ source: string;
24
+ }
25
+ export interface HookDecision {
26
+ decision: 'allow' | 'deny' | 'require_approval';
27
+ reasons: string[];
28
+ }
29
+ export declare function resolveWardForCwd(cwd: string): ResolvedWard | null;
30
+ /** Decide a Codex tool call against a WARD policy. */
31
+ export declare function evaluateCall(policy: WardPolicy, toolName: string, toolInput: unknown, cwd?: string): HookDecision;
32
+ /** WARD decision → Codex output; undefined means print nothing (continue). */
33
+ export declare function toHookOutput(result: HookDecision, source: string): CodexHookOutput | undefined;
34
+ export declare function runPreToolUseHook(failClosed: boolean): Promise<never>;
35
+ //# sourceMappingURL=hook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../src/hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,EAAsC,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAC3F,OAAO,EAAsC,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAItF,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,kBAAkB,CAAC;IAChD,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAmBlE;AAID,sDAAsD;AACtD,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,GAAE,MAAsB,GAAG,YAAY,CA0BhI;AAED,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAM9F;AAmBD,wBAAsB,iBAAiB,CAAC,UAAU,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAoC3E"}
package/dist/hook.js ADDED
@@ -0,0 +1,137 @@
1
+ /**
2
+ * PreToolUse hook handler: reads Codex's payload from stdin, finds the
3
+ * active WARD.md, decides with Ward's shared evaluator, and prints a deny or
4
+ * nothing.
5
+ *
6
+ * WARD.md resolution (cwd = the payload's cwd):
7
+ * 1. $WEAVE_WARD_PATH
8
+ * 2. <cwd>/WARD.md
9
+ * 3. <cwd>/.codex/WARD.md
10
+ * 4. <cwd>/.weave/WARD.md
11
+ * 5. $CODEX_HOME/WARD.md (default ~/.codex/WARD.md)
12
+ *
13
+ * Failure modes:
14
+ * - A WARD.md that exists but is invalid always denies: a typo must not
15
+ * silently switch enforcement off.
16
+ * - Malformed payloads and evaluator errors allow by default (with a note
17
+ * on stderr); --fail-closed denies instead.
18
+ */
19
+ import { readFileSync, existsSync } from 'node:fs';
20
+ import { join, resolve } from 'node:path';
21
+ import { parseAndValidate, evaluateToolCall } from '@weave_protocol/ward';
22
+ import { TOOL_MAPPINGS } from './types.js';
23
+ import { patchTargets } from './patch.js';
24
+ import { userWardPath } from './config.js';
25
+ export function resolveWardForCwd(cwd) {
26
+ const candidates = [
27
+ process.env.WEAVE_WARD_PATH,
28
+ cwd && join(cwd, 'WARD.md'),
29
+ cwd && join(cwd, '.codex', 'WARD.md'),
30
+ cwd && join(cwd, '.weave', 'WARD.md'),
31
+ userWardPath(),
32
+ ].filter((p) => !!p);
33
+ for (const path of candidates) {
34
+ const full = resolve(path);
35
+ if (!existsSync(full))
36
+ continue;
37
+ const result = parseAndValidate(readFileSync(full, 'utf8'));
38
+ if (!result.valid || !result.policy) {
39
+ throw new Error(`Invalid WARD.md at ${full}: ${result.errors.map((e) => e.message).join('; ')}`);
40
+ }
41
+ return { policy: result.policy, source: full };
42
+ }
43
+ return null;
44
+ }
45
+ const RANK = { allow: 0, require_approval: 1, deny: 2 };
46
+ /** Decide a Codex tool call against a WARD policy. */
47
+ export function evaluateCall(policy, toolName, toolInput, cwd = process.cwd()) {
48
+ const input = toolInput && typeof toolInput === 'object' && !Array.isArray(toolInput)
49
+ ? toolInput
50
+ : { command: toolInput };
51
+ const opts = { mappings: TOOL_MAPPINGS, cwd };
52
+ // apply_patch: the files the patch writes and deletes, not its text
53
+ if (toolName === 'apply_patch') {
54
+ const { writes, deletes } = patchTargets(String(input.command ?? ''));
55
+ const results = [
56
+ evaluateToolCall(policy, 'apply_patch', { target: writes }, {
57
+ ...opts, mappings: { apply_patch: { capability: 'file_write', pathField: 'target', fsOp: 'write' } },
58
+ }),
59
+ ...(deletes.length
60
+ ? [evaluateToolCall(policy, 'apply_patch', { target: deletes }, {
61
+ ...opts, mappings: { apply_patch: { capability: 'file_write', pathField: 'target', fsOp: 'delete' } },
62
+ })]
63
+ : []),
64
+ ];
65
+ const worst = results.reduce((a, b) => (RANK[b.decision] > RANK[a.decision] ? b : a));
66
+ return { decision: worst.decision, reasons: results.flatMap((r) => r.reasons) };
67
+ }
68
+ const { decision, reasons } = evaluateToolCall(policy, toolName, input, opts);
69
+ return { decision, reasons };
70
+ }
71
+ /** WARD decision → Codex output; undefined means print nothing (continue). */
72
+ export function toHookOutput(result, source) {
73
+ if (result.decision === 'allow')
74
+ return undefined;
75
+ const reason = result.decision === 'deny'
76
+ ? `WARD: ${result.reasons.join(' | ')} (policy: ${source})`
77
+ : `WARD requires approval before this call: ${result.reasons.join(' | ')} (policy: ${source}). Ask the user to approve it or update WARD.md.`;
78
+ return { hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'deny', permissionDecisionReason: reason } };
79
+ }
80
+ async function readStdin() {
81
+ if (process.stdin.isTTY)
82
+ return '';
83
+ let data = '';
84
+ process.stdin.setEncoding('utf8');
85
+ for await (const chunk of process.stdin)
86
+ data += chunk;
87
+ return data;
88
+ }
89
+ function emit(output) {
90
+ if (output)
91
+ process.stdout.write(JSON.stringify(output));
92
+ process.exit(0);
93
+ }
94
+ const denyWith = (reason) => ({
95
+ hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'deny', permissionDecisionReason: reason },
96
+ });
97
+ export async function runPreToolUseHook(failClosed) {
98
+ const raw = await readStdin();
99
+ if (!raw.trim())
100
+ emit();
101
+ let payload;
102
+ try {
103
+ payload = JSON.parse(raw);
104
+ }
105
+ catch {
106
+ if (failClosed)
107
+ emit(denyWith('WARD hook: malformed payload from Codex'));
108
+ process.stderr.write('weave-ward-codex: malformed hook payload, allowing\n');
109
+ emit();
110
+ }
111
+ if (!payload.tool_name)
112
+ emit();
113
+ const cwd = payload.cwd || process.cwd();
114
+ let resolved;
115
+ try {
116
+ resolved = resolveWardForCwd(cwd);
117
+ }
118
+ catch (err) {
119
+ // A policy exists but can't be used: deny rather than run unprotected.
120
+ emit(denyWith(`WARD policy could not be loaded: ${err instanceof Error ? err.message : String(err)}. Fix WARD.md to continue.`));
121
+ }
122
+ if (!resolved)
123
+ emit();
124
+ let result;
125
+ try {
126
+ result = evaluateCall(resolved.policy, payload.tool_name, payload.tool_input, cwd);
127
+ }
128
+ catch (err) {
129
+ const msg = err instanceof Error ? err.message : String(err);
130
+ if (failClosed)
131
+ emit(denyWith(`WARD evaluation failed: ${msg}`));
132
+ process.stderr.write(`weave-ward-codex: WARD evaluation failed (${msg}), allowing\n`);
133
+ emit();
134
+ }
135
+ emit(toHookOutput(result, resolved.source));
136
+ }
137
+ //# sourceMappingURL=hook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook.js","sourceRoot":"","sources":["../src/hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAmB,MAAM,sBAAsB,CAAC;AAC3F,OAAO,EAAE,aAAa,EAA6C,MAAM,YAAY,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAY3C,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,MAAM,UAAU,GAAG;QACjB,OAAO,CAAC,GAAG,CAAC,eAAe;QAC3B,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC;QAC3B,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,SAAS,CAAC;QACrC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,SAAS,CAAC;QACrC,YAAY,EAAE;KACf,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAElC,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,SAAS;QAChC,MAAM,MAAM,GAAG,gBAAgB,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QAC5D,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,KAAK,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnG,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACjD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,IAAI,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAW,CAAC;AAEjE,sDAAsD;AACtD,MAAM,UAAU,YAAY,CAAC,MAAkB,EAAE,QAAgB,EAAE,SAAkB,EAAE,GAAG,GAAW,OAAO,CAAC,GAAG,EAAE;IAChH,MAAM,KAAK,GACT,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;QACrE,CAAC,CAAE,SAAqC;QACxC,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,EAAE,QAAQ,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC;IAE9C,oEAAoE;IACpE,IAAI,QAAQ,KAAK,aAAa,EAAE,CAAC;QAC/B,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;QACtE,MAAM,OAAO,GAAG;YACd,gBAAgB,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;gBAC1D,GAAG,IAAI,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;aACrG,CAAC;YACF,GAAG,CAAC,OAAO,CAAC,MAAM;gBAChB,CAAC,CAAC,CAAC,gBAAgB,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE;wBAC9D,GAAG,IAAI,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;qBACtG,CAAC,CAAC;gBACH,CAAC,CAAC,EAAE,CAAC;SACR,CAAC;QACF,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACtF,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAClF,CAAC;IAED,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,gBAAgB,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IAC9E,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AAC/B,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,YAAY,CAAC,MAAoB,EAAE,MAAc;IAC/D,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,SAAS,CAAC;IAClD,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,KAAK,MAAM;QACvC,CAAC,CAAC,SAAS,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,MAAM,GAAG;QAC3D,CAAC,CAAC,4CAA4C,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,MAAM,kDAAkD,CAAC;IAChJ,OAAO,EAAE,kBAAkB,EAAE,EAAE,aAAa,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,EAAE,wBAAwB,EAAE,MAAM,EAAE,EAAE,CAAC;AAC/H,CAAC;AAED,KAAK,UAAU,SAAS;IACtB,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACnC,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK;QAAE,IAAI,IAAI,KAAK,CAAC;IACvD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,IAAI,CAAC,MAAwB;IACpC,IAAI,MAAM;QAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,QAAQ,GAAG,CAAC,MAAc,EAAmB,EAAE,CAAC,CAAC;IACrD,kBAAkB,EAAE,EAAE,aAAa,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,EAAE,wBAAwB,EAAE,MAAM,EAAE;CAClH,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,UAAmB;IACzD,MAAM,GAAG,GAAG,MAAM,SAAS,EAAE,CAAC;IAC9B,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,CAAC;IAExB,IAAI,OAAuB,CAAC;IAC5B,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,UAAU;YAAE,IAAI,CAAC,QAAQ,CAAC,yCAAyC,CAAC,CAAC,CAAC;QAC1E,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,sDAAsD,CAAC,CAAC;QAC7E,IAAI,EAAE,CAAC;IACT,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,SAAS;QAAE,IAAI,EAAE,CAAC;IAE/B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAEzC,IAAI,QAA6B,CAAC;IAClC,IAAI,CAAC;QACH,QAAQ,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,uEAAuE;QACvE,IAAI,CAAC,QAAQ,CAAC,oCAAoC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC,CAAC;IACnI,CAAC;IACD,IAAI,CAAC,QAAQ;QAAE,IAAI,EAAE,CAAC;IAEtB,IAAI,MAAoB,CAAC;IACzB,IAAI,CAAC;QACH,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACrF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,IAAI,UAAU;YAAE,IAAI,CAAC,QAAQ,CAAC,2BAA2B,GAAG,EAAE,CAAC,CAAC,CAAC;QACjE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,6CAA6C,GAAG,eAAe,CAAC,CAAC;QACtF,IAAI,EAAE,CAAC;IACT,CAAC;IAED,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @weave_protocol/adapter-codex — WARD.md enforcement for OpenAI Codex CLI.
3
+ */
4
+ export * from './types.js';
5
+ export { patchTargets } from './patch.js';
6
+ export type { PatchTargets } from './patch.js';
7
+ export { STATUS_MESSAGE, codexHome, hooksJsonPath, userWardPath, readHooks, writeHooks, installHook, removeHook, isHookInstalled, } from './config.js';
8
+ export type { HooksFile, InstallOptions } from './config.js';
9
+ export { resolveWardForCwd, evaluateCall, toHookOutput } from './hook.js';
10
+ export type { ResolvedWard, HookDecision } from './hook.js';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EACL,cAAc,EACd,SAAS,EACT,aAAa,EACb,YAAY,EACZ,SAAS,EACT,UAAU,EACV,WAAW,EACX,UAAU,EACV,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC1E,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @weave_protocol/adapter-codex — WARD.md enforcement for OpenAI Codex CLI.
3
+ */
4
+ export * from './types.js';
5
+ export { patchTargets } from './patch.js';
6
+ export { STATUS_MESSAGE, codexHome, hooksJsonPath, userWardPath, readHooks, writeHooks, installHook, removeHook, isHookInstalled, } from './config.js';
7
+ export { resolveWardForCwd, evaluateCall, toHookOutput } from './hook.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,EACL,cAAc,EACd,SAAS,EACT,aAAa,EACb,YAAY,EACZ,SAAS,EACT,UAAU,EACV,WAAW,EACX,UAAU,EACV,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * The files a Codex apply_patch touches. The patch format marks each file:
3
+ *
4
+ * *** Add File: <path> new file → write
5
+ * *** Update File: <path> edit in place → write
6
+ * *** Move to: <path> rename target → write
7
+ * *** Delete File: <path> removal → delete
8
+ *
9
+ * Paths are relative to the session cwd unless absolute.
10
+ */
11
+ export interface PatchTargets {
12
+ writes: string[];
13
+ deletes: string[];
14
+ }
15
+ export declare function patchTargets(patch: string): PatchTargets;
16
+ //# sourceMappingURL=patch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patch.d.ts","sourceRoot":"","sources":["../src/patch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAID,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,CASxD"}
package/dist/patch.js ADDED
@@ -0,0 +1,23 @@
1
+ /**
2
+ * The files a Codex apply_patch touches. The patch format marks each file:
3
+ *
4
+ * *** Add File: <path> new file → write
5
+ * *** Update File: <path> edit in place → write
6
+ * *** Move to: <path> rename target → write
7
+ * *** Delete File: <path> removal → delete
8
+ *
9
+ * Paths are relative to the session cwd unless absolute.
10
+ */
11
+ const MARKER = /^\*\*\* (Add File|Update File|Move to|Delete File):\s*(.+?)\s*$/;
12
+ export function patchTargets(patch) {
13
+ const writes = [];
14
+ const deletes = [];
15
+ for (const line of patch.split(/\r?\n/)) {
16
+ const m = MARKER.exec(line);
17
+ if (!m)
18
+ continue;
19
+ (m[1] === 'Delete File' ? deletes : writes).push(m[2]);
20
+ }
21
+ return { writes, deletes };
22
+ }
23
+ //# sourceMappingURL=patch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patch.js","sourceRoot":"","sources":["../src/patch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,MAAM,MAAM,GAAG,iEAAiE,CAAC;AAEjF,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QACxC,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Codex CLI hook contract (https://developers.openai.com/codex/hooks):
3
+ *
4
+ * stdin { session_id, transcript_path, cwd, hook_event_name, model,
5
+ * turn_id, tool_name, tool_use_id, tool_input, permission_mode }
6
+ * stdout { hookSpecificOutput: { hookEventName: "PreToolUse",
7
+ * permissionDecision: "deny", permissionDecisionReason } }
8
+ * or nothing (the call continues)
9
+ *
10
+ * Shell commands (including unified exec) arrive as tool_name "Bash" with
11
+ * tool_input.command; file edits as "apply_patch" with the patch text in
12
+ * tool_input.command; MCP tools as mcp__<server>__<tool>. "ask" is not
13
+ * supported, so a WARD require_approval is a deny whose reason says so.
14
+ * Hosted tools (web search) never reach PreToolUse.
15
+ */
16
+ import type { ToolMapping } from '@weave_protocol/ward';
17
+ export interface CodexHookInput {
18
+ session_id?: string;
19
+ transcript_path?: string | null;
20
+ cwd?: string;
21
+ hook_event_name?: string;
22
+ model?: string;
23
+ turn_id?: string;
24
+ tool_name?: string;
25
+ tool_use_id?: string;
26
+ tool_input?: unknown;
27
+ permission_mode?: string;
28
+ }
29
+ export interface CodexHookOutput {
30
+ hookSpecificOutput?: {
31
+ hookEventName: 'PreToolUse';
32
+ permissionDecision: 'deny';
33
+ permissionDecisionReason: string;
34
+ };
35
+ }
36
+ /**
37
+ * Codex's local tools. apply_patch is decided from the files its patch
38
+ * touches (see patch.ts); unknown tools, including MCP tools, use their own
39
+ * name as the capability and Ward checks their path and URL arguments.
40
+ */
41
+ export declare const TOOL_MAPPINGS: Record<string, ToolMapping>;
42
+ /** One PreToolUse matcher group in hooks.json. */
43
+ export interface CodexHookGroup {
44
+ matcher?: string;
45
+ hooks: Array<{
46
+ type: 'command' | 'mcp_tool';
47
+ command?: string;
48
+ timeout?: number;
49
+ statusMessage?: string;
50
+ async?: boolean;
51
+ }>;
52
+ }
53
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,kBAAkB,CAAC,EAAE;QACnB,aAAa,EAAE,YAAY,CAAC;QAC5B,kBAAkB,EAAE,MAAM,CAAC;QAC3B,wBAAwB,EAAE,MAAM,CAAC;KAClC,CAAC;CACH;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAMrD,CAAC;AAEF,kDAAkD;AAClD,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC;QACX,IAAI,EAAE,SAAS,GAAG,UAAU,CAAC;QAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB,CAAC,CAAC;CACJ"}
package/dist/types.js ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Codex CLI hook contract (https://developers.openai.com/codex/hooks):
3
+ *
4
+ * stdin { session_id, transcript_path, cwd, hook_event_name, model,
5
+ * turn_id, tool_name, tool_use_id, tool_input, permission_mode }
6
+ * stdout { hookSpecificOutput: { hookEventName: "PreToolUse",
7
+ * permissionDecision: "deny", permissionDecisionReason } }
8
+ * or nothing (the call continues)
9
+ *
10
+ * Shell commands (including unified exec) arrive as tool_name "Bash" with
11
+ * tool_input.command; file edits as "apply_patch" with the patch text in
12
+ * tool_input.command; MCP tools as mcp__<server>__<tool>. "ask" is not
13
+ * supported, so a WARD require_approval is a deny whose reason says so.
14
+ * Hosted tools (web search) never reach PreToolUse.
15
+ */
16
+ /**
17
+ * Codex's local tools. apply_patch is decided from the files its patch
18
+ * touches (see patch.ts); unknown tools, including MCP tools, use their own
19
+ * name as the capability and Ward checks their path and URL arguments.
20
+ */
21
+ export const TOOL_MAPPINGS = {
22
+ Bash: { capability: 'shell_exec', commandField: 'command' },
23
+ apply_patch: { capability: 'file_write' },
24
+ view_image: { capability: 'file_read', pathField: 'path', fsOp: 'read' },
25
+ update_plan: { capability: 'task_planning' },
26
+ spawn_agent: { capability: 'subagent' },
27
+ };
28
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAyBH;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAgC;IACxD,IAAI,EAAE,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE;IAC3D,WAAW,EAAE,EAAE,UAAU,EAAE,YAAY,EAAE;IACzC,UAAU,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE;IACxE,WAAW,EAAE,EAAE,UAAU,EAAE,eAAe,EAAE;IAC5C,WAAW,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE;CACxC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,55 @@
1
1
  {
2
2
  "name": "@weave_protocol/adapter-codex",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "Weave Protocol adapter for OpenAI Codex CLI - enforces WARD.md policies via Codex's PreToolUse hook",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "weave-ward-codex": "dist/cli.js"
10
+ },
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "dev": "tsc --watch",
14
+ "test": "npm run build && node --test test/*.test.mjs",
15
+ "prepublishOnly": "npm run build"
16
+ },
17
+ "keywords": [
18
+ "weave-protocol",
19
+ "ward",
20
+ "codex",
21
+ "codex-cli",
22
+ "openai",
23
+ "agent-security",
24
+ "ai-security",
25
+ "hooks",
26
+ "harness-adapter",
27
+ "policy-enforcement",
28
+ "ward-md"
29
+ ],
30
+ "author": "Trent Yoxall",
31
+ "license": "Apache-2.0",
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "git+https://github.com/Tyox-all/Weave_Protocol.git",
35
+ "directory": "adapter-codex"
36
+ },
37
+ "homepage": "https://github.com/Tyox-all/Weave_Protocol/tree/main/adapter-codex#readme",
38
+ "bugs": {
39
+ "url": "https://github.com/Tyox-all/Weave_Protocol/issues"
40
+ },
41
+ "dependencies": {
42
+ "@weave_protocol/ward": "^0.3.0"
43
+ },
44
+ "devDependencies": {
45
+ "@types/node": "^26.6.6",
46
+ "typescript": "^7.0.2"
47
+ },
48
+ "engines": {
49
+ "node": ">=18.0.0"
50
+ },
51
+ "files": [
52
+ "dist/",
53
+ "README.md"
54
+ ]
55
+ }