oh-my-openagent 4.17.1 → 4.18.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 (80) hide show
  1. package/.agents/skills/codex-qa/SKILL.md +2 -0
  2. package/dist/cli/get-local-version/types.d.ts +1 -1
  3. package/dist/cli/index.js +55 -25
  4. package/dist/cli-node/index.js +55 -25
  5. package/dist/index.js +23 -17
  6. package/dist/skills/frontend/SKILL.md +1 -1
  7. package/dist/skills/frontend/references/design/README.md +9 -0
  8. package/dist/skills/frontend/references/design/design-system-architecture.md +4 -2
  9. package/dist/skills/frontend/references/design/layout-skill.md +107 -0
  10. package/dist/skills/programming/SKILL.md +12 -2
  11. package/package.json +14 -13
  12. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  13. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  14. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  15. package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
  16. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  17. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  18. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  19. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  20. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.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/hooks/hooks.json +2 -2
  23. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  24. package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus/gpt-5.6.md +7 -5
  25. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  26. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  27. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  28. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  29. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  30. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  31. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  32. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  33. package/packages/omo-codex/plugin/components/ultrawork/directive.md +37 -10
  34. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  35. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  36. package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +37 -10
  37. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +37 -10
  38. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  39. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  40. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +1 -1
  41. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +4 -4
  42. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  43. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  44. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  45. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  46. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  47. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  48. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  49. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  50. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  51. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  52. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  53. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  54. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  55. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  56. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  57. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  58. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
  59. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  60. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
  61. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  62. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  63. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  64. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  65. package/packages/omo-codex/plugin/package-lock.json +13 -13
  66. package/packages/omo-codex/plugin/package.json +1 -1
  67. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +1 -1
  68. package/packages/omo-codex/plugin/skills/frontend/references/design/README.md +9 -0
  69. package/packages/omo-codex/plugin/skills/frontend/references/design/design-system-architecture.md +4 -2
  70. package/packages/omo-codex/plugin/skills/frontend/references/design/layout-skill.md +107 -0
  71. package/packages/omo-codex/plugin/skills/programming/SKILL.md +12 -2
  72. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +37 -10
  73. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +1 -1
  74. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +4 -4
  75. package/packages/omo-codex/scripts/install-dist/install-local.mjs +24 -12
  76. package/packages/shared-skills/skills/frontend/SKILL.md +1 -1
  77. package/packages/shared-skills/skills/frontend/references/design/README.md +9 -0
  78. package/packages/shared-skills/skills/frontend/references/design/design-system-architecture.md +4 -2
  79. package/packages/shared-skills/skills/frontend/references/design/layout-skill.md +107 -0
  80. package/packages/shared-skills/skills/programming/SKILL.md +12 -2
@@ -69,6 +69,8 @@ Windows.
69
69
  | `scripts/hook-unit-probe.sh` | the `ultrawork` component injects `<ultrawork-mode>` on an `ulw` UserPromptSubmit (also a manual `--component/--event` mode) |
70
70
  | `scripts/tui-smoke.sh` | the real codex TUI boots in the isolated home, renders, and survives (no early exit); captures the pane |
71
71
 
72
+ To tell a dev dogfood build apart from a published one on a REAL `~/.codex` (NOT the isolated QA home), the repo ships `bun run install:codex-dev`, which stamps the plugin version as `dev` — visible as the `(OmO dev)` hook-status prefix every turn and as a `[DEV]` badge in `omo get-local-version`. Use it to confirm which build is loaded during manual dogfooding; it writes to the real home, so it is NEVER part of the isolated QA flow above.
73
+
72
74
  When TUI visual QA evidence is needed, follow
73
75
  `docs/reference/web-terminal-visual-qa.md`: render the TUI through the real
74
76
  xterm.js web terminal - NEVER the `tmux capture-pane` frame, which degrades
@@ -5,7 +5,7 @@ export interface VersionInfo {
5
5
  isLocalDev: boolean;
6
6
  isPinned: boolean;
7
7
  pinnedVersion: string | null;
8
- status: "up-to-date" | "outdated" | "local-dev" | "pinned" | "pinned-mismatch" | "error" | "unknown";
8
+ status: "up-to-date" | "outdated" | "local-dev" | "dev" | "pinned" | "pinned-mismatch" | "error" | "unknown";
9
9
  }
