@litfamily/litcodex 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/README.md +18 -21
  2. package/dist/cli.d.ts +1 -1
  3. package/dist/cli.js +2 -38
  4. package/dist/config-migration/profile-files.d.ts +4 -0
  5. package/dist/config-migration/profile-files.js +22 -0
  6. package/dist/install/capability-preflight-error.js +5 -1
  7. package/dist/install/codex.d.ts +1 -0
  8. package/dist/install/generated-skill-payload-hashes.d.ts +1 -6
  9. package/dist/install/generated-skill-payload-hashes.js +1 -6
  10. package/dist/install/host-capabilities.d.ts +2 -0
  11. package/dist/install/host-capabilities.js +13 -1
  12. package/dist/install/index.js +3 -1
  13. package/dist/install/skill-catalog.d.ts +1 -1
  14. package/dist/install/skill-catalog.js +1 -6
  15. package/dist/install/skill-resource-hashes.d.ts +1 -1
  16. package/dist/install/skill-resource-hashes.js +1 -1
  17. package/dist/install/strict-config-probe.d.ts +2 -0
  18. package/dist/install/strict-config-probe.js +34 -5
  19. package/dist/install/uninstall.d.ts +2 -0
  20. package/dist/install/uninstall.js +34 -0
  21. package/marketplace/plugins/litcodex/.codex-plugin/plugin.json +1 -1
  22. package/marketplace/plugins/litcodex/components/auto-update/package.json +1 -1
  23. package/marketplace/plugins/litcodex/components/comment-checker/package.json +1 -1
  24. package/marketplace/plugins/litcodex/components/git-bash/package.json +1 -1
  25. package/marketplace/plugins/litcodex/components/lit-loop/dist/cli.js +3 -20
  26. package/marketplace/plugins/litcodex/components/lit-loop/dist/codex-hook.js +1 -8
  27. package/marketplace/plugins/litcodex/components/lit-loop/dist/hook-cli.d.ts +2 -1
  28. package/marketplace/plugins/litcodex/components/lit-loop/dist/hook-cli.js +4 -27
  29. package/marketplace/plugins/litcodex/components/lit-loop/dist/markers.d.ts +0 -2
  30. package/marketplace/plugins/litcodex/components/lit-loop/dist/markers.js +0 -2
  31. package/marketplace/plugins/litcodex/components/lit-loop/dist/modes.d.ts +1 -3
  32. package/marketplace/plugins/litcodex/components/lit-loop/dist/modes.js +1 -10
  33. package/marketplace/plugins/litcodex/components/lit-loop/package.json +1 -1
  34. package/marketplace/plugins/litcodex/components/lsp/package.json +1 -1
  35. package/marketplace/plugins/litcodex/components/rules/dist/static-injection.js +2 -2
  36. package/marketplace/plugins/litcodex/components/rules/package.json +1 -1
  37. package/marketplace/plugins/litcodex/components/start-work-continuation/package.json +1 -1
  38. package/marketplace/plugins/litcodex/components/telemetry/package.json +1 -1
  39. package/marketplace/plugins/litcodex/components/wikify-knowledge/package.json +1 -1
  40. package/marketplace/plugins/litcodex/skills/browser-drive/scripts/capability-probe.mjs +13 -5
  41. package/node_modules/@litcodex/lit-loop/README.md +1 -7
  42. package/node_modules/@litcodex/lit-loop/dist/cli.js +3 -20
  43. package/node_modules/@litcodex/lit-loop/dist/codex-hook.js +1 -8
  44. package/node_modules/@litcodex/lit-loop/dist/hook-cli.d.ts +2 -1
  45. package/node_modules/@litcodex/lit-loop/dist/hook-cli.js +4 -27
  46. package/node_modules/@litcodex/lit-loop/dist/markers.d.ts +0 -2
  47. package/node_modules/@litcodex/lit-loop/dist/markers.js +0 -2
  48. package/node_modules/@litcodex/lit-loop/dist/modes.d.ts +1 -3
  49. package/node_modules/@litcodex/lit-loop/dist/modes.js +1 -10
  50. package/node_modules/@litcodex/lit-loop/package.json +1 -1
  51. package/node_modules/@litcodex/lit-loop/skills/browser-drive/scripts/capability-probe.mjs +13 -5
  52. package/package.json +2 -2
  53. package/readme-assets/badge-version.svg +1 -1
  54. package/readme-assets/cover-motion.webp +0 -0
  55. package/marketplace/plugins/litcodex/components/lit-loop/directives/skill-observer.md +0 -105
  56. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/apply.d.ts +0 -16
  57. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/apply.js +0 -227
  58. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/config.d.ts +0 -13
  59. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/config.js +0 -12
  60. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/curator.d.ts +0 -14
  61. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/curator.js +0 -112
  62. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/hook.d.ts +0 -19
  63. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/hook.js +0 -435
  64. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/ownership.d.ts +0 -6
  65. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/ownership.js +0 -145
  66. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/paths.d.ts +0 -18
  67. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/paths.js +0 -43
  68. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/review.d.ts +0 -28
  69. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/review.js +0 -702
  70. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/store.d.ts +0 -32
  71. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/store.js +0 -667
  72. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/transaction.d.ts +0 -26
  73. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/transaction.js +0 -524
  74. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/types.d.ts +0 -81
  75. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/types.js +0 -246
  76. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/usage.d.ts +0 -6
  77. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop/usage.js +0 -119
  78. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop-cli.d.ts +0 -8
  79. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-loop-cli.js +0 -111
  80. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-observer-cli.d.ts +0 -3
  81. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-observer-cli.js +0 -116
  82. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-observer-route.d.ts +0 -6
  83. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-observer-route.js +0 -12
  84. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-observer.d.ts +0 -18
  85. package/marketplace/plugins/litcodex/components/lit-loop/dist/skill-observer.js +0 -946
  86. package/marketplace/plugins/litcodex/skills/skill-observer/SKILL.md +0 -215
  87. package/marketplace/plugins/litcodex/skills/skill-observer/agents/openai.yaml +0 -6
  88. package/marketplace/plugins/litcodex/skills/skill-observer/references/review-contract.md +0 -77
  89. package/node_modules/@litcodex/lit-loop/directives/skill-observer.md +0 -105
  90. package/node_modules/@litcodex/lit-loop/dist/skill-loop/apply.d.ts +0 -16
  91. package/node_modules/@litcodex/lit-loop/dist/skill-loop/apply.js +0 -227
  92. package/node_modules/@litcodex/lit-loop/dist/skill-loop/config.d.ts +0 -13
  93. package/node_modules/@litcodex/lit-loop/dist/skill-loop/config.js +0 -12
  94. package/node_modules/@litcodex/lit-loop/dist/skill-loop/curator.d.ts +0 -14
  95. package/node_modules/@litcodex/lit-loop/dist/skill-loop/curator.js +0 -112
  96. package/node_modules/@litcodex/lit-loop/dist/skill-loop/hook.d.ts +0 -19
  97. package/node_modules/@litcodex/lit-loop/dist/skill-loop/hook.js +0 -435
  98. package/node_modules/@litcodex/lit-loop/dist/skill-loop/ownership.d.ts +0 -6
  99. package/node_modules/@litcodex/lit-loop/dist/skill-loop/ownership.js +0 -145
  100. package/node_modules/@litcodex/lit-loop/dist/skill-loop/paths.d.ts +0 -18
  101. package/node_modules/@litcodex/lit-loop/dist/skill-loop/paths.js +0 -43
  102. package/node_modules/@litcodex/lit-loop/dist/skill-loop/review.d.ts +0 -28
  103. package/node_modules/@litcodex/lit-loop/dist/skill-loop/review.js +0 -702
  104. package/node_modules/@litcodex/lit-loop/dist/skill-loop/store.d.ts +0 -32
  105. package/node_modules/@litcodex/lit-loop/dist/skill-loop/store.js +0 -667
  106. package/node_modules/@litcodex/lit-loop/dist/skill-loop/transaction.d.ts +0 -26
  107. package/node_modules/@litcodex/lit-loop/dist/skill-loop/transaction.js +0 -524
  108. package/node_modules/@litcodex/lit-loop/dist/skill-loop/types.d.ts +0 -81
  109. package/node_modules/@litcodex/lit-loop/dist/skill-loop/types.js +0 -246
  110. package/node_modules/@litcodex/lit-loop/dist/skill-loop/usage.d.ts +0 -6
  111. package/node_modules/@litcodex/lit-loop/dist/skill-loop/usage.js +0 -119
  112. package/node_modules/@litcodex/lit-loop/dist/skill-loop-cli.d.ts +0 -8
  113. package/node_modules/@litcodex/lit-loop/dist/skill-loop-cli.js +0 -111
  114. package/node_modules/@litcodex/lit-loop/dist/skill-observer-cli.d.ts +0 -3
  115. package/node_modules/@litcodex/lit-loop/dist/skill-observer-cli.js +0 -116
  116. package/node_modules/@litcodex/lit-loop/dist/skill-observer-route.d.ts +0 -6
  117. package/node_modules/@litcodex/lit-loop/dist/skill-observer-route.js +0 -12
  118. package/node_modules/@litcodex/lit-loop/dist/skill-observer.d.ts +0 -18
  119. package/node_modules/@litcodex/lit-loop/dist/skill-observer.js +0 -946
  120. package/node_modules/@litcodex/lit-loop/skills/skill-observer/SKILL.md +0 -215
  121. package/node_modules/@litcodex/lit-loop/skills/skill-observer/references/review-contract.md +0 -77
