diff --git a/.codex-plugin/README.md b/.codex-plugin/README.md index ed4ece00e..64ade090e 100644 --- a/.codex-plugin/README.md +++ b/.codex-plugin/README.md @@ -77,6 +77,67 @@ Once the cached skills are available, invoke `$configure-ecc` inside Codex for ECC's guided configuration. Installing the plugin again is idempotent and does not create a second scope or duplicate hook registration. +## Runtime dependencies and Codex 0.164.0 cache checks + +Native marketplace installation copies ECC's source; it does not run `npm ci` +for its hook dependencies. If a hook reports a missing runtime package, first +run `codex plugin list --json` with the same `CODEX_HOME` as the affected +session. Find the installed, enabled `ecc@ecc` entry and its version; do not +select a version merely because its directory exists. From an ECC checkout, +check that version explicitly: + +```bash +# Replace with the version from Codex's installed entry. +node scripts/codex/check-plugin-cache.js --version '' +``` + +If the affected session's hook warning identifies the exact ECC plugin root, +prefer `node scripts/codex/check-plugin-cache.js --plugin-dir "/absolute/path/to/active/ecc/cache"`. +Use the same `CODEX_HOME` for the version check (or pass `--codex-home`). The +checker's default comes from the checkout's `package.json`; it does not discover +the active version, and a passing check against an older cache is insufficient. +Confirm the selected root matches the affected session before installing. Do +not use the deprecated sync script to repair the native plugin. + +Codex 0.164.0 can reject a plugin after a normal dependency install with +`unsupported plugin entry type ... node_modules/.bin/js-yaml`. npm normally +creates executable symlinks in `.bin`; that Codex version's hook fingerprint +walker accepts only directories and regular files. See +[ECC #3742](https://github.com/affaan-m/ECC/issues/3742) and the +[Codex fingerprint implementation](https://github.com/openai/codex/blob/rust-v0.164.0/codex-rs/hooks/src/engine/plugin_fingerprint.rs). + +For an explicitly chosen cache-local dependency install, use npm's +[`--no-bin-links`](https://docs.npmjs.com/cli/v11/commands/npm-ci#bin-links) +option to install the runtime packages without creating executable links: + +```bash +# Set this to the active ECC plugin root confirmed above. +ECC_PLUGIN_CACHE="/absolute/path/to/active/ecc/cache" +( + set -eu + cd -- "$ECC_PLUGIN_CACHE" + test -f package.json + test -f package-lock.json + npm ci --omit=dev --ignore-scripts --no-audit --no-fund --no-bin-links + node -e "require('js-yaml'); require('@iarna/toml'); require('ajv'); require('sql.js'); require('zod')" +) +``` + +The cache root must contain ECC's `package.json` and `package-lock.json`. The +subshell stops on a failed directory change, missing manifest, or failed install +before running any later command, and leaves the caller's directory unchanged. +`npm ci` replaces its dependency tree; this opt-in command is not part of the +default Codex installer. The final command checks Node package resolution, not +Codex hook execution. Executable shortcuts in `node_modules/.bin` are +intentionally unavailable; ECC hooks load these packages through Node. + +Restart Codex, review the updated hook definitions in `/hooks`, and verify a +new session's actual hook result. Do not disable fingerprint or trust checks. +This addresses npm-generated executable links, not every possible unsupported +cache entry or the upstream Codex defect. A marketplace refresh can replace +cache-local changes; recheck the active version before applying the command +again. + ## Native plugin versus legacy managed sync The commands above are the native Codex plugin path. The deprecated legacy managed sync @@ -93,11 +154,12 @@ history or native plugin caches. Older pre-manifest installs are cleaned conservatively and unverifiable files are retained with warnings. After install, `codex plugin list` is only a registration check. From an ECC -checkout, run the cache check to verify that the installed manifest can resolve -its referenced skills, MCP config, and assets: +checkout, set `ECC_PLUGIN_CACHE` to the active root identified above, then run +the cache check to verify that the installed manifest can resolve its referenced +skills, MCP config, and assets: ```bash -node scripts/codex/check-plugin-cache.js +node scripts/codex/check-plugin-cache.js --plugin-dir "$ECC_PLUGIN_CACHE" ``` The installed plugin registers under the short slug `ecc` so tool and command names diff --git a/.codex/AGENTS.md b/.codex/AGENTS.md index 9f6c5d28a..7ceffb283 100644 --- a/.codex/AGENTS.md +++ b/.codex/AGENTS.md @@ -5,6 +5,9 @@ This supplements the root `AGENTS.md` with Codex-specific guidance. For repo navigation, surface ownership, and PR diff packet guidance, read `docs/CODEX-NAVIGATION-GUIDE.md` after this supplement. +For native cache dependency installation and Codex 0.164.0 executable-link +rejections, use the [runtime dependency procedure](../.codex-plugin/README.md#runtime-dependencies-and-codex-01640-cache-checks). + ## Model Recommendations | Task Type | Recommended Model | diff --git a/README.md b/README.md index 7e34937a9..80966f5b0 100644 --- a/README.md +++ b/README.md @@ -2114,6 +2114,10 @@ node scripts/codex/check-plugin-cache.js ``` If it reports unresolved parent references, refresh the native cache with `codex plugin marketplace upgrade ecc`, run `codex plugin add ecc@ecc` again, and restart Codex. Registration in `codex plugin list` confirms the marketplace entry, while the cache check verifies that the installed manifest can resolve its skills, MCP configuration, and assets. Use `bash scripts/sync-ecc-to-codex.sh` only when you intentionally need the legacy copied-configuration compatibility path. + +If Codex 0.164.0 reports `unsupported plugin entry type` after you install hook +dependencies into the cache, see the [cache-local runtime dependency procedure](.codex-plugin/README.md#runtime-dependencies-and-codex-01640-cache-checks). +It avoids npm executable symlinks without disabling Codex's hook trust checks. More answers: [TROUBLESHOOTING.md](TROUBLESHOOTING.md) covers memory, hooks, installation, performance, and common error messages. [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md) tracks workarounds for open Claude Code bugs. diff --git a/scripts/codex/check-plugin-cache.js b/scripts/codex/check-plugin-cache.js index 0a21cc48f..e293ae5b3 100644 --- a/scripts/codex/check-plugin-cache.js +++ b/scripts/codex/check-plugin-cache.js @@ -227,13 +227,15 @@ function checkCache(options) { if (failures > 0) { log(`${failures} cached manifest reference(s) do not resolve.`); log('codex plugin list only confirms marketplace registration; it is not proof of runtime skill loading.'); - const syncScript = path.join(REPO_ROOT, 'scripts', 'sync-ecc-to-codex.sh'); - if (fs.existsSync(syncScript)) { - log('Use the supported sync path until the cache contains the referenced files:'); - log('npm install && bash scripts/sync-ecc-to-codex.sh'); + log('Refresh the native marketplace and re-add the plugin using the same CODEX_HOME as the affected session:'); + if (options.marketplace === 'ecc' && options.plugin === 'ecc') { + log('codex plugin marketplace upgrade ecc'); + log('codex plugin add ecc@ecc'); } else { - log('Use the supported manual sync workflow from your ECC installation.'); + log('Follow the requested plugin marketplace instructions to refresh and re-add that native plugin.'); } + log('Restart Codex, confirm the active plugin root with codex plugin list --json, and re-run this checker with --plugin-dir ACTIVE_ROOT (or --version ACTIVE_VERSION).'); + log('See .codex-plugin/README.md for native cache recovery and runtime dependency instructions.'); return 1; } diff --git a/tests/scripts/codex-hooks.test.js b/tests/scripts/codex-hooks.test.js index 007b98cfa..43830f6ff 100644 --- a/tests/scripts/codex-hooks.test.js +++ b/tests/scripts/codex-hooks.test.js @@ -660,7 +660,13 @@ if ( assert.match(result.stdout, /\[FAIL\] skills missing/); assert.match(result.stdout, /\[FAIL\] mcpServers missing/); assert.match(result.stdout, /codex plugin list only confirms marketplace registration/); - assert.match(result.stdout, /sync-ecc-to-codex\.sh/); + assert.match(result.stdout, /codex plugin marketplace upgrade ecc/); + assert.match(result.stdout, /codex plugin add ecc@ecc/); + assert.match(result.stdout, /same CODEX_HOME/); + assert.match(result.stdout, /active plugin root/); + assert.match(result.stdout, /--plugin-dir ACTIVE_ROOT/); + assert.match(result.stdout, /--version ACTIVE_VERSION/); + assert.doesNotMatch(result.stdout, /npm install|sync-ecc-to-codex\.sh/); } finally { cleanup(homeDir); }