fix(codex): fix marketplace manifest, registration ordering, and EPERM guard#56
Merged
Conversation
…e the plugin codex plugin marketplace add looks for a manifest at the ROOT of the path provided. The manifest was buried in .agents/plugins/, causing the marketplace root does not contain a supported manifest error on every new install via both Route A (local npm junction) and Route B (git sparse checkout). Changes: - packages/codex-plugin/marketplace.json: new root-level manifest, name=switchbot, source.path=./ - .agents/plugins/marketplace.json: rename from codex-plugin to switchbot (both agree) - package.json: add marketplace.json to files array so it ships in the npm package - CODEX_PLUGIN_DEFAULT_ID: switchbot@codex-plugin -> switchbot@switchbot - CODEX_PLUGIN_LEGACY_IDS: add switchbot@codex-plugin for backward-compat cleanup - resolveMarketplaceName / resolvePluginIdentifier: check root marketplace.json first - plugin remove loops: deduplicate IDs with Set to avoid double-removing on fallback paths - setup / repair output: add 3-state status block (CLI / Credentials / Codex plugin) and clear Restart Codex Desktop instruction on success Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
.gitattributes sets text=auto eol=lf for the whole repo so Git never converts LF->CRLF on Windows checkout. This eliminates the phantom "modified" entries on auth.js / policy-edit.js / start.js that appeared whenever core.autocrlf=true. package-lock.json was missing the 3.7.3->3.7.4 and codex-plugin 0.1.0->0.1.2 version bumps that should have been part of the v3.7.4 release commit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…lt ID CODEX_PLUGIN_DEFAULT_ID changed from switchbot@codex-plugin to switchbot@switchbot. The legacy IDs array now has 2 entries, so the deduped plugin-remove loop emits 3 calls on Route B (vs 2 before). Four tests updated: - runCodexPluginRegistration x2: add 3rd remove mock - registerCodexPluginAuto routes-git: add 3rd remove mock - stepRegisterCodexPlugin success: add 3rd remove mock + expect switchbot@switchbot Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ests
Previously pre-commit only ran build + tests/version.test.ts (~2 s).
That meant breaking changes to codex-checks / codex.ts / codex-plugin
would only surface in CI — never locally before the push.
New verify:pre-commit:
npm run build
&& npm test -- tests/version.test.ts
tests/install/codex-checks.test.ts
tests/commands/codex.test.ts
&& npm run test:workspaces
Coverage now locked at pre-commit:
- codex-checks.test.ts : resolvePluginId, Route A/B/auto, stepRegister
- codex.test.ts : setup / repair step outputs
- test:workspaces : packages/codex-plugin (install, auth, resolve)
Total timing ~8 s (was ~2 s). Acceptable for the safety gain.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ale DB, fix plugin path Three bugs fixed: 1. **Op ordering**: plugin removes must happen BEFORE marketplace add. When plugin remove deletes the last plugin in a marketplace, Codex auto-deletes the marketplace directory. Old code did marketplace add first, then plugin remove — which destroyed the just-added marketplace. 2. **Stale DB**: add marketplace remove before marketplace add. After Codex deletes the marketplace directory it leaves a stale DB record. Subsequent marketplace add says "already added" without recreating the directory, so plugin add fails. Fix: run `codex plugin marketplace remove` for all known names first. 3. **Plugin path in marketplace.json**: `path: "./"` (root) is not discovered by Codex 0.133.0. Move plugin files to plugins/switchbot/ and point marketplace.json there. Also fixes Route B (git sparse checkout) which needs the plugin in a proper subdirectory to be listed by `codex plugin list`. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Codex sparse checkout (`--sparse packages/codex-plugin`) clones the full repo structure with the repository root as the marketplace root. Placing marketplace.json at packages/codex-plugin/ puts it at the wrong level — Codex looks for the manifest at the clone root, not the sparse path. Adding a root-level marketplace.json that points the plugin path to ./packages/codex-plugin/plugins/switchbot fixes Route B registration. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…cation and format Codex CLI looks for marketplace manifests at two locations: .agents/plugins/marketplace.json (old format) .claude-plugin/marketplace.json (new format, matching claude-plugins-official) The old .agents/plugins/marketplace.json had path '../../' which resolves to two levels above the marketplace root, causing Codex to silently skip the entire marketplace in plugin list and plugin add. Changes: - Add .claude-plugin/marketplace.json at repo root (Route B, git sparse checkout) with path ./packages/codex-plugin/plugins/switchbot Also add --sparse .claude-plugin to the git marketplace add command - Add packages/codex-plugin/.claude-plugin/marketplace.json (Route A, local npm) with path ./plugins/switchbot - Remove packages/codex-plugin/.agents/plugins/marketplace.json (wrong path) - Remove root marketplace.json (Codex does not check that location) - Add packages/codex-plugin/plugins/switchbot/.mcp.json (was referenced by plugin.json mcpServers field but missing from the directory) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…r-32 retry - packages/codex-plugin/package.json: bump to 0.1.3, replace .agents/ with .claude-plugin/ and plugins/ in files array so Codex finds the manifest - codex-checks.ts resolveMarketplaceName: check .claude-plugin/marketplace.json first (canonical for >=0.1.3), then marketplace.json, then .agents/ legacy - install.js resolvePluginIdentifier: same priority order as above - runCodexPluginRegistrationGit: increase os-error-32 retry wait 3 s -> 10 s to give Windows Defender time to finish scanning the cloned files Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Run the same Codex release gate before push, CI, and publish so marketplace registration regressions fail before users hit setup. Add Route A and Route B smokes plus package-level install assertions to cover fresh plugin registration. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Re-add openclaw-skill to the monorepo publish/smoke workflows and bump it to 0.1.1. Align the package metadata, README, and JS entrypoint with the actual runtime contract where OpenClaw bootstraps via bin/start.js and delegates to switchbot mcp serve. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…lugin fallback Replace hardcoded 'switchbot@codex-plugin' with CODEX_PLUGIN_DEFAULT_ID constant in the repairStepRemovePlugin function. This ensures the repair step correctly removes the currently-installed 'switchbot@switchbot' plugin when resolveCodexPackageRoot() fails, now that the constant was updated to reflect the new plugin ID. Also update the test to verify the correct constant is used and to expect all three plugin IDs (default + 2 legacy) to be removed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When HEAD is detached (e.g., tag-triggered CI releases), 'git rev-parse --abbrev-ref HEAD' returns 'HEAD', causing 'git clone --branch HEAD' to fail. Solution: detect detached HEAD via --abbrev-ref returning 'HEAD', then: 1. Use full commit SHA from 'git rev-parse HEAD' 2. Clone without --branch (since git clone --branch requires named refs) 3. Let existing checkout step handle both branch names and SHAs Fixes smoke test crashes on tag-based releases and detached HEAD checkouts. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…g for git ref detection
- Change regex from /^[0-9a-f]{40}$/ to /^[0-9a-fA-F]{40}$/ to accept uppercase hex in CODEX_GIT_MARKETPLACE_REF
- Wrap ref detection block in try/catch to provide informative error if git rev-parse fails
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace hardcoded '0.1.3' version check with dynamic read from packages/codex-plugin/package.json, ensuring the test doesn't break when the plugin version is bumped. Aligns with the pattern used in smoke-codex-pack-install.mjs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…lugin/marketplace.json Replace the if/else chain in resolvePluginIdentifier with sequential independent if blocks in a for loop. This allows fallback paths to work even if earlier manifest files exist but contain invalid JSON (e.g., interrupted write). Mirrors the correct pattern already used in src/install/codex-checks.ts (resolveMarketplaceName function). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add index-based ordering assertions to ensure all `codex plugin remove` calls happen BEFORE `codex plugin marketplace add`, not after. The previous check using Array.includes only verified presence, not order. This enforces the critical invariant introduced in this PR: stale plugins must be removed before the marketplace source is added. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add test case to ensure that runCodexPluginRegistrationGit passes both --sparse flags (packages/codex-plugin and .claude-plugin) to the marketplace add command. Previously only return values were tested. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
.claude-plugin/marketplace.json) so Codex CLI correctly recognizes the pluginmarketplace.jsonfor git sparse checkout@switchbot/openclaw-skillto delegation model — bootstraps CLI/auth then hands off toswitchbot mcp serveresolveMarketplaceSourceRootsymlink/junction creation in bothsrc/install/codex-checks.tsandpackages/codex-plugin/bin/install.js, with tests covering all three call-site branchesTest Plan
npm test— all tests pass (2,769 tests)npm run verify:release-gate— build + unit + smoke tests pass (runs on pre-push hook)switchbot codex repairsucceeds after stale DB state@switchbot/openclaw-skillbootstraps and delegates toswitchbot mcp serve