oh-my-opencode 4.14.2 → 4.15.1

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 (145) hide show
  1. package/dist/cli/index.js +644 -530
  2. package/dist/cli-node/index.js +644 -530
  3. package/dist/index.js +13 -13
  4. package/dist/skills/frontend/ATTRIBUTION.md +10 -2
  5. package/dist/skills/frontend/SKILL.md +7 -3
  6. package/dist/skills/frontend/references/design/README.md +11 -34
  7. package/dist/skills/frontend/references/design/clone-from-url.md +65 -0
  8. package/dist/skills/frontend/references/designpowers/EVIDENCE.md +10 -2
  9. package/dist/skills/frontend/references/designpowers/UPSTREAM.md +1 -1
  10. package/dist/skills/programming/SKILL.md +5 -3
  11. package/dist/skills/remove-ai-slops/SKILL.md +34 -15
  12. package/dist/skills/visual-qa/SKILL.md +11 -0
  13. package/dist/skills/visual-qa/scripts/skill-prompt-contract.test.ts +42 -0
  14. package/package.json +13 -13
  15. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  16. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +194 -102
  17. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  18. package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
  19. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  20. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  21. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  22. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  23. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  24. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  25. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  26. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  27. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  28. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  29. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +1 -1
  30. package/packages/omo-codex/plugin/package-lock.json +13 -13
  31. package/packages/omo-codex/plugin/package.json +1 -1
  32. package/packages/omo-codex/plugin/scripts/auto-update-plan.mjs +147 -2
  33. package/packages/omo-codex/plugin/scripts/auto-update-release-notes.mjs +33 -0
  34. package/packages/omo-codex/plugin/scripts/auto-update.mjs +48 -10
  35. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +18 -0
  36. package/packages/omo-codex/plugin/skills/frontend/ATTRIBUTION.md +10 -2
  37. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +7 -3
  38. package/packages/omo-codex/plugin/skills/frontend/references/design/README.md +11 -34
  39. package/packages/omo-codex/plugin/skills/frontend/references/design/clone-from-url.md +65 -0
  40. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/EVIDENCE.md +10 -2
  41. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/UPSTREAM.md +1 -1
  42. package/packages/omo-codex/plugin/skills/programming/SKILL.md +5 -3
  43. package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +34 -15
  44. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +1 -1
  45. package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +3 -3
  46. package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +11 -0
  47. package/packages/omo-codex/plugin/test/auto-update-release-notes.test.mjs +32 -0
  48. package/packages/omo-codex/plugin/test/auto-update.test.mjs +153 -3
  49. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +18 -1
  50. package/packages/omo-codex/plugin/test/sync-skills.test.mjs +39 -10
  51. package/packages/omo-codex/plugin/test/ulw-research-skill-contract.test.mjs +19 -1
  52. package/packages/omo-codex/scripts/install-dist/install-local.mjs +444 -330
  53. package/packages/shared-skills/skills/frontend/ATTRIBUTION.md +10 -2
  54. package/packages/shared-skills/skills/frontend/SKILL.md +7 -3
  55. package/packages/shared-skills/skills/frontend/references/design/README.md +11 -34
  56. package/packages/shared-skills/skills/frontend/references/design/clone-from-url.md +65 -0
  57. package/packages/shared-skills/skills/frontend/references/designpowers/EVIDENCE.md +10 -2
  58. package/packages/shared-skills/skills/frontend/references/designpowers/UPSTREAM.md +1 -1
  59. package/packages/shared-skills/skills/programming/SKILL.md +5 -3
  60. package/packages/shared-skills/skills/remove-ai-slops/SKILL.md +34 -15
  61. package/packages/shared-skills/skills/visual-qa/SKILL.md +11 -0
  62. package/packages/shared-skills/skills/visual-qa/scripts/skill-prompt-contract.test.ts +42 -0
  63. package/packages/omo-codex/plugin/skills/ultraresearch/SKILL.md +0 -10
  64. package/packages/omo-codex/plugin/skills/ultraresearch/agents/openai.yaml +0 -2
  65. /package/dist/skills/frontend/references/designpowers/vendor/skills/accessible-content/{SKILL.md → reference.md} +0 -0
  66. /package/dist/skills/frontend/references/designpowers/vendor/skills/adaptive-interfaces/{SKILL.md → reference.md} +0 -0
  67. /package/dist/skills/frontend/references/designpowers/vendor/skills/cognitive-accessibility/{SKILL.md → reference.md} +0 -0
  68. /package/dist/skills/frontend/references/designpowers/vendor/skills/design-debate/{SKILL.md → reference.md} +0 -0
  69. /package/dist/skills/frontend/references/designpowers/vendor/skills/design-debt-tracker/{SKILL.md → reference.md} +0 -0
  70. /package/dist/skills/frontend/references/designpowers/vendor/skills/design-handoff/{SKILL.md → reference.md} +0 -0
  71. /package/dist/skills/frontend/references/designpowers/vendor/skills/design-md/{SKILL.md → reference.md} +0 -0
  72. /package/dist/skills/frontend/references/designpowers/vendor/skills/design-retrospective/{SKILL.md → reference.md} +0 -0
  73. /package/dist/skills/frontend/references/designpowers/vendor/skills/design-review/{SKILL.md → reference.md} +0 -0
  74. /package/dist/skills/frontend/references/designpowers/vendor/skills/design-system-alignment/{SKILL.md → reference.md} +0 -0
  75. /package/dist/skills/frontend/references/designpowers/vendor/skills/designpowers-critique/{SKILL.md → reference.md} +0 -0
  76. /package/dist/skills/frontend/references/designpowers/vendor/skills/heuristic-evaluation/{SKILL.md → reference.md} +0 -0
  77. /package/dist/skills/frontend/references/designpowers/vendor/skills/inclusive-personas/{SKILL.md → reference.md} +0 -0
  78. /package/dist/skills/frontend/references/designpowers/vendor/skills/inspiration-scouting/{SKILL.md → reference.md} +0 -0
  79. /package/dist/skills/frontend/references/designpowers/vendor/skills/interaction-design/{SKILL.md → reference.md} +0 -0
  80. /package/dist/skills/frontend/references/designpowers/vendor/skills/motion-choreography/{SKILL.md → reference.md} +0 -0
  81. /package/dist/skills/frontend/references/designpowers/vendor/skills/research-planning/{SKILL.md → reference.md} +0 -0
  82. /package/dist/skills/frontend/references/designpowers/vendor/skills/responsive-patterns/{SKILL.md → reference.md} +0 -0
  83. /package/dist/skills/frontend/references/designpowers/vendor/skills/synthetic-user-testing/{SKILL.md → reference.md} +0 -0
  84. /package/dist/skills/frontend/references/designpowers/vendor/skills/taste-feedback/{SKILL.md → reference.md} +0 -0
  85. /package/dist/skills/frontend/references/designpowers/vendor/skills/taste-report/{SKILL.md → reference.md} +0 -0
  86. /package/dist/skills/frontend/references/designpowers/vendor/skills/token-architecture/{SKILL.md → reference.md} +0 -0
  87. /package/dist/skills/frontend/references/designpowers/vendor/skills/ui-composition/{SKILL.md → reference.md} +0 -0
  88. /package/dist/skills/frontend/references/designpowers/vendor/skills/usability-testing/{SKILL.md → reference.md} +0 -0
  89. /package/dist/skills/frontend/references/designpowers/vendor/skills/verification-before-shipping/{SKILL.md → reference.md} +0 -0
  90. /package/dist/skills/frontend/references/designpowers/vendor/skills/voice-and-tone/{SKILL.md → reference.md} +0 -0
  91. /package/dist/skills/frontend/references/designpowers/vendor/skills/writing-design-plans/{SKILL.md → reference.md} +0 -0
  92. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/accessible-content/{SKILL.md → reference.md} +0 -0
  93. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/adaptive-interfaces/{SKILL.md → reference.md} +0 -0
  94. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/cognitive-accessibility/{SKILL.md → reference.md} +0 -0
  95. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/design-debate/{SKILL.md → reference.md} +0 -0
  96. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/design-debt-tracker/{SKILL.md → reference.md} +0 -0
  97. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/design-handoff/{SKILL.md → reference.md} +0 -0
  98. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/design-md/{SKILL.md → reference.md} +0 -0
  99. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/design-retrospective/{SKILL.md → reference.md} +0 -0
  100. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/design-review/{SKILL.md → reference.md} +0 -0
  101. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/design-system-alignment/{SKILL.md → reference.md} +0 -0
  102. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/designpowers-critique/{SKILL.md → reference.md} +0 -0
  103. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/heuristic-evaluation/{SKILL.md → reference.md} +0 -0
  104. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/inclusive-personas/{SKILL.md → reference.md} +0 -0
  105. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/inspiration-scouting/{SKILL.md → reference.md} +0 -0
  106. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/interaction-design/{SKILL.md → reference.md} +0 -0
  107. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/motion-choreography/{SKILL.md → reference.md} +0 -0
  108. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/research-planning/{SKILL.md → reference.md} +0 -0
  109. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/responsive-patterns/{SKILL.md → reference.md} +0 -0
  110. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/synthetic-user-testing/{SKILL.md → reference.md} +0 -0
  111. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/taste-feedback/{SKILL.md → reference.md} +0 -0
  112. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/taste-report/{SKILL.md → reference.md} +0 -0
  113. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/token-architecture/{SKILL.md → reference.md} +0 -0
  114. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/ui-composition/{SKILL.md → reference.md} +0 -0
  115. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/usability-testing/{SKILL.md → reference.md} +0 -0
  116. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/verification-before-shipping/{SKILL.md → reference.md} +0 -0
  117. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/voice-and-tone/{SKILL.md → reference.md} +0 -0
  118. /package/packages/omo-codex/plugin/skills/frontend/references/designpowers/vendor/skills/writing-design-plans/{SKILL.md → reference.md} +0 -0
  119. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/accessible-content/{SKILL.md → reference.md} +0 -0
  120. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/adaptive-interfaces/{SKILL.md → reference.md} +0 -0
  121. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/cognitive-accessibility/{SKILL.md → reference.md} +0 -0
  122. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/design-debate/{SKILL.md → reference.md} +0 -0
  123. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/design-debt-tracker/{SKILL.md → reference.md} +0 -0
  124. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/design-handoff/{SKILL.md → reference.md} +0 -0
  125. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/design-md/{SKILL.md → reference.md} +0 -0
  126. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/design-retrospective/{SKILL.md → reference.md} +0 -0
  127. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/design-review/{SKILL.md → reference.md} +0 -0
  128. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/design-system-alignment/{SKILL.md → reference.md} +0 -0
  129. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/designpowers-critique/{SKILL.md → reference.md} +0 -0
  130. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/heuristic-evaluation/{SKILL.md → reference.md} +0 -0
  131. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/inclusive-personas/{SKILL.md → reference.md} +0 -0
  132. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/inspiration-scouting/{SKILL.md → reference.md} +0 -0
  133. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/interaction-design/{SKILL.md → reference.md} +0 -0
  134. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/motion-choreography/{SKILL.md → reference.md} +0 -0
  135. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/research-planning/{SKILL.md → reference.md} +0 -0
  136. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/responsive-patterns/{SKILL.md → reference.md} +0 -0
  137. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/synthetic-user-testing/{SKILL.md → reference.md} +0 -0
  138. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/taste-feedback/{SKILL.md → reference.md} +0 -0
  139. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/taste-report/{SKILL.md → reference.md} +0 -0
  140. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/token-architecture/{SKILL.md → reference.md} +0 -0
  141. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/ui-composition/{SKILL.md → reference.md} +0 -0
  142. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/usability-testing/{SKILL.md → reference.md} +0 -0
  143. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/verification-before-shipping/{SKILL.md → reference.md} +0 -0
  144. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/voice-and-tone/{SKILL.md → reference.md} +0 -0
  145. /package/packages/shared-skills/skills/frontend/references/designpowers/vendor/skills/writing-design-plans/{SKILL.md → reference.md} +0 -0
@@ -147,7 +147,7 @@ async function downloadFromManifest(options) {
147
147
 
148
148
  // components/bootstrap/src/hook.ts
149
149
  import { spawn as spawn2 } from "node:child_process";
150
- import { stat as stat5 } from "node:fs/promises";
150
+ import { stat as stat6 } from "node:fs/promises";
151
151
  import { fileURLToPath as fileURLToPath3 } from "node:url";
152
152
 
153
153
  // scripts/auto-update-state.mjs
@@ -438,9 +438,9 @@ async function readOptionalFile(path) {
438
438
  }
439
439
 
440
440
  // components/bootstrap/src/worker.ts
441
- import { appendFile as appendFile2, mkdir as mkdir8, readFile as readFile12 } from "node:fs/promises";
441
+ import { appendFile as appendFile2, mkdir as mkdir8, readFile as readFile13 } from "node:fs/promises";
442
442
  import { homedir as homedir4 } from "node:os";
443
- import { dirname as dirname7, join as join19, resolve as resolve6 } from "node:path";
443
+ import { dirname as dirname8, join as join20, resolve as resolve7 } from "node:path";
444
444
  import { fileURLToPath as fileURLToPath2 } from "node:url";
445
445
 
446
446
  // components/bootstrap/src/provision.ts
@@ -861,8 +861,8 @@ async function defaultVersionProbe2(binaryPath) {
861
861
  }
862
862
 
863
863
  // components/bootstrap/src/setup.ts
864
- import { copyFile as copyFile2, mkdir as mkdir7, readdir as readdir3, rm as rm9, stat as stat4 } from "node:fs/promises";
865
- import { join as join18 } from "node:path";
864
+ import { copyFile as copyFile2, mkdir as mkdir7, readdir as readdir4, rm as rm10, stat as stat5 } from "node:fs/promises";
865
+ import { join as join19 } from "node:path";
866
866
 
867
867
  // ../src/install/link-cached-plugin-agents.ts
868
868
  import { copyFile, lstat as lstat2, mkdir as mkdir4, readFile as readFile5, readdir, rm as rm6, writeFile as writeFile3 } from "node:fs/promises";
@@ -1167,8 +1167,8 @@ function nodeErrorCode2(error) {
1167
1167
  }
1168
1168
 
1169
1169
  // ../src/install/codex-cache-bins.ts
1170
- import { chmod as chmod2, lstat as lstat5, mkdir as mkdir5, readFile as readFile7, readdir as readdir2, readlink as readlink2, rm as rm8, stat as stat3, symlink, writeFile as writeFile4 } from "node:fs/promises";
1171
- import { basename as basename4, isAbsolute as isAbsolute2, join as join12, relative as relative2, resolve as resolve3, sep } from "node:path";
1170
+ import { chmod as chmod2, lstat as lstat6, mkdir as mkdir5, readFile as readFile8, readdir as readdir3, readlink as readlink3, rm as rm9, stat as stat4, symlink, writeFile as writeFile4 } from "node:fs/promises";
1171
+ import { basename as basename4, isAbsolute as isAbsolute3, join as join13, relative as relative2, resolve as resolve4, sep } from "node:path";
1172
1172
 
1173
1173
  // ../src/install/codex-cache-command-shim.ts
1174
1174
  var COMMAND_SHIM_MARKER = ":: generated by oh-my-openagent Codex installer";
@@ -1211,6 +1211,10 @@ function windowsCommandShim(targetPath) {
1211
1211
  `);
1212
1212
  }
1213
1213
 
1214
+ // ../src/install/codex-cache-dangling-bins.ts
1215
+ import { lstat as lstat4, readFile as readFile6, readdir as readdir2, readlink, rm as rm7, stat as stat3 } from "node:fs/promises";
1216
+ import { dirname as dirname5, isAbsolute as isAbsolute2, join as join10, resolve as resolve3 } from "node:path";
1217
+
1214
1218
  // ../src/install/codex-cache-fs.ts
1215
1219
  import { lstat as lstat3 } from "node:fs/promises";
1216
1220
  async function fileExistsStrict(path) {
@@ -1230,9 +1234,96 @@ function isNodeErrorWithCode(error) {
1230
1234
  return typeof error === "object" && error !== null && "code" in error;
1231
1235
  }
1232
1236
 
1237
+ // ../src/install/codex-cache-dangling-bins.ts
1238
+ async function removeDanglingManagedComponentBins(binDir, platform, managedBinNames) {
1239
+ const entries = await readdir2(binDir, { withFileTypes: true });
1240
+ for (const entry of entries) {
1241
+ const binName = managedBinNameForEntry(entry.name, platform);
1242
+ if (binName === null || !managedBinNames.has(binName))
1243
+ continue;
1244
+ const linkPath = join10(binDir, entry.name);
1245
+ if (platform === "win32") {
1246
+ await removeDanglingGeneratedCommandShim(linkPath);
1247
+ continue;
1248
+ }
1249
+ await removeDanglingManagedSymlink(linkPath);
1250
+ }
1251
+ }
1252
+ function managedBinNameForEntry(name, platform) {
1253
+ if (platform === "win32")
1254
+ return name.endsWith(".cmd") ? name.slice(0, -4) : null;
1255
+ return name;
1256
+ }
1257
+ async function removeDanglingManagedSymlink(linkPath) {
1258
+ try {
1259
+ const linkStat = await lstat4(linkPath);
1260
+ if (!linkStat.isSymbolicLink())
1261
+ return;
1262
+ const linkTarget = await readlink(linkPath);
1263
+ const target = isAbsolute2(linkTarget) ? linkTarget : resolve3(dirname5(linkPath), linkTarget);
1264
+ if (!await isFileSystemEntry(target) && isManagedComponentBinTarget(target))
1265
+ await rm7(linkPath, { force: true });
1266
+ } catch (error) {
1267
+ if (isNodeErrorWithCode(error) && error.code === "ENOENT")
1268
+ return;
1269
+ throw error;
1270
+ }
1271
+ }
1272
+ async function removeDanglingGeneratedCommandShim(linkPath) {
1273
+ try {
1274
+ const linkStat = await lstat4(linkPath);
1275
+ if (!linkStat.isFile())
1276
+ return;
1277
+ const content = await readFile6(linkPath, "utf8");
1278
+ if (!content.includes(COMMAND_SHIM_MARKER))
1279
+ return;
1280
+ const target = extractCommandShimTarget(content);
1281
+ if (target !== null && !await isFileSystemEntry(target) && isManagedComponentBinTarget(target))
1282
+ await rm7(linkPath, { force: true });
1283
+ } catch (error) {
1284
+ if (isNodeErrorWithCode(error) && error.code === "ENOENT")
1285
+ return;
1286
+ throw error;
1287
+ }
1288
+ }
1289
+ async function isFileSystemEntry(path) {
1290
+ try {
1291
+ await stat3(path);
1292
+ return true;
1293
+ } catch (error) {
1294
+ if (isNodeErrorWithCode(error) && error.code === "ENOENT")
1295
+ return false;
1296
+ throw error;
1297
+ }
1298
+ }
1299
+ function extractCommandShimTarget(content) {
1300
+ const match = /"([^"\r\n]+components[\\/][^"\r\n]+[\\/]dist[\\/]cli\.js)" %\*/.exec(content);
1301
+ return match?.[1] ?? null;
1302
+ }
1303
+ function isManagedComponentBinTarget(target) {
1304
+ const parts = target.split(/[\\/]+/);
1305
+ const suffix = parts.slice(-4);
1306
+ return suffix[0] === "components" && suffix[2] === "dist" && suffix[3] === "cli.js" && (hasOmoPluginCachePrefix(parts, parts.length - 4) || hasOmoCodexPluginPrefix(parts, parts.length - 4));
1307
+ }
1308
+ function hasOmoPluginCachePrefix(parts, endExclusive) {
1309
+ for (let index = 0;index < endExclusive - 4; index += 1) {
1310
+ if (parts[index] === "plugins" && parts[index + 1] === "cache" && parts[index + 2] === "sisyphuslabs" && parts[index + 3] === "omo") {
1311
+ return index + 4 < endExclusive;
1312
+ }
1313
+ }
1314
+ return false;
1315
+ }
1316
+ function hasOmoCodexPluginPrefix(parts, endExclusive) {
1317
+ for (let index = 0;index <= endExclusive - 3; index += 1) {
1318
+ if (parts[index] === "packages" && parts[index + 1] === "omo-codex" && parts[index + 2] === "plugin")
1319
+ return true;
1320
+ }
1321
+ return false;
1322
+ }
1323
+
1233
1324
  // ../src/install/codex-cache-legacy-bins.ts
1234
- import { lstat as lstat4, readFile as readFile6, readlink, rm as rm7 } from "node:fs/promises";
1235
- import { join as join10 } from "node:path";
1325
+ import { lstat as lstat5, readFile as readFile7, readlink as readlink2, rm as rm8 } from "node:fs/promises";
1326
+ import { join as join11 } from "node:path";
1236
1327
  var LEGACY_CODEX_COMPONENT_BINS = [
1237
1328
  { name: "omo", component: "ulw-loop" },
1238
1329
  { name: "codex-comment-checker", component: "comment-checker" },
@@ -1244,26 +1335,26 @@ var LEGACY_CODEX_COMPONENT_BINS = [
1244
1335
  ];
1245
1336
  async function removeLegacyCodexComponentBins(binDir, platform) {
1246
1337
  for (const entry of LEGACY_CODEX_COMPONENT_BINS) {
1247
- const linkPath = join10(binDir, platform === "win32" ? `${entry.name}.cmd` : entry.name);
1338
+ const linkPath = join11(binDir, platform === "win32" ? `${entry.name}.cmd` : entry.name);
1248
1339
  await removeLegacyCodexComponentBin(linkPath, entry.component, platform);
1249
1340
  }
1250
1341
  }
1251
1342
  async function removeLegacyCodexComponentBin(linkPath, component, platform) {
1252
1343
  try {
1253
- const stat3 = await lstat4(linkPath);
1344
+ const stat4 = await lstat5(linkPath);
1254
1345
  if (platform !== "win32") {
1255
- if (!stat3.isSymbolicLink())
1346
+ if (!stat4.isSymbolicLink())
1256
1347
  return;
1257
- const target = await readlink(linkPath);
1348
+ const target = await readlink2(linkPath);
1258
1349
  if (isManagedLegacyComponentTarget(target, component))
1259
- await rm7(linkPath, { force: true });
1350
+ await rm8(linkPath, { force: true });
1260
1351
  return;
1261
1352
  }
1262
- if (!stat3.isFile())
1353
+ if (!stat4.isFile())
1263
1354
  return;
1264
- const content = await readFile6(linkPath, "utf8");
1355
+ const content = await readFile7(linkPath, "utf8");
1265
1356
  if (content.includes(COMMAND_SHIM_MARKER))
1266
- await rm7(linkPath, { force: true });
1357
+ await rm8(linkPath, { force: true });
1267
1358
  } catch (error) {
1268
1359
  if (isNodeErrorWithCode2(error) && error.code === "ENOENT")
1269
1360
  return;
@@ -1274,7 +1365,7 @@ function isManagedLegacyComponentTarget(target, component) {
1274
1365
  const parts = target.split(/[\\/]+/);
1275
1366
  const suffixStart = parts.length - 4;
1276
1367
  const suffix = parts.slice(-4);
1277
- return suffix[0] === "components" && suffix[1] === component && suffix[2] === "dist" && suffix[3] === "cli.js" && (hasPluginCachePrefix(parts, suffixStart) || hasOmoCodexPluginPrefix(parts, suffixStart));
1368
+ return suffix[0] === "components" && suffix[1] === component && suffix[2] === "dist" && suffix[3] === "cli.js" && (hasPluginCachePrefix(parts, suffixStart) || hasOmoCodexPluginPrefix2(parts, suffixStart));
1278
1369
  }
1279
1370
  function hasPluginCachePrefix(parts, endExclusive) {
1280
1371
  for (let index = 0;index < endExclusive - 1; index += 1) {
@@ -1283,7 +1374,7 @@ function hasPluginCachePrefix(parts, endExclusive) {
1283
1374
  }
1284
1375
  return false;
1285
1376
  }
1286
- function hasOmoCodexPluginPrefix(parts, endExclusive) {
1377
+ function hasOmoCodexPluginPrefix2(parts, endExclusive) {
1287
1378
  for (let index = 0;index <= endExclusive - 3; index += 1) {
1288
1379
  if (parts[index] === "packages" && parts[index + 1] === "omo-codex" && parts[index + 2] === "plugin")
1289
1380
  return true;
@@ -1295,10 +1386,10 @@ function isNodeErrorWithCode2(error) {
1295
1386
  }
1296
1387
 
1297
1388
  // ../src/install/codex-cache-runtime-wrapper.ts
1298
- import { join as join11 } from "node:path";
1389
+ import { join as join12 } from "node:path";
1299
1390
  var RUNTIME_WRAPPER_MARKER = "OMO_GENERATED_RUNTIME_WRAPPER";
1300
1391
  function posixRuntimeWrapper(cliPath, codexHome, binDir, nodeCliPath) {
1301
- const ulwLoopBin = toPosixPath(join11(binDir, "omo-ulw-loop"));
1392
+ const ulwLoopBin = toPosixPath(join12(binDir, "omo-ulw-loop"));
1302
1393
  const nodeCli = escapePosixDoubleQuoted(toPosixPath(nodeCliPath));
1303
1394
  const escapedCliPath = escapePosixDoubleQuoted(toPosixPath(cliPath));
1304
1395
  const escapedCodexHome = escapePosixDoubleQuoted(toPosixPath(codexHome));
@@ -1343,7 +1434,7 @@ function posixRuntimeWrapper(cliPath, codexHome, binDir, nodeCliPath) {
1343
1434
  `);
1344
1435
  }
1345
1436
  function windowsRuntimeWrapper(cliPath, codexHome, binDir, nodeCliPath) {
1346
- const ulwLoopBin = join11(binDir, "omo-ulw-loop.cmd");
1437
+ const ulwLoopBin = join12(binDir, "omo-ulw-loop.cmd");
1347
1438
  return [
1348
1439
  "@echo off",
1349
1440
  `rem ${RUNTIME_WRAPPER_MARKER}`,
@@ -1391,6 +1482,7 @@ async function linkCachedPluginBins(input) {
1391
1482
  const platform = input.platform ?? process.platform;
1392
1483
  await mkdir5(input.binDir, { recursive: true });
1393
1484
  await removeLegacyCodexComponentBins(input.binDir, platform);
1485
+ await removeDanglingManagedComponentBins(input.binDir, platform, new Set(binLinks.map((link) => link.name)));
1394
1486
  const linked = [];
1395
1487
  for (const link of binLinks) {
1396
1488
  const linkPath = await linkCachedPluginBin(input.binDir, link, platform);
@@ -1399,35 +1491,35 @@ async function linkCachedPluginBins(input) {
1399
1491
  return linked;
1400
1492
  }
1401
1493
  async function linkRootRuntimeBin(input) {
1402
- const cliPath = join12(input.repoRoot, "dist", "cli", "index.js");
1494
+ const cliPath = join13(input.repoRoot, "dist", "cli", "index.js");
1403
1495
  if (!await isFile2(cliPath))
1404
1496
  return null;
1405
- const nodeCliPath = join12(input.repoRoot, "dist", "cli-node", "index.js");
1497
+ const nodeCliPath = join13(input.repoRoot, "dist", "cli-node", "index.js");
1406
1498
  const platform = input.platform ?? process.platform;
1407
1499
  await mkdir5(input.binDir, { recursive: true });
1408
1500
  if (platform === "win32") {
1409
- const linkPath2 = join12(input.binDir, "omo.cmd");
1501
+ const linkPath2 = join13(input.binDir, "omo.cmd");
1410
1502
  await replaceRuntimeWrapper(linkPath2, windowsRuntimeWrapper(cliPath, input.codexHome, input.binDir, nodeCliPath));
1411
1503
  return { name: "omo", path: linkPath2, target: cliPath };
1412
1504
  }
1413
- const linkPath = join12(input.binDir, "omo");
1505
+ const linkPath = join13(input.binDir, "omo");
1414
1506
  await replaceRuntimeWrapper(linkPath, posixRuntimeWrapper(cliPath, input.codexHome, input.binDir, nodeCliPath));
1415
1507
  await chmod2(linkPath, 493);
1416
1508
  return { name: "omo", path: linkPath, target: cliPath };
1417
1509
  }
1418
1510
  async function linkCachedPluginBin(binDir, link, platform) {
1419
1511
  if (platform === "win32") {
1420
- const linkPath2 = join12(binDir, `${link.name}.cmd`);
1512
+ const linkPath2 = join13(binDir, `${link.name}.cmd`);
1421
1513
  await replaceCommandShim(linkPath2, link.target);
1422
1514
  return linkPath2;
1423
1515
  }
1424
- const linkPath = join12(binDir, link.name);
1516
+ const linkPath = join13(binDir, link.name);
1425
1517
  await replaceSymlink(linkPath, link.target);
1426
1518
  return linkPath;
1427
1519
  }
1428
1520
  async function isFile2(path) {
1429
1521
  try {
1430
- return (await stat3(path)).isFile();
1522
+ return (await stat4(path)).isFile();
1431
1523
  } catch (error) {
1432
1524
  if (isNodeErrorWithCode(error) && error.code === "ENOENT")
1433
1525
  return false;
@@ -1440,23 +1532,23 @@ async function discoverPackageBins(root) {
1440
1532
  return links;
1441
1533
  }
1442
1534
  async function collectPackageBins(directory, root, links) {
1443
- const entries = await readdir2(directory, { withFileTypes: true });
1535
+ const entries = await readdir3(directory, { withFileTypes: true });
1444
1536
  if (entries.some((entry) => entry.isFile() && entry.name === "package.json")) {
1445
- await appendPackageBinLinks(join12(directory, "package.json"), directory, root, links);
1537
+ await appendPackageBinLinks(join13(directory, "package.json"), directory, root, links);
1446
1538
  }
1447
1539
  for (const entry of entries) {
1448
1540
  if (!entry.isDirectory())
1449
1541
  continue;
1450
1542
  if (entry.name === "node_modules" || entry.name === ".git" || entry.name === "dist")
1451
1543
  continue;
1452
- const childPath = join12(directory, entry.name);
1544
+ const childPath = join13(directory, entry.name);
1453
1545
  if (!childPath.startsWith(root))
1454
1546
  continue;
1455
1547
  await collectPackageBins(childPath, root, links);
1456
1548
  }
1457
1549
  }
1458
1550
  async function appendPackageBinLinks(packageJsonPath, packageRoot, root, links) {
1459
- const packageJson = JSON.parse(await readFile7(packageJsonPath, "utf8"));
1551
+ const packageJson = JSON.parse(await readFile8(packageJsonPath, "utf8"));
1460
1552
  if (!isPlainRecord(packageJson))
1461
1553
  return;
1462
1554
  const packageName = packageJson.name;
@@ -1491,10 +1583,10 @@ function isReservedNestedBinName(name, packageRoot, root) {
1491
1583
  function resolvePackageBinTarget(packageRoot, target) {
1492
1584
  if (target.includes("\x00"))
1493
1585
  throw new Error("Package bin target must stay inside package root");
1494
- const root = resolve3(packageRoot);
1495
- const resolvedTarget = resolve3(root, target);
1586
+ const root = resolve4(packageRoot);
1587
+ const resolvedTarget = resolve4(root, target);
1496
1588
  const relativeTarget = relative2(root, resolvedTarget);
1497
- if (relativeTarget === "" || relativeTarget !== ".." && !relativeTarget.startsWith(`..${sep}`) && !isAbsolute2(relativeTarget)) {
1589
+ if (relativeTarget === "" || relativeTarget !== ".." && !relativeTarget.startsWith(`..${sep}`) && !isAbsolute3(relativeTarget)) {
1498
1590
  return resolvedTarget;
1499
1591
  }
1500
1592
  throw new Error("Package bin target must stay inside package root");
@@ -1502,7 +1594,7 @@ function resolvePackageBinTarget(packageRoot, target) {
1502
1594
  async function replaceSymlink(linkPath, targetPath) {
1503
1595
  if (await existingNonSymlink(linkPath))
1504
1596
  throw new Error(`${linkPath} already exists and is not a symlink`);
1505
- await rm8(linkPath, { force: true });
1597
+ await rm9(linkPath, { force: true });
1506
1598
  await symlink(targetPath, linkPath);
1507
1599
  }
1508
1600
  async function replaceCommandShim(linkPath, targetPath) {
@@ -1513,17 +1605,17 @@ async function replaceCommandShim(linkPath, targetPath) {
1513
1605
  async function replaceRuntimeWrapper(linkPath, content) {
1514
1606
  if (await existingNonRuntimeWrapper(linkPath))
1515
1607
  throw new Error(`${linkPath} already exists and is not a generated OMO runtime wrapper`);
1516
- await rm8(linkPath, { force: true });
1608
+ await rm9(linkPath, { force: true });
1517
1609
  await writeFile4(linkPath, content);
1518
1610
  }
1519
1611
  async function existingNonRuntimeWrapper(path) {
1520
1612
  try {
1521
- const stat4 = await lstat5(path);
1522
- if (stat4.isSymbolicLink())
1613
+ const stat5 = await lstat6(path);
1614
+ if (stat5.isSymbolicLink())
1523
1615
  return false;
1524
- if (!stat4.isFile())
1616
+ if (!stat5.isFile())
1525
1617
  return true;
1526
- const content = await readFile7(path, "utf8");
1618
+ const content = await readFile8(path, "utf8");
1527
1619
  return !content.includes(RUNTIME_WRAPPER_MARKER);
1528
1620
  } catch (error) {
1529
1621
  if (isNodeErrorWithCode(error) && error.code === "ENOENT")
@@ -1533,10 +1625,10 @@ async function existingNonRuntimeWrapper(path) {
1533
1625
  }
1534
1626
  async function existingNonShim(path) {
1535
1627
  try {
1536
- const stat4 = await lstat5(path);
1537
- if (!stat4.isFile())
1628
+ const stat5 = await lstat6(path);
1629
+ if (!stat5.isFile())
1538
1630
  return true;
1539
- const content = await readFile7(path, "utf8");
1631
+ const content = await readFile8(path, "utf8");
1540
1632
  if (content.includes(COMMAND_SHIM_MARKER))
1541
1633
  return false;
1542
1634
  throw new Error(`${path} already exists and is not a generated command shim`);
@@ -1548,10 +1640,10 @@ async function existingNonShim(path) {
1548
1640
  }
1549
1641
  async function existingNonSymlink(path) {
1550
1642
  try {
1551
- const stat4 = await lstat5(path);
1552
- if (!stat4.isSymbolicLink())
1643
+ const stat5 = await lstat6(path);
1644
+ if (!stat5.isSymbolicLink())
1553
1645
  return true;
1554
- await readlink2(path);
1646
+ await readlink3(path);
1555
1647
  return false;
1556
1648
  } catch (error) {
1557
1649
  if (isNodeErrorWithCode(error) && error.code === "ENOENT")
@@ -1561,8 +1653,8 @@ async function existingNonSymlink(path) {
1561
1653
  }
1562
1654
 
1563
1655
  // ../src/install/codex-config-toml.ts
1564
- import { mkdir as mkdir6, readFile as readFile9 } from "node:fs/promises";
1565
- import { dirname as dirname6 } from "node:path";
1656
+ import { mkdir as mkdir6, readFile as readFile10 } from "node:fs/promises";
1657
+ import { dirname as dirname7 } from "node:path";
1566
1658
 
1567
1659
  // ../src/install/toml-section-editor.ts
1568
1660
  function findTomlSection(config, header) {
@@ -1920,13 +2012,13 @@ function tomlKeySegment(value) {
1920
2012
  }
1921
2013
 
1922
2014
  // ../src/install/codex-config-atomic-write.ts
1923
- import { lstat as lstat6, readlink as readlink3, realpath, rename as rename3, unlink, writeFile as writeFile5 } from "node:fs/promises";
1924
- import { basename as basename5, dirname as dirname5, isAbsolute as isAbsolute3, join as join13, resolve as resolve4 } from "node:path";
2015
+ import { lstat as lstat7, readlink as readlink4, realpath, rename as rename3, unlink, writeFile as writeFile5 } from "node:fs/promises";
2016
+ import { basename as basename5, dirname as dirname6, isAbsolute as isAbsolute4, join as join14, resolve as resolve5 } from "node:path";
1925
2017
  var RENAME_RETRY_DELAYS_MS = [10, 25, 50];
1926
2018
  var RETRIABLE_RENAME_CODES = new Set(["EPERM", "EBUSY"]);
1927
2019
  async function writeFileAtomic(targetPath, data) {
1928
2020
  const writeTarget = await resolveSymlinkTarget(targetPath);
1929
- const temporaryPath = join13(dirname5(writeTarget), `.tmp-${basename5(writeTarget)}-${process.pid}-${Date.now()}`);
2021
+ const temporaryPath = join14(dirname6(writeTarget), `.tmp-${basename5(writeTarget)}-${process.pid}-${Date.now()}`);
1930
2022
  await writeFile5(temporaryPath, data);
1931
2023
  try {
1932
2024
  await renameWithRetry(temporaryPath, writeTarget);
@@ -1941,7 +2033,7 @@ async function writeFileAtomic(targetPath, data) {
1941
2033
  }
1942
2034
  async function resolveSymlinkTarget(targetPath) {
1943
2035
  try {
1944
- const linkStats = await lstat6(targetPath);
2036
+ const linkStats = await lstat7(targetPath);
1945
2037
  if (!linkStats.isSymbolicLink())
1946
2038
  return targetPath;
1947
2039
  } catch (error) {
@@ -1954,8 +2046,8 @@ async function resolveSymlinkTarget(targetPath) {
1954
2046
  } catch (error) {
1955
2047
  if (!(error instanceof Error))
1956
2048
  throw error;
1957
- const linkValue = await readlink3(targetPath);
1958
- return isAbsolute3(linkValue) ? linkValue : resolve4(dirname5(targetPath), linkValue);
2049
+ const linkValue = await readlink4(targetPath);
2050
+ return isAbsolute4(linkValue) ? linkValue : resolve5(dirname6(targetPath), linkValue);
1959
2051
  }
1960
2052
  }
1961
2053
  async function renameWithRetry(fromPath, toPath) {
@@ -2296,8 +2388,8 @@ function isRootSetting(line, key) {
2296
2388
  }
2297
2389
 
2298
2390
  // ../src/install/codex-model-catalog.ts
2299
- import { readFile as readFile8 } from "node:fs/promises";
2300
- import { join as join14 } from "node:path";
2391
+ import { readFile as readFile9 } from "node:fs/promises";
2392
+ import { join as join15 } from "node:path";
2301
2393
  var FALLBACK_CODEX_MODEL_CATALOG = {
2302
2394
  current: {
2303
2395
  model: "gpt-5.5",
@@ -2316,9 +2408,9 @@ var FALLBACK_CODEX_MODEL_CATALOG = {
2316
2408
  ]
2317
2409
  };
2318
2410
  async function readCodexModelCatalog(codexPackageRoot) {
2319
- const catalogPath = join14(codexPackageRoot, "plugin", "model-catalog.json");
2411
+ const catalogPath = join15(codexPackageRoot, "plugin", "model-catalog.json");
2320
2412
  try {
2321
- const parsed = JSON.parse(await readFile8(catalogPath, "utf8"));
2413
+ const parsed = JSON.parse(await readFile9(catalogPath, "utf8"));
2322
2414
  return parseCodexModelCatalog(parsed) ?? FALLBACK_CODEX_MODEL_CATALOG;
2323
2415
  } catch (error) {
2324
2416
  if (error instanceof Error)
@@ -2452,10 +2544,10 @@ function readBooleanSetting(sectionText, key) {
2452
2544
 
2453
2545
  // ../src/install/codex-config-toml.ts
2454
2546
  async function updateCodexConfig(input) {
2455
- await mkdir6(dirname6(input.configPath), { recursive: true });
2547
+ await mkdir6(dirname7(input.configPath), { recursive: true });
2456
2548
  let config = "";
2457
2549
  if (await exists3(input.configPath))
2458
- config = await readFile9(input.configPath, "utf8");
2550
+ config = await readFile10(input.configPath, "utf8");
2459
2551
  const pluginSet = new Set(input.pluginNames);
2460
2552
  for (const legacyMarketplaceName of legacyMarketplaceNames(input.marketplaceName)) {
2461
2553
  config = removeMarketplaceBlock(config, legacyMarketplaceName);
@@ -2491,7 +2583,7 @@ async function updateCodexConfig(input) {
2491
2583
  }
2492
2584
  async function exists3(path) {
2493
2585
  try {
2494
- await readFile9(path, "utf8");
2586
+ await readFile10(path, "utf8");
2495
2587
  return true;
2496
2588
  } catch (error) {
2497
2589
  if (error instanceof Error)
@@ -2501,15 +2593,15 @@ async function exists3(path) {
2501
2593
  }
2502
2594
 
2503
2595
  // ../src/install/codex-git-bash-mcp-env.ts
2504
- import { readFile as readFile10, writeFile as writeFile6 } from "node:fs/promises";
2505
- import { join as join15 } from "node:path";
2596
+ import { readFile as readFile11, writeFile as writeFile6 } from "node:fs/promises";
2597
+ import { join as join16 } from "node:path";
2506
2598
  var GIT_BASH_ENV_KEY = "OMO_CODEX_GIT_BASH_PATH";
2507
2599
  var CODEGRAPH_RELATIVE_ARGS = new Set(["components/codegraph/dist/serve.js", "./components/codegraph/dist/serve.js"]);
2508
2600
  async function stampGitBashMcpEnv(input) {
2509
- const manifestPath = join15(input.pluginRoot, ".mcp.json");
2601
+ const manifestPath = join16(input.pluginRoot, ".mcp.json");
2510
2602
  if (!await fileExistsStrict(manifestPath))
2511
2603
  return false;
2512
- const parsed = JSON.parse(await readFile10(manifestPath, "utf8"));
2604
+ const parsed = JSON.parse(await readFile11(manifestPath, "utf8"));
2513
2605
  if (!isPlainRecord(parsed) || !isPlainRecord(parsed["mcpServers"]))
2514
2606
  return false;
2515
2607
  let changed = stampCodegraphMcpPath(parsed["mcpServers"], input.pluginRoot);
@@ -2539,14 +2631,14 @@ function stampCodegraphMcpPath(mcpServers, pluginRoot) {
2539
2631
  const entrypoint = args[0];
2540
2632
  if (typeof entrypoint !== "string" || !CODEGRAPH_RELATIVE_ARGS.has(entrypoint))
2541
2633
  return false;
2542
- codegraphServer["args"] = [join15(pluginRoot, "components", "codegraph", "dist", "serve.js"), ...args.slice(1)];
2634
+ codegraphServer["args"] = [join16(pluginRoot, "components", "codegraph", "dist", "serve.js"), ...args.slice(1)];
2543
2635
  return true;
2544
2636
  }
2545
2637
 
2546
2638
  // ../src/install/codex-hook-trust.ts
2547
2639
  import { createHash as createHash3 } from "node:crypto";
2548
- import { readFile as readFile11 } from "node:fs/promises";
2549
- import { join as join16 } from "node:path";
2640
+ import { readFile as readFile12 } from "node:fs/promises";
2641
+ import { join as join17 } from "node:path";
2550
2642
  var EVENT_LABELS = new Map([
2551
2643
  ["PreToolUse", "pre_tool_use"],
2552
2644
  ["PermissionRequest", "permission_request"],
@@ -2560,18 +2652,18 @@ var EVENT_LABELS = new Map([
2560
2652
  ["Stop", "stop"]
2561
2653
  ]);
2562
2654
  async function trustedHookStatesForPlugin(input) {
2563
- const manifestPath = join16(input.pluginRoot, ".codex-plugin", "plugin.json");
2655
+ const manifestPath = join17(input.pluginRoot, ".codex-plugin", "plugin.json");
2564
2656
  if (!await exists4(manifestPath))
2565
2657
  return [];
2566
- const manifest = JSON.parse(await readFile11(manifestPath, "utf8"));
2658
+ const manifest = JSON.parse(await readFile12(manifestPath, "utf8"));
2567
2659
  if (!isPlainRecord(manifest))
2568
2660
  return [];
2569
2661
  const states = [];
2570
2662
  for (const hookPath of hookManifestPaths(manifest.hooks)) {
2571
- const hooksPath = join16(input.pluginRoot, hookPath);
2663
+ const hooksPath = join17(input.pluginRoot, hookPath);
2572
2664
  if (!await exists4(hooksPath))
2573
2665
  continue;
2574
- const parsed = JSON.parse(await readFile11(hooksPath, "utf8"));
2666
+ const parsed = JSON.parse(await readFile12(hooksPath, "utf8"));
2575
2667
  if (!isPlainRecord(parsed) || !isPlainRecord(parsed.hooks))
2576
2668
  continue;
2577
2669
  states.push(...trustedHookStatesForHooksFile({
@@ -2654,7 +2746,7 @@ function stripDotSlash(value) {
2654
2746
  }
2655
2747
  async function exists4(path) {
2656
2748
  try {
2657
- await readFile11(path, "utf8");
2749
+ await readFile12(path, "utf8");
2658
2750
  return true;
2659
2751
  } catch (error) {
2660
2752
  if (error instanceof Error)
@@ -2665,17 +2757,17 @@ async function exists4(path) {
2665
2757
 
2666
2758
  // ../src/install/codex-installer-bin-dir.ts
2667
2759
  import { homedir as homedir3 } from "node:os";
2668
- import { join as join17, resolve as resolve5 } from "node:path";
2760
+ import { join as join18, resolve as resolve6 } from "node:path";
2669
2761
  function resolveCodexInstallerBinDir(input) {
2670
2762
  const explicitBinDir = input.binDir ?? input.env?.CODEX_LOCAL_BIN_DIR;
2671
2763
  if (explicitBinDir !== undefined && explicitBinDir.trim().length > 0)
2672
- return resolve5(explicitBinDir.trim());
2764
+ return resolve6(explicitBinDir.trim());
2673
2765
  const homeDir = input.homeDir ?? homedir3();
2674
- const defaultCodexHome = resolve5(homeDir, ".codex");
2675
- const resolvedCodexHome = resolve5(input.codexHome);
2766
+ const defaultCodexHome = resolve6(homeDir, ".codex");
2767
+ const resolvedCodexHome = resolve6(input.codexHome);
2676
2768
  if (resolvedCodexHome !== defaultCodexHome)
2677
- return join17(resolvedCodexHome, "bin");
2678
- return resolve5(homeDir, ".local", "bin");
2769
+ return join18(resolvedCodexHome, "bin");
2770
+ return resolve6(homeDir, ".local", "bin");
2679
2771
  }
2680
2772
  // ../../utils/src/runtime/git-bash.ts
2681
2773
  import { execFileSync as execFileSync2 } from "node:child_process";
@@ -2764,8 +2856,8 @@ var resolveGitBashForCurrentProcess2 = (input = {}) => {
2764
2856
  return toCodexResolution(resolveGitBashForCurrentProcess(input));
2765
2857
  };
2766
2858
  async function prepareGitBashForInstall(input) {
2767
- const resolve6 = input.resolveGitBash ?? (() => resolveGitBashForCurrentProcess2({ platform: input.platform, env: input.env }));
2768
- const initialResolution = resolve6();
2859
+ const resolve7 = input.resolveGitBash ?? (() => resolveGitBashForCurrentProcess2({ platform: input.platform, env: input.env }));
2860
+ const initialResolution = resolve7();
2769
2861
  return initialResolution;
2770
2862
  }
2771
2863
  function toCodexResolution(resolution) {
@@ -2828,9 +2920,9 @@ async function resolveGitBashStep(options, degraded) {
2828
2920
  return false;
2829
2921
  }
2830
2922
  async function linkBundledAgentsStep(options) {
2831
- const agentsTarget = join18(options.codexHome, "agents");
2923
+ const agentsTarget = join19(options.codexHome, "agents");
2832
2924
  try {
2833
- const stageRoot = join18(options.pluginData, "bootstrap", "agents-stage");
2925
+ const stageRoot = join19(options.pluginData, "bootstrap", "agents-stage");
2834
2926
  await stageBundledAgents(options.pluginRoot, stageRoot);
2835
2927
  const preservedReasoning = await capturePreservedAgentReasoning({ codexHome: options.codexHome });
2836
2928
  const preservedServiceTier = await capturePreservedAgentServiceTier({ codexHome: options.codexHome });
@@ -2856,23 +2948,23 @@ async function linkBundledAgentsStep(options) {
2856
2948
  }
2857
2949
  }
2858
2950
  async function stageBundledAgents(pluginRoot, stageRoot) {
2859
- await rm9(stageRoot, { force: true, recursive: true });
2951
+ await rm10(stageRoot, { force: true, recursive: true });
2860
2952
  await mkdir7(stageRoot, { recursive: true });
2861
- const componentsRoot = join18(pluginRoot, "components");
2953
+ const componentsRoot = join19(pluginRoot, "components");
2862
2954
  for (const componentName of await directoryNames(componentsRoot)) {
2863
- const agentsDir = join18(componentsRoot, componentName, "agents");
2955
+ const agentsDir = join19(componentsRoot, componentName, "agents");
2864
2956
  const agentFiles = (await fileNames(agentsDir)).filter((name) => name.endsWith(".toml"));
2865
2957
  if (agentFiles.length === 0)
2866
2958
  continue;
2867
- const stagedAgentsDir = join18(stageRoot, "components", componentName, "agents");
2959
+ const stagedAgentsDir = join19(stageRoot, "components", componentName, "agents");
2868
2960
  await mkdir7(stagedAgentsDir, { recursive: true });
2869
2961
  for (const agentFile of agentFiles) {
2870
- await copyFile2(join18(agentsDir, agentFile), join18(stagedAgentsDir, agentFile));
2962
+ await copyFile2(join19(agentsDir, agentFile), join19(stagedAgentsDir, agentFile));
2871
2963
  }
2872
2964
  }
2873
2965
  }
2874
2966
  async function updateConfigStep(options, inputs, degraded) {
2875
- const configPath = join18(options.codexHome, "config.toml");
2967
+ const configPath = join19(options.codexHome, "config.toml");
2876
2968
  try {
2877
2969
  await assertWritableConfigIfPresent(configPath);
2878
2970
  const trustedHookStates = await trustedHookStatesForPlugin({
@@ -2903,7 +2995,7 @@ async function updateConfigStep(options, inputs, degraded) {
2903
2995
  }
2904
2996
  async function assertWritableConfigIfPresent(configPath) {
2905
2997
  try {
2906
- if (((await stat4(configPath)).mode & 146) === 0)
2998
+ if (((await stat5(configPath)).mode & 146) === 0)
2907
2999
  throw new Error(`${configPath} has no write permission bits set`);
2908
3000
  } catch (error) {
2909
3001
  if (errorCode(error) === "ENOENT")
@@ -2928,7 +3020,7 @@ async function linkComponentBinsStep(options, degraded) {
2928
3020
  await linkRuntimeWrapperStep(options, binDir, degraded);
2929
3021
  }
2930
3022
  async function linkRuntimeWrapperStep(options, binDir, degraded) {
2931
- const cliPath = join18(options.pluginRoot, "dist", "cli", "index.js");
3023
+ const cliPath = join19(options.pluginRoot, "dist", "cli", "index.js");
2932
3024
  try {
2933
3025
  const linked = await linkRootRuntimeBin({
2934
3026
  binDir,
@@ -2961,7 +3053,7 @@ async function stampGitBashEnvStep(options, degraded) {
2961
3053
  degraded.push({
2962
3054
  component: "git-bash-env",
2963
3055
  hint: BOOTSTRAP_DOCTOR_HINT,
2964
- reason: `failed to stamp ${join18(options.pluginRoot, ".mcp.json")}: ${errorMessage(error)}`
3056
+ reason: `failed to stamp ${join19(options.pluginRoot, ".mcp.json")}: ${errorMessage(error)}`
2965
3057
  });
2966
3058
  }
2967
3059
  }
@@ -2973,7 +3065,7 @@ async function fileNames(root) {
2973
3065
  }
2974
3066
  async function entryNames(root, keep) {
2975
3067
  try {
2976
- const entries = await readdir3(root, { withFileTypes: true });
3068
+ const entries = await readdir4(root, { withFileTypes: true });
2977
3069
  return entries.filter((entry) => keep(entry)).map((entry) => entry.name).sort();
2978
3070
  } catch (error) {
2979
3071
  if (error instanceof Error && "code" in error && error.code === "ENOENT")
@@ -3029,11 +3121,11 @@ function resolvePluginDataRoot(env) {
3029
3121
  const fromEnv = env["PLUGIN_DATA"]?.trim();
3030
3122
  if (fromEnv !== undefined && fromEnv.length > 0)
3031
3123
  return fromEnv;
3032
- return join19(homedir4(), ".local", "share", "lazycodex");
3124
+ return join20(homedir4(), ".local", "share", "lazycodex");
3033
3125
  }
3034
3126
  async function readPluginVersion(pluginRoot) {
3035
3127
  try {
3036
- const parsed = JSON.parse(await readFile12(join19(pluginRoot, ".codex-plugin", "plugin.json"), "utf8"));
3128
+ const parsed = JSON.parse(await readFile13(join20(pluginRoot, ".codex-plugin", "plugin.json"), "utf8"));
3037
3129
  if (typeof parsed !== "object" || parsed === null)
3038
3130
  return;
3039
3131
  const version = parsed["version"];
@@ -3100,7 +3192,7 @@ async function runBootstrapWorker(options = {}) {
3100
3192
  degraded.push({
3101
3193
  component: "bootstrap",
3102
3194
  hint: BOOTSTRAP_DOCTOR_HINT,
3103
- reason: `plugin version unresolved from ${join19(pluginRoot, ".codex-plugin", "plugin.json")}`
3195
+ reason: `plugin version unresolved from ${join20(pluginRoot, ".codex-plugin", "plugin.json")}`
3104
3196
  });
3105
3197
  }
3106
3198
  for (const step of steps) {
@@ -3139,12 +3231,12 @@ function resolvePluginRoot(env) {
3139
3231
  const fromEnv = env["PLUGIN_ROOT"]?.trim();
3140
3232
  if (fromEnv !== undefined && fromEnv.length > 0)
3141
3233
  return fromEnv;
3142
- return resolve6(dirname7(fileURLToPath2(import.meta.url)), "..", "..", "..");
3234
+ return resolve7(dirname8(fileURLToPath2(import.meta.url)), "..", "..", "..");
3143
3235
  }
3144
3236
  async function appendBootstrapLog(pluginData, now, event, details) {
3145
3237
  try {
3146
- const logPath = join19(pluginData, "bootstrap", "bootstrap.log");
3147
- await mkdir8(dirname7(logPath), { recursive: true });
3238
+ const logPath = join20(pluginData, "bootstrap", "bootstrap.log");
3239
+ await mkdir8(dirname8(logPath), { recursive: true });
3148
3240
  await appendFile2(logPath, `${JSON.stringify({ timestamp: new Date(now).toISOString(), event, ...details })}
3149
3241
  `);
3150
3242
  } catch {}
@@ -3226,7 +3318,7 @@ function defaultWorkerCliPath() {
3226
3318
  }
3227
3319
  async function isLockFresh(lockPath, now) {
3228
3320
  try {
3229
- const lockStat = await stat5(lockPath);
3321
+ const lockStat = await stat6(lockPath);
3230
3322
  return now - lockStat.mtimeMs < DEFAULT_LOCK_STALE_MS;
3231
3323
  } catch {
3232
3324
  return false;