From 91b4251fea3a3f96a5afa8fee374f829f8708155 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Mon, 20 Jul 2026 01:32:47 -0400 Subject: [PATCH] fix: align Codex hook sources --- AGENTS.md | 1 + integrations/catalog.json | 51 +++++++++++++++++++++++++++++++ test/integration-catalog.test.mjs | 51 +++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index e0999ce..5306701 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -29,6 +29,7 @@ This repository publishes the open-source server, console, integration catalog, - Write Auggie hooks only to `~/.augment/settings.json`; keep system and workspace settings read-only. Generate `.cmd` wrappers on Windows and `.sh` wrappers on Unix because Auggie dispatches supported script paths, and express hook timeouts in milliseconds. - Validate Auggie matcher syntax during installation with Node.js `new RegExp`; keep status and uninstall independent from the JavaScript validator so recovery remains available offline. - Write Cline file hooks to `$CLINE_DIR/hooks` with `~/.cline/hooks` as the default; keep Documents and workspace hook roots read-only. Use supported event filenames, preserve official hook input byte-for-byte, use `process.execPath` in Node and Go wrappers, and resolve Python runtimes from absolute shebangs. Translate guard exit code `2` into JSON stdout with `cancel: true`. Treat hook errors, timeouts, and invalid control JSON as fail-open. +- Model Codex JSON files, inline TOML layers, managed `requirements.toml`, and plugin-bundled hooks as additive stable sources. SDK adapters write only `~/.codex/hooks.json`, preserve project and managed sources, retain the three-level matcher contract, and require `/hooks` trust review for changed user hooks. - Write GitHub Copilot CLI hooks only to `$COPILOT_HOME/hooks/elydora-audit.json` with `~/.copilot/hooks/elydora-audit.json` as the default. Migrate exact Elydora-owned entries from project `.github/hooks/hooks.json`, preserve native camelCase input, require `disableAllHooks` to be false, and commit runtime plus hook documents in one rollback-capable transaction. - Model Cursor as one CLI-and-IDE hook contract. Preserve user, project, and enterprise sources in documented priority order; forward `tool_name`, `tool_input`, and `conversation_id`; use exit code `2` for denial; record `failClosed` as the per-script failure-mode control. - Write Node Cursor hooks only to `~/.cursor/hooks.json`; keep project and enterprise sources read-only. Register `preToolUse`, `postToolUse`, and `postToolUseFailure`, preserve the complete native payload, emit valid native JSON responses, retain PowerShell exit codes, and commit guard, runtime metadata, private key, audit runtime, and user hooks in one rollback-capable transaction. diff --git a/integrations/catalog.json b/integrations/catalog.json index c764093..e3eb0af 100644 --- a/integrations/catalog.json +++ b/integrations/catalog.json @@ -110,6 +110,57 @@ "mechanism": "exit_code_2", "failure_mode": "fail_open" }, + "contract_variants": [ + { + "id": "inlinetoml", + "release_channel": "stable", + "activation": "Hooks configured inline in an active Codex config.toml or managed requirements.toml layer", + "config_format": "toml", + "config_paths": [ + "~/.codex/config.toml", + ".codex/config.toml", + "requirements.toml" + ], + "events": { + "before_tool": "PreToolUse", + "after_tool": "PostToolUse" + }, + "event_fields": { + "name": "tool_name", + "input": "tool_input", + "session": "session_id" + }, + "blocking": { + "mechanism": "exit_code_2", + "failure_mode": "fail_open" + }, + "source_url": "https://learn.chatgpt.com/docs/hooks" + }, + { + "id": "pluginbundle", + "release_channel": "stable", + "activation": "An enabled Codex plugin supplies hooks through its manifest or default hooks file", + "config_format": "plugin", + "config_paths": [ + ".codex-plugin/plugin.json", + "hooks/hooks.json" + ], + "events": { + "before_tool": "PreToolUse", + "after_tool": "PostToolUse" + }, + "event_fields": { + "name": "tool_name", + "input": "tool_input", + "session": "session_id" + }, + "blocking": { + "mechanism": "exit_code_2", + "failure_mode": "fail_open" + }, + "source_url": "https://learn.chatgpt.com/docs/hooks" + } + ], "adapters": { "node": true, "python": true, "go": true }, "delivery_state": "available", "source_url": "https://learn.chatgpt.com/docs/hooks" diff --git a/test/integration-catalog.test.mjs b/test/integration-catalog.test.mjs index e065a5b..b3ee79b 100644 --- a/test/integration-catalog.test.mjs +++ b/test/integration-catalog.test.mjs @@ -277,6 +277,57 @@ test('high-drift providers retain their verified hook contracts', async () => { '~/.codex/hooks.json', '.codex/hooks.json', ]); + assert.deepEqual(providers.get('codex').contract_variants, [ + { + id: 'inlinetoml', + release_channel: 'stable', + activation: 'Hooks configured inline in an active Codex config.toml or managed requirements.toml layer', + config_format: 'toml', + config_paths: [ + '~/.codex/config.toml', + '.codex/config.toml', + 'requirements.toml', + ], + events: { + before_tool: 'PreToolUse', + after_tool: 'PostToolUse', + }, + event_fields: { + name: 'tool_name', + input: 'tool_input', + session: 'session_id', + }, + blocking: { + mechanism: 'exit_code_2', + failure_mode: 'fail_open', + }, + source_url: 'https://learn.chatgpt.com/docs/hooks', + }, + { + id: 'pluginbundle', + release_channel: 'stable', + activation: 'An enabled Codex plugin supplies hooks through its manifest or default hooks file', + config_format: 'plugin', + config_paths: [ + '.codex-plugin/plugin.json', + 'hooks/hooks.json', + ], + events: { + before_tool: 'PreToolUse', + after_tool: 'PostToolUse', + }, + event_fields: { + name: 'tool_name', + input: 'tool_input', + session: 'session_id', + }, + blocking: { + mechanism: 'exit_code_2', + failure_mode: 'fail_open', + }, + source_url: 'https://learn.chatgpt.com/docs/hooks', + }, + ]); assert.deepEqual(providers.get('copilot').config_paths, [ '$COPILOT_HOME/hooks/*.json', '~/.copilot/hooks/*.json',