|
| 1 | +# Plugin Data Root Bootstrap Implementation Plan |
| 2 | + |
| 3 | +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. |
| 4 | +
|
| 5 | +**Goal:** Make installed `$zcode:*` skills resolve and bootstrap a stable writable plugin data directory when `PLUGIN_DATA` is absent. |
| 6 | + |
| 7 | +**Architecture:** Introduce a focused plugin-data path resolver, use it at every companion and hook entry point, and extend setup's existing Codex app-server configuration transaction to preserve and add the required writable root before any state write. Installed cache identity determines the marketplace-qualified namespace; source checkouts use an unqualified development namespace. |
| 8 | + |
| 9 | +**Tech Stack:** Node.js 22.13+ ESM, Codex app-server JSONL configuration API, Node built-in test runner, JSDoc/TypeScript checking, ESLint. |
| 10 | + |
| 11 | +--- |
| 12 | + |
| 13 | +### Task 1: Resolve and bootstrap plugin data safely |
| 14 | + |
| 15 | +**Files:** |
| 16 | +- Create: `scripts/lib/plugin-data.mjs` |
| 17 | +- Modify: `scripts/zcode-companion.mjs` |
| 18 | +- Modify: `scripts/lib/codex-config.mjs` |
| 19 | +- Modify: `hooks/session-lifecycle-hook.mjs` |
| 20 | +- Modify: `hooks/user-prompt-hook.mjs` |
| 21 | +- Modify: `hooks/subagent-hook.mjs` |
| 22 | +- Modify: `hooks/stop-review-gate-hook.mjs` |
| 23 | +- Modify: `hooks/session-end-hook.mjs` |
| 24 | +- Modify: `tests/setup.test.mjs` |
| 25 | +- Modify: `tests/integration/marketplace-install.test.mjs` |
| 26 | +- Create or modify: `tests/plugin-data.test.mjs` |
| 27 | +- Modify: `README.md` |
| 28 | +- Modify: `README.zh-CN.md` |
| 29 | +- Modify: `CHANGELOG.md` |
| 30 | + |
| 31 | +- [ ] **Step 1: Write failing resolver tests** |
| 32 | + |
| 33 | +Cover explicit `ZCODE_DATA_ROOT`, validated injected roots, installed cache identity, |
| 34 | +marketplace-qualified fallback, source-checkout fallback, `CODEX_HOME`, symlink-equivalent |
| 35 | +paths, and rejection/ignoring of foreign injected roots. |
| 36 | + |
| 37 | +- [ ] **Step 2: Run the resolver tests and verify RED** |
| 38 | + |
| 39 | +Run: `node --test tests/plugin-data.test.mjs` |
| 40 | + |
| 41 | +Expected: FAIL because the shared resolver does not exist. |
| 42 | + |
| 43 | +- [ ] **Step 3: Implement the minimal shared resolver** |
| 44 | + |
| 45 | +Create `scripts/lib/plugin-data.mjs` with pure path/identity functions and a single |
| 46 | +`resolvePluginDataRoot({ env, pluginRoot })` public entry point. Do not create files in |
| 47 | +the resolver. |
| 48 | + |
| 49 | +- [ ] **Step 4: Run resolver tests and verify GREEN** |
| 50 | + |
| 51 | +Run: `node --test tests/plugin-data.test.mjs` |
| 52 | + |
| 53 | +Expected: PASS. |
| 54 | + |
| 55 | +- [ ] **Step 5: Write failing setup bootstrap tests** |
| 56 | + |
| 57 | +Exercise the real companion setup entry without `PLUGIN_DATA`. Assert that it derives |
| 58 | +the installed root, preserves existing `sandbox_workspace_write.writable_roots`, emits |
| 59 | +one version-checked `config/batchWrite`, returns `restart-required`, performs no plugin |
| 60 | +state write before restart, and honors an already-effective writable root on rerun. |
| 61 | + |
| 62 | +- [ ] **Step 6: Run setup tests and verify RED** |
| 63 | + |
| 64 | +Run: `node --test tests/setup.test.mjs tests/integration/marketplace-install.test.mjs` |
| 65 | + |
| 66 | +Expected: FAIL with the current `DATA_ROOT_REQUIRED` or missing writable-root edit. |
| 67 | + |
| 68 | +- [ ] **Step 7: Integrate resolver and setup bootstrap** |
| 69 | + |
| 70 | +Resolve the data root before companion routing. Reorder setup so Codex configuration is |
| 71 | +read and the writable root is installed before model or gate state is accessed. Preserve |
| 72 | +existing roots and user-layer version checks. Return restart guidance without writing |
| 73 | +state when the sandbox root has just changed or is overridden. |
| 74 | + |
| 75 | +- [ ] **Step 8: Use the resolver in hooks** |
| 76 | + |
| 77 | +Replace direct `process.env.PLUGIN_DATA` assumptions with the shared resolver so hooks |
| 78 | +and skills select the same root while retaining fail-closed hook behavior. |
| 79 | + |
| 80 | +- [ ] **Step 9: Run focused tests and verify GREEN** |
| 81 | + |
| 82 | +Run: `node --test tests/plugin-data.test.mjs tests/setup.test.mjs tests/hooks.test.mjs tests/integration/marketplace-install.test.mjs` |
| 83 | + |
| 84 | +Expected: PASS. |
| 85 | + |
| 86 | +- [ ] **Step 10: Update user-facing documentation** |
| 87 | + |
| 88 | +Document the derived plugin-data location, marketplace qualification, restart-required |
| 89 | +setup behavior, and the fact that state never lives in the repository or plugin cache. |
| 90 | + |
| 91 | +- [ ] **Step 11: Run the complete quality gate** |
| 92 | + |
| 93 | +Run: `npm run check` |
| 94 | + |
| 95 | +Expected: PASS with only the documented credential-gated E2E skips. |
| 96 | + |
| 97 | +- [ ] **Step 12: Self-review and commit** |
| 98 | + |
| 99 | +Run `git diff --check`, inspect the full diff for unrelated changes and secret/path |
| 100 | +leaks, then commit with a focused bug-fix message. |
0 commit comments