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
@@ -1,5 +1,5 @@
1
1
  import assert from "node:assert/strict";
2
- import { mkdir, mkdtemp, readFile, utimes, writeFile } from "node:fs/promises";
2
+ import { mkdir, mkdtemp, readFile, symlink, utimes, writeFile } from "node:fs/promises";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
5
  import test from "node:test";
@@ -303,9 +303,20 @@ function marketplaceCheckEnv(root, pluginRoot, spawnLogPath, extra = {}) {
303
303
  }
304
304
 
305
305
  test("#given marketplace plugin root without install snapshot #when running check #then skips npx update with marketplace-flow log and upgrade notice", async () => {
306
- const { root, pluginRoot } = await makeStorePluginRoot("lazycodex-auto-update-marketplace-");
306
+ const root = await mkdtemp(join(tmpdir(), "lazycodex-auto-update-marketplace-"));
307
+ const codexHome = join(root, "codex-home");
308
+ const pluginRoot = join(codexHome, "plugins", "cache", "sisyphuslabs", "omo", "1.0.0");
307
309
  const spawnLogPath = join(root, "spawn.log");
308
- const env = marketplaceCheckEnv(root, pluginRoot, spawnLogPath);
310
+ await mkdir(join(codexHome, "plugins", "cache", "sisyphuslabs", ".agents", "plugins"), { recursive: true });
311
+ await mkdir(pluginRoot, { recursive: true });
312
+ await writeFile(
313
+ join(codexHome, "plugins", "cache", "sisyphuslabs", ".agents", "plugins", "marketplace.json"),
314
+ JSON.stringify({
315
+ name: "sisyphuslabs",
316
+ plugins: [{ name: "omo", source: { source: "local", path: "./omo/1.0.0" } }],
317
+ }),
318
+ );
319
+ const env = marketplaceCheckEnv(root, pluginRoot, spawnLogPath, { CODEX_HOME: codexHome });
309
320
 
310
321
  const result = await runAutoUpdateCheck({ env, now: 123_456 });
311
322
 
@@ -329,6 +340,145 @@ test("#given marketplace plugin root without install snapshot #when running chec
329
340
  ]);
330
341
  });
331
342
 
343
+ test("#given marketplace flow with stale local cache state #when running check #then starts npx repair instead of marketplace skip", async () => {
344
+ const { root, pluginRoot } = await makeStorePluginRoot("lazycodex-auto-update-marketplace-repair-");
345
+ const spawnLogPath = join(root, "spawn.log");
346
+ const binDir = join(root, "bin");
347
+ const codexHome = join(root, "codex-home");
348
+ const missingCachedCli = join(codexHome, "plugins", "cache", "sisyphuslabs", "omo", "1.0.1", "components", "ulw-loop", "dist", "cli.js");
349
+ await mkdir(join(codexHome, "plugins", "cache", "sisyphuslabs", ".agents", "plugins"), { recursive: true });
350
+ await mkdir(binDir, { recursive: true });
351
+ await writeFile(
352
+ join(codexHome, "plugins", "cache", "sisyphuslabs", ".agents", "plugins", "marketplace.json"),
353
+ JSON.stringify({
354
+ name: "sisyphuslabs",
355
+ plugins: [{ name: "omo", source: { source: "local", path: "./omo/1.0.1" } }],
356
+ }),
357
+ );
358
+ await symlink(missingCachedCli, join(binDir, "ulw"));
359
+ const env = marketplaceCheckEnv(root, pluginRoot, spawnLogPath, {
360
+ CODEX_HOME: codexHome,
361
+ CODEX_LOCAL_BIN_DIR: binDir,
362
+ });
363
+
364
+ const result = await runAutoUpdateCheck({ env, now: 123_456 });
365
+
366
+ assert.equal(result.started, true);
367
+ assert.equal(result.status, 0);
368
+ assert.equal(await readFile(spawnLogPath, "utf8"), "ok");
369
+ assert.equal(result.notices.length, 1);
370
+ assert.match(result.notices[0], /repair/i);
371
+ assert.match(result.notices[0], /stale local LazyCodex cache/i);
372
+ assert.match(result.notices[0], /bundled reinstall repair/);
373
+ assert.doesNotMatch(result.notices[0], /Repair command/);
374
+ assert.doesNotMatch(result.notices[0], /plugins[\\/]+cache[\\/]+sisyphuslabs/);
375
+ const logEntries = (await readFile(env.LAZYCODEX_AUTO_UPDATE_LOG_PATH, "utf8")).trim().split("\n").map((line) => JSON.parse(line));
376
+ assert.equal(logEntries[0].event, "started");
377
+ assert.equal(logEntries[0].kind, "marketplace-local-repair");
378
+ assert.equal(logEntries[0].command, undefined);
379
+ assert.equal(logEntries[0].args, undefined);
380
+ assert.deepEqual(logEntries[0].repairReasons, [
381
+ { kind: "missing-marketplace-payload" },
382
+ { kind: "dangling-managed-bin", binName: "ulw" },
383
+ ]);
384
+ });
385
+
386
+ test("#given stale marketplace cache and recent success state #when resolving plan #then repair bypasses success throttle", async () => {
387
+ const { root, pluginRoot } = await makeStorePluginRoot("lazycodex-auto-update-marketplace-repair-throttle-");
388
+ const spawnLogPath = join(root, "spawn.log");
389
+ const codexHome = join(root, "codex-home");
390
+ await mkdir(join(codexHome, "plugins", "cache", "sisyphuslabs", ".agents", "plugins"), { recursive: true });
391
+ await writeFile(
392
+ join(codexHome, "plugins", "cache", "sisyphuslabs", ".agents", "plugins", "marketplace.json"),
393
+ JSON.stringify({
394
+ name: "sisyphuslabs",
395
+ plugins: [{ name: "omo", source: { source: "local", path: "./omo/1.0.1" } }],
396
+ }),
397
+ );
398
+ const env = marketplaceCheckEnv(root, pluginRoot, spawnLogPath, {
399
+ CODEX_HOME: codexHome,
400
+ LAZYCODEX_LATEST_VERSION: "1.0.1",
401
+ });
402
+
403
+ const plan = resolveAutoUpdatePlan({ env, now: 123_457, lastCheckedAt: 123_456, lastStatus: "success" });
404
+
405
+ assert.equal(plan.shouldRun, true);
406
+ assert.equal(plan.kind, "marketplace-local-repair");
407
+ assert.deepEqual(plan.repairReasons, [{ kind: "missing-marketplace-payload" }]);
408
+ });
409
+
410
+ test("#given stale marketplace cache and recent started state #when resolving plan #then repair honors retry throttle", async () => {
411
+ const { root, pluginRoot } = await makeStorePluginRoot("lazycodex-auto-update-marketplace-repair-retry-");
412
+ const spawnLogPath = join(root, "spawn.log");
413
+ const codexHome = join(root, "codex-home");
414
+ await mkdir(join(codexHome, "plugins", "cache", "sisyphuslabs", ".agents", "plugins"), { recursive: true });
415
+ await writeFile(
416
+ join(codexHome, "plugins", "cache", "sisyphuslabs", ".agents", "plugins", "marketplace.json"),
417
+ JSON.stringify({
418
+ name: "sisyphuslabs",
419
+ plugins: [{ name: "omo", source: { source: "local", path: "./omo/1.0.1" } }],
420
+ }),
421
+ );
422
+ const env = marketplaceCheckEnv(root, pluginRoot, spawnLogPath, {
423
+ CODEX_HOME: codexHome,
424
+ LAZYCODEX_LATEST_VERSION: "1.0.1",
425
+ });
426
+
427
+ const plan = resolveAutoUpdatePlan({ env, now: 123_457, lastAttemptedAt: 123_456, lastStatus: "started" });
428
+
429
+ assert.equal(plan.shouldRun, false);
430
+ assert.equal(plan.reason, "retry-throttled");
431
+ });
432
+
433
+ test("#given marketplace flow with stale Windows generated shim #when resolving plan #then starts local repair", async () => {
434
+ const { root, pluginRoot } = await makeStorePluginRoot("lazycodex-auto-update-marketplace-windows-repair-");
435
+ const spawnLogPath = join(root, "spawn.log");
436
+ const binDir = join(root, "bin");
437
+ const codexHome = join(root, "codex-home");
438
+ const missingCachedCli = join(codexHome, "plugins", "cache", "sisyphuslabs", "omo", "1.0.1", "components", "ulw-loop", "dist", "cli.js");
439
+ await mkdir(binDir, { recursive: true });
440
+ await writeFile(
441
+ join(binDir, "omo-ulw-loop.cmd"),
442
+ [
443
+ "@echo off",
444
+ ":: generated by oh-my-openagent Codex installer",
445
+ `\"${missingCachedCli}\" %*`,
446
+ "",
447
+ ].join("\r\n"),
448
+ );
449
+ const env = marketplaceCheckEnv(root, pluginRoot, spawnLogPath, {
450
+ CODEX_HOME: codexHome,
451
+ CODEX_LOCAL_BIN_DIR: binDir,
452
+ LAZYCODEX_LATEST_VERSION: "1.0.1",
453
+ });
454
+
455
+ const plan = resolveAutoUpdatePlan({ env, now: 123_456 });
456
+
457
+ assert.equal(plan.shouldRun, true);
458
+ assert.equal(plan.kind, "marketplace-local-repair");
459
+ assert.deepEqual(plan.repairReasons, [{ kind: "dangling-managed-bin", binName: "omo-ulw-loop" }]);
460
+ });
461
+
462
+ test("#given marketplace flow with non-managed stale cache-shaped bin #when resolving plan #then skips local repair", async () => {
463
+ const { root, pluginRoot } = await makeStorePluginRoot("lazycodex-auto-update-marketplace-user-bin-");
464
+ const spawnLogPath = join(root, "spawn.log");
465
+ const binDir = join(root, "bin");
466
+ const codexHome = join(root, "codex-home");
467
+ const missingCachedCli = join(codexHome, "plugins", "cache", "sisyphuslabs", "omo", "1.0.1", "components", "ulw-loop", "dist", "cli.js");
468
+ await mkdir(binDir, { recursive: true });
469
+ await symlink(missingCachedCli, join(binDir, "user-tool"));
470
+ const env = marketplaceCheckEnv(root, pluginRoot, spawnLogPath, {
471
+ CODEX_HOME: codexHome,
472
+ CODEX_LOCAL_BIN_DIR: binDir,
473
+ LAZYCODEX_LATEST_VERSION: "1.0.1",
474
+ });
475
+
476
+ const plan = resolveAutoUpdatePlan({ env, now: 123_456 });
477
+
478
+ assert.equal(plan.shouldRun, false);
479
+ assert.equal(plan.reason, "marketplace-flow");
480
+ });
481
+
332
482
  test("#given install snapshot at plugin root #when running check #then npx update behavior is unchanged", async () => {
333
483
  const { root, pluginRoot } = await makeStorePluginRoot("lazycodex-auto-update-npx-snapshot-");
334
484
  await writeFile(join(pluginRoot, "lazycodex-install.json"), JSON.stringify({ packageName: "lazycodex-ai", version: "1.0.0" }));
@@ -25,13 +25,14 @@ export const expectedSkills = [
25
25
  "start-work",
26
26
  "teammode",
27
27
  "ultimate-browsing",
28
- "ultraresearch",
29
28
  "ulw-loop",
30
29
  "ulw-plan",
31
30
  "ulw-research",
32
31
  "visual-qa",
33
32
  ];
34
33
 
34
+ export const hiddenSharedSkills = ["ultraresearch"];
35
+
35
36
  export const componentSkillSources = [
36
37
  ["comment-checker", "components/comment-checker/skills/comment-checker"],
37
38
  ["lsp", "components/lsp/skills/lsp"],
@@ -92,6 +93,22 @@ const reviewWorkCodexGatePattern =
92
93
  /\nWhen `review-work` is used as a final implementation, PR, or `\$start-work`\ngate, it is blocking\. A timeout, missing deliverable, ack-only response,\nexplicit `BLOCKED:`, or inconclusive lane is not a pass\. Treat that lane as\nfailed, investigate the underlying uncertainty with the `debugging` skill when\nruntime behavior may be wrong, fix with evidence, and rerun the affected lane\nbefore claiming completion, creating or handing off a PR, or merging\.\n\nWhen reviewing a PR or branch, collect diff, file contents, and verification\nresults from a dedicated review worktree attached to that branch\. Never\ncheckout, test, or edit the review branch in the main worktree\.\n\nReview evidence must be safe to share\. Redact or mask secrets and sensitive\nuser data before including evidence in logs, PR bodies, or handoffs\. Never\ninclude raw tokens, credentials, auth headers, cookies, API keys, env dumps,\nprivate logs, or PII; summarize with lengths, hashes, and short non-sensitive\nprefixes when identity is needed\.\n/;
93
94
 
94
95
  export function removeCodexSkillOverlays(skillName, content) {
96
+ if (skillName === "ulw-research") {
97
+ return content
98
+ .replace(
99
+ ", any 'ulw' research wording,",
100
+ ", the legacy alias 'ultraresearch', any 'ulw' research wording,",
101
+ )
102
+ .replace(
103
+ "the word \"ulw-research\" (also `/ulw-research`, `$ulw-research`), ",
104
+ "the word \"ulw-research\" (also `/ulw-research`, `$ulw-research`), the legacy alias \"ultraresearch\" (also `/ultraresearch`, `$ultraresearch`), ",
105
+ )
106
+ .replace(
107
+ "answer those normally, and mention that `ulw-research` is available when a question would clearly benefit from it.",
108
+ "answer those normally, and mention that `ulw-research` is available (legacy alias: `ultraresearch`) when a question would clearly benefit from it.",
109
+ )
110
+ .replace("# ULW-Research Synthesis: <query>", "# Ultraresearch Synthesis: <query>");
111
+ }
95
112
  if (skillName === "start-work") {
96
113
  return content
97
114
  .replace(startWorkCodexCompletion, startWorkOriginalCompletion)
@@ -9,6 +9,7 @@ import {
9
9
  assertPackagedContentMatches,
10
10
  componentSkillSources,
11
11
  expectedSkills,
12
+ hiddenSharedSkills,
12
13
  listSkillFiles,
13
14
  removeCodexCompatibilityGuidance,
14
15
  removeCodexSkillOverlays,
@@ -29,6 +30,13 @@ function excludeGeneratedSkillMetadata(files) {
29
30
  return files.filter((file) => !generatedSkillMetadataFiles.has(file.replaceAll("\\", "/")));
30
31
  }
31
32
 
33
+ async function assertNoLegacyResearchAliasInTree(rootDir, label) {
34
+ for (const file of await listSkillFiles(rootDir)) {
35
+ const content = await readFile(join(rootDir, file), "utf8");
36
+ assert.doesNotMatch(content, /ultraresearch/i, `${label}/${file} must not expose ultraresearch`);
37
+ }
38
+ }
39
+
32
40
  test("#given synced aggregate Codex skills #when inspected #then component and shared skills are present", async () => {
33
41
  // given
34
42
  const skillsRoot = join(root, "skills");
@@ -47,6 +55,26 @@ test("#given synced aggregate Codex skills #when inspected #then component and s
47
55
  }
48
56
  });
49
57
 
58
+ test("#given reference-only designpowers frontend files #when synced for Codex #then nested SKILL.md files are not packaged", async () => {
59
+ // given
60
+ const frontendReferencesRoot = join(root, "skills", "frontend", "references");
61
+ const designpowersVendorSkillsRoot = join(frontendReferencesRoot, "designpowers", "vendor", "skills");
62
+
63
+ // when
64
+ const nestedSkillFiles = (await listSkillFiles(frontendReferencesRoot))
65
+ .map((file) => file.replaceAll("\\", "/"))
66
+ .filter((file) => file.endsWith("/SKILL.md") || file === "SKILL.md")
67
+ .sort();
68
+ const designpowersReferenceFiles = (await listSkillFiles(designpowersVendorSkillsRoot))
69
+ .map((file) => file.replaceAll("\\", "/"))
70
+ .filter((file) => file.endsWith("/reference.md"))
71
+ .sort();
72
+
73
+ // then
74
+ assert.deepEqual(nestedSkillFiles, []);
75
+ assert.equal(designpowersReferenceFiles.length, 27);
76
+ });
77
+
50
78
  test("#given aggregate Codex skills #when source wiring is inspected #then shared skills are imported from the shared-skills package", async () => {
51
79
  // given
52
80
  const pluginPackageJson = JSON.parse(await readFile(join(root, "package.json"), "utf8"));
@@ -85,6 +113,7 @@ test("#given shared skill package source #when aggregate Codex shared skills are
85
113
  // when / then
86
114
  for (const skillName of sharedSkillNames) {
87
115
  if (componentSkillNames.has(skillName)) continue;
116
+ if (hiddenSharedSkills.includes(skillName)) continue;
88
117
  const sharedContent = await readFile(join(sharedSkillsRoot, skillName, "SKILL.md"), "utf8");
89
118
  const aggregateContent = await readFile(join(aggregateSkillsRoot, skillName, "SKILL.md"), "utf8");
90
119
  assert.equal(
@@ -145,7 +174,7 @@ test("#given component skill sources #when aggregate Codex component skills are
145
174
  const sourceContent = await readFile(join(sourceDir, relativePath), "utf8");
146
175
  const aggregateContent = await readFile(join(aggregateDir, relativePath), "utf8");
147
176
  assert.equal(
148
- removeCodexCompatibilityGuidance(aggregateContent),
177
+ removeCodexSkillOverlays(skillName, removeCodexCompatibilityGuidance(aggregateContent)),
149
178
  removeCodexCompatibilityGuidance(sourceContent),
150
179
  `${skillName}/${relativePath} drifted from its component skill source`,
151
180
  );
@@ -181,18 +210,18 @@ test("#given synced ulw-loop skill #when Codex hint metadata is inspected #then
181
210
  assert.match(interfaceMetadata, /- "ulw-loop"/);
182
211
  });
183
212
 
184
- test("#given synced legacy ultraresearch alias #when inspected #then it points users at ulw-research", async () => {
213
+ test("#given shipped Codex skill payloads #when legacy ultraresearch alias is inspected #then it is not packaged", async () => {
185
214
  // given
186
- const skillRoot = join(root, "skills", "ultraresearch");
187
-
188
- // when
189
- const skill = await readFile(join(skillRoot, "SKILL.md"), "utf8");
190
- const interfaceMetadata = await readFile(join(skillRoot, "agents", "openai.yaml"), "utf8");
215
+ const skillsRoot = join(root, "skills");
216
+ const skillRoot = join(skillsRoot, "ultraresearch");
191
217
 
192
218
  // then
193
- assert.match(skill, /^---\r?\nname: ultraresearch\r?\n/m);
194
- assert.match(skill, /legacy name for `ulw-research`/);
195
- assert.match(interfaceMetadata, /display_name: "\(OmO\) ultraresearch"/);
219
+ await assert.rejects(readFile(join(skillRoot, "SKILL.md"), "utf8"), { code: "ENOENT" });
220
+ await assert.rejects(readFile(join(skillRoot, "agents", "openai.yaml"), "utf8"), { code: "ENOENT" });
221
+ await assertNoLegacyResearchAliasInTree(skillsRoot, "skills");
222
+ for (const [skillName, sourcePath] of componentSkillSources) {
223
+ await assertNoLegacyResearchAliasInTree(join(root, sourcePath), `components/${skillName}`);
224
+ }
196
225
  });
197
226
 
198
227
  test("#given synced git-master skill #when inspected #then commits and git history route through it", async () => {
@@ -77,7 +77,11 @@ test("#given ulw-research description #when activation policy is inspected #then
77
77
  for (const copy of await readUlwResearchCopies()) {
78
78
  const description = frontmatterDescription(copy.content);
79
79
  assert.match(description, /ulw-research/i, `${copy.label}: description must name the ulw-research trigger`);
80
- assert.match(description, /ultraresearch/i, `${copy.label}: description must preserve ultraresearch discoverability`);
80
+ if (copy.label === "shared") {
81
+ assert.match(description, /ultraresearch/i, `${copy.label}: description must preserve ultraresearch discoverability`);
82
+ } else {
83
+ assert.doesNotMatch(description, /ultraresearch/i, `${copy.label}: description must not expose ultraresearch`);
84
+ }
81
85
  assert.match(description, /\bulw\b/i, `${copy.label}: description must preserve ulw discoverability`);
82
86
  assert.match(description, /explicit/i, `${copy.label}: description must gate activation on explicit demand`);
83
87
  assert.match(
@@ -89,6 +93,20 @@ test("#given ulw-research description #when activation policy is inspected #then
89
93
  }
90
94
  });
91
95
 
96
+ test("#given packaged ulw-research skill #when scanned for legacy aliases #then ultraresearch is not exposed", async () => {
97
+ const packaged = (await readUlwResearchCopies()).find((copy) => copy.label === "packaged");
98
+ assert.notEqual(packaged, undefined, "packaged copy not found");
99
+ assert.doesNotMatch(packaged.content, /ultraresearch/i, "packaged ulw-research must not expose ultraresearch");
100
+ });
101
+
102
+ test("#given packaged ulw-research skill #when Codex guidance is inspected #then compatibility guidance is preserved", async () => {
103
+ const packaged = (await readUlwResearchCopies()).find((copy) => copy.label === "packaged");
104
+ assert.notEqual(packaged, undefined, "packaged copy not found");
105
+ assert.match(packaged.content, /## Codex Harness Tool Compatibility/);
106
+ assert.match(packaged.content, /multi_agent_v1\.spawn_agent/);
107
+ assert.match(packaged.content, /multi_agent_v1\.wait_agent/);
108
+ });
109
+
92
110
  test("#given ulw-research body #when authority is inspected #then it takes precedence over exploration-bounding instructions", async () => {
93
111
  for (const copy of await readUlwResearchCopies()) {
94
112
  assert.match(