diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index a4917778..812e72c7 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -21,6 +21,7 @@ "workflow" ], "skills": "./skills/", + "hooks": {}, "interface": { "displayName": "Superpowers", "shortDescription": "Planning, TDD, debugging, and delivery workflows for coding agents", diff --git a/tests/codex/test-marketplace-manifest.sh b/tests/codex/test-marketplace-manifest.sh index 3045cde6..4301a06e 100755 --- a/tests/codex/test-marketplace-manifest.sh +++ b/tests/codex/test-marketplace-manifest.sh @@ -51,10 +51,25 @@ if not plugin_manifest.exists(): manifest = json.loads(plugin_manifest.read_text(encoding="utf-8")) assert_equal(manifest.get("name"), plugin.get("name"), "plugin manifest name") + +# Codex auto-discovers a plugin's hooks/hooks.json whenever the Codex manifest +# has no `hooks` field: load_plugin_hooks falls back to a hardcoded +# DEFAULT_HOOKS_CONFIG_FILE = "hooks/hooks.json" and registers it. That file is +# the Claude Code SessionStart hook, it is tracked in this repo, and this +# marketplace installs the whole repo root (source url "./"), so on Codex the +# fallback re-registers the SessionStart hook and its install-time trust prompt. +# Declaring an empty inline hooks object ({}) parses as an empty inline hook set +# and suppresses the auto-discovery. An absent field, an empty array ([]), and +# an empty inline list all collapse back to the fallback, so the value must be +# exactly an empty object. +hooks_config = repo_root / "hooks" / "hooks.json" +if not hooks_config.exists(): + raise AssertionError("hooks/hooks.json must exist (Claude Code SessionStart hook)") + assert_equal( manifest.get("hooks"), - None, - "Codex manifest ships no hooks", + {}, + "Codex manifest must declare empty hooks {} to suppress hooks/hooks.json auto-discovery", ) print("Codex marketplace manifest looks good")