10
10
  export interface GetLocalVersionOptions {
11
11
  directory?: string;
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.17.1",
2148
+ version: "4.18.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",
@@ -2252,6 +2252,7 @@ var init_package = __esm(() => {
2252
2252
  build: "bun run script/build.ts",
2253
2253
  "build:cli-node": "bun run script/build-cli-node.ts",
2254
2254
  "build:codex-install": "bun run script/build-codex-install.ts",
2255
+ "install:codex-dev": "bun run script/build-codex-install.ts && bun run script/install-codex-dev.ts",
2255
2256
  "build:codex-plugin": "npm --prefix packages/omo-codex/plugin ci && bun run --cwd packages/omo-codex/plugin build",
2256
2257
  "build:senpi-plugin": "node packages/omo-senpi/plugin/scripts/build-extension.mjs && node packages/omo-senpi/plugin/scripts/sync-skills.mjs && node packages/omo-senpi/plugin/scripts/embed-directive.mjs --check",
2257
2258
  "build:materialize-frontend": "node packages/omo-codex/plugin/scripts/materialize-shared-upstreams.mjs --strict",
@@ -2356,18 +2357,18 @@ var init_package = __esm(() => {
2356
2357
  typescript: "^6.0.3"
2357
2358
  },
2358
2359
  optionalDependencies: {
2359
- "oh-my-opencode-darwin-arm64": "4.17.1",
2360
- "oh-my-opencode-darwin-x64": "4.17.1",
2361
- "oh-my-opencode-darwin-x64-baseline": "4.17.1",
2362
- "oh-my-opencode-linux-arm64": "4.17.1",
2363
- "oh-my-opencode-linux-arm64-musl": "4.17.1",
2364
- "oh-my-opencode-linux-x64": "4.17.1",
2365
- "oh-my-opencode-linux-x64-baseline": "4.17.1",
2366
- "oh-my-opencode-linux-x64-musl": "4.17.1",
2367
- "oh-my-opencode-linux-x64-musl-baseline": "4.17.1",
2368
- "oh-my-opencode-windows-arm64": "4.17.1",
2369
- "oh-my-opencode-windows-x64": "4.17.1",
2370
- "oh-my-opencode-windows-x64-baseline": "4.17.1"
2360
+ "oh-my-opencode-darwin-arm64": "4.18.0",
2361
+ "oh-my-opencode-darwin-x64": "4.18.0",
2362
+ "oh-my-opencode-darwin-x64-baseline": "4.18.0",
2363
+ "oh-my-opencode-linux-arm64": "4.18.0",
2364
+ "oh-my-opencode-linux-arm64-musl": "4.18.0",
2365
+ "oh-my-opencode-linux-x64": "4.18.0",
2366
+ "oh-my-opencode-linux-x64-baseline": "4.18.0",
2367
+ "oh-my-opencode-linux-x64-musl": "4.18.0",
2368
+ "oh-my-opencode-linux-x64-musl-baseline": "4.18.0",
2369
+ "oh-my-opencode-windows-arm64": "4.18.0",
2370
+ "oh-my-opencode-windows-x64": "4.18.0",
2371
+ "oh-my-opencode-windows-x64-baseline": "4.18.0"
2371
2372
  },
2372
2373
  overrides: {
2373
2374
  "@earendil-works/pi-agent-core": "0.80.3",
@@ -72601,7 +72602,7 @@ var package_default2;
72601
72602
  var init_package2 = __esm(() => {
72602
72603
  package_default2 = {
72603
72604
  name: "@oh-my-opencode/omo-codex",
72604
- version: "4.17.1",
72605
+ version: "4.18.0",
72605
72606
  type: "module",
72606
72607
  private: true,
72607
72608
  description: "Codex harness adapter for oh-my-openagent. Vendored Codex plugin namespace (omo) + TypeScript installer + telemetry.",
@@ -75325,9 +75326,11 @@ function collectCommands(value, commands) {
75325
75326
 
75326
75327
  // packages/omo-codex/src/install/codex-cache-install.ts
75327
75328
  async function installCachedPlugin(input) {
75329
+ const env2 = input.env ?? process.env;
75330
+ const npmInstallEnv = sanitizeNpmInstallEnv(env2);
75328
75331
  if (input.buildSource !== false) {
75329
- await maybeRunNpmInstall(input.sourcePath, input.runCommand);
75330
- await maybeRunNpmBuild(input.sourcePath, input.runCommand);
75332
+ await maybeRunNpmInstall(input.sourcePath, input.runCommand, npmInstallEnv);
75333
+ await maybeRunNpmBuild(input.sourcePath, input.runCommand, env2);
75331
75334
  }
75332
75335
  const targetPath = join33(input.codexHome, "plugins", "cache", input.marketplaceName, input.name, input.version);
75333
75336
  const tempPath = createTempSiblingPath(targetPath);
@@ -75337,10 +75340,10 @@ async function installCachedPlugin(input) {
75337
75340
  await rewriteCachedPackageLocalFileDependencies(tempPath, input.sourcePath);
75338
75341
  await copyBundledMcpRuntimeDists({ pluginRoot: tempPath, sourceRoot: input.sourcePath });
75339
75342
  await copyRootRuntimeDists({ pluginRoot: tempPath, sourcePath: input.sourcePath });
75340
- await maybeRunNpmInstall(tempPath, input.runCommand, ["ci", "--omit=dev"]);
75343
+ await maybeRunNpmInstall(tempPath, input.runCommand, npmInstallEnv, ["ci", "--omit=dev"]);
75341
75344
  await removeCachedManagedNpmBinShims(tempPath);
75342
75345
  if (input.buildSource === false)
75343
- await maybeRunNpmSyncSkills(tempPath, input.runCommand);
75346
+ await maybeRunNpmSyncSkills(tempPath, input.runCommand, env2);
75344
75347
  await assertNoRemovedSparkshellPromptReferences(tempPath);
75345
75348
  await rewriteCachedMcpManifest(tempPath, input.sourcePath);
75346
75349
  await rewriteCachedManifestRoot(tempPath, tempPath, targetPath);
@@ -75352,12 +75355,12 @@ async function installCachedPlugin(input) {
75352
75355
  }
75353
75356
  return { name: input.name, version: input.version, path: targetPath };
75354
75357
  }
75355
- async function maybeRunNpmInstall(cwd, runCommand, args = ["install"]) {
75358
+ async function maybeRunNpmInstall(cwd, runCommand, env2, args = ["install"]) {
75356
75359
  if (!await fileExistsStrict(join33(cwd, "package.json")))
75357
75360
  return;
75358
- await runCommand("npm", args, { cwd });
75361
+ await runCommand("npm", args, { cwd, env: env2 });
75359
75362
  }
75360
- async function maybeRunNpmBuild(cwd, runCommand) {
75363
+ async function maybeRunNpmBuild(cwd, runCommand, env2) {
75361
75364
  if (!await fileExistsStrict(join33(cwd, "package.json")))
75362
75365
  return;
75363
75366
  const packageJson = JSON.parse(await readFile8(join33(cwd, "package.json"), "utf8"));
@@ -75366,9 +75369,9 @@ async function maybeRunNpmBuild(cwd, runCommand) {
75366
75369
  const scripts = packageJson.scripts;
75367
75370
  if (!isPlainRecord3(scripts) || typeof scripts.build !== "string")
75368
75371
  return;
75369
- await runCommand("npm", ["run", "build"], { cwd });
75372
+ await runCommand("npm", ["run", "build"], { cwd, env: env2 });
75370
75373
  }
75371
- async function maybeRunNpmSyncSkills(cwd, runCommand) {
75374
+ async function maybeRunNpmSyncSkills(cwd, runCommand, env2) {
75372
75375
  if (!await fileExistsStrict(join33(cwd, "package.json")))
75373
75376
  return;
75374
75377
  const packageJson = JSON.parse(await readFile8(join33(cwd, "package.json"), "utf8"));
@@ -75377,7 +75380,10 @@ async function maybeRunNpmSyncSkills(cwd, runCommand) {
75377
75380
  const scripts = packageJson.scripts;
75378
75381
  if (!isPlainRecord3(scripts) || typeof scripts["sync:skills"] !== "string")
75379
75382
  return;
75380
- await runCommand("npm", ["run", "sync:skills"], { cwd });
75383
+ await runCommand("npm", ["run", "sync:skills"], { cwd, env: env2 });
75384
+ }
75385
+ function sanitizeNpmInstallEnv(env2) {
75386
+ return Object.fromEntries(Object.entries(env2).filter(([key]) => key.toLowerCase() !== "npm_config_allow_scripts"));
75381
75387
  }
75382
75388
  function createTempSiblingPath(targetPath) {
75383
75389
  return join33(dirname13(targetPath), `.tmp-${basename7(targetPath)}-${process.pid}-${Date.now()}`);
@@ -77407,6 +77413,10 @@ async function readDistributionManifest(repoRoot) {
77407
77413
  }
77408
77414
  }
77409
77415
  function resolveLazyCodexPluginVersion(input) {
77416
+ const override = input.versionOverride?.trim();
77417
+ if (override !== undefined && override.length > 0) {
77418
+ return override;
77419
+ }
77410
77420
  if (input.marketplaceName === "sisyphuslabs" && input.pluginName === "omo" && input.distributionManifest !== undefined) {
77411
77421
  return input.distributionManifest.version;
77412
77422
  }
@@ -77957,6 +77967,7 @@ async function runCodexInstaller(options = {}) {
77957
77967
  return;
77958
77968
  });
77959
77969
  const buildSource = await shouldBuildSourcePackages(repoRoot);
77970
+ const versionOverride = env3.LAZYCODEX_DEV_VERSION?.trim() || undefined;
77960
77971
  const gitBashResolution = await prepareGitBashForInstall({
77961
77972
  platform,
77962
77973
  env: env3,
@@ -77983,13 +77994,15 @@ async function runCodexInstaller(options = {}) {
77983
77994
  manifestVersion: manifest.version,
77984
77995
  marketplaceName: marketplace.name,
77985
77996
  pluginName: entry.name,
77986
- distributionManifest
77997
+ distributionManifest,
77998
+ versionOverride
77987
77999
  });
77988
78000
  validatePathSegment(version2, "plugin version");
77989
78001
  log4(`Building ${entry.name}@${version2}`);
77990
78002
  const plugin = await installCachedPlugin({
77991
78003
  buildSource,
77992
78004
  codexHome,
78005
+ env: env3,
77993
78006
  marketplaceName: marketplace.name,
77994
78007
  name: entry.name,
77995
78008
  runCommand,
@@ -99070,6 +99083,10 @@ function formatVersionOutput(info) {
99070
99083
  lines.push(` ${SYMBOLS3.dev} ${import_picocolors17.default.cyan("Running in local development mode")}`);
99071
99084
  lines.push(` ${import_picocolors17.default.dim("Using file:// protocol from config")}`);
99072
99085
  break;
99086
+ case "dev":
99087
+ lines.push(` ${SYMBOLS3.dev} ${import_picocolors17.default.cyan("Running a local dev build")}`);
99088
+ lines.push(` ${import_picocolors17.default.dim("Installed from source; update checks are skipped")}`);
99089
+ break;
99073
99090
  case "pinned":
99074
99091
  lines.push(` ${SYMBOLS3.pin} ${import_picocolors17.default.magenta(`Version pinned to ${info.pinnedVersion}`)}`);
99075
99092
  lines.push(` ${import_picocolors17.default.dim("Update check skipped for pinned versions")}`);
@@ -99142,6 +99159,19 @@ async function getLocalVersion(options = {}) {
99142
99159
  console.log(options.json ? formatJsonOutput(info2) : formatVersionOutput(info2));
99143
99160
  return 1;
99144
99161
  }
99162
+ if (!/^\d+\.\d+\.\d+/.test(currentVersion)) {
99163
+ const info2 = {
99164
+ currentVersion,
99165
+ latestVersion: null,
99166
+ isUpToDate: false,
99167
+ isLocalDev: true,
99168
+ isPinned: false,
99169
+ pinnedVersion: null,
99170
+ status: "dev"
99171
+ };
99172
+ console.log(options.json ? formatJsonOutput(info2) : formatVersionOutput(info2));
99173
+ return 0;
99174
+ }
99145
99175
  const { extractChannel: extractChannel2 } = await Promise.resolve().then(() => (init_auto_update_checker(), exports_auto_update_checker));
99146
99176
  const channel = extractChannel2(pluginInfo?.pinnedVersion ?? currentVersion);
99147
99177
  const latestVersion = await getLatestVersion(channel);
@@ -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.17.1",
2149
+ version: "4.18.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",
@@ -2253,6 +2253,7 @@ var init_package = __esm(() => {
2253
2253
  build: "bun run script/build.ts",
2254
2254
  "build:cli-node": "bun run script/build-cli-node.ts",
2255
2255
  "build:codex-install": "bun run script/build-codex-install.ts",
2256
+ "install:codex-dev": "bun run script/build-codex-install.ts && bun run script/install-codex-dev.ts",
2256
2257
  "build:codex-plugin": "npm --prefix packages/omo-codex/plugin ci && bun run --cwd packages/omo-codex/plugin build",
2257
2258
  "build:senpi-plugin": "node packages/omo-senpi/plugin/scripts/build-extension.mjs && node packages/omo-senpi/plugin/scripts/sync-skills.mjs && node packages/omo-senpi/plugin/scripts/embed-directive.mjs --check",
2258
2259
  "build:materialize-frontend": "node packages/omo-codex/plugin/scripts/materialize-shared-upstreams.mjs --strict",
@@ -2357,18 +2358,18 @@ var init_package = __esm(() => {
2357
2358
  typescript: "^6.0.3"
2358
2359
  },
2359
2360
  optionalDependencies: {
2360
- "oh-my-opencode-darwin-arm64": "4.17.1",
2361
- "oh-my-opencode-darwin-x64": "4.17.1",
2362
- "oh-my-opencode-darwin-x64-baseline": "4.17.1",
2363
- "oh-my-opencode-linux-arm64": "4.17.1",
2364
- "oh-my-opencode-linux-arm64-musl": "4.17.1",
2365
- "oh-my-opencode-linux-x64": "4.17.1",
2366
- "oh-my-opencode-linux-x64-baseline": "4.17.1",
2367
- "oh-my-opencode-linux-x64-musl": "4.17.1",
2368
- "oh-my-opencode-linux-x64-musl-baseline": "4.17.1",
2369
- "oh-my-opencode-windows-arm64": "4.17.1",
2370
- "oh-my-opencode-windows-x64": "4.17.1",
2371
- "oh-my-opencode-windows-x64-baseline": "4.17.1"
2361
+ "oh-my-opencode-darwin-arm64": "4.18.0",
2362
+ "oh-my-opencode-darwin-x64": "4.18.0",
2363
+ "oh-my-opencode-darwin-x64-baseline": "4.18.0",
2364
+ "oh-my-opencode-linux-arm64": "4.18.0",
2365
+ "oh-my-opencode-linux-arm64-musl": "4.18.0",
2366
+ "oh-my-opencode-linux-x64": "4.18.0",
2367
+ "oh-my-opencode-linux-x64-baseline": "4.18.0",
2368
+ "oh-my-opencode-linux-x64-musl": "4.18.0",
2369
+ "oh-my-opencode-linux-x64-musl-baseline": "4.18.0",
2370
+ "oh-my-opencode-windows-arm64": "4.18.0",
2371
+ "oh-my-opencode-windows-x64": "4.18.0",
2372
+ "oh-my-opencode-windows-x64-baseline": "4.18.0"
2372
2373
  },
2373
2374
  overrides: {
2374
2375
  "@earendil-works/pi-agent-core": "0.80.3",
@@ -72657,7 +72658,7 @@ var package_default2;
72657
72658
  var init_package2 = __esm(() => {
72658
72659
  package_default2 = {
72659
72660
  name: "@oh-my-opencode/omo-codex",
72660
- version: "4.17.1",
72661
+ version: "4.18.0",
72661
72662
  type: "module",
72662
72663
  private: true,
72663
72664
  description: "Codex harness adapter for oh-my-openagent. Vendored Codex plugin namespace (omo) + TypeScript installer + telemetry.",
@@ -75381,9 +75382,11 @@ function collectCommands(value, commands) {
75381
75382
 
75382
75383
  // packages/omo-codex/src/install/codex-cache-install.ts
75383
75384
  async function installCachedPlugin(input) {
75385
+ const env2 = input.env ?? process.env;
75386
+ const npmInstallEnv = sanitizeNpmInstallEnv(env2);
75384
75387
  if (input.buildSource !== false) {
75385
- await maybeRunNpmInstall(input.sourcePath, input.runCommand);
75386
- await maybeRunNpmBuild(input.sourcePath, input.runCommand);
75388
+ await maybeRunNpmInstall(input.sourcePath, input.runCommand, npmInstallEnv);
75389
+ await maybeRunNpmBuild(input.sourcePath, input.runCommand, env2);
75387
75390
  }
75388
75391
  const targetPath = join33(input.codexHome, "plugins", "cache", input.marketplaceName, input.name, input.version);
75389
75392
  const tempPath = createTempSiblingPath(targetPath);
@@ -75393,10 +75396,10 @@ async function installCachedPlugin(input) {
75393
75396
  await rewriteCachedPackageLocalFileDependencies(tempPath, input.sourcePath);
75394
75397
  await copyBundledMcpRuntimeDists({ pluginRoot: tempPath, sourceRoot: input.sourcePath });
75395
75398
  await copyRootRuntimeDists({ pluginRoot: tempPath, sourcePath: input.sourcePath });
75396
- await maybeRunNpmInstall(tempPath, input.runCommand, ["ci", "--omit=dev"]);
75399
+ await maybeRunNpmInstall(tempPath, input.runCommand, npmInstallEnv, ["ci", "--omit=dev"]);
75397
75400
  await removeCachedManagedNpmBinShims(tempPath);
75398
75401
  if (input.buildSource === false)
75399
- await maybeRunNpmSyncSkills(tempPath, input.runCommand);
75402
+ await maybeRunNpmSyncSkills(tempPath, input.runCommand, env2);
75400
75403
  await assertNoRemovedSparkshellPromptReferences(tempPath);
75401
75404
  await rewriteCachedMcpManifest(tempPath, input.sourcePath);
75402
75405
  await rewriteCachedManifestRoot(tempPath, tempPath, targetPath);
@@ -75408,12 +75411,12 @@ async function installCachedPlugin(input) {
75408
75411
  }
75409
75412
  return { name: input.name, version: input.version, path: targetPath };
75410
75413
  }
75411
- async function maybeRunNpmInstall(cwd, runCommand, args = ["install"]) {
75414
+ async function maybeRunNpmInstall(cwd, runCommand, env2, args = ["install"]) {
75412
75415
  if (!await fileExistsStrict(join33(cwd, "package.json")))
75413
75416
  return;
75414
- await runCommand("npm", args, { cwd });
75417
+ await runCommand("npm", args, { cwd, env: env2 });
75415
75418
  }
75416
- async function maybeRunNpmBuild(cwd, runCommand) {
75419
+ async function maybeRunNpmBuild(cwd, runCommand, env2) {
75417
75420
  if (!await fileExistsStrict(join33(cwd, "package.json")))
75418
75421
  return;
75419
75422
  const packageJson = JSON.parse(await readFile8(join33(cwd, "package.json"), "utf8"));
@@ -75422,9 +75425,9 @@ async function maybeRunNpmBuild(cwd, runCommand) {
75422
75425
  const scripts = packageJson.scripts;
75423
75426
  if (!isPlainRecord3(scripts) || typeof scripts.build !== "string")
75424
75427
  return;
75425
- await runCommand("npm", ["run", "build"], { cwd });
75428
+ await runCommand("npm", ["run", "build"], { cwd, env: env2 });
75426
75429
  }
75427
- async function maybeRunNpmSyncSkills(cwd, runCommand) {
75430
+ async function maybeRunNpmSyncSkills(cwd, runCommand, env2) {
75428
75431
  if (!await fileExistsStrict(join33(cwd, "package.json")))
75429
75432
  return;
75430
75433
  const packageJson = JSON.parse(await readFile8(join33(cwd, "package.json"), "utf8"));
@@ -75433,7 +75436,10 @@ async function maybeRunNpmSyncSkills(cwd, runCommand) {
75433
75436
  const scripts = packageJson.scripts;
75434
75437
  if (!isPlainRecord3(scripts) || typeof scripts["sync:skills"] !== "string")
75435
75438
  return;
75436
- await runCommand("npm", ["run", "sync:skills"], { cwd });
75439
+ await runCommand("npm", ["run", "sync:skills"], { cwd, env: env2 });
75440
+ }
75441
+ function sanitizeNpmInstallEnv(env2) {
75442
+ return Object.fromEntries(Object.entries(env2).filter(([key]) => key.toLowerCase() !== "npm_config_allow_scripts"));
75437
75443
  }
75438
75444
  function createTempSiblingPath(targetPath) {
75439
75445
  return join33(dirname13(targetPath), `.tmp-${basename7(targetPath)}-${process.pid}-${Date.now()}`);
@@ -77463,6 +77469,10 @@ async function readDistributionManifest(repoRoot) {
77463
77469
  }
77464
77470
  }
77465
77471
  function resolveLazyCodexPluginVersion(input) {
77472
+ const override = input.versionOverride?.trim();
77473
+ if (override !== undefined && override.length > 0) {
77474
+ return override;
77475
+ }
77466
77476
  if (input.marketplaceName === "sisyphuslabs" && input.pluginName === "omo" && input.distributionManifest !== undefined) {
77467
77477
  return input.distributionManifest.version;
77468
77478
  }
@@ -78013,6 +78023,7 @@ async function runCodexInstaller(options = {}) {
78013
78023
  return;
78014
78024
  });
78015
78025
  const buildSource = await shouldBuildSourcePackages(repoRoot);
78026
+ const versionOverride = env3.LAZYCODEX_DEV_VERSION?.trim() || undefined;
78016
78027
  const gitBashResolution = await prepareGitBashForInstall({
78017
78028
  platform,
78018
78029
  env: env3,
@@ -78039,13 +78050,15 @@ async function runCodexInstaller(options = {}) {
78039
78050
  manifestVersion: manifest.version,
78040
78051
  marketplaceName: marketplace.name,
78041
78052
  pluginName: entry.name,
78042
- distributionManifest
78053
+ distributionManifest,
78054
+ versionOverride
78043
78055
  });
78044
78056
  validatePathSegment(version2, "plugin version");
78045
78057
  log4(`Building ${entry.name}@${version2}`);
78046
78058
  const plugin = await installCachedPlugin({
78047
78059
  buildSource,
78048
78060
  codexHome,
78061
+ env: env3,
78049
78062
  marketplaceName: marketplace.name,
78050
78063
  name: entry.name,
78051
78064
  runCommand,
@@ -99126,6 +99139,10 @@ function formatVersionOutput(info) {
99126
99139
  lines.push(` ${SYMBOLS3.dev} ${import_picocolors17.default.cyan("Running in local development mode")}`);
99127
99140
  lines.push(` ${import_picocolors17.default.dim("Using file:// protocol from config")}`);
99128
99141
  break;
99142
+ case "dev":
99143
+ lines.push(` ${SYMBOLS3.dev} ${import_picocolors17.default.cyan("Running a local dev build")}`);
99144
+ lines.push(` ${import_picocolors17.default.dim("Installed from source; update checks are skipped")}`);
99145
+ break;
99129
99146
  case "pinned":
99130
99147
  lines.push(` ${SYMBOLS3.pin} ${import_picocolors17.default.magenta(`Version pinned to ${info.pinnedVersion}`)}`);
99131
99148
  lines.push(` ${import_picocolors17.default.dim("Update check skipped for pinned versions")}`);
@@ -99198,6 +99215,19 @@ async function getLocalVersion(options = {}) {
99198
99215
  console.log(options.json ? formatJsonOutput(info2) : formatVersionOutput(info2));
99199
99216
  return 1;
99200
99217
  }
99218
+ if (!/^\d+\.\d+\.\d+/.test(currentVersion)) {
99219
+ const info2 = {
99220
+ currentVersion,
99221
+ latestVersion: null,
99222
+ isUpToDate: false,
99223
+ isLocalDev: true,
99224
+ isPinned: false,
99225
+ pinnedVersion: null,
99226
+ status: "dev"
99227
+ };
99228
+ console.log(options.json ? formatJsonOutput(info2) : formatVersionOutput(info2));
99229
+ return 0;
99230
+ }
99201
99231
  const { extractChannel: extractChannel2 } = await Promise.resolve().then(() => (init_auto_update_checker(), exports_auto_update_checker));
99202
99232
  const channel = extractChannel2(pluginInfo?.pinnedVersion ?? currentVersion);
99203
99233
  const latestVersion = await getLatestVersion(channel);
package/dist/index.js CHANGED
@@ -6777,11 +6777,17 @@ function toGitFileStatus(statusToken) {
6777
6777
  return "deleted";
6778
6778
  return "modified";
6779
6779
  }
6780
+ function normalizeGitStatusPath(statusToken, filePath) {
6781
+ if (statusToken !== "R" && statusToken !== "C")
6782
+ return filePath;
6783
+ const arrowIndex = filePath.lastIndexOf(" -> ");
6784
+ return arrowIndex === -1 ? filePath : filePath.slice(arrowIndex + 4);
6785
+ }
6780
6786
  function parseGitStatusPorcelainLine(line) {
6781
6787
  if (!line)
6782
6788
  return null;
6783
6789
  const statusToken = line.substring(0, 2).trim();
6784
- const filePath = line.substring(3);
6790
+ const filePath = normalizeGitStatusPath(statusToken, line.substring(3));
6785
6791
  if (!filePath)
6786
6792
  return null;
6787
6793
  return {
@@ -89664,7 +89670,7 @@ function getCachedVersion(options = {}) {
89664
89670
  // package.json
89665
89671
  var package_default = {
89666
89672
  name: "oh-my-opencode",
89667
- version: "4.17.1",
89673
+ version: "4.18.0",
89668
89674
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
89669
89675
  main: "./dist/index.js",
89670
89676
  types: "dist/index.d.ts",
@@ -89771,6 +89777,7 @@ var package_default = {
89771
89777
  build: "bun run script/build.ts",
89772
89778
  "build:cli-node": "bun run script/build-cli-node.ts",
89773
89779
  "build:codex-install": "bun run script/build-codex-install.ts",
89780
+ "install:codex-dev": "bun run script/build-codex-install.ts && bun run script/install-codex-dev.ts",
89774
89781
  "build:codex-plugin": "npm --prefix packages/omo-codex/plugin ci && bun run --cwd packages/omo-codex/plugin build",
89775
89782
  "build:senpi-plugin": "node packages/omo-senpi/plugin/scripts/build-extension.mjs && node packages/omo-senpi/plugin/scripts/sync-skills.mjs && node packages/omo-senpi/plugin/scripts/embed-directive.mjs --check",
89776
89783
  "build:materialize-frontend": "node packages/omo-codex/plugin/scripts/materialize-shared-upstreams.mjs --strict",
@@ -89875,18 +89882,18 @@ var package_default = {
89875
89882
  typescript: "^6.0.3"
89876
89883
  },
89877
89884
  optionalDependencies: {
89878
- "oh-my-opencode-darwin-arm64": "4.17.1",
89879
- "oh-my-opencode-darwin-x64": "4.17.1",
89880
- "oh-my-opencode-darwin-x64-baseline": "4.17.1",
89881
- "oh-my-opencode-linux-arm64": "4.17.1",
89882
- "oh-my-opencode-linux-arm64-musl": "4.17.1",
89883
- "oh-my-opencode-linux-x64": "4.17.1",
89884
- "oh-my-opencode-linux-x64-baseline": "4.17.1",
89885
- "oh-my-opencode-linux-x64-musl": "4.17.1",
89886
- "oh-my-opencode-linux-x64-musl-baseline": "4.17.1",
89887
- "oh-my-opencode-windows-arm64": "4.17.1",
89888
- "oh-my-opencode-windows-x64": "4.17.1",
89889
- "oh-my-opencode-windows-x64-baseline": "4.17.1"
89885
+ "oh-my-opencode-darwin-arm64": "4.18.0",
89886
+ "oh-my-opencode-darwin-x64": "4.18.0",
89887
+ "oh-my-opencode-darwin-x64-baseline": "4.18.0",
89888
+ "oh-my-opencode-linux-arm64": "4.18.0",
89889
+ "oh-my-opencode-linux-arm64-musl": "4.18.0",
89890
+ "oh-my-opencode-linux-x64": "4.18.0",
89891
+ "oh-my-opencode-linux-x64-baseline": "4.18.0",
89892
+ "oh-my-opencode-linux-x64-musl": "4.18.0",
89893
+ "oh-my-opencode-linux-x64-musl-baseline": "4.18.0",
89894
+ "oh-my-opencode-windows-arm64": "4.18.0",
89895
+ "oh-my-opencode-windows-x64": "4.18.0",
89896
+ "oh-my-opencode-windows-x64-baseline": "4.18.0"
89890
89897
  },
89891
89898
  overrides: {
89892
89899
  "@earendil-works/pi-agent-core": "0.80.3",
@@ -117697,9 +117704,8 @@ async function getSdkAllSessions(client3) {
117697
117704
  return sessions.map((session) => session.id);
117698
117705
  }
117699
117706
  async function sdkSessionExists(client3, sessionID) {
117700
- const response = await fetchSdkResponse(() => client3.session.list());
117701
- const sessions = normalizeSDKResponse(response, []);
117702
- return sessions.some((session) => session.id === sessionID);
117707
+ const messages = await getSdkSessionMessages(client3, sessionID);
117708
+ return messages.length > 0;
117703
117709
  }
117704
117710
  async function getSdkSessionMessages(client3, sessionID) {
117705
117711
  const response = await fetchSdkResponse(() => client3.session.messages({ path: { id: sessionID } }));
@@ -32,7 +32,7 @@ Every implementation must choose one of these branches before UI code changes:
32
32
  - **Embedded references:** use `references/design/_INDEX.md` to shortlist 2-3 plausible Layer B references, then read exactly one Layer A style skill and one Layer B reference in full — every line, no partial reads (they are 200-500 lines; a sliced read produces the flattened token set this gate exists to prevent). Log the shortlist, the pick, and why. Use `open-design` only when the curated set has no fit; add `ui-ux-db` lookups for palette/type/domain questions.
33
33
  - **Lazyweb real-product screens:** READ `references/design/lazyweb.md` FIRST and run its recipe verbatim — do not improvise curl calls against lazyweb.com; the recipe mints its own anonymous token. Log the queries run, how many screens you actually VIEWED, and the layout grammar harvested — never pixel copies.
34
34
  - **Imagen concept drafts:** generate 2-3 imagen concept drafts, each seeded with the loaded Layer A + Layer B tokens (palette, type, material); pick the strongest and treat the chosen draft as the reference-fidelity contract. Log the draft paths and the pick.
35
- Synthesize every lane into `DESIGN.md`. Treat sources as source material, not mood labels: extract tokens, layout grammar, component anatomy, interaction states, motion, and taste decisions, then recombine them into project-specific primitives. Never freestyle past the selected references, never copy logos or brand-specific copy. Then run the Primitive Showcase Gate (`references/design/README.md` Phase 0) before any product screen.
35
+ Synthesize every lane into `DESIGN.md`. Treat sources as source material, not mood labels: extract tokens, layout grammar, component anatomy, interaction states, motion, and taste decisions, then recombine them into project-specific primitives. Before laying out sections, inventory the content blocks and assign each a job — hook, explain, prove, compare, convert, navigate, retain — then order sections by the visitor's decision path, not by visual symmetry. Never freestyle past the selected references, never copy logos or brand-specific copy. Then run the Primitive Showcase Gate (`references/design/README.md` Phase 0) before any product screen.
36
36
  3. **Existing project with `DESIGN.md` or a component system:** read it, follow it, and update it before implementation only when the requested work needs a new token, primitive, state, motion rule, accessibility constraint, accepted debt, or reference-fidelity requirement.
37
37
  4. **Existing project with UI but no `DESIGN.md` and no reusable component layer:** STOP and ask the user one focused question: should you preserve the current look with copy-nearby styling, or extract a real `DESIGN.md` plus reusable components before continuing? Do not silently choose.
38
38
 
@@ -169,6 +169,12 @@ Triggers (mid-conversation, not initial): "you keep leaving placeholders", "stop
169
169
 
170
170
  **Action:** Add `output-skill.md` on top of whatever is currently loaded. This stacks cleanly — it is purely about output completeness, not visual style.
171
171
 
172
+ ### Step 8 — Is the screen an app shell, not a scroll-the-page site?
173
+
174
+ Triggers: dashboard, settings, mail/inbox, list-detail, command surface, split panes, fixed sidebar + scrolling body, admin console — or the user reports a layout that breaks when content gets long, empty, or unbroken (panel won't scroll, footer pushed off-screen, horizontal overflow on mobile).
175
+
176
+ **Action:** Add `layout-skill.md` on top of whatever style skill you selected in Steps 1-2. It carries scroll-ownership doctrine, the two silently-failing CSS contracts (`min-block-size: 0` scroll shells, `minmax(min(…),100%)` grids), the named-primitive vocabulary, container-vs-viewport routing, and the content-stress matrix. It adds no visual direction — the style skill still owns taste. Skip it for pure scroll-the-document marketing pages, where `taste-skill` layout guidance already fits.
177
+
172
178
  ## Stacking rules (read this once, internalize it)
173
179
 
174
180
  1. **At most one Layer A *style* skill at a time.** A layout cannot be both `minimalist-skill` and `brutalist-skill` simultaneously — they encode opposite spacing and typography philosophies. Pick one.
@@ -177,6 +183,7 @@ Triggers (mid-conversation, not initial): "you keep leaving placeholders", "stop
177
183
  4. **`redesign-skill.md` replaces a style-skill** when the task is auditing, not building. Stack a Layer B brand if the user wants a specific direction.
178
184
  5. **`image-to-code-skill.md` pairs with one imagegen skill** for the full flow.
179
185
  6. **Layer B (brand DESIGN.md) is orthogonal to Layer A.** You can pair any Layer A skill with any Layer B brand. Use Layer B as the source of color/type/component tokens; let Layer A drive the execution discipline.
186
+ 7. **`layout-skill.md` stacks on top of any style skill** for app-shell / dashboard / split-pane work. It owns spatial structure and scroll ownership only — no visual direction — so it never conflicts with the style skill you picked.
180
187
 
181
188
  ## Anti-patterns — do not do these
182
189
 
@@ -218,6 +225,8 @@ Once references are loaded, before writing any UI code:
218
225
  | "Generate a brand identity board for {company}" | `imagegen-brandkit.md` |
219
226
  | "Stop using placeholders" | Add `output-skill.md` to current stack |
220
227
  | "Also output a DESIGN.md doc" | Add `stitch-skill.md` to current stack |
228
+ | "Build a dashboard / settings / inbox / app shell" | one style skill (usually `taste-skill.md`) + `layout-skill.md` |
229
+ | "Panel won't scroll / footer pushed off-screen / mobile overflow" | Add `layout-skill.md` to current stack |
221
230
 
222
231
  ## Phase Final — Design QA (MANDATORY, runs after implementation)
223
232
 
@@ -116,7 +116,7 @@ All spacing derives from a base of **4px**.
116
116
  - Breakpoints: sm 640px, md 768px, lg 1024px, xl 1280px, 2xl 1536px
117
117
 
118
118
  ### Rules
119
- - No magic numbers. Every spacing value maps to a token.
119
+ - Tokenize design *intent* spacing steps, content width, gutters, section gaps, density steps. Keep browser *mechanics* raw: `auto`, `%`, `min-content`, `max-content`, `fit-content`, `clamp()`, viewport/container units, intrinsic sizing. A `clamp(1rem, 4vw, 2rem)` gap or a `minmax(min(16rem, 100%), 1fr)` track is mechanics, not a magic number — do not force it into a token.
120
120
  - Asymmetric spacing is intentional, not accidental — document why.
121
121
 
122
122
  ## 5. Components
@@ -130,6 +130,7 @@ Document reusable patterns before implementation for greenfield work, and as the
130
130
  - **States**: default, hover, active, focus, disabled, loading, empty, error
131
131
  - **Accessibility**: keyboard, ARIA, contrast
132
132
  - **Motion**: entry/exit animations
133
+ - **Layout**: spatial primitive (stack / cluster / sidebar / grid / shell…) and, if the component scrolls or pins anything, its scroll owner
133
134
 
134
135
  Greenfield starts with the primitives you are about to build, assembled from
135
136
  the selected references' component anatomy and adapted to the user's product.
@@ -214,13 +215,14 @@ After every component implementation, check:
214
215
 
215
216
  - [ ] All colors reference tokens from Section 2. No raw hex outside `DESIGN.md`.
216
217
  - [ ] All font sizes match Section 3 scale. No arbitrary sizes.
217
- - [ ] All spacing values are multiples of `--space-1` (4px). No magic numbers.
218
+ - [ ] Spacing intent maps to a token (Section 4); browser mechanics (`clamp()`, intrinsic sizing, container units) stay raw. No arbitrary px.
218
219
  - [ ] Interactive elements have all required states from Section 5 and Section 6.
219
220
  - [ ] Depth treatment matches the chosen strategy from Section 7.
220
221
  - [ ] Component reused 2+ times? Documented in Section 5.
221
222
  - [ ] Motion follows the timing table. No arbitrary durations.
222
223
  - [ ] Component visual QA passed for each primitive and required state before product screens were composed.
223
224
  - [ ] Section 8 accessibility constraints hold for the new component; any new debt is recorded in Section 8, not silently accepted.
225
+ - [ ] Survives content stress: empty, long label, unbroken string. Reflows to one readable column at 375px with no horizontal scroll of primary content.
224
226
 
225
227
  ## Memory Management
226
228