package/README.md CHANGED
@@ -1,6 +1,7 @@
1
- <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litcodex@1.0.0/readme-assets/cover.webp" width="100%" alt="LitCodex v5 armory cover" /></p>
1
+ <p align="center"><picture><source media="(prefers-reduced-motion: reduce)" srcset="https://cdn.jsdelivr.net/npm/@litfamily/litcodex@1.0.2/readme-assets/cover.webp" /><img src="https://cdn.jsdelivr.net/npm/@litfamily/litcodex@1.0.2/readme-assets/cover-motion.webp" width="100%" alt="LitCodex cover art. An orange signal moves through orbital paths above the CODEX CLI wordmark. The static family cover appears for reduced-motion preference." /></picture></p>
2
+ <p align="center"><a href="https://cdn.jsdelivr.net/npm/@litfamily/litcodex@1.0.2/readme-assets/cover.webp">View the static cover</a></p>
2
3
 
3
- <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litcodex@1.0.0/readme-assets/ascii-readme.svg" width="480" alt="LIT ASCII B mark" /></p>
4
+ <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litcodex@1.0.2/readme-assets/ascii-readme.svg" width="480" alt="LIT ASCII B mark" /></p>
4
5
 
5
6
  <details>
6
7
  <summary>Copy ASCII logo</summary>
@@ -32,12 +33,12 @@ LIT · codex
32
33
  </details>
33
34
 
34
35
  <p align="center">
35
- <a href="#install"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litcodex@1.0.0/readme-assets/badge-version.svg" alt="1.0.0" /></a>
36
- <a href="https://github.com/wjgoarxiv/litcodex/blob/main/LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litcodex@1.0.0/readme-assets/badge-license.svg" alt="MIT license" /></a>
36
+ <a href="#install"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litcodex@1.0.2/readme-assets/badge-version.svg" alt="1.0.2" /></a>
37
+ <a href="https://github.com/wjgoarxiv/litcodex/blob/main/LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litcodex@1.0.2/readme-assets/badge-license.svg" alt="MIT license" /></a>
37
38
  </p>
38
39
 
39
40
  <p align="center">
40
- <a href="https://github.com/wjgoarxiv/litcodex/blob/main/docs/usage.md"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litcodex@1.0.0/readme-assets/lucide-book-open.svg" width="16" alt="" /> Docs</a> &nbsp; <a href="#install">Install</a> &nbsp; <a href="https://github.com/wjgoarxiv/litcodex/blob/main/docs/assets/readme/ignition-film.mp4"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litcodex@1.0.0/readme-assets/lucide-play.svg" width="16" alt="" /> Ignition</a> &nbsp; <a href="https://github.com/wjgoarxiv/litcodex/blob/main/LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litcodex@1.0.0/readme-assets/lucide-shield-check.svg" width="16" alt="" /> MIT</a>
41
+ <a href="https://github.com/wjgoarxiv/litcodex/blob/main/docs/usage.md"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litcodex@1.0.2/readme-assets/lucide-book-open.svg" width="16" alt="" /> Docs</a> &nbsp; <a href="#install">Install</a> &nbsp; <a href="https://github.com/wjgoarxiv/litcodex/blob/main/docs/assets/readme/ignition-film.mp4"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litcodex@1.0.2/readme-assets/lucide-play.svg" width="16" alt="" /> Ignition</a> &nbsp; <a href="https://github.com/wjgoarxiv/litcodex/blob/main/LICENSE"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litcodex@1.0.2/readme-assets/lucide-shield-check.svg" width="16" alt="" /> MIT</a>
41
42
  </p>
42
43
 
43
44
  # @litfamily/litcodex
@@ -79,7 +80,7 @@ Append `lit` to a prompt to activate the Codex CLI hook. It routes the request i
79
80
 
80
81
  The hook is an entry signal; it does not prove that a model result or visual check completed.
81
82
 
82
- <p align="center"><a href="https://github.com/wjgoarxiv/litcodex/blob/main/docs/assets/readme/ignition-film.mp4"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litcodex@1.0.0/readme-assets/ignition-poster.png" width="720" alt="Ignition motion poster" /></a></p>
83
+ <p align="center"><a href="https://github.com/wjgoarxiv/litcodex/blob/main/docs/assets/readme/ignition-film.mp4"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litcodex@1.0.2/readme-assets/ignition-poster.png" width="720" alt="Ignition motion poster" /></a></p>
83
84
 
84
85
  Select the poster for the optional film; this README keeps motion opt-in.
85
86
 
@@ -93,30 +94,30 @@ Host limit: Codex CLI owns hook and agent execution, while authentication, model
93
94
  and any visual check remain host capabilities. A route mark or static editorial image is not completion
94
95
  evidence.
95
96
 
96
- <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litcodex@1.0.0/readme-assets/litcodex-ignition-1600.webp" width="49%" alt="LitCodex ignition editorial cue" /> <img src="https://cdn.jsdelivr.net/npm/@litfamily/litcodex@1.0.0/readme-assets/litcodex-continuity-1600.webp" width="49%" alt="LitCodex continuity editorial cue" /></p>
97
+ <p align="center"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litcodex@1.0.2/readme-assets/litcodex-ignition-1600.webp" width="49%" alt="LitCodex ignition editorial cue" /> <img src="https://cdn.jsdelivr.net/npm/@litfamily/litcodex@1.0.2/readme-assets/litcodex-continuity-1600.webp" width="49%" alt="LitCodex continuity editorial cue" /></p>
97
98
 
98
99
  ## What is LitCodex
99
100
 
100
101
  LitCodex adds planning, review, research, and a durable execution loop to Codex CLI. Its `UserPromptSubmit`
101
- hook routes your request into the right discipline; the bundled library provides 39 skills. A goal is complete
102
+ hook routes your request into the right discipline; the bundled library provides 38 skills. A goal is complete
102
103
  only after every success criterion passes. The npm package is self-contained and installs without a GitHub clone.
103
104
 
104
105
  ## Install
105
106
 
106
- > Install `@litfamily/litcodex@1.0.0` with the scoped command below. See [migration guidance](https://github.com/wjgoarxiv/litcodex/blob/main/docs/npm-migration.md).
107
+ > Install `@litfamily/litcodex@1.0.2` with the scoped command below. See [migration guidance](https://github.com/wjgoarxiv/litcodex/blob/main/docs/npm-migration.md).
107
108
 
108
109
  With **Node.js 22+** and **Codex CLI** installed, run:
109
110
 
110
111
  ```sh
111
- npm exec --yes --package @litfamily/litcodex@1.0.0 -- litcodex install
112
+ npm exec --yes --package @litfamily/litcodex@1.0.2 -- litcodex install
112
113
  ```
113
114
 
114
115
  The installer registers the plugin, hooks, and agents, then updates managed keys in `~/.codex/config.toml`.
115
116
  It asks for the lead model, helper model, and output style. Codex authentication and model access are required
116
117
  when you run model work; installation itself does not require GitHub credentials.
117
118
 
118
- Preview changes with `npm exec --yes --package @litfamily/litcodex@1.0.0 -- litcodex --dry-run install`. For unattended setup, use
119
- `npm exec --yes --package @litfamily/litcodex@1.0.0 -- litcodex install --yes`. An explicit `--style <id>` still applies.
119
+ Preview changes with `npm exec --yes --package @litfamily/litcodex@1.0.2 -- litcodex --dry-run install`. For unattended setup, use
120
+ `npm exec --yes --package @litfamily/litcodex@1.0.2 -- litcodex install --yes`. An explicit `--style <id>` still applies.
120
121
 
121
122
  For a persistent command:
122
123
 
@@ -125,7 +126,7 @@ npm install -g @litfamily/litcodex
125
126
  litcodex install
126
127
  ```
127
128
 
128
- > Without a global install, use `npm exec --yes --package @litfamily/litcodex@1.0.0 -- litcodex <command>`, such as `npm exec --yes --package @litfamily/litcodex@1.0.0 -- litcodex doctor`.
129
+ > Without a global install, use `npm exec --yes --package @litfamily/litcodex@1.0.2 -- litcodex <command>`, such as `npm exec --yes --package @litfamily/litcodex@1.0.2 -- litcodex doctor`.
129
130
 
130
131
  For an isolated trial apart from existing settings, follow the [isolated trial guide](https://github.com/wjgoarxiv/litcodex/blob/main/docs/npm-migration.md#isolated-local-trial).
131
132
  Changing only `CODEX_HOME` can still discover settings in your existing home.
@@ -205,8 +206,6 @@ from the Codex picker or with a scoped mention, including `$litcodex:lit-handoff
205
206
  | `litcodex uninstall` | Remove the plugin and LitCodex-managed config |
206
207
  | `litcodex config migrate` | Preview or apply managed Codex config keys |
207
208
  | `litcodex hook user-prompt-submit` | Run the host hook entrypoint |
208
- | `litcodex observer` | Record one proposal from bounded JSON on stdin |
209
- | `litcodex skill-loop <command>` | Review, approve, reject, roll back, or curate agent-owned skill proposals |
210
209
  | `litcodex loop create` | Derive goals and criteria from a brief |
211
210
  | `litcodex loop status --json` | Inspect loop state as JSON |
212
211
  | `litcodex loop run` | Select the next runnable goal |
@@ -226,7 +225,7 @@ See [state and recovery](https://github.com/wjgoarxiv/litcodex/blob/main/docs/us
226
225
  ## Verify it worked
227
226
 
228
227
  ```sh
229
- npm exec --yes --package @litfamily/litcodex@1.0.0 -- litcodex doctor
228
+ npm exec --yes --package @litfamily/litcodex@1.0.2 -- litcodex doctor
230
229
  ```
231
230
 
232
231
  `litcodex doctor` checks registration, hooks, config, and host capabilities. `litcodex loop doctor` checks
@@ -236,8 +235,6 @@ project loop state. A successful installation check does not prove authenticated
236
235
 
237
236
  - Plans and evidence stay reviewable. No criterion is marked complete merely because a test command ran.
238
237
  - Installation preserves unrelated Codex settings. Preview changes before `--reconfigure`.
239
- - Skill learning requires explicit review and apply; `autoApply` stays `false`. Only marked agent-owned skills
240
- may be changed. [Approval, rollback, and recovery rules](https://github.com/wjgoarxiv/litcodex/blob/main/docs/usage.md#skill-learning-loop).
241
238
  - The doctor diagnostic core never modifies Codex config, install state, or plugin state. An eligible interactive
242
239
  doctor may show a cached advisory notice. Its detached worker performs a fixed registry refresh at
243
240
  `~/.litcodex/update-check.json`; that worker never installs packages.
@@ -259,7 +256,7 @@ project loop state. A successful installation check does not prove authenticated
259
256
  ## Uninstall
260
257
 
261
258
  ```sh
262
- npm exec --yes --package @litfamily/litcodex@1.0.0 -- litcodex uninstall
259
+ npm exec --yes --package @litfamily/litcodex@1.0.2 -- litcodex uninstall
263
260
  ```
264
261
 
265
262
  `litcodex uninstall` removes the plugin and LitCodex-managed config while preserving unrelated settings.
@@ -274,7 +271,7 @@ npm exec --yes --package @litfamily/litcodex@1.0.0 -- litcodex uninstall
274
271
  The bundled skill library also includes `autoconference`, `autoresearch`, `browser-drive`, `coding-session-audit`,
275
272
  `comment-checker`, `debugging`, `frontend-ui-ux`, `lit-commit`, `lit-crucible`, `lit-init`, `lit-korean`, `lit-fetch`,
276
273
  `litcodex-contribute-bug-fix`, `litcodex-doctor`, `litcodex-report-bug`, `lsp`, `lsp-setup`, `lit-code`, `refactor`,
277
- `lit-burnoff`, `skill-observer`, `structural-search`, `lit-team`, `visual-qa`, and `wikify`.
274
+ `lit-burnoff`, `structural-search`, `lit-team`, `visual-qa`, and `wikify`.
278
275
 
279
276
  Tests, fixtures, test helpers, and Vitest configuration remain tracked repository coverage and are excluded from npm and installed marketplace payloads.
280
277
 
@@ -284,7 +281,7 @@ Tests, fixtures, test helpers, and Vitest configuration remain tracked repositor
284
281
 
285
282
  Select the poster to watch the 10-second film.
286
283
 
287
- <p align="center"><a href="https://github.com/wjgoarxiv/litcodex/blob/main/docs/assets/readme/ignition-film.mp4"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litcodex@1.0.0/readme-assets/ignition-poster.png" width="720" alt="Ignition motion graphic poster" /></a></p>
284
+ <p align="center"><a href="https://github.com/wjgoarxiv/litcodex/blob/main/docs/assets/readme/ignition-film.mp4"><img src="https://cdn.jsdelivr.net/npm/@litfamily/litcodex@1.0.2/readme-assets/ignition-poster.png" width="720" alt="Ignition motion graphic poster" /></a></p>
288
285
 
289
286
  [Animated GIF](https://github.com/wjgoarxiv/litcodex/blob/main/docs/assets/readme/ignition-readme.gif) · [Media and icon credits](https://github.com/wjgoarxiv/litcodex/blob/main/docs/assets/readme/README.md)
290
287
 
package/dist/cli.d.ts CHANGED
@@ -17,7 +17,7 @@ export declare function dispatch(argv: readonly string[]): DispatchResult;
17
17
  /**
18
18
  * Async process entry used by `bin/litcodex.js`. It owns the side-effecting routes: install/doctor/
19
19
  * uninstall (install/* modules, which are the ONLY code that ever spawns `codex`), `config migrate`
20
- * (M13, in-process), and the bundled `@litcodex/lit-loop` runtime routes `loop`/`hook`/`observer`. Returns the
20
+ * (M13, in-process), and the bundled `@litcodex/lit-loop` runtime routes `loop`/`hook`. Returns the
21
21
  * integer exit code; the bin owns `process.exit`. No forwarding, no exec-wrapper, no harness.
22
22
  */
23
23
  export declare function runCli(argv: readonly string[]): Promise<number>;
package/dist/cli.js CHANGED
@@ -55,19 +55,7 @@ const ROUTES = {
55
55
  config: configRouteHandler,
56
56
  loop: () => ok("litcodex loop\n"),
57
57
  hook: () => ok("litcodex hook\n"),
58
- observer: observerRouteHandler,
59
- "skill-loop": () => ok("litcodex skill-loop\n"),
60
58
  };
61
- function observerRouteHandler(rest, dryRun) {
62
- if (dryRun || rest.length > 0) {
63
- return {
64
- stdout: "",
65
- stderr: "litcodex observer: this command accepts no arguments.\n",
66
- exitCode: CONFIG_USAGE_EXIT_CODE,
67
- };
68
- }
69
- return ok("litcodex observer\n");
70
- }
71
59
  /**
72
60
  * Synchronous arm of the `config` route. The real `config migrate` work is async and is run by
73
61
  * `runCli` BEFORE `dispatch`; this sync handler only handles routing-level outcomes: an unknown
@@ -96,8 +84,6 @@ function renderHelp() {
96
84
  " litcodex config migrate Migrate Codex config for LitCodex",
97
85
  " litcodex loop <sub> Run a Lit-Loop subcommand",
98
86
  " litcodex hook user-prompt-submit Run the UserPromptSubmit hook",
99
- " litcodex observer Record one proposal from bounded stdin",
100
- " litcodex skill-loop <sub> Review, apply, reject, or roll back skill proposals",
101
87
  " litcodex --dry-run <command> Resolve a command without applying it",
102
88
  " litcodex --help Show this help",
103
89
  " litcodex --version Show the @litfamily/litcodex version",
@@ -167,7 +153,7 @@ export function dispatch(argv) {
167
153
  /**
168
154
  * Async process entry used by `bin/litcodex.js`. It owns the side-effecting routes: install/doctor/
169
155
  * uninstall (install/* modules, which are the ONLY code that ever spawns `codex`), `config migrate`
170
- * (M13, in-process), and the bundled `@litcodex/lit-loop` runtime routes `loop`/`hook`/`observer`. Returns the
156
+ * (M13, in-process), and the bundled `@litcodex/lit-loop` runtime routes `loop`/`hook`. Returns the
171
157
  * integer exit code; the bin owns `process.exit`. No forwarding, no exec-wrapper, no harness.
172
158
  */
173
159
  export async function runCli(argv) {
@@ -176,28 +162,6 @@ export async function runCli(argv) {
176
162
  const head = rest[0];
177
163
  const isHelp = rest.includes("--help") || rest.includes("-h");
178
164
  const isVersion = rest.includes("--version") || rest.includes("-v");
179
- if (!isHelp && !isVersion && head === "observer") {
180
- const observerResult = observerRouteHandler(rest.slice(1), dryRun);
181
- if (observerResult.exitCode !== 0)
182
- return dispatchExit(observerResult);
183
- const { runSkillObserverCli } = await import("@litcodex/lit-loop/dist/skill-observer-cli.js");
184
- return runSkillObserverCli(process.stdin, process.stdout, process.stderr);
185
- }
186
- if (!isHelp && !isVersion && head === "skill-loop") {
187
- if (dryRun)
188
- return dispatchExit({
189
- stdout: "",
190
- stderr: "litcodex skill-loop: --dry-run is not supported.\n",
191
- exitCode: 64,
192
- });
193
- const { skillLoopCommand } = await import("@litcodex/lit-loop/dist/skill-loop-cli.js");
194
- return skillLoopCommand(rest.slice(1), {
195
- cwd: process.cwd(),
196
- env: process.env,
197
- stdout: process.stdout,
198
- stderr: process.stderr,
199
- });
200
- }
201
165
  if (!isHelp && !isVersion) {
202
166
  if (head === "config" && rest[1] === "migrate") {
203
167
  const passthrough = dryRun ? [...rest.slice(2), "--dry-run"] : rest.slice(2);
@@ -231,7 +195,7 @@ export async function runCli(argv) {
231
195
  }
232
196
  const hooks = await import("@litcodex/lit-loop/dist/hook-cli.js");
233
197
  return rest[1] === "stop"
234
- ? hooks.runStopSkillReviewHookCli(process.stdin, process.stdout, process.stderr)
198
+ ? hooks.runStopPlanPersistenceHookCli(process.stdin, process.stdout, process.stderr)
235
199
  : hooks.runUserPromptSubmitHookCli(process.stdin, process.stdout, process.stderr);
236
200
  }
237
201
  }
@@ -9,3 +9,7 @@ export declare function ensureGpt56ProfileFiles(args: {
9
9
  readonly reconfigure: boolean;
10
10
  readonly modelContexts?: Gpt56ModelContexts;
11
11
  }): Promise<ProfileFileResult>;
12
+ /** The per-model profile file names LitCodex may write directly under `codexHome`. */
13
+ export declare const GPT56_PROFILE_FILE_NAMES: readonly string[];
14
+ /** True when `content` is exactly what LitCodex would have written for `name` (bare, or with the limits it still recognizes as its own). Used by uninstall to remove only files it authored. */
15
+ export declare function isManagedGpt56ProfileContent(name: string, content: string): boolean;
@@ -56,6 +56,28 @@ function profileContent() {
56
56
  "gpt56-luna-max.config.toml": renderProfile(GPT56_MODELS.luna, "max"),
57
57
  };
58
58
  }
59
+ /** The per-model profile file names LitCodex may write directly under `codexHome`. */
60
+ export const GPT56_PROFILE_FILE_NAMES = Object.keys(profileContent());
61
+ /** True when `content` is exactly what LitCodex would have written for `name` (bare, or with the limits it still recognizes as its own). Used by uninstall to remove only files it authored. */
62
+ export function isManagedGpt56ProfileContent(name, content) {
63
+ const desired = profileContent()[name];
64
+ if (desired === undefined)
65
+ return false;
66
+ if (content === desired)
67
+ return true;
68
+ switch (name) {
69
+ case "gpt56-sol-high.config.toml":
70
+ return isExactGeneratedExplicitSolProfile(content);
71
+ case "gpt56-terra-high.config.toml":
72
+ return isExactGeneratedTerraProfile(content);
73
+ case "gpt56-luna-max.config.toml":
74
+ return isExactGeneratedLunaProfile(content);
75
+ case "gpt6-astra-xhigh.config.toml":
76
+ return isExactGeneratedAstraProfile(content);
77
+ default:
78
+ return false;
79
+ }
80
+ }
59
81
  function renderProfile(model, effort) {
60
82
  return `model = ${JSON.stringify(model)}\nmodel_reasoning_effort = ${JSON.stringify(effort)}\n`;
61
83
  }
@@ -27,7 +27,11 @@ export function capabilityPreflightError(capabilities, codexBin) {
27
27
  // When that also fails, the existing Codex configuration on this machine is what
28
28
  // the resolved binary cannot load, and LitCodex's managed settings are innocent.
29
29
  if (reason === "host-config-incompatible") {
30
- return new InstallError("LITCODEX_INSTALL_HOST_CONFIG_INCOMPATIBLE", `The existing Codex configuration on this machine could not be loaded by the Codex that ran, with or without LitCodex settings; no install mutation was attempted.${resolved} This usually means that Codex is older than the one that last wrote the configuration.`, { capabilities });
30
+ const detail = capabilities.concurrency.detail;
31
+ const explanation = detail === undefined
32
+ ? " This usually means that Codex is older than the one that last wrote the configuration."
33
+ : ` Codex reported: ${detail}.`;
34
+ return new InstallError("LITCODEX_INSTALL_HOST_CONFIG_INCOMPATIBLE", `The existing Codex configuration on this machine could not be loaded by the Codex that ran, with or without LitCodex settings; no install mutation was attempted.${resolved}${explanation}`, { capabilities });
31
35
  }
32
36
  return new InstallError("LITCODEX_INSTALL_CONFIG_WRITE_FAILED", `Codex strict config rejected LitCodex managed settings; no install mutation was attempted.${resolved}`, { capabilities });
33
37
  }
@@ -10,6 +10,7 @@ export interface SpawnOptions {
10
10
  readonly stdio: "inherit" | "pipe";
11
11
  readonly timeout?: number;
12
12
  readonly env?: NodeJS.ProcessEnv;
13
+ readonly cwd?: string;
13
14
  readonly shell?: false;
14
15
  readonly windowsVerbatimArguments?: boolean;
15
16
  }
@@ -6,12 +6,7 @@ export declare const BROWSER_DRIVE_PAYLOAD_HASHES: {
6
6
  readonly "SKILL.md": "74f89ce0b7462e397952ac9d074b8a29a0133cccbc3e7179e8ec63128d88724f";
7
7
  readonly "agents/openai.yaml": "1b9a859e2da403ffc3a526b3d36e9bd6bfd95af087b7ec4ae71f6b615ced7828";
8
8
  readonly "references/snapshot-act-loop.md": "7aff2f4145413d61aaac577c2e551e3ed11a14b78dd46d047409c91a522ece1f";
9
- readonly "scripts/capability-probe.mjs": "7e8fa7b0c5243c51893c929ecdca4996eae83cad307590c5ac2ae8c34af1625c";
10
- };
11
- export declare const SKILL_OBSERVER_PAYLOAD_HASHES: {
12
- readonly "SKILL.md": "e56a3dd538f2e986f19abbc360f8902551a06e4c38903114ceb2ffba6681458d";
13
- readonly "agents/openai.yaml": "584a177dd2db92fdeb5a742643de035ff0932dd75cb01192953852df02fad3fe";
14
- readonly "references/review-contract.md": "f55dc8334f3b8d8498c84d57725fa03af8fbd689b2dd7cce25e49931629ee54f";
9
+ readonly "scripts/capability-probe.mjs": "95bac59fd820e5a1e1d7f43e984ddf9f8ffdcb10b4803d566afe06be316ad953";
15
10
  };
16
11
  export declare const FRONTEND_UIUX_PAYLOAD_HASHES: {
17
12
  readonly "SKILL.md": "b5fdb88106a0e23112686b120f4da0f250ac66c8909afaafbdf00f0ae823c88b";
@@ -7,12 +7,7 @@ export const BROWSER_DRIVE_PAYLOAD_HASHES = {
7
7
  "SKILL.md": "74f89ce0b7462e397952ac9d074b8a29a0133cccbc3e7179e8ec63128d88724f",
8
8
  "agents/openai.yaml": "1b9a859e2da403ffc3a526b3d36e9bd6bfd95af087b7ec4ae71f6b615ced7828",
9
9
  "references/snapshot-act-loop.md": "7aff2f4145413d61aaac577c2e551e3ed11a14b78dd46d047409c91a522ece1f",
10
- "scripts/capability-probe.mjs": "7e8fa7b0c5243c51893c929ecdca4996eae83cad307590c5ac2ae8c34af1625c",
11
- };
12
- export const SKILL_OBSERVER_PAYLOAD_HASHES = {
13
- "SKILL.md": "e56a3dd538f2e986f19abbc360f8902551a06e4c38903114ceb2ffba6681458d",
14
- "agents/openai.yaml": "584a177dd2db92fdeb5a742643de035ff0932dd75cb01192953852df02fad3fe",
15
- "references/review-contract.md": "f55dc8334f3b8d8498c84d57725fa03af8fbd689b2dd7cce25e49931629ee54f",
10
+ "scripts/capability-probe.mjs": "95bac59fd820e5a1e1d7f43e984ddf9f8ffdcb10b4803d566afe06be316ad953",
16
11
  };
17
12
  export const FRONTEND_UIUX_PAYLOAD_HASHES = {
18
13
  "SKILL.md": "b5fdb88106a0e23112686b120f4da0f250ac66c8909afaafbdf00f0ae823c88b",
@@ -7,6 +7,8 @@ export interface CapabilityReport {
7
7
  readonly reason: string;
8
8
  readonly observedSource: string;
9
9
  readonly limit?: number;
10
+ /** Extra diagnostic text observed from Codex itself: a startup warning on acceptance, or the doctor-reported failure detail on host-config-incompatible rejection. */
11
+ readonly detail?: string;
10
12
  }
11
13
  export interface HostCapabilities {
12
14
  readonly concurrency: CapabilityReport;
@@ -64,6 +64,10 @@ export function probeHostCapabilities(codexBin, spawn, selection = {}) {
64
64
  hostConfigRejected: baselineProbe?.kind === "rejected",
65
65
  timedOut: isTimeout(versionResult) || rootProbe.kind === "timeout",
66
66
  versionSupport,
67
+ ...(rootProbe.kind === "accepted" && rootProbe.warning !== undefined ? { rootWarning: rootProbe.warning } : {}),
68
+ ...(baselineProbe?.kind === "rejected" && baselineProbe.detail !== undefined
69
+ ? { hostConfigDetail: baselineProbe.detail }
70
+ : {}),
67
71
  });
68
72
  return {
69
73
  concurrency,
@@ -99,14 +103,21 @@ function concurrencyReport(args) {
99
103
  }
100
104
  if (!args.rootAccepted) {
101
105
  const reason = args.hostConfigRejected === true ? "host-config-incompatible" : "strict-config-rejected";
102
- return { status: "unavailable", reason, observedSource };
106
+ return {
107
+ status: "unavailable",
108
+ reason,
109
+ observedSource,
110
+ ...(args.hostConfigDetail === undefined ? {} : { detail: args.hostConfigDetail }),
111
+ };
103
112
  }
113
+ const detail = args.rootWarning === undefined ? {} : { detail: args.rootWarning };
104
114
  if (args.versionSupport.kind === "newer-stable") {
105
115
  return {
106
116
  status: "advisory",
107
117
  limit: HARD_CONCURRENCY_LIMIT,
108
118
  reason: "strict config accepted on a newer stable Codex; configured concurrency is usable but runtime enforcement is not yet source-verified",
109
119
  observedSource,
120
+ ...detail,
110
121
  };
111
122
  }
112
123
  return {
@@ -114,6 +125,7 @@ function concurrencyReport(args) {
114
125
  limit: HARD_CONCURRENCY_LIMIT,
115
126
  reason: "strict-config accepted the reserved collaboration schema, max_concurrent_threads_per_session=20, and agents.max_depth=1",
116
127
  observedSource,
128
+ ...detail,
117
129
  };
118
130
  }
119
131
  function autoCompactionReport(args) {
@@ -5,7 +5,7 @@
5
5
  // argv into typed `InstallOptions`, and return an integer exit code. `--dry-run` returns BEFORE any
6
6
  // spawn or fs write (renders the plan only). Unknown/bad flags exit 1.
7
7
  import { spawnSync } from "node:child_process";
8
- import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
8
+ import { existsSync, mkdirSync, readdirSync, readFileSync, rmdirSync, rmSync, writeFileSync } from "node:fs";
9
9
  import { createRequire } from "node:module";
10
10
  import { join } from "node:path";
11
11
  import readline from "node:readline/promises";
@@ -40,6 +40,7 @@ const realSpawn = (cmd, args, opts) => {
40
40
  shell: invocation.shell,
41
41
  windowsVerbatimArguments: invocation.windowsVerbatimArguments || opts.windowsVerbatimArguments === true,
42
42
  ...(opts.env === undefined ? {} : { env: opts.env }),
43
+ ...(opts.cwd === undefined ? {} : { cwd: opts.cwd }),
43
44
  });
44
45
  const out = {
45
46
  status: res.status,
@@ -384,6 +385,7 @@ export function runUninstallCli(args, io = defaultIo()) {
384
385
  existsSync,
385
386
  readdirSync: (path) => readdirSync(path),
386
387
  rmSync,
388
+ rmdirSync: (path) => rmdirSync(path),
387
389
  readFileSync: (path, enc) => readFileSync(path, enc),
388
390
  writeFileSync: (path, data) => {
389
391
  writeFileSync(path, data);
@@ -6,7 +6,7 @@ import type { ReadonlyFsLike } from "./codex.js";
6
6
  * marketplace has every supported skill entry point, while the companion test
7
7
  * compares it with the repository's package contract.
8
8
  */
9
- export declare const CANONICAL_SKILL_IDS: readonly ["autoconference", "autoresearch", "browser-drive", "coding-session-audit", "comment-checker", "debugging", "deep-interview", "frontend-ui-ux", "lit-burnoff", "lit-burnoff-file", "lit-code", "lit-commit", "lit-comprehend", "lit-crucible", "lit-fetch", "lit-handoff", "lit-init", "lit-korean", "lit-loop", "lit-plan", "lit-recap", "lit-scientific-visualization", "lit-team", "litcodex-contribute-bug-fix", "litcodex-doctor", "litcodex-report-bug", "litgoal", "litresearch", "litwork", "lsp", "lsp-setup", "refactor", "review-work", "rules", "skill-observer", "start-work", "structural-search", "visual-qa", "wikify"];
9
+ export declare const CANONICAL_SKILL_IDS: readonly ["autoconference", "autoresearch", "browser-drive", "coding-session-audit", "comment-checker", "debugging", "deep-interview", "frontend-ui-ux", "lit-burnoff", "lit-burnoff-file", "lit-code", "lit-commit", "lit-comprehend", "lit-crucible", "lit-fetch", "lit-handoff", "lit-init", "lit-korean", "lit-loop", "lit-plan", "lit-recap", "lit-scientific-visualization", "lit-team", "litcodex-contribute-bug-fix", "litcodex-doctor", "litcodex-report-bug", "litgoal", "litresearch", "litwork", "lsp", "lsp-setup", "refactor", "review-work", "rules", "start-work", "structural-search", "visual-qa", "wikify"];
10
10
  export declare const CANONICAL_SKILL_RESOURCE_PATHS: readonly ["lsp/references/runtime-triage.md", ...string[]];
11
11
  export interface SkillCatalogPayloadReport {
12
12
  readonly complete: boolean;
@@ -1,6 +1,6 @@
1
1
  import { join } from "node:path";
2
2
  import { payloadExact } from "./bundled-skills.js";
3
- import { AUTOCONFERENCE_PAYLOAD_HASHES, AUTORESEARCH_PAYLOAD_HASHES, BROWSER_DRIVE_PAYLOAD_HASHES, CODING_SESSION_AUDIT_PAYLOAD_HASHES, DEEP_INTERVIEW_PAYLOAD_HASHES, FRONTEND_UIUX_PAYLOAD_HASHES, SKILL_OBSERVER_PAYLOAD_HASHES, STRUCTURAL_SEARCH_PAYLOAD_HASHES, VISUAL_QA_PAYLOAD_HASHES, WIKIFY_PAYLOAD_HASHES, } from "./skill-resource-hashes.js";
3
+ import { AUTOCONFERENCE_PAYLOAD_HASHES, AUTORESEARCH_PAYLOAD_HASHES, BROWSER_DRIVE_PAYLOAD_HASHES, CODING_SESSION_AUDIT_PAYLOAD_HASHES, DEEP_INTERVIEW_PAYLOAD_HASHES, FRONTEND_UIUX_PAYLOAD_HASHES, STRUCTURAL_SEARCH_PAYLOAD_HASHES, VISUAL_QA_PAYLOAD_HASHES, WIKIFY_PAYLOAD_HASHES, } from "./skill-resource-hashes.js";
4
4
  /**
5
5
  * The Codex-native skill directories shipped in the LitCodex marketplace payload.
6
6
  *
@@ -43,7 +43,6 @@ export const CANONICAL_SKILL_IDS = [
43
43
  "refactor",
44
44
  "review-work",
45
45
  "rules",
46
- "skill-observer",
47
46
  "start-work",
48
47
  "structural-search",
49
48
  "visual-qa",
@@ -66,9 +65,6 @@ export const CANONICAL_SKILL_RESOURCE_PATHS = [
66
65
  ...Object.keys(FRONTEND_UIUX_PAYLOAD_HASHES)
67
66
  .filter((path) => path !== "SKILL.md")
68
67
  .map((path) => `frontend-ui-ux/${path}`),
69
- ...Object.keys(SKILL_OBSERVER_PAYLOAD_HASHES)
70
- .filter((path) => path !== "SKILL.md")
71
- .map((path) => `skill-observer/${path}`),
72
68
  ...Object.keys(VISUAL_QA_PAYLOAD_HASHES)
73
69
  .filter((path) => path !== "SKILL.md")
74
70
  .map((path) => `visual-qa/${path}`),
@@ -93,7 +89,6 @@ export function probeSkillCatalogPayload(fs, marketplaceRoot) {
93
89
  ["browser-drive", BROWSER_DRIVE_PAYLOAD_HASHES],
94
90
  ["deep-interview", DEEP_INTERVIEW_PAYLOAD_HASHES],
95
91
  ["frontend-ui-ux", FRONTEND_UIUX_PAYLOAD_HASHES],
96
- ["skill-observer", SKILL_OBSERVER_PAYLOAD_HASHES],
97
92
  ["visual-qa", VISUAL_QA_PAYLOAD_HASHES],
98
93
  ["structural-search", STRUCTURAL_SEARCH_PAYLOAD_HASHES],
99
94
  ["coding-session-audit", CODING_SESSION_AUDIT_PAYLOAD_HASHES],
@@ -1 +1 @@
1
- export { AUTOCONFERENCE_PAYLOAD_HASHES, AUTORESEARCH_PAYLOAD_HASHES, BROWSER_DRIVE_PAYLOAD_HASHES, CODING_SESSION_AUDIT_PAYLOAD_HASHES, DEEP_INTERVIEW_PAYLOAD_HASHES, FRONTEND_UIUX_PAYLOAD_HASHES, SKILL_OBSERVER_PAYLOAD_HASHES, STRUCTURAL_SEARCH_PAYLOAD_HASHES, VISUAL_QA_PAYLOAD_HASHES, WIKIFY_PAYLOAD_HASHES, } from "./generated-skill-payload-hashes.js";
1
+ export { AUTOCONFERENCE_PAYLOAD_HASHES, AUTORESEARCH_PAYLOAD_HASHES, BROWSER_DRIVE_PAYLOAD_HASHES, CODING_SESSION_AUDIT_PAYLOAD_HASHES, DEEP_INTERVIEW_PAYLOAD_HASHES, FRONTEND_UIUX_PAYLOAD_HASHES, STRUCTURAL_SEARCH_PAYLOAD_HASHES, VISUAL_QA_PAYLOAD_HASHES, WIKIFY_PAYLOAD_HASHES, } from "./generated-skill-payload-hashes.js";
@@ -1 +1 @@
1
- export { AUTOCONFERENCE_PAYLOAD_HASHES, AUTORESEARCH_PAYLOAD_HASHES, BROWSER_DRIVE_PAYLOAD_HASHES, CODING_SESSION_AUDIT_PAYLOAD_HASHES, DEEP_INTERVIEW_PAYLOAD_HASHES, FRONTEND_UIUX_PAYLOAD_HASHES, SKILL_OBSERVER_PAYLOAD_HASHES, STRUCTURAL_SEARCH_PAYLOAD_HASHES, VISUAL_QA_PAYLOAD_HASHES, WIKIFY_PAYLOAD_HASHES, } from "./generated-skill-payload-hashes.js";
1
+ export { AUTOCONFERENCE_PAYLOAD_HASHES, AUTORESEARCH_PAYLOAD_HASHES, BROWSER_DRIVE_PAYLOAD_HASHES, CODING_SESSION_AUDIT_PAYLOAD_HASHES, DEEP_INTERVIEW_PAYLOAD_HASHES, FRONTEND_UIUX_PAYLOAD_HASHES, STRUCTURAL_SEARCH_PAYLOAD_HASHES, VISUAL_QA_PAYLOAD_HASHES, WIKIFY_PAYLOAD_HASHES, } from "./generated-skill-payload-hashes.js";
@@ -1,8 +1,10 @@
1
1
  import { type SpawnLike } from "./codex.js";
2
2
  export type StrictConfigProbe = {
3
3
  readonly kind: "accepted";
4
+ readonly warning?: string;
4
5
  } | {
5
6
  readonly kind: "rejected";
7
+ readonly detail?: string;
6
8
  } | {
7
9
  readonly kind: "timeout";
8
10
  };
@@ -13,7 +13,12 @@ export function probeStrictConfig(args) {
13
13
  if (existsSync(sourceConfig)) {
14
14
  writeFileSync(join(probeHome, "config.toml"), readFileSync(sourceConfig), { mode: 0o600 });
15
15
  }
16
- return runProbe({ ...args, env: { ...args.env, CODEX_HOME: probeHome } });
16
+ // cwd matters here: Codex resolves per-project trust/overlay state from the *caller's*
17
+ // cwd, not from CODEX_HOME. Inheriting the real caller cwd let an unrelated trusted
18
+ // project entry in the copied config.toml (e.g. `[projects."$HOME"]`) change how that
19
+ // same config parses, turning a healthy host into a false refusal. Pointing cwd at the
20
+ // disposable probe home keeps the result a function of the config content alone.
21
+ return runProbe({ ...args, env: { ...args.env, CODEX_HOME: probeHome }, cwd: probeHome });
17
22
  }
18
23
  finally {
19
24
  rmSync(probeHome, { recursive: true, force: true, maxRetries: 3, retryDelay: 50 });
@@ -24,6 +29,7 @@ function runProbe(args) {
24
29
  stdio: "pipe",
25
30
  timeout: STRICT_CONFIG_PROBE_TIMEOUT_MS,
26
31
  ...(args.env === undefined ? {} : { env: args.env }),
32
+ ...(args.cwd === undefined ? {} : { cwd: args.cwd }),
27
33
  });
28
34
  if (isTimeout(result))
29
35
  return { kind: "timeout" };
@@ -31,7 +37,16 @@ function runProbe(args) {
31
37
  return { kind: "rejected" };
32
38
  try {
33
39
  const parsed = JSON.parse(result.stdout ?? "");
34
- return configLoadStatus(parsed) === "ok" ? { kind: "accepted" } : { kind: "rejected" };
40
+ const load = inspectConfigLoad(parsed);
41
+ if (load === null)
42
+ return { kind: "rejected" };
43
+ // A "warning" config.load status still parsed config.toml successfully — Codex is
44
+ // reporting something advisory (e.g. an ignored project-local key), not a load
45
+ // failure. Only a genuinely unparsable/failed load is a real rejection.
46
+ if (load.status === "ok" || (load.status === "warning" && load.parseOk)) {
47
+ return load.warning === undefined ? { kind: "accepted" } : { kind: "accepted", warning: load.warning };
48
+ }
49
+ return load.detail === undefined ? { kind: "rejected" } : { kind: "rejected", detail: load.detail };
35
50
  }
36
51
  catch (error) {
37
52
  if (error instanceof SyntaxError)
@@ -42,11 +57,25 @@ function runProbe(args) {
42
57
  function isTimeout(result) {
43
58
  return result.error instanceof Error && "code" in result.error && result.error.code === "ETIMEDOUT";
44
59
  }
45
- function configLoadStatus(value) {
60
+ function inspectConfigLoad(value) {
46
61
  if (!isRecord(value) || !isRecord(value["checks"]) || !isRecord(value["checks"]["config.load"]))
47
62
  return null;
48
- const status = value["checks"]["config.load"]["status"];
49
- return typeof status === "string" ? status : null;
63
+ const check = value["checks"]["config.load"];
64
+ const status = check["status"];
65
+ if (typeof status !== "string")
66
+ return null;
67
+ const details = isRecord(check["details"]) ? check["details"] : {};
68
+ const parseOk = details["config.toml parse"] === "ok";
69
+ const warning = typeof details["startup warning"] === "string" ? details["startup warning"] : undefined;
70
+ const notes = Array.isArray(check["notes"]) ? check["notes"].filter((note) => typeof note === "string") : [];
71
+ const summary = typeof check["summary"] === "string" ? check["summary"] : undefined;
72
+ const detailParts = [summary, ...notes].filter((part) => part !== undefined && part.length > 0);
73
+ return {
74
+ status,
75
+ parseOk,
76
+ ...(warning === undefined ? {} : { warning }),
77
+ ...(detailParts.length === 0 ? {} : { detail: detailParts.join(": ") }),
78
+ };
50
79
  }
51
80
  function isRecord(value) {
52
81
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -6,6 +6,8 @@ export interface UninstallFs {
6
6
  recursive?: boolean;
7
7
  force?: boolean;
8
8
  }): void;
9
+ /** Removes an empty directory only; must throw (not silently recurse) if the directory is non-empty. */
10
+ rmdirSync?(path: string): void;
9
11
  lstatSync?(path: string): {
10
12
  isSymbolicLink(): boolean;
11
13
  isDirectory(): boolean;
@@ -3,6 +3,7 @@ import { lstatSync as nativeLstatSync } from "node:fs";
3
3
  import { join } from "node:path";
4
4
  import { removeSubagentDefaults } from "../config-migration/multi-agent-v2-guard.js";
5
5
  import { ensureNativeDefaultAgentConfig } from "../config-migration/native-default-route.js";
6
+ import { GPT56_PROFILE_FILE_NAMES, isManagedGpt56ProfileContent } from "../config-migration/profile-files.js";
6
7
  import { NATIVE_DEFAULT_AGENT_FILE } from "./agent-routing.js";
7
8
  import { prepareAgentSources } from "./agents-install.js";
8
9
  import { isSafeManagedMarketplaceRoot, LITCODEX_MARKETPLACE, LITCODEX_PLUGIN_REF, managedMarketplaceRoot, } from "./marketplace.js";
@@ -25,6 +26,7 @@ export function runUninstall(deps) {
25
26
  }
26
27
  removeManagedAgents(deps);
27
28
  removeManagedSubagentDefaults(deps);
29
+ removeManagedProfileFiles(deps);
28
30
  return { ok: pluginOk && marketplaceOk, codexHome: deps.codexHome };
29
31
  }
30
32
  function isSafeUninstallPaths(deps) {
@@ -102,6 +104,38 @@ function removeManagedAgents(deps) {
102
104
  catch {
103
105
  // Best-effort agent cleanup must not hide the authoritative Codex removal result.
104
106
  }
107
+ removeIfEmptyDirectory(deps, agentsDir);
108
+ }
109
+ /** Best-effort per-model profile removal: only files whose content matches what LitCodex generates. */
110
+ function removeManagedProfileFiles(deps) {
111
+ if (!isDirectoryNonSymlink(deps, deps.codexHome) || deps.fs.readFileSync === undefined)
112
+ return;
113
+ for (const name of GPT56_PROFILE_FILE_NAMES) {
114
+ const path = join(deps.codexHome, name);
115
+ if (!isRegularNonSymlink(deps, path))
116
+ continue;
117
+ try {
118
+ const content = deps.fs.readFileSync(path, "utf8");
119
+ if (isManagedGpt56ProfileContent(name, content))
120
+ deps.fs.rmSync(path);
121
+ }
122
+ catch {
123
+ // Preserve unreadable or unremovable profiles while checking the rest.
124
+ }
125
+ }
126
+ }
127
+ /** Non-recursive: only removes a managed directory that install created and that is now empty. */
128
+ function removeIfEmptyDirectory(deps, path) {
129
+ if (deps.fs.rmdirSync === undefined || !isDirectoryNonSymlink(deps, path))
130
+ return;
131
+ try {
132
+ if (deps.fs.readdirSync(path).length > 0)
133
+ return;
134
+ deps.fs.rmdirSync(path);
135
+ }
136
+ catch {
137
+ // A non-empty or otherwise unremovable directory is left in place.
138
+ }
105
139
  }
106
140
  const MANAGED_DEFAULT_HEADER = [
107
141
  'name = "default"',
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "litcodex",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "LitCodex Codex plugin: the lit-loop activation, durable loop runtime, and local review-gated knowledge.",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@litcodex/auto-update",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "LitCodex foreground update barrier for the SessionStart and management lifecycles.",
5
5
  "type": "module",
6
6
  "private": true,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@litcodex/comment-checker",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "LitCodex Comment-Checker hook: flags low-value / AI-slop comments introduced by edits.",
5
5
  "type": "module",
6
6
  "private": true,