oh-my-opencode 4.14.1 → 4.15.0

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 (50) hide show
  1. package/dist/cli/index.js +88 -35
  2. package/dist/cli-node/index.js +88 -35
  3. package/dist/index.js +13 -13
  4. package/dist/skills/frontend/ATTRIBUTION.md +14 -1
  5. package/dist/skills/frontend/SKILL.md +11 -6
  6. package/dist/skills/frontend/references/design/README.md +15 -37
  7. package/dist/skills/frontend/references/design/_INDEX.md +5 -3
  8. package/dist/skills/frontend/references/design/aside.md +209 -0
  9. package/dist/skills/frontend/references/design/clone-from-url.md +65 -0
  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/package.json +1 -1
  17. package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
  18. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  19. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  20. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  21. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  22. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  23. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  24. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  25. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  26. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  27. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  28. package/packages/omo-codex/plugin/package-lock.json +13 -13
  29. package/packages/omo-codex/plugin/package.json +1 -1
  30. package/packages/omo-codex/plugin/skills/frontend/ATTRIBUTION.md +14 -1
  31. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +11 -6
  32. package/packages/omo-codex/plugin/skills/frontend/references/design/README.md +15 -37
  33. package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +5 -3
  34. package/packages/omo-codex/plugin/skills/frontend/references/design/aside.md +209 -0
  35. package/packages/omo-codex/plugin/skills/frontend/references/design/clone-from-url.md +65 -0
  36. package/packages/omo-codex/plugin/skills/programming/SKILL.md +5 -3
  37. package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +34 -15
  38. package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +11 -0
  39. package/packages/omo-codex/plugin/test/aggregate-skills.test.mjs +23 -0
  40. package/packages/omo-codex/scripts/install-dist/install-local.mjs +67 -14
  41. package/packages/shared-skills/skills/frontend/ATTRIBUTION.md +14 -1
  42. package/packages/shared-skills/skills/frontend/SKILL.md +11 -6
  43. package/packages/shared-skills/skills/frontend/references/design/README.md +15 -37
  44. package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +5 -3
  45. package/packages/shared-skills/skills/frontend/references/design/aside.md +209 -0
  46. package/packages/shared-skills/skills/frontend/references/design/clone-from-url.md +65 -0
  47. package/packages/shared-skills/skills/programming/SKILL.md +5 -3
  48. package/packages/shared-skills/skills/remove-ai-slops/SKILL.md +34 -15
  49. package/packages/shared-skills/skills/visual-qa/SKILL.md +11 -0
  50. package/packages/shared-skills/skills/visual-qa/scripts/skill-prompt-contract.test.ts +42 -0
package/dist/cli/index.js CHANGED
@@ -2145,7 +2145,7 @@ var package_default;
2145
2145
  var init_package = __esm(() => {
2146
2146
  package_default = {
2147
2147
  name: "oh-my-opencode",
2148
- version: "4.14.1",
2148
+ version: "4.15.0",
2149
2149
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
2150
2150
  main: "./dist/index.js",
2151
2151
  types: "dist/index.d.ts",
@@ -2336,18 +2336,18 @@ var init_package = __esm(() => {
2336
2336
  typescript: "^6.0.3"
2337
2337
  },
2338
2338
  optionalDependencies: {
2339
- "oh-my-opencode-darwin-arm64": "4.14.1",
2340
- "oh-my-opencode-darwin-x64": "4.14.1",
2341
- "oh-my-opencode-darwin-x64-baseline": "4.14.1",
2342
- "oh-my-opencode-linux-arm64": "4.14.1",
2343
- "oh-my-opencode-linux-arm64-musl": "4.14.1",
2344
- "oh-my-opencode-linux-x64": "4.14.1",
2345
- "oh-my-opencode-linux-x64-baseline": "4.14.1",
2346
- "oh-my-opencode-linux-x64-musl": "4.14.1",
2347
- "oh-my-opencode-linux-x64-musl-baseline": "4.14.1",
2348
- "oh-my-opencode-windows-arm64": "4.14.1",
2349
- "oh-my-opencode-windows-x64": "4.14.1",
2350
- "oh-my-opencode-windows-x64-baseline": "4.14.1"
2339
+ "oh-my-opencode-darwin-arm64": "4.15.0",
2340
+ "oh-my-opencode-darwin-x64": "4.15.0",
2341
+ "oh-my-opencode-darwin-x64-baseline": "4.15.0",
2342
+ "oh-my-opencode-linux-arm64": "4.15.0",
2343
+ "oh-my-opencode-linux-arm64-musl": "4.15.0",
2344
+ "oh-my-opencode-linux-x64": "4.15.0",
2345
+ "oh-my-opencode-linux-x64-baseline": "4.15.0",
2346
+ "oh-my-opencode-linux-x64-musl": "4.15.0",
2347
+ "oh-my-opencode-linux-x64-musl-baseline": "4.15.0",
2348
+ "oh-my-opencode-windows-arm64": "4.15.0",
2349
+ "oh-my-opencode-windows-x64": "4.15.0",
2350
+ "oh-my-opencode-windows-x64-baseline": "4.15.0"
2351
2351
  },
2352
2352
  overrides: {
2353
2353
  hono: "^4.12.18",
@@ -72637,7 +72637,7 @@ var package_default2;
72637
72637
  var init_package2 = __esm(() => {
72638
72638
  package_default2 = {
72639
72639
  name: "@oh-my-opencode/omo-codex",
72640
- version: "4.14.1",
72640
+ version: "4.15.0",
72641
72641
  type: "module",
72642
72642
  private: true,
72643
72643
  description: "Codex harness adapter for oh-my-openagent. Vendored Codex plugin namespace (omo) + TypeScript installer + telemetry.",
@@ -74787,7 +74787,7 @@ async function existingNonSymlink(path7) {
74787
74787
  }
74788
74788
  }
74789
74789
  // packages/omo-codex/src/install/codex-cache-install.ts
74790
- import { cp as cp2, mkdir as mkdir3, readFile as readFile7, rename, rm as rm3 } from "fs/promises";
74790
+ import { cp as cp2, mkdir as mkdir3, readFile as readFile7, readdir as readdir3, rename, rm as rm3 } from "fs/promises";
74791
74791
  import { basename as basename7, dirname as dirname12, join as join32, sep as sep5 } from "path";
74792
74792
 
74793
74793
  // packages/omo-codex/src/install/codex-cache-bundled-mcps.ts
@@ -75280,6 +75280,7 @@ async function installCachedPlugin(input) {
75280
75280
  await removeCachedManagedNpmBinShims(tempPath);
75281
75281
  if (input.buildSource === false)
75282
75282
  await maybeRunNpmSyncSkills(tempPath, input.runCommand);
75283
+ await assertNoRemovedSparkshellPromptReferences(tempPath);
75283
75284
  await rewriteCachedMcpManifest(tempPath, input.sourcePath);
75284
75285
  await rewriteCachedManifestRoot(tempPath, tempPath, targetPath);
75285
75286
  await assertHookCommandTargets(tempPath);
@@ -75358,6 +75359,58 @@ function shouldCopyPluginPath(path7, root) {
75358
75359
  const parts = relative5.split(sep5);
75359
75360
  return !parts.some((part) => part === ".git" || part === "node_modules");
75360
75361
  }
75362
+ var removedSparkshellReferencePattern = /\b(?:sparkshell|spark[-_\s]+shell)\b/i;
75363
+ var removedSparkshellPromptSurfaceDirs = new Set([".codex-plugin", "agents", "bundled-rules", "hooks", "skills"]);
75364
+ var removedSparkshellPromptSurfaceFiles = new Set(["directive.md", "plugin.json"]);
75365
+ var removedSparkshellTextFilePattern = /\.(?:json|md|toml|ya?ml)$/i;
75366
+ async function assertNoRemovedSparkshellPromptReferences(pluginRoot) {
75367
+ for (const filePath of await listRemovedSparkshellPromptSurfaceFiles(pluginRoot, "")) {
75368
+ const content = await readFile7(join32(pluginRoot, filePath), "utf8");
75369
+ if (!removedSparkshellReferencePattern.test(content))
75370
+ continue;
75371
+ throw new Error(`removed sparkshell reference found in Codex plugin prompt surface: ${filePath}`);
75372
+ }
75373
+ }
75374
+ async function listRemovedSparkshellPromptSurfaceFiles(pluginRoot, relativeDirectory) {
75375
+ const directory = relativeDirectory === "" ? pluginRoot : join32(pluginRoot, relativeDirectory);
75376
+ const entries = await readdir3(directory, { withFileTypes: true });
75377
+ const files = [];
75378
+ for (const entry of entries) {
75379
+ const relativePath = relativeDirectory === "" ? entry.name : join32(relativeDirectory, entry.name);
75380
+ if (entry.isDirectory()) {
75381
+ if (shouldDescendIntoRemovedSparkshellPromptSurface(relativePath)) {
75382
+ files.push(...await listRemovedSparkshellPromptSurfaceFiles(pluginRoot, relativePath));
75383
+ }
75384
+ continue;
75385
+ }
75386
+ if (shouldCheckRemovedSparkshellPromptFile(relativePath))
75387
+ files.push(relativePath);
75388
+ }
75389
+ return files.sort();
75390
+ }
75391
+ function shouldDescendIntoRemovedSparkshellPromptSurface(relativePath) {
75392
+ const parts = relativePath.split(sep5);
75393
+ if (parts.some((part) => part === ".git" || part === "dist" || part === "node_modules"))
75394
+ return false;
75395
+ if (parts[0] === "components") {
75396
+ if (parts.length <= 2)
75397
+ return true;
75398
+ return removedSparkshellPromptSurfaceDirs.has(parts[2]);
75399
+ }
75400
+ return removedSparkshellPromptSurfaceDirs.has(parts[0]);
75401
+ }
75402
+ function shouldCheckRemovedSparkshellPromptFile(relativePath) {
75403
+ if (!removedSparkshellTextFilePattern.test(relativePath))
75404
+ return false;
75405
+ const parts = relativePath.split(sep5);
75406
+ const fileName = parts.at(-1) ?? "";
75407
+ if (parts[0] === "components") {
75408
+ if (parts.length === 3)
75409
+ return removedSparkshellPromptSurfaceFiles.has(fileName);
75410
+ return parts.length > 3 && removedSparkshellPromptSurfaceDirs.has(parts[2]);
75411
+ }
75412
+ return removedSparkshellPromptSurfaceDirs.has(parts[0]);
75413
+ }
75361
75414
  async function copyRootRuntimeDists(input) {
75362
75415
  const repoRoot = repoRootForCodexPluginSource(input.sourcePath);
75363
75416
  if (repoRoot === null)
@@ -75382,7 +75435,7 @@ function repoRootForCodexPluginSource(sourcePath) {
75382
75435
  return dirname12(packagesRoot);
75383
75436
  }
75384
75437
  // packages/omo-codex/src/install/codex-cache-prune.ts
75385
- import { lstat as lstat4, readdir as readdir3, rm as rm4, stat as stat3 } from "fs/promises";
75438
+ import { lstat as lstat4, readdir as readdir4, rm as rm4, stat as stat3 } from "fs/promises";
75386
75439
  import { join as join33 } from "path";
75387
75440
  async function pruneMarketplaceCache(input) {
75388
75441
  const cacheRoot = join33(input.codexHome, "plugins", "cache", input.marketplaceName);
@@ -75410,11 +75463,11 @@ async function pruneMarketplacePluginCaches(input) {
75410
75463
  }
75411
75464
  async function readCacheEntries(path7) {
75412
75465
  const emptyEntries = [];
75413
- return readCacheRoot(path7, () => readdir3(path7, { withFileTypes: true }), emptyEntries);
75466
+ return readCacheRoot(path7, () => readdir4(path7, { withFileTypes: true }), emptyEntries);
75414
75467
  }
75415
75468
  async function readCacheEntryNames(path7) {
75416
75469
  const emptyNames = [];
75417
- return readCacheRoot(path7, () => readdir3(path7), emptyNames);
75470
+ return readCacheRoot(path7, () => readdir4(path7), emptyNames);
75418
75471
  }
75419
75472
  async function readCacheRoot(path7, readEntries, fallback) {
75420
75473
  try {
@@ -76577,7 +76630,7 @@ function toCodexResolution(resolution) {
76577
76630
  }
76578
76631
 
76579
76632
  // packages/omo-codex/src/install/link-cached-plugin-agents.ts
76580
- import { copyFile, lstat as lstat7, mkdir as mkdir6, readFile as readFile13, readdir as readdir4, rm as rm6, writeFile as writeFile6 } from "fs/promises";
76633
+ import { copyFile, lstat as lstat7, mkdir as mkdir6, readFile as readFile13, readdir as readdir5, rm as rm6, writeFile as writeFile6 } from "fs/promises";
76581
76634
  import { basename as basename9, join as join40 } from "path";
76582
76635
 
76583
76636
  // packages/omo-codex/src/install/retired-managed-agent-purge.ts
@@ -76645,7 +76698,7 @@ async function capturePreservedAgentReasoning(input) {
76645
76698
  if (!await exists4(agentsDir))
76646
76699
  return new Map;
76647
76700
  const preserved = new Map;
76648
- const agentEntries = await readdir4(agentsDir, { withFileTypes: true });
76701
+ const agentEntries = await readdir5(agentsDir, { withFileTypes: true });
76649
76702
  for (const entry of agentEntries) {
76650
76703
  if (!entry.name.endsWith(".toml"))
76651
76704
  continue;
@@ -76663,7 +76716,7 @@ async function capturePreservedAgentServiceTier(input) {
76663
76716
  if (!await exists4(agentsDir))
76664
76717
  return new Map;
76665
76718
  const preserved = new Map;
76666
- const agentEntries = await readdir4(agentsDir, { withFileTypes: true });
76719
+ const agentEntries = await readdir5(agentsDir, { withFileTypes: true });
76667
76720
  for (const entry of agentEntries) {
76668
76721
  if (!entry.name.endsWith(".toml"))
76669
76722
  continue;
@@ -76720,7 +76773,7 @@ async function discoverBundledAgents(pluginRoot) {
76720
76773
  const componentsRoot = join40(pluginRoot, "components");
76721
76774
  if (!await exists4(componentsRoot))
76722
76775
  return [];
76723
- const componentEntries = await readdir4(componentsRoot, { withFileTypes: true });
76776
+ const componentEntries = await readdir5(componentsRoot, { withFileTypes: true });
76724
76777
  const agents = [];
76725
76778
  for (const entry of componentEntries) {
76726
76779
  if (!entry.isDirectory())
@@ -76728,7 +76781,7 @@ async function discoverBundledAgents(pluginRoot) {
76728
76781
  const agentsRoot = join40(componentsRoot, entry.name, "agents");
76729
76782
  if (!await exists4(agentsRoot))
76730
76783
  continue;
76731
- const agentEntries = await readdir4(agentsRoot, { withFileTypes: true });
76784
+ const agentEntries = await readdir5(agentsRoot, { withFileTypes: true });
76732
76785
  for (const file2 of agentEntries) {
76733
76786
  if (!file2.isFile() || !file2.name.endsWith(".toml"))
76734
76787
  continue;
@@ -77035,7 +77088,7 @@ function shouldCopyMarketplaceSourcePath(path7, root) {
77035
77088
  }
77036
77089
 
77037
77090
  // packages/omo-codex/src/install/lazycodex-version-stamp.ts
77038
- import { readdir as readdir5, readFile as readFile15, writeFile as writeFile8 } from "fs/promises";
77091
+ import { readdir as readdir6, readFile as readFile15, writeFile as writeFile8 } from "fs/promises";
77039
77092
  import { join as join43 } from "path";
77040
77093
  async function readDistributionManifest(repoRoot) {
77041
77094
  try {
@@ -77128,7 +77181,7 @@ async function stampHookStatusMessages(path7, version) {
77128
77181
  async function stampComponentVersions(input) {
77129
77182
  let entries;
77130
77183
  try {
77131
- entries = await readdir5(join43(input.pluginRoot, "components"));
77184
+ entries = await readdir6(join43(input.pluginRoot, "components"));
77132
77185
  } catch (error) {
77133
77186
  if (error instanceof Error)
77134
77187
  return;
@@ -77419,7 +77472,7 @@ function formatUnknownError(error) {
77419
77472
  }
77420
77473
 
77421
77474
  // packages/omo-codex/src/install/lsp-daemon-reaper.ts
77422
- import { readFile as readFile17, readdir as readdir6, rm as rm8 } from "fs/promises";
77475
+ import { readFile as readFile17, readdir as readdir7, rm as rm8 } from "fs/promises";
77423
77476
  import { connect } from "net";
77424
77477
  import { join as join45 } from "path";
77425
77478
  async function reapLspDaemons(codexHome, deps = {}) {
@@ -77429,7 +77482,7 @@ async function reapLspDaemons(codexHome, deps = {}) {
77429
77482
  const reaped = [];
77430
77483
  let entries;
77431
77484
  try {
77432
- entries = await readdir6(daemonRoot);
77485
+ entries = await readdir7(daemonRoot);
77433
77486
  } catch {
77434
77487
  return reaped;
77435
77488
  }
@@ -77903,7 +77956,7 @@ function defaultRunCommand2(command, args) {
77903
77956
  });
77904
77957
  }
77905
77958
  // packages/omo-codex/src/install/codex-cleanup.ts
77906
- import { lstat as lstat10, readFile as readFile19, readdir as readdir7, rm as rm9, rmdir } from "fs/promises";
77959
+ import { lstat as lstat10, readFile as readFile19, readdir as readdir8, rm as rm9, rmdir } from "fs/promises";
77907
77960
  import { homedir as homedir8 } from "os";
77908
77961
  import { isAbsolute as isAbsolute9, join as join53, relative as relative7, resolve as resolve16 } from "path";
77909
77962
 
@@ -78125,7 +78178,7 @@ async function collectBootstrapDataDirsByGlob(codexHome) {
78125
78178
  async function walkForManagedBootstrapDirs(directory, depth, results) {
78126
78179
  if (depth > BOOTSTRAP_DATA_GLOB_MAX_DEPTH)
78127
78180
  return;
78128
- const entries = await readdir7(directory, { withFileTypes: true }).catch(() => null);
78181
+ const entries = await readdir8(directory, { withFileTypes: true }).catch(() => null);
78129
78182
  if (entries === null)
78130
78183
  return;
78131
78184
  for (const entry of entries) {
@@ -78183,7 +78236,7 @@ async function collectInstalledAgentPaths(codexHome, configPath) {
78183
78236
  ];
78184
78237
  const versionRoot = join53(codexHome, "plugins", "cache", "sisyphuslabs", "omo");
78185
78238
  if (await exists6(versionRoot)) {
78186
- const entries = await readdir7(versionRoot, { withFileTypes: true });
78239
+ const entries = await readdir8(versionRoot, { withFileTypes: true });
78187
78240
  for (const entry of entries) {
78188
78241
  if (entry.isDirectory())
78189
78242
  manifestPaths.push(join53(versionRoot, entry.name, INSTALLED_AGENTS_MANIFEST));
@@ -100532,7 +100585,7 @@ async function pathExists(dir) {
100532
100585
  // packages/omo-opencode/src/cli/doctor/checks/codex.ts
100533
100586
  init_src();
100534
100587
  import { existsSync as existsSync58 } from "fs";
100535
- import { lstat as lstat11, readdir as readdir8, readFile as readFile20 } from "fs/promises";
100588
+ import { lstat as lstat11, readdir as readdir9, readFile as readFile20 } from "fs/promises";
100536
100589
  import { homedir as homedir21 } from "os";
100537
100590
  import { basename as basename13, join as join77, resolve as resolve20 } from "path";
100538
100591
  // packages/omo-opencode/package.json
@@ -100723,7 +100776,7 @@ async function resolveInstalledPluginRoot(codexHome) {
100723
100776
  const pluginRoot = join77(codexHome, "plugins", "cache", MARKETPLACE_NAME, PLUGIN_NAME2);
100724
100777
  if (!existsSync58(pluginRoot))
100725
100778
  return null;
100726
- const versions2 = await readdir8(pluginRoot, { withFileTypes: true });
100779
+ const versions2 = await readdir9(pluginRoot, { withFileTypes: true });
100727
100780
  const candidates = versions2.filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort(compareVersionsDescending);
100728
100781
  return candidates.length === 0 ? null : join77(pluginRoot, candidates[0] ?? DEFAULT_PLUGIN_VERSION);
100729
100782
  }
@@ -100762,7 +100815,7 @@ async function readLinkedAgents(codexHome) {
100762
100815
  const agentsDir = join77(codexHome, "agents");
100763
100816
  if (!existsSync58(agentsDir))
100764
100817
  return [];
100765
- const entries = await readdir8(agentsDir, { withFileTypes: true });
100818
+ const entries = await readdir9(agentsDir, { withFileTypes: true });
100766
100819
  return entries.filter((entry) => entry.isFile() || entry.isSymbolicLink()).map((entry) => basename13(entry.name, ".toml")).sort();
100767
100820
  }
100768
100821
  async function readJson(path16) {
@@ -100873,7 +100926,7 @@ async function pathExists2(path16) {
100873
100926
 
100874
100927
  // packages/omo-opencode/src/cli/doctor/checks/codex-components.ts
100875
100928
  init_src();
100876
- import { readdir as readdir9, readFile as readFile21, stat as stat4 } from "fs/promises";
100929
+ import { readdir as readdir10, readFile as readFile21, stat as stat4 } from "fs/promises";
100877
100930
  import { homedir as homedir22 } from "os";
100878
100931
  import { dirname as dirname29, isAbsolute as isAbsolute11, join as join78, relative as relative10, resolve as resolve21, sep as sep9 } from "path";
100879
100932
  var CODEX_COMPONENTS_CHECK_ID = "codex-components";
@@ -101014,7 +101067,7 @@ async function findHookManifestPaths(root) {
101014
101067
  async function findManifestPaths(root, manifestName) {
101015
101068
  let entries;
101016
101069
  try {
101017
- entries = await readdir9(root, { withFileTypes: true });
101070
+ entries = await readdir10(root, { withFileTypes: true });
101018
101071
  } catch {
101019
101072
  return [];
101020
101073
  }
@@ -2146,7 +2146,7 @@ var package_default;
2146
2146
  var init_package = __esm(() => {
2147
2147
  package_default = {
2148
2148
  name: "oh-my-opencode",
2149
- version: "4.14.1",
2149
+ version: "4.15.0",
2150
2150
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
2151
2151
  main: "./dist/index.js",
2152
2152
  types: "dist/index.d.ts",
@@ -2337,18 +2337,18 @@ var init_package = __esm(() => {
2337
2337
  typescript: "^6.0.3"
2338
2338
  },
2339
2339
  optionalDependencies: {
2340
- "oh-my-opencode-darwin-arm64": "4.14.1",
2341
- "oh-my-opencode-darwin-x64": "4.14.1",
2342
- "oh-my-opencode-darwin-x64-baseline": "4.14.1",
2343
- "oh-my-opencode-linux-arm64": "4.14.1",
2344
- "oh-my-opencode-linux-arm64-musl": "4.14.1",
2345
- "oh-my-opencode-linux-x64": "4.14.1",
2346
- "oh-my-opencode-linux-x64-baseline": "4.14.1",
2347
- "oh-my-opencode-linux-x64-musl": "4.14.1",
2348
- "oh-my-opencode-linux-x64-musl-baseline": "4.14.1",
2349
- "oh-my-opencode-windows-arm64": "4.14.1",
2350
- "oh-my-opencode-windows-x64": "4.14.1",
2351
- "oh-my-opencode-windows-x64-baseline": "4.14.1"
2340
+ "oh-my-opencode-darwin-arm64": "4.15.0",
2341
+ "oh-my-opencode-darwin-x64": "4.15.0",
2342
+ "oh-my-opencode-darwin-x64-baseline": "4.15.0",
2343
+ "oh-my-opencode-linux-arm64": "4.15.0",
2344
+ "oh-my-opencode-linux-arm64-musl": "4.15.0",
2345
+ "oh-my-opencode-linux-x64": "4.15.0",
2346
+ "oh-my-opencode-linux-x64-baseline": "4.15.0",
2347
+ "oh-my-opencode-linux-x64-musl": "4.15.0",
2348
+ "oh-my-opencode-linux-x64-musl-baseline": "4.15.0",
2349
+ "oh-my-opencode-windows-arm64": "4.15.0",
2350
+ "oh-my-opencode-windows-x64": "4.15.0",
2351
+ "oh-my-opencode-windows-x64-baseline": "4.15.0"
2352
2352
  },
2353
2353
  overrides: {
2354
2354
  hono: "^4.12.18",
@@ -72693,7 +72693,7 @@ var package_default2;
72693
72693
  var init_package2 = __esm(() => {
72694
72694
  package_default2 = {
72695
72695
  name: "@oh-my-opencode/omo-codex",
72696
- version: "4.14.1",
72696
+ version: "4.15.0",
72697
72697
  type: "module",
72698
72698
  private: true,
72699
72699
  description: "Codex harness adapter for oh-my-openagent. Vendored Codex plugin namespace (omo) + TypeScript installer + telemetry.",
@@ -74843,7 +74843,7 @@ async function existingNonSymlink(path7) {
74843
74843
  }
74844
74844
  }
74845
74845
  // packages/omo-codex/src/install/codex-cache-install.ts
74846
- import { cp as cp2, mkdir as mkdir3, readFile as readFile7, rename, rm as rm3 } from "node:fs/promises";
74846
+ import { cp as cp2, mkdir as mkdir3, readFile as readFile7, readdir as readdir3, rename, rm as rm3 } from "node:fs/promises";
74847
74847
  import { basename as basename7, dirname as dirname12, join as join32, sep as sep5 } from "node:path";
74848
74848
 
74849
74849
  // packages/omo-codex/src/install/codex-cache-bundled-mcps.ts
@@ -75336,6 +75336,7 @@ async function installCachedPlugin(input) {
75336
75336
  await removeCachedManagedNpmBinShims(tempPath);
75337
75337
  if (input.buildSource === false)
75338
75338
  await maybeRunNpmSyncSkills(tempPath, input.runCommand);
75339
+ await assertNoRemovedSparkshellPromptReferences(tempPath);
75339
75340
  await rewriteCachedMcpManifest(tempPath, input.sourcePath);
75340
75341
  await rewriteCachedManifestRoot(tempPath, tempPath, targetPath);
75341
75342
  await assertHookCommandTargets(tempPath);
@@ -75414,6 +75415,58 @@ function shouldCopyPluginPath(path7, root) {
75414
75415
  const parts = relative5.split(sep5);
75415
75416
  return !parts.some((part) => part === ".git" || part === "node_modules");
75416
75417
  }
75418
+ var removedSparkshellReferencePattern = /\b(?:sparkshell|spark[-_\s]+shell)\b/i;
75419
+ var removedSparkshellPromptSurfaceDirs = new Set([".codex-plugin", "agents", "bundled-rules", "hooks", "skills"]);
75420
+ var removedSparkshellPromptSurfaceFiles = new Set(["directive.md", "plugin.json"]);
75421
+ var removedSparkshellTextFilePattern = /\.(?:json|md|toml|ya?ml)$/i;
75422
+ async function assertNoRemovedSparkshellPromptReferences(pluginRoot) {
75423
+ for (const filePath of await listRemovedSparkshellPromptSurfaceFiles(pluginRoot, "")) {
75424
+ const content = await readFile7(join32(pluginRoot, filePath), "utf8");
75425
+ if (!removedSparkshellReferencePattern.test(content))
75426
+ continue;
75427
+ throw new Error(`removed sparkshell reference found in Codex plugin prompt surface: ${filePath}`);
75428
+ }
75429
+ }
75430
+ async function listRemovedSparkshellPromptSurfaceFiles(pluginRoot, relativeDirectory) {
75431
+ const directory = relativeDirectory === "" ? pluginRoot : join32(pluginRoot, relativeDirectory);
75432
+ const entries = await readdir3(directory, { withFileTypes: true });
75433
+ const files = [];
75434
+ for (const entry of entries) {
75435
+ const relativePath = relativeDirectory === "" ? entry.name : join32(relativeDirectory, entry.name);
75436
+ if (entry.isDirectory()) {
75437
+ if (shouldDescendIntoRemovedSparkshellPromptSurface(relativePath)) {
75438
+ files.push(...await listRemovedSparkshellPromptSurfaceFiles(pluginRoot, relativePath));
75439
+ }
75440
+ continue;
75441
+ }
75442
+ if (shouldCheckRemovedSparkshellPromptFile(relativePath))
75443
+ files.push(relativePath);
75444
+ }
75445
+ return files.sort();
75446
+ }
75447
+ function shouldDescendIntoRemovedSparkshellPromptSurface(relativePath) {
75448
+ const parts = relativePath.split(sep5);
75449
+ if (parts.some((part) => part === ".git" || part === "dist" || part === "node_modules"))
75450
+ return false;
75451
+ if (parts[0] === "components") {
75452
+ if (parts.length <= 2)
75453
+ return true;
75454
+ return removedSparkshellPromptSurfaceDirs.has(parts[2]);
75455
+ }
75456
+ return removedSparkshellPromptSurfaceDirs.has(parts[0]);
75457
+ }
75458
+ function shouldCheckRemovedSparkshellPromptFile(relativePath) {
75459
+ if (!removedSparkshellTextFilePattern.test(relativePath))
75460
+ return false;
75461
+ const parts = relativePath.split(sep5);
75462
+ const fileName = parts.at(-1) ?? "";
75463
+ if (parts[0] === "components") {
75464
+ if (parts.length === 3)
75465
+ return removedSparkshellPromptSurfaceFiles.has(fileName);
75466
+ return parts.length > 3 && removedSparkshellPromptSurfaceDirs.has(parts[2]);
75467
+ }
75468
+ return removedSparkshellPromptSurfaceDirs.has(parts[0]);
75469
+ }
75417
75470
  async function copyRootRuntimeDists(input) {
75418
75471
  const repoRoot = repoRootForCodexPluginSource(input.sourcePath);
75419
75472
  if (repoRoot === null)
@@ -75438,7 +75491,7 @@ function repoRootForCodexPluginSource(sourcePath) {
75438
75491
  return dirname12(packagesRoot);
75439
75492
  }
75440
75493
  // packages/omo-codex/src/install/codex-cache-prune.ts
75441
- import { lstat as lstat4, readdir as readdir3, rm as rm4, stat as stat3 } from "node:fs/promises";
75494
+ import { lstat as lstat4, readdir as readdir4, rm as rm4, stat as stat3 } from "node:fs/promises";
75442
75495
  import { join as join33 } from "node:path";
75443
75496
  async function pruneMarketplaceCache(input) {
75444
75497
  const cacheRoot = join33(input.codexHome, "plugins", "cache", input.marketplaceName);
@@ -75466,11 +75519,11 @@ async function pruneMarketplacePluginCaches(input) {
75466
75519
  }
75467
75520
  async function readCacheEntries(path7) {
75468
75521
  const emptyEntries = [];
75469
- return readCacheRoot(path7, () => readdir3(path7, { withFileTypes: true }), emptyEntries);
75522
+ return readCacheRoot(path7, () => readdir4(path7, { withFileTypes: true }), emptyEntries);
75470
75523
  }
75471
75524
  async function readCacheEntryNames(path7) {
75472
75525
  const emptyNames = [];
75473
- return readCacheRoot(path7, () => readdir3(path7), emptyNames);
75526
+ return readCacheRoot(path7, () => readdir4(path7), emptyNames);
75474
75527
  }
75475
75528
  async function readCacheRoot(path7, readEntries, fallback) {
75476
75529
  try {
@@ -76633,7 +76686,7 @@ function toCodexResolution(resolution) {
76633
76686
  }
76634
76687
 
76635
76688
  // packages/omo-codex/src/install/link-cached-plugin-agents.ts
76636
- import { copyFile, lstat as lstat7, mkdir as mkdir6, readFile as readFile13, readdir as readdir4, rm as rm6, writeFile as writeFile6 } from "node:fs/promises";
76689
+ import { copyFile, lstat as lstat7, mkdir as mkdir6, readFile as readFile13, readdir as readdir5, rm as rm6, writeFile as writeFile6 } from "node:fs/promises";
76637
76690
  import { basename as basename9, join as join40 } from "node:path";
76638
76691
 
76639
76692
  // packages/omo-codex/src/install/retired-managed-agent-purge.ts
@@ -76701,7 +76754,7 @@ async function capturePreservedAgentReasoning(input) {
76701
76754
  if (!await exists4(agentsDir))
76702
76755
  return new Map;
76703
76756
  const preserved = new Map;
76704
- const agentEntries = await readdir4(agentsDir, { withFileTypes: true });
76757
+ const agentEntries = await readdir5(agentsDir, { withFileTypes: true });
76705
76758
  for (const entry of agentEntries) {
76706
76759
  if (!entry.name.endsWith(".toml"))
76707
76760
  continue;
@@ -76719,7 +76772,7 @@ async function capturePreservedAgentServiceTier(input) {
76719
76772
  if (!await exists4(agentsDir))
76720
76773
  return new Map;
76721
76774
  const preserved = new Map;
76722
- const agentEntries = await readdir4(agentsDir, { withFileTypes: true });
76775
+ const agentEntries = await readdir5(agentsDir, { withFileTypes: true });
76723
76776
  for (const entry of agentEntries) {
76724
76777
  if (!entry.name.endsWith(".toml"))
76725
76778
  continue;
@@ -76776,7 +76829,7 @@ async function discoverBundledAgents(pluginRoot) {
76776
76829
  const componentsRoot = join40(pluginRoot, "components");
76777
76830
  if (!await exists4(componentsRoot))
76778
76831
  return [];
76779
- const componentEntries = await readdir4(componentsRoot, { withFileTypes: true });
76832
+ const componentEntries = await readdir5(componentsRoot, { withFileTypes: true });
76780
76833
  const agents = [];
76781
76834
  for (const entry of componentEntries) {
76782
76835
  if (!entry.isDirectory())
@@ -76784,7 +76837,7 @@ async function discoverBundledAgents(pluginRoot) {
76784
76837
  const agentsRoot = join40(componentsRoot, entry.name, "agents");
76785
76838
  if (!await exists4(agentsRoot))
76786
76839
  continue;
76787
- const agentEntries = await readdir4(agentsRoot, { withFileTypes: true });
76840
+ const agentEntries = await readdir5(agentsRoot, { withFileTypes: true });
76788
76841
  for (const file2 of agentEntries) {
76789
76842
  if (!file2.isFile() || !file2.name.endsWith(".toml"))
76790
76843
  continue;
@@ -77091,7 +77144,7 @@ function shouldCopyMarketplaceSourcePath(path7, root) {
77091
77144
  }
77092
77145
 
77093
77146
  // packages/omo-codex/src/install/lazycodex-version-stamp.ts
77094
- import { readdir as readdir5, readFile as readFile15, writeFile as writeFile8 } from "node:fs/promises";
77147
+ import { readdir as readdir6, readFile as readFile15, writeFile as writeFile8 } from "node:fs/promises";
77095
77148
  import { join as join43 } from "node:path";
77096
77149
  async function readDistributionManifest(repoRoot) {
77097
77150
  try {
@@ -77184,7 +77237,7 @@ async function stampHookStatusMessages(path7, version) {
77184
77237
  async function stampComponentVersions(input) {
77185
77238
  let entries;
77186
77239
  try {
77187
- entries = await readdir5(join43(input.pluginRoot, "components"));
77240
+ entries = await readdir6(join43(input.pluginRoot, "components"));
77188
77241
  } catch (error) {
77189
77242
  if (error instanceof Error)
77190
77243
  return;
@@ -77475,7 +77528,7 @@ function formatUnknownError(error) {
77475
77528
  }
77476
77529
 
77477
77530
  // packages/omo-codex/src/install/lsp-daemon-reaper.ts
77478
- import { readFile as readFile17, readdir as readdir6, rm as rm8 } from "node:fs/promises";
77531
+ import { readFile as readFile17, readdir as readdir7, rm as rm8 } from "node:fs/promises";
77479
77532
  import { connect } from "node:net";
77480
77533
  import { join as join45 } from "node:path";
77481
77534
  async function reapLspDaemons(codexHome, deps = {}) {
@@ -77485,7 +77538,7 @@ async function reapLspDaemons(codexHome, deps = {}) {
77485
77538
  const reaped = [];
77486
77539
  let entries;
77487
77540
  try {
77488
- entries = await readdir6(daemonRoot);
77541
+ entries = await readdir7(daemonRoot);
77489
77542
  } catch {
77490
77543
  return reaped;
77491
77544
  }
@@ -77959,7 +78012,7 @@ function defaultRunCommand2(command, args) {
77959
78012
  });
77960
78013
  }
77961
78014
  // packages/omo-codex/src/install/codex-cleanup.ts
77962
- import { lstat as lstat10, readFile as readFile19, readdir as readdir7, rm as rm9, rmdir } from "node:fs/promises";
78015
+ import { lstat as lstat10, readFile as readFile19, readdir as readdir8, rm as rm9, rmdir } from "node:fs/promises";
77963
78016
  import { homedir as homedir8 } from "node:os";
77964
78017
  import { isAbsolute as isAbsolute9, join as join53, relative as relative7, resolve as resolve16 } from "node:path";
77965
78018
 
@@ -78181,7 +78234,7 @@ async function collectBootstrapDataDirsByGlob(codexHome) {
78181
78234
  async function walkForManagedBootstrapDirs(directory, depth, results) {
78182
78235
  if (depth > BOOTSTRAP_DATA_GLOB_MAX_DEPTH)
78183
78236
  return;
78184
- const entries = await readdir7(directory, { withFileTypes: true }).catch(() => null);
78237
+ const entries = await readdir8(directory, { withFileTypes: true }).catch(() => null);
78185
78238
  if (entries === null)
78186
78239
  return;
78187
78240
  for (const entry of entries) {
@@ -78239,7 +78292,7 @@ async function collectInstalledAgentPaths(codexHome, configPath) {
78239
78292
  ];
78240
78293
  const versionRoot = join53(codexHome, "plugins", "cache", "sisyphuslabs", "omo");
78241
78294
  if (await exists6(versionRoot)) {
78242
- const entries = await readdir7(versionRoot, { withFileTypes: true });
78295
+ const entries = await readdir8(versionRoot, { withFileTypes: true });
78243
78296
  for (const entry of entries) {
78244
78297
  if (entry.isDirectory())
78245
78298
  manifestPaths.push(join53(versionRoot, entry.name, INSTALLED_AGENTS_MANIFEST));
@@ -100588,7 +100641,7 @@ async function pathExists(dir) {
100588
100641
  // packages/omo-opencode/src/cli/doctor/checks/codex.ts
100589
100642
  init_src();
100590
100643
  import { existsSync as existsSync58 } from "node:fs";
100591
- import { lstat as lstat11, readdir as readdir8, readFile as readFile20 } from "node:fs/promises";
100644
+ import { lstat as lstat11, readdir as readdir9, readFile as readFile20 } from "node:fs/promises";
100592
100645
  import { homedir as homedir21 } from "node:os";
100593
100646
  import { basename as basename13, join as join77, resolve as resolve20 } from "node:path";
100594
100647
  // packages/omo-opencode/package.json
@@ -100779,7 +100832,7 @@ async function resolveInstalledPluginRoot(codexHome) {
100779
100832
  const pluginRoot = join77(codexHome, "plugins", "cache", MARKETPLACE_NAME, PLUGIN_NAME2);
100780
100833
  if (!existsSync58(pluginRoot))
100781
100834
  return null;
100782
- const versions2 = await readdir8(pluginRoot, { withFileTypes: true });
100835
+ const versions2 = await readdir9(pluginRoot, { withFileTypes: true });
100783
100836
  const candidates = versions2.filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort(compareVersionsDescending);
100784
100837
  return candidates.length === 0 ? null : join77(pluginRoot, candidates[0] ?? DEFAULT_PLUGIN_VERSION);
100785
100838
  }
@@ -100818,7 +100871,7 @@ async function readLinkedAgents(codexHome) {
100818
100871
  const agentsDir = join77(codexHome, "agents");
100819
100872
  if (!existsSync58(agentsDir))
100820
100873
  return [];
100821
- const entries = await readdir8(agentsDir, { withFileTypes: true });
100874
+ const entries = await readdir9(agentsDir, { withFileTypes: true });
100822
100875
  return entries.filter((entry) => entry.isFile() || entry.isSymbolicLink()).map((entry) => basename13(entry.name, ".toml")).sort();
100823
100876
  }
100824
100877
  async function readJson(path16) {
@@ -100929,7 +100982,7 @@ async function pathExists2(path16) {
100929
100982
 
100930
100983
  // packages/omo-opencode/src/cli/doctor/checks/codex-components.ts
100931
100984
  init_src();
100932
- import { readdir as readdir9, readFile as readFile21, stat as stat4 } from "node:fs/promises";
100985
+ import { readdir as readdir10, readFile as readFile21, stat as stat4 } from "node:fs/promises";
100933
100986
  import { homedir as homedir22 } from "node:os";
100934
100987
  import { dirname as dirname29, isAbsolute as isAbsolute11, join as join78, relative as relative10, resolve as resolve21, sep as sep9 } from "node:path";
100935
100988
  var CODEX_COMPONENTS_CHECK_ID = "codex-components";
@@ -101070,7 +101123,7 @@ async function findHookManifestPaths(root) {
101070
101123
  async function findManifestPaths(root, manifestName) {
101071
101124
  let entries;
101072
101125
  try {
101073
- entries = await readdir9(root, { withFileTypes: true });
101126
+ entries = await readdir10(root, { withFileTypes: true });
101074
101127
  } catch {
101075
101128
  return [];
101076
101129
  }
package/dist/index.js CHANGED
@@ -88678,7 +88678,7 @@ function getCachedVersion(options = {}) {
88678
88678
  // package.json
88679
88679
  var package_default = {
88680
88680
  name: "oh-my-opencode",
88681
- version: "4.14.1",
88681
+ version: "4.15.0",
88682
88682
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
88683
88683
  main: "./dist/index.js",
88684
88684
  types: "dist/index.d.ts",
@@ -88869,18 +88869,18 @@ var package_default = {
88869
88869
  typescript: "^6.0.3"
88870
88870
  },
88871
88871
  optionalDependencies: {
88872
- "oh-my-opencode-darwin-arm64": "4.14.1",
88873
- "oh-my-opencode-darwin-x64": "4.14.1",
88874
- "oh-my-opencode-darwin-x64-baseline": "4.14.1",
88875
- "oh-my-opencode-linux-arm64": "4.14.1",
88876
- "oh-my-opencode-linux-arm64-musl": "4.14.1",
88877
- "oh-my-opencode-linux-x64": "4.14.1",
88878
- "oh-my-opencode-linux-x64-baseline": "4.14.1",
88879
- "oh-my-opencode-linux-x64-musl": "4.14.1",
88880
- "oh-my-opencode-linux-x64-musl-baseline": "4.14.1",
88881
- "oh-my-opencode-windows-arm64": "4.14.1",
88882
- "oh-my-opencode-windows-x64": "4.14.1",
88883
- "oh-my-opencode-windows-x64-baseline": "4.14.1"
88872
+ "oh-my-opencode-darwin-arm64": "4.15.0",
88873
+ "oh-my-opencode-darwin-x64": "4.15.0",
88874
+ "oh-my-opencode-darwin-x64-baseline": "4.15.0",
88875
+ "oh-my-opencode-linux-arm64": "4.15.0",
88876
+ "oh-my-opencode-linux-arm64-musl": "4.15.0",
88877
+ "oh-my-opencode-linux-x64": "4.15.0",
88878
+ "oh-my-opencode-linux-x64-baseline": "4.15.0",
88879
+ "oh-my-opencode-linux-x64-musl": "4.15.0",
88880
+ "oh-my-opencode-linux-x64-musl-baseline": "4.15.0",
88881
+ "oh-my-opencode-windows-arm64": "4.15.0",
88882
+ "oh-my-opencode-windows-x64": "4.15.0",
88883
+ "oh-my-opencode-windows-x64-baseline": "4.15.0"
88884
88884
  },
88885
88885
  overrides: {
88886
88886
  hono: "^4.12.18",
@@ -186,10 +186,23 @@ SOFTWARE.
186
186
 
187
187
  ## 5. Project-original files
188
188
 
189
- `frontend/SKILL.md`, `frontend/references/design/README.md`, `_INDEX.md`,
189
+ `frontend/SKILL.md`, `frontend/references/design/README.md`, `_INDEX.md`, `aside.md`,
190
190
  `design-system-architecture.md`, `react-dev-tooling-skill.md`,
191
191
  `frontend/references/perfection/README.md`, `react-perf-tooling.md`, and
192
192
  `frontend/scripts/perfection/lighthouse-audit.py` are original to this project and require
193
193
  no third-party attribution. The perfection docs and script only invoke third-party tools
194
194
  (react-scan, react-doctor, react-grab, playwright-lighthouse, lighthouse, chrome-launcher)
195
195
  at runtime; no source from those tools is vendored, so their licenses are not carried here.
196
+
197
+ `frontend/references/design/aside.md` is a project-original synthesis from live browser
198
+ capture evidence and a local reconnaissance run following the MIT-licensed
199
+ `JCodesMore/ai-website-cloner-template` workflow; it is not copied from Aside or from the
200
+ template. Aside names, trademarks, product text, and visual assets remain the property of
201
+ their respective owners and are referenced only for descriptive design-analysis purposes.
202
+
203
+ `frontend/references/design/clone-from-url.md` is a project-original runtime-extraction
204
+ workflow guide. Its browser + `getComputedStyle` clone approach follows the same
205
+ MIT-licensed `JCodesMore/ai-website-cloner-template` clone-website workflow that `aside.md`
206
+ cites; no source from that template is copied. It carries no third-party attribution beyond
207
+ that lineage note, and it grants no license to copy any target site's trademarks, brand
208
+ assets, or proprietary copy.