oh-my-opencode 4.16.0 → 4.16.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/.agents/skills/codex-qa/SKILL.md +9 -7
  2. package/.agents/skills/codex-qa/references/logging-debug.md +6 -4
  3. package/.agents/skills/opencode-qa/SKILL.md +9 -9
  4. package/.agents/skills/opencode-qa/references/tui-tmux.md +10 -8
  5. package/dist/cli/codex-ulw-loop.d.ts +8 -0
  6. package/dist/cli/get-local-version/types.d.ts +1 -1
  7. package/dist/cli/index.js +260 -207
  8. package/dist/cli-node/index.js +260 -207
  9. package/dist/features/background-agent/parent-wake-dedupe.d.ts +1 -0
  10. package/dist/features/background-agent/parent-wake-flush-runner.d.ts +2 -0
  11. package/dist/features/background-agent/parent-wake-prompt-dispatch.d.ts +1 -0
  12. package/dist/features/builtin-commands/templates/refactor-sections/intro-and-analysis.d.ts +1 -1
  13. package/dist/features/builtin-commands/templates/remove-ai-slops.d.ts +1 -1
  14. package/dist/features/builtin-commands/templates/start-work.d.ts +1 -1
  15. package/dist/features/monitor/process.d.ts +17 -1
  16. package/dist/index.js +1098 -1020
  17. package/dist/skills/frontend/SKILL.md +9 -9
  18. package/dist/skills/frontend/references/design/README.md +7 -3
  19. package/dist/skills/frontend/references/design/_INDEX.md +1 -1
  20. package/dist/skills/frontend/references/design/design-system-architecture.md +24 -2
  21. package/dist/skills/frontend/references/designpowers/README.md +2 -2
  22. package/dist/skills/frontend/references/designpowers/lane-b-execution.md +1 -1
  23. package/dist/skills/review-work/SKILL.md +3 -1
  24. package/dist/skills/start-work/SKILL.md +4 -2
  25. package/dist/skills/ulw-research/SKILL.md +3 -1
  26. package/dist/skills/visual-qa/SKILL.md +13 -17
  27. package/docs/reference/web-terminal-visual-qa.md +39 -45
  28. package/package.json +31 -25
  29. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  30. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  31. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  32. package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
  33. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  34. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  35. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  36. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  37. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  38. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  39. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  40. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  41. package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus.md +1 -1
  42. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  43. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  44. package/packages/omo-codex/plugin/components/start-work-continuation/directive.md +3 -3
  45. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  46. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  47. package/packages/omo-codex/plugin/components/start-work-continuation/test/codex-hook.test.ts +1 -1
  48. package/packages/omo-codex/plugin/components/teammode/AGENTS.md +1 -1
  49. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  50. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  51. package/packages/omo-codex/plugin/components/teammode/skills/teammode/SKILL.md +3 -3
  52. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  53. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  54. package/packages/omo-codex/plugin/components/ultrawork/directive.md +19 -10
  55. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  56. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  57. package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +19 -10
  58. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +13 -0
  59. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +2 -0
  60. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +22 -1
  61. package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +4 -0
  62. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +19 -10
  63. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +15 -2
  64. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.js +2 -1
  65. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +89 -27
  66. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.d.ts +6 -0
  67. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +55 -9
  68. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-snapshot.d.ts +15 -0
  69. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-snapshot.js +33 -0
  70. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-types.d.ts +10 -3
  71. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering.js +15 -11
  72. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +2 -2
  73. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  74. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +3 -1
  75. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +7 -7
  76. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +17 -2
  77. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-steering.ts +2 -1
  78. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +59 -11
  79. package/packages/omo-codex/plugin/components/ulw-loop/src/steering-snapshot.ts +38 -0
  80. package/packages/omo-codex/plugin/components/ulw-loop/src/steering-types.ts +11 -3
  81. package/packages/omo-codex/plugin/components/ulw-loop/src/steering.ts +15 -7
  82. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-create-goals.test.ts +16 -0
  83. package/packages/omo-codex/plugin/components/ulw-loop/test/plan-io.test.ts +260 -2
  84. package/packages/omo-codex/plugin/components/ulw-loop/test/skill-contract.test.ts +1 -1
  85. package/packages/omo-codex/plugin/components/ulw-loop/test/steering-snapshot.test.ts +124 -0
  86. package/packages/omo-codex/plugin/components/ulw-loop/test/steering.test.ts +101 -2
  87. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  88. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  89. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  90. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  91. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  92. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  93. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  94. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  95. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  96. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  97. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  98. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  99. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  100. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  101. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  102. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
  103. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
  104. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  105. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  106. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  107. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  108. package/packages/omo-codex/plugin/package-lock.json +13 -13
  109. package/packages/omo-codex/plugin/package.json +1 -1
  110. package/packages/omo-codex/plugin/scripts/auto-update.mjs +64 -17
  111. package/packages/omo-codex/plugin/scripts/hook-status-message.mjs +10 -6
  112. package/packages/omo-codex/plugin/scripts/migrate-codex-config/multi-agent-v2-guard.mjs +186 -20
  113. package/packages/omo-codex/plugin/scripts/migrate-codex-config/subagent-limit-guard.mjs +51 -3
  114. package/packages/omo-codex/plugin/scripts/migrate-codex-config.mjs +33 -5
  115. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +1 -1
  116. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +9 -9
  117. package/packages/omo-codex/plugin/skills/frontend/references/design/README.md +7 -3
  118. package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +1 -1
  119. package/packages/omo-codex/plugin/skills/frontend/references/design/design-system-architecture.md +24 -2
  120. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/README.md +2 -2
  121. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-b-execution.md +1 -1
  122. package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +1 -1
  123. package/packages/omo-codex/plugin/skills/refactor/SKILL.md +1 -1
  124. package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +1 -1
  125. package/packages/omo-codex/plugin/skills/review-work/SKILL.md +1 -1
  126. package/packages/omo-codex/plugin/skills/start-work/SKILL.md +3 -3
  127. package/packages/omo-codex/plugin/skills/teammode/SKILL.md +3 -3
  128. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +19 -10
  129. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +3 -1
  130. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +7 -7
  131. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +13 -0
  132. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +2 -0
  133. package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +1 -1
  134. package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +14 -18
  135. package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +4 -4
  136. package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +1 -1
  137. package/packages/omo-codex/plugin/test/auto-update.test.mjs +35 -1
  138. package/packages/omo-codex/plugin/test/bootstrap-hooks.test.mjs +1 -1
  139. package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +22 -9
  140. package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +275 -19
  141. package/packages/omo-codex/plugin/test/subagent-limit-migration.test.mjs +33 -0
  142. package/packages/omo-codex/plugin/test/sync-hook-status-messages.test.mjs +6 -6
  143. package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +4 -2
  144. package/packages/omo-codex/plugin/test/ulw-plan-skill-contract.test.mjs +52 -0
  145. package/packages/omo-codex/scripts/install-dist/install-local.mjs +65 -39
  146. package/packages/omo-codex/scripts/install-lazycodex-version-stamp.test.mjs +2 -2
  147. package/packages/shared-skills/skills/frontend/SKILL.md +9 -9
  148. package/packages/shared-skills/skills/frontend/references/design/README.md +7 -3
  149. package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +1 -1
  150. package/packages/shared-skills/skills/frontend/references/design/design-system-architecture.md +24 -2
  151. package/packages/shared-skills/skills/frontend/references/designpowers/README.md +2 -2
  152. package/packages/shared-skills/skills/frontend/references/designpowers/lane-b-execution.md +1 -1
  153. package/packages/shared-skills/skills/review-work/SKILL.md +3 -1
  154. package/packages/shared-skills/skills/start-work/SKILL.md +4 -2
  155. package/packages/shared-skills/skills/ulw-research/SKILL.md +3 -1
  156. package/packages/shared-skills/skills/visual-qa/SKILL.md +13 -17
  157. package/script/qa/strip-ansi.mjs +10 -0
  158. package/script/qa/web-terminal-visual-qa.mjs +112 -195
  159. package/script/qa/xterm-live-terminal.mjs +180 -0
  160. package/script/qa/web-terminal-renderer.mjs +0 -218
@@ -96,20 +96,20 @@ var init_atomic_write = __esm(() => {
96
96
 
97
97
  // packages/telemetry-core/src/activity-state.ts
98
98
  import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync } from "node:fs";
99
- import { basename as basename6, join as join30 } from "node:path";
99
+ import { basename as basename6, join as join31 } from "node:path";
100
100
  function resolveTelemetryStateDir(product, options = {}) {
101
101
  const dataDir = resolveXdgDataDir(product.cacheDirName, {
102
102
  env: options.env,
103
103
  osProvider: options.osProvider
104
104
  });
105
- const xdgStateDir = options.env?.XDG_DATA_HOME === undefined ? undefined : join30(options.env.XDG_DATA_HOME, product.cacheDirName);
105
+ const xdgStateDir = options.env?.XDG_DATA_HOME === undefined ? undefined : join31(options.env.XDG_DATA_HOME, product.cacheDirName);
106
106
  if (dataDir === xdgStateDir || xdgStateDir === undefined && basename6(dataDir) === product.cacheDirName) {
107
107
  return dataDir;
108
108
  }
109
- return join30(dataDir, product.cacheDirName);
109
+ return join31(dataDir, product.cacheDirName);
110
110
  }
111
111
  function getTelemetryActivityStateFilePath(stateDir) {
112
- return join30(stateDir, POSTHOG_ACTIVITY_STATE_FILE);
112
+ return join31(stateDir, POSTHOG_ACTIVITY_STATE_FILE);
113
113
  }
114
114
  function getDailyActiveCaptureState(input) {
115
115
  const state = readPostHogActivityState(input.stateDir, input.diagnostics);
@@ -180,9 +180,9 @@ var DEFAULT_POSTHOG_HOST = "https://us.i.posthog.com", DEFAULT_POSTHOG_API_KEY =
180
180
 
181
181
  // packages/telemetry-core/src/diagnostics.ts
182
182
  import { appendFileSync, existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync2 } from "node:fs";
183
- import { join as join31 } from "node:path";
183
+ import { join as join32 } from "node:path";
184
184
  function getTelemetryDiagnosticsFilePath(diagnosticsDir) {
185
- return join31(diagnosticsDir, DIAGNOSTICS_FILE_NAME);
185
+ return join32(diagnosticsDir, DIAGNOSTICS_FILE_NAME);
186
186
  }
187
187
  function writeTelemetryDiagnostic(input, options) {
188
188
  const now = options.now ?? new Date;
@@ -5903,7 +5903,7 @@ var package_default;
5903
5903
  var init_package = __esm(() => {
5904
5904
  package_default = {
5905
5905
  name: "@oh-my-opencode/omo-codex",
5906
- version: "4.16.0",
5906
+ version: "4.16.1",
5907
5907
  type: "module",
5908
5908
  private: true,
5909
5909
  description: "Codex harness adapter for oh-my-openagent. Vendored Codex plugin namespace (omo) + TypeScript installer + telemetry.",
@@ -6122,8 +6122,8 @@ var init_telemetry = __esm(() => {
6122
6122
  });
6123
6123
 
6124
6124
  // packages/omo-codex/src/install/install-local-cli.ts
6125
- import { readFile as readFile20 } from "node:fs/promises";
6126
- import { dirname as dirname11, join as join36, resolve as resolve10 } from "node:path";
6125
+ import { readFile as readFile21 } from "node:fs/promises";
6126
+ import { dirname as dirname11, join as join37, resolve as resolve10 } from "node:path";
6127
6127
  import { fileURLToPath as fileURLToPath2 } from "node:url";
6128
6128
 
6129
6129
  // packages/utils/src/runtime/spawn.ts
@@ -6456,7 +6456,7 @@ var defaultRunCommand = async (command, args, options) => {
6456
6456
  };
6457
6457
 
6458
6458
  // packages/omo-codex/src/install/install-codex.ts
6459
- import { join as join32, resolve as resolve9 } from "node:path";
6459
+ import { join as join33, resolve as resolve9 } from "node:path";
6460
6460
  import { existsSync as existsSync7 } from "node:fs";
6461
6461
  import { homedir as homedir2 } from "node:os";
6462
6462
 
@@ -9485,7 +9485,11 @@ function stampHookGroups(hooks, version) {
9485
9485
  function stampHookStatusMessage(hook, version) {
9486
9486
  if (!isPlainRecord(hook) || typeof hook.statusMessage !== "string")
9487
9487
  return;
9488
- hook.statusMessage = hook.statusMessage.replace(/^LazyCodex\([^)]+\):\s*/, "(OmO) ");
9488
+ hook.statusMessage = hook.statusMessage.replace(/^(?:LazyCodex\([^)]+\):|\(OmO(?:\s+[^)]+)?\))\s*/, `(OmO ${normalizeHookStatusVersion(version)}) `);
9489
+ }
9490
+ function normalizeHookStatusVersion(version) {
9491
+ const normalized = version.trim();
9492
+ return normalized.length === 0 ? "local" : normalized;
9489
9493
  }
9490
9494
 
9491
9495
  // packages/omo-codex/src/install/codex-project-local-cleanup.ts
@@ -9802,11 +9806,32 @@ function resolveCodexInstallerBinDir(input) {
9802
9806
  return resolve8(homeDir, ".local", "bin");
9803
9807
  }
9804
9808
 
9805
- // packages/omo-codex/src/install/omo-sot-migration.ts
9809
+ // packages/omo-codex/src/install/codex-git-bash-hooks.ts
9810
+ import { readFile as readFile19, writeFile as writeFile10 } from "node:fs/promises";
9806
9811
  import { join as join27 } from "node:path";
9812
+ var WINDOWS_ONLY_GIT_BASH_HOOKS = new Set([
9813
+ "./hooks/pre-tool-use-recommending-git-bash-mcp.json",
9814
+ "./hooks/post-compact-resetting-git-bash-mcp-reminder.json"
9815
+ ]);
9816
+ async function removeGitBashHooksOffWindows(input) {
9817
+ if (input.platform === "win32")
9818
+ return;
9819
+ const manifestPath = join27(input.pluginRoot, ".codex-plugin", "plugin.json");
9820
+ const parsed = JSON.parse(await readFile19(manifestPath, "utf8"));
9821
+ if (!isPlainRecord(parsed) || !Array.isArray(parsed.hooks))
9822
+ return;
9823
+ const hooks = parsed.hooks.filter((hook) => typeof hook !== "string" || !WINDOWS_ONLY_GIT_BASH_HOOKS.has(hook));
9824
+ if (hooks.length === parsed.hooks.length)
9825
+ return;
9826
+ await writeFile10(manifestPath, `${JSON.stringify({ ...parsed, hooks }, null, "\t")}
9827
+ `);
9828
+ }
9829
+
9830
+ // packages/omo-codex/src/install/omo-sot-migration.ts
9831
+ import { join as join28 } from "node:path";
9807
9832
  async function seedAndMigrateOmoSot(input) {
9808
9833
  const commandEnv = { ...input.env };
9809
- const scriptPath = join27(input.repoRoot, "packages", "omo-codex", "plugin", "scripts", "migrate-omo-sot.mjs");
9834
+ const scriptPath = join28(input.repoRoot, "packages", "omo-codex", "plugin", "scripts", "migrate-omo-sot.mjs");
9810
9835
  try {
9811
9836
  await input.runCommand(process.execPath, [scriptPath, "--seed"], {
9812
9837
  cwd: input.repoRoot,
@@ -9820,7 +9845,7 @@ async function seedAndMigrateOmoSot(input) {
9820
9845
  }
9821
9846
 
9822
9847
  // packages/omo-codex/src/install/install-ast-grep-sg.ts
9823
- import { join as join29 } from "node:path";
9848
+ import { join as join30 } from "node:path";
9824
9849
 
9825
9850
  // packages/utils/src/ast-grep/sg-manifest.ts
9826
9851
  function normalizeRuntimePlatform(platform = process.platform) {
@@ -9840,11 +9865,11 @@ function runtimeSlug(platform = process.platform, arch = process.arch) {
9840
9865
  // packages/utils/src/ast-grep/install-script.ts
9841
9866
  import { spawn as spawn2 } from "node:child_process";
9842
9867
  import { existsSync as existsSync4 } from "node:fs";
9843
- import { join as join28 } from "node:path";
9868
+ import { join as join29 } from "node:path";
9844
9869
  var AST_GREP_BIN_DIR_ENV_KEY = "OMO_AST_GREP_BIN_DIR";
9845
9870
  var AST_GREP_INSTALL_TIMEOUT_MS = 30000;
9846
9871
  function astGrepRuntimeDir(baseDir, platform = process.platform, arch = process.arch) {
9847
- return join28(baseDir, "runtime", "ast-grep", runtimeSlug(platform, arch));
9872
+ return join29(baseDir, "runtime", "ast-grep", runtimeSlug(platform, arch));
9848
9873
  }
9849
9874
  function isMissingExecutable(error) {
9850
9875
  if (!("code" in error))
@@ -9882,7 +9907,7 @@ function defaultSpawnProcess(command, args, options) {
9882
9907
  };
9883
9908
  }
9884
9909
  function scriptPathForPlatform(skillDir, platform) {
9885
- return join28(skillDir, platform === "win32" ? "install.ps1" : "install.sh");
9910
+ return join29(skillDir, platform === "win32" ? "install.ps1" : "install.sh");
9886
9911
  }
9887
9912
  function invocationsForPlatform(scriptPath, platform) {
9888
9913
  if (platform !== "win32")
@@ -9954,7 +9979,7 @@ async function installAstGrepForCodex(options) {
9954
9979
  return;
9955
9980
  const platform = options.platform ?? process.platform;
9956
9981
  const targetDir = astGrepRuntimeDir(options.codexHome, platform, options.arch ?? process.arch);
9957
- const skillDir = join29(plugin.path, "skills", "ast-grep");
9982
+ const skillDir = join30(plugin.path, "skills", "ast-grep");
9958
9983
  const installer = options.installer ?? runAstGrepSkillInstall;
9959
9984
  try {
9960
9985
  const result = await installer({ platform, skillDir, targetDir });
@@ -9987,7 +10012,7 @@ async function runCodexInstaller(options = {}) {
9987
10012
  const env2 = options.env ?? process.env;
9988
10013
  const platform = options.platform ?? process.platform;
9989
10014
  const repoRoot = resolve9(options.repoRoot ?? findRepoRoot({ importerDir: import.meta.dir, env: env2 }));
9990
- const codexHome = resolve9(options.codexHome ?? env2.CODEX_HOME ?? join32(homedir2(), ".codex"));
10015
+ const codexHome = resolve9(options.codexHome ?? env2.CODEX_HOME ?? join33(homedir2(), ".codex"));
9991
10016
  const projectDirectory = resolve9(options.projectDirectory ?? env2.OMO_CODEX_PROJECT ?? process.cwd());
9992
10017
  const binDir = resolveCodexInstallerBinDir({ binDir: options.binDir, codexHome, env: env2 });
9993
10018
  const runCommand = options.runCommand ?? defaultRunCommand;
@@ -10003,9 +10028,9 @@ async function runCodexInstaller(options = {}) {
10003
10028
  if (!gitBashResolution.found) {
10004
10029
  throw new Error(gitBashResolution.installHint);
10005
10030
  }
10006
- const codexPackageRoot = join32(repoRoot, "packages", "omo-codex");
10031
+ const codexPackageRoot = join33(repoRoot, "packages", "omo-codex");
10007
10032
  const marketplace = await readMarketplace(repoRoot, {
10008
- marketplacePath: join32(codexPackageRoot, "marketplace.json")
10033
+ marketplacePath: join33(codexPackageRoot, "marketplace.json")
10009
10034
  });
10010
10035
  const distributionManifest = await readDistributionManifest(repoRoot);
10011
10036
  const installed = [];
@@ -10037,6 +10062,7 @@ async function runCodexInstaller(options = {}) {
10037
10062
  if (marketplace.name === "sisyphuslabs" && plugin.name === "omo") {
10038
10063
  await stampLazyCodexPluginVersion({ pluginRoot: plugin.path, version: version2 });
10039
10064
  await writeLazyCodexInstallSnapshot({ pluginRoot: plugin.path, distributionManifest });
10065
+ await removeGitBashHooksOffWindows({ platform, pluginRoot: plugin.path });
10040
10066
  }
10041
10067
  const links = await linkCachedPluginBins({ binDir, pluginRoot: plugin.path, platform });
10042
10068
  for (const link of links) {
@@ -10047,7 +10073,7 @@ async function runCodexInstaller(options = {}) {
10047
10073
  if (runtimeLink !== null)
10048
10074
  log(`Linked ${runtimeLink.name} -> ${runtimeLink.target}`);
10049
10075
  else
10050
- log(`Warning: skipped the omo runtime wrapper because ${join32(repoRoot, "dist", "cli", "index.js")} is missing; omo ulw-loop commands will be unavailable until a package shipping dist/cli is installed`);
10076
+ log(`Warning: skipped the omo runtime wrapper because ${join33(repoRoot, "dist", "cli", "index.js")} is missing; omo ulw-loop commands will be unavailable until a package shipping dist/cli is installed`);
10051
10077
  }
10052
10078
  pluginSources.push({ name: entry.name, sourcePath });
10053
10079
  installed.push(plugin);
@@ -10101,13 +10127,13 @@ async function runCodexInstaller(options = {}) {
10101
10127
  });
10102
10128
  }
10103
10129
  await reapLspDaemons(codexHome).catch(() => []);
10104
- const marketplaceRoot = join32(codexHome, "plugins", "cache", marketplace.name);
10130
+ const marketplaceRoot = join33(codexHome, "plugins", "cache", marketplace.name);
10105
10131
  await writeCachedMarketplaceManifest({
10106
10132
  marketplaceName: marketplace.name,
10107
10133
  marketplaceRoot,
10108
10134
  plugins: installed
10109
10135
  });
10110
- const configPath = join32(codexHome, "config.toml");
10136
+ const configPath = join33(codexHome, "config.toml");
10111
10137
  await updateCodexConfig({
10112
10138
  configPath,
10113
10139
  repoRoot: codexPackageRoot,
@@ -10167,7 +10193,7 @@ function findRepoRootFromImporter(importerDir) {
10167
10193
  for (let depth = 0;depth <= 7; depth += 1) {
10168
10194
  if (isRepoRootWithCodexPlugin(current))
10169
10195
  return current;
10170
- for (const wrapperPackageRoot of [join32(current, "node_modules", "oh-my-openagent"), join32(current, "oh-my-openagent")]) {
10196
+ for (const wrapperPackageRoot of [join33(current, "node_modules", "oh-my-openagent"), join33(current, "oh-my-openagent")]) {
10171
10197
  if (isRepoRootWithCodexPlugin(wrapperPackageRoot))
10172
10198
  return wrapperPackageRoot;
10173
10199
  }
@@ -10185,7 +10211,7 @@ function findRepoRoot(input) {
10185
10211
  return findRepoRootFromImporter(input.importerDir);
10186
10212
  }
10187
10213
  function isRepoRootWithCodexPlugin(repoRoot) {
10188
- return existsSync7(join32(repoRoot, "packages", "omo-codex", "plugin", ".codex-plugin", "plugin.json"));
10214
+ return existsSync7(join33(repoRoot, "packages", "omo-codex", "plugin", ".codex-plugin", "plugin.json"));
10189
10215
  }
10190
10216
  function codexMarketplaceSource(marketplaceRoot) {
10191
10217
  return { sourceType: "local", source: marketplaceRoot };
@@ -10498,12 +10524,12 @@ function shellQuote(value) {
10498
10524
  // packages/omo-codex/src/install/lazycodex-manual-update.ts
10499
10525
  import { spawn as spawn3, spawnSync as spawnSync3 } from "node:child_process";
10500
10526
  import { readFileSync as readFileSync3 } from "node:fs";
10501
- import { dirname as dirname10, join as join34 } from "node:path";
10527
+ import { dirname as dirname10, join as join35 } from "node:path";
10502
10528
  import { createInterface as createInterface2 } from "node:readline/promises";
10503
10529
  import { fileURLToPath } from "node:url";
10504
10530
 
10505
10531
  // packages/omo-codex/src/install/lazycodex-bun-global-paths.ts
10506
- import { join as join33 } from "node:path";
10532
+ import { join as join34 } from "node:path";
10507
10533
  function isBunGlobalEntrypointPath(invokedPath, env2) {
10508
10534
  if (typeof invokedPath !== "string" || invokedPath.trim().length === 0)
10509
10535
  return false;
@@ -10514,8 +10540,8 @@ function resolveBunGlobalRoots(env2) {
10514
10540
  const bunInstallRoot = env2.BUN_INSTALL?.trim();
10515
10541
  const homeRoot = env2.HOME?.trim();
10516
10542
  return [
10517
- ...bunInstallRoot ? [join33(bunInstallRoot, "bin"), join33(bunInstallRoot, "install", "global", "node_modules")] : [],
10518
- ...homeRoot ? [join33(homeRoot, ".bun", "bin"), join33(homeRoot, ".bun", "install", "global", "node_modules")] : []
10543
+ ...bunInstallRoot ? [join34(bunInstallRoot, "bin"), join34(bunInstallRoot, "install", "global", "node_modules")] : [],
10544
+ ...homeRoot ? [join34(homeRoot, ".bun", "bin"), join34(homeRoot, ".bun", "install", "global", "node_modules")] : []
10519
10545
  ].map(normalizePathForPrefix);
10520
10546
  }
10521
10547
  function normalizePathForPrefix(path2) {
@@ -10608,7 +10634,7 @@ function resolveCurrentVersion(env2) {
10608
10634
  if (env2.LAZYCODEX_CURRENT_VERSION?.trim())
10609
10635
  return env2.LAZYCODEX_CURRENT_VERSION.trim();
10610
10636
  const pluginRoot = dirname10(dirname10(fileURLToPath(import.meta.url)));
10611
- return readVersionManifest(resolveInstalledVersionPath(env2, pluginRoot)) ?? readVersionManifest(join34(pluginRoot, "..", "..", "..", "package.json")) ?? readVersionManifest(join34(pluginRoot, ".codex-plugin", "plugin.json"));
10637
+ return readVersionManifest(resolveInstalledVersionPath(env2, pluginRoot)) ?? readVersionManifest(join35(pluginRoot, "..", "..", "..", "package.json")) ?? readVersionManifest(join35(pluginRoot, ".codex-plugin", "plugin.json"));
10612
10638
  }
10613
10639
  function resolveLatestVersion(env2) {
10614
10640
  if (env2.LAZYCODEX_LATEST_VERSION?.trim())
@@ -10724,7 +10750,7 @@ function compareVersions(left, right) {
10724
10750
  function resolveInstalledVersionPath(env2, pluginRoot) {
10725
10751
  if (env2.LAZYCODEX_INSTALLED_VERSION_FILE?.trim())
10726
10752
  return env2.LAZYCODEX_INSTALLED_VERSION_FILE.trim();
10727
- return join34(pluginRoot, INSTALLED_VERSION_FILE);
10753
+ return join35(pluginRoot, INSTALLED_VERSION_FILE);
10728
10754
  }
10729
10755
  function readVersionManifest(path2) {
10730
10756
  try {
@@ -10740,15 +10766,15 @@ function readVersionManifest(path2) {
10740
10766
  }
10741
10767
  }
10742
10768
  // packages/omo-codex/src/install/codex-git-bash-mcp-env.ts
10743
- import { readFile as readFile19, writeFile as writeFile10 } from "node:fs/promises";
10744
- import { join as join35 } from "node:path";
10769
+ import { readFile as readFile20, writeFile as writeFile11 } from "node:fs/promises";
10770
+ import { join as join36 } from "node:path";
10745
10771
  var GIT_BASH_ENV_KEY2 = "OMO_CODEX_GIT_BASH_PATH";
10746
10772
  var CODEGRAPH_RELATIVE_ARGS2 = new Set(["components/codegraph/dist/serve.js", "./components/codegraph/dist/serve.js"]);
10747
10773
  async function stampGitBashMcpEnv(input) {
10748
- const manifestPath = join35(input.pluginRoot, ".mcp.json");
10774
+ const manifestPath = join36(input.pluginRoot, ".mcp.json");
10749
10775
  if (!await fileExistsStrict(manifestPath))
10750
10776
  return false;
10751
- const parsed = JSON.parse(await readFile19(manifestPath, "utf8"));
10777
+ const parsed = JSON.parse(await readFile20(manifestPath, "utf8"));
10752
10778
  if (!isPlainRecord(parsed) || !isPlainRecord(parsed["mcpServers"]))
10753
10779
  return false;
10754
10780
  let changed = stampCodegraphMcpPath(parsed["mcpServers"], input.pluginRoot);
@@ -10766,7 +10792,7 @@ async function stampGitBashMcpEnv(input) {
10766
10792
  }
10767
10793
  if (!changed)
10768
10794
  return false;
10769
- await writeFile10(manifestPath, `${JSON.stringify(parsed, null, "\t")}
10795
+ await writeFile11(manifestPath, `${JSON.stringify(parsed, null, "\t")}
10770
10796
  `);
10771
10797
  return true;
10772
10798
  }
@@ -10778,7 +10804,7 @@ function stampCodegraphMcpPath(mcpServers, pluginRoot) {
10778
10804
  const entrypoint = args[0];
10779
10805
  if (typeof entrypoint !== "string" || !CODEGRAPH_RELATIVE_ARGS2.has(entrypoint))
10780
10806
  return false;
10781
- codegraphServer["args"] = [join35(pluginRoot, "components", "codegraph", "dist", "serve.js"), ...args.slice(1)];
10807
+ codegraphServer["args"] = [join36(pluginRoot, "components", "codegraph", "dist", "serve.js"), ...args.slice(1)];
10782
10808
  return true;
10783
10809
  }
10784
10810
 
@@ -10799,7 +10825,7 @@ async function runLazyCodexInstallLocalCli(input) {
10799
10825
  return 0;
10800
10826
  }
10801
10827
  if (parsed.kind === "version") {
10802
- const packageJson = JSON.parse(await readFile20(join36(input.defaultRepoRoot, "package.json"), "utf8"));
10828
+ const packageJson = JSON.parse(await readFile21(join37(input.defaultRepoRoot, "package.json"), "utf8"));
10803
10829
  const version2 = typeof packageJson.version === "string" ? packageJson.version : "unknown";
10804
10830
  input.log(`lazycodex-ai ${version2}`);
10805
10831
  return 0;
@@ -77,8 +77,8 @@ test("#given sisyphuslabs lazycodex install #when installing locally #then stamp
77
77
  assert.equal(manifest.version, "4.7.6");
78
78
  assert.equal(packageJson.version, "4.7.6");
79
79
  assert.equal(componentPackageJson.version, "4.7.6");
80
- assert.equal(hooks.hooks.PostToolUse[0].hooks[0].statusMessage, "(OmO) Checking Comments");
81
- assert.equal(componentHooks.hooks.UserPromptSubmit[0].hooks[0].statusMessage, "(OmO) Checking Ulw-Loop Steering");
80
+ assert.equal(hooks.hooks.PostToolUse[0].hooks[0].statusMessage, "(OmO 4.7.6) Checking Comments");
81
+ assert.equal(componentHooks.hooks.UserPromptSubmit[0].hooks[0].statusMessage, "(OmO 4.7.6) Checking Ulw-Loop Steering");
82
82
  assert.deepEqual(snapshot, {
83
83
  packageName: "lazycodex-ai",
84
84
  version: "4.7.6",
@@ -16,7 +16,7 @@ This file is a router, not a rulebook. The rules live in four rulesets under `re
16
16
  | ANY UI implementation, styling, redesign, mockup, or visual decision | `references/design/README.md` FIRST. It enforces two mandatory gates — the Design System Gate (a `DESIGN.md` must exist before any component is written) and the React Dev Tooling Gate (react-grab / react-scan / react-doctor installed by default) — then routes to the taste and brand references below. |
17
17
  | Writing or modifying frontend code, OR auditing performance / SEO / accessibility / quality | ALSO `references/perfection/README.md`. Lighthouse 100 in every category, measured on real Playwright Chromium (never the `lighthouse` CLI), achieved through architecture — never by dropping animations or hiding content. |
18
18
  | Looking up a concrete style, color palette, font pairing, chart type, landing-page structure, or UX guideline — or generating a project design system from keywords | `references/ui-ux-db/README.md`. A searchable CSV database with a CLI; a lookup tool, not a posture. Load on demand; `design` stays the source of truth for taste and the `DESIGN.md` contract. |
19
- | Design operating-layer work: personas, cognitive accessibility, design critique, design debt, handoff, synthetic user testing, or designpowers-style guidance | `references/designpowers/README.md`. This is an internal frontend ruleset, not a separate skill. It enriches `/frontend` routing with design brief, role-reference, accessibility, evidence, and debt language while preserving the `design` and `perfection` gates. |
19
+ | ANY implementation or redesign that creates or updates `DESIGN.md` — plus explicit operating-layer asks (personas, critique, debt, handoff, synthetic user testing) | `references/designpowers/README.md` + `references/designpowers/lane-c-review.md`. An internal frontend ruleset, not a separate skill: lane-c is the Phase Final flatness/critique reviewer, and its accessibility-constraints and accepted-debt language fills the required `DESIGN.md` sections. Load other lanes only when their phase applies. |
20
20
 
21
21
  **For implementation work, design + perfection load together.** A page that hits Lighthouse 100 but looks like AI slop has failed; a page that looks beautiful but ships a 2 MB bundle has failed. Both win or neither does.
22
22
 
@@ -28,15 +28,15 @@ Every implementation must choose one of these branches before UI code changes:
28
28
  - **Static visual reference** (screenshot, generated mockup, Stitch/Imagen output, Figma export, overview, or annotated packet): load `references/design/image-to-code-skill.md` plus the relevant design/perfection files, extract the reference's exact tokens, layout geometry, copy, spacing, states, and responsive intent into `DESIGN.md`, then implement reusable primitives against that contract.
29
29
  - **Live site or URL reference** (the user names a site to clone or gives a URL): load `references/design/clone-from-url.md`. Drive a real browser and extract the runtime truth via `getComputedStyle` — tokens, layout geometry, default/hover/focus/active states, transitions and keyframes, and downloaded assets — into `DESIGN.md`, then clone-code reusable primitives against that contract.
30
30
  Final QA for both runs `/visual-qa` in reference-fidelity mode: compare the actual UI against the reference pixel-by-pixel and verify the code is an extensible design-system implementation, not a screenshot-matched one-off.
31
- 2. **Greenfield or fresh setup:** if the user gave no concrete visual reference, design direction is a research deliverable, not a vibe. Fire every available research lane IN PARALLEL before `DESIGN.md` is written; skip a lane only when its tool or network is genuinely unavailable, and name the skip in `DESIGN.md`:
32
- - **Embedded references:** use `references/design/_INDEX.md` to shortlist 2-3 plausible Layer B references, then deeply load exactly one Layer A style skill and one Layer B brand/design-system reference; use `open-design` only when the curated set has no fit; add `ui-ux-db` lookups for palette/type/domain questions.
33
- - **Lazyweb real-product screens:** run the curl-only recipe in `references/design/lazyweb.md` to see how shipped products in the target domain actually look; harvest layout grammar and component patterns, never pixel copies.
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.
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. Define Section 5 primitives and their default/hover/active/focus/disabled/loading/empty/error states before code, and pass each through mobile/tablet/desktop visual QA before product screens.
31
+ 2. **Greenfield or fresh setup:** if the user gave no concrete visual reference, design research is a build step with named deliverables — not exploration to be budgeted. Exploration-stop instincts ("enough exploration", two-wave caps) do not apply here. Fire every research lane IN PARALLEL before `DESIGN.md` is written, and open `DESIGN.md` with a `## 0. Research Log` section recording each lane's deliverable — a lane with no Research Log line did not run. Skip a lane only when its tool or network is genuinely unavailable, and name the skip in `DESIGN.md`:
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
+ - **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
+ - **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.
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
 
39
- When `references/designpowers/README.md` is loaded for implementation, redesign, or design-system work, feed its personas, accessibility, critique, debt, handoff, and role-reference guidance into the branch above. The resulting `DESIGN.md` is the implementation contract: tokens, typography, spacing, primitives, motion, responsive behavior, accessibility constraints, and accepted debt must be named there before code uses them. Verify component primitives, states, and final screens with real visual QA evidence; pass design-system decisions, implementation evidence, and unresolved debt into `/review-work` for significant implementation work.
39
+ For implementation, redesign, or design-system work that creates or updates `DESIGN.md`, `references/designpowers/README.md` + `lane-c-review.md` are part of the default load feed their personas, accessibility, critique, debt, handoff, and role-reference guidance into the branch above. The resulting `DESIGN.md` is the implementation contract: tokens, typography, spacing, primitives, motion, responsive behavior, accessibility constraints, and accepted debt must be named there before code uses them. Verify component primitives, states, and final screens with real visual QA evidence; pass design-system decisions, implementation evidence, and unresolved debt into `/review-work` for significant implementation work.
40
40
 
41
41
  ## Ruleset 1 — design (`references/design/`)
42
42
 
@@ -46,7 +46,7 @@ The reference library has one architecture file, 12 taste skills (Layer A — *h
46
46
 
47
47
  | File | Read when |
48
48
  |---|---|
49
- | `design-system-architecture.md` | The project has no `DESIGN.md` (defines the 7-section structure you must create first), or you are extracting a design system from existing UI code. |
49
+ | `design-system-architecture.md` | The project has no `DESIGN.md` (defines the structure you must create first — 8 sections plus a greenfield-only `## 0. Research Log`), or you are extracting a design system from existing UI code. |
50
50
 
51
51
  ### Layer A — taste skills (pick AT MOST ONE style skill; they encode opposing philosophies)
52
52
 
@@ -102,7 +102,7 @@ Domains: `product` `style` `typography` `color` `landing` `chart` `ux` `react` `
102
102
 
103
103
  ## Ruleset 4 — designpowers (`references/designpowers/`)
104
104
 
105
- `README.md` routes design operating-layer guidance from the pinned `Owl-Listener/designpowers` reference corpus into the existing frontend workflow. Load it when a frontend task needs explicit personas, accessibility and cognitive constraints, design critique, design debt, handoff, synthetic user testing, motion guidance, or role-reference prompts. It does not replace this frontend skill, `/visual-qa`, `/ulw-plan`, `/start-work`, or `/review-work`; it supplies richer design context that must first be distilled into the project `DESIGN.md`, then used as the design-system contract for implementation and verification.
105
+ `README.md` routes design operating-layer guidance from the pinned `Owl-Listener/designpowers` reference corpus into the existing frontend workflow. Load it — together with `lane-c-review.md` — for every implementation or redesign that creates or updates `DESIGN.md`, and additionally when a task needs explicit personas, accessibility and cognitive constraints, design critique, design debt, handoff, synthetic user testing, motion guidance, or role-reference prompts. It does not replace this frontend skill, `/visual-qa`, `/ulw-plan`, `/start-work`, or `/review-work`; it supplies richer design context that must first be distilled into the project `DESIGN.md`, then used as the design-system contract for implementation and verification.
106
106
 
107
107
  ## Quick routes — most common requests
108
108
 
@@ -38,12 +38,12 @@ Before touching any UI code, before routing to any reference, before even thinki
38
38
 
39
39
  1. Read `design-system-architecture.md` — it defines the exact structure.
40
40
  2. Identify the branch: greenfield setup, existing UI with implicit patterns/components, or existing UI with no reusable component layer.
41
- 3. **Greenfield setup:** if the user gave no concrete visual reference, use `_INDEX.md` to shortlist 2-3 plausible Layer B references, then deeply load exactly one Layer A style skill and one Layer B brand/design-system reference; use `open-design` only when the curated set has no fit. Treat those references as source material, not mood labels: extract tokens, layout grammar, component anatomy, interaction states, motion, and taste decisions into `DESIGN.md`, then recombine them into project-specific primitives. Customize for the user's product and content, but do not freestyle past the selected references; never copy logos, trademarked assets, or brand-specific copy.
41
+ 3. **Greenfield setup:** if the user gave no concrete visual reference, use `_INDEX.md` to shortlist 2-3 plausible Layer B references, then read exactly one Layer A style skill and one Layer B brand/design-system reference in full — every line, no partial reads; use `open-design` only when the curated set has no fit. Open `DESIGN.md` with a `## 0. Research Log` recording each research lane's deliverable (embedded-reference shortlist + pick, lazyweb screens viewed, imagen drafts — see the SKILL.md workflow); a lane with no line did not run. Treat those references as source material, not mood labels: extract tokens, layout grammar, component anatomy, interaction states, motion, and taste decisions into `DESIGN.md`, then recombine them into project-specific primitives. Customize for the user's product and content, but do not freestyle past the selected references; never copy logos, trademarked assets, or brand-specific copy.
42
42
  - **Commit a distinctive direction BEFORE extracting tokens.** In 1-2 sentences, name the atmosphere, the signature material, the color story, and the one moment a visitor will remember. For an expressive brief, sketch 2-3 genuinely different directions and pick the boldest one you can defend with the loaded reference; do not average them, because the average IS the generic default this skill exists to beat. A locked, never-revisited one-shot decision is how a page ends up flat.
43
43
  - **The reference's distinctive material MUST survive extraction (expressive briefs).** The common failure is loading a rich reference and then distilling it into a generic dark-SaaS token set. Your `DESIGN.md` must carry the *non-default* decisions forward and name which reference each came from: the actual elevation recipe (the specific layers that make a surface read as glass/glossy, not a single blur), a multi-stop perceptual color ramp (not one brand hex reused at varied opacity), the explicit display/body/mono type choices, and one signature interaction. Self-check before writing code: if your `DESIGN.md` could describe any generic dark SaaS, you flattened the reference — go back and put the specific material in.
44
44
  4. **Existing UI with implicit patterns/components:** extract the colors, typography, spacing, primitives, states, and motion already in use. Write `DESIGN.md` to codify what exists before changing UI code.
45
45
  5. **Existing UI with no reusable component layer:** STOP and ask whether to preserve the current style with copy-nearby edits or extract a `DESIGN.md` plus reusable components first. Do not silently choose the cheaper path or the larger refactor.
46
- 6. **Do not proceed to product screens until `DESIGN.md` exists, Section 5 names the reusable primitives and their states, and each primitive plus required state passes mobile/tablet/desktop visual QA in a component showcase or equivalent state harness.**
46
+ 6. Finish the triage at the Primitive Showcase Gate below.
47
47
 
48
48
  #### If YES design system exists → READ IT, FOLLOW IT
49
49
 
@@ -52,7 +52,11 @@ Before touching any UI code, before routing to any reference, before even thinki
52
52
  3. If you need a token that doesn't exist, **add it to `DESIGN.md` first**, then use it.
53
53
  4. Never introduce raw hex codes, arbitrary px values, or ad-hoc component patterns that bypass the system.
54
54
 
55
- **This gate is non-negotiable. No design system = no UI work. Period.**
55
+ **The Design System Gate is non-negotiable. No design system = no UI work. Period.**
56
+
57
+ ### Primitive Showcase Gate (MANDATORY)
58
+
59
+ **Do not proceed to product screens until `DESIGN.md` exists, Section 5 names the reusable primitives and their states, and each primitive plus required state passes mobile/tablet/desktop visual QA in a component showcase or equivalent state harness.** Skipping this gate ships ad-hoc-styled product screens and re-enters the redesign loop.
56
60
 
57
61
 
58
62
  ## Phase 0.5 — React Dev Tooling Gate (MANDATORY for React projects)
@@ -13,7 +13,7 @@ All reference files live flat in this directory. Three layers:
13
13
 
14
14
  | File | Purpose | Load when |
15
15
  |---|---|---|
16
- | `design-system-architecture.md` | Defines the 7-section `DESIGN.md` structure (atmosphere, color tokens, typography scale, spacing system, components, motion, depth). Creation workflow for new and existing projects. Validation rules and memory management. | Phase 0 fires and no `DESIGN.md` exists in the project. Also load when extracting a design system from existing code. |
16
+ | `design-system-architecture.md` | Defines the `DESIGN.md` structure — 8 sections plus a greenfield-only `## 0. Research Log` (atmosphere, color tokens, typography scale, spacing system, components, motion, depth, accessibility constraints & accepted debt). Creation workflow for new and existing projects. Validation rules and memory management. | Phase 0 fires and no `DESIGN.md` exists in the project. Also load when extracting a design system from existing code. |
17
17
 
18
18
  ---
19
19
 
@@ -16,11 +16,19 @@ Every frontend project MUST have a `DESIGN.md` at its root. This file is the sin
16
16
 
17
17
  ## DESIGN.md Structure
18
18
 
19
- The file has 7 sections. Every section is mandatory. Skip nothing.
19
+ The file has 8 sections plus a greenfield-only `## 0. Research Log`. Every section is mandatory. Skip nothing.
20
20
 
21
21
  ```markdown
22
22
  # [Project Name] Design System
23
23
 
24
+ ## 0. Research Log (greenfield only)
25
+
26
+ One line per research lane, written before the sections below — a lane with no line did not run:
27
+ - Embedded refs: shortlisted [2-3 Layer B candidates] → picked [Layer A] + [Layer B] because [reason]
28
+ - Lazyweb: [N] queries, [M] screens viewed → [layout grammar taken]
29
+ - Imagen drafts: [paths] → picked [draft] as the reference-fidelity contract
30
+ - Skipped lanes: [lane] — [tool/network reason]
31
+
24
32
  ## 1. Atmosphere & Identity
25
33
 
26
34
  One paragraph. What this product FEELS like. Not what it does — how it feels to use.
@@ -165,6 +173,19 @@ If borders:
165
173
 
166
174
  If tonal-shift:
167
175
  Surfaces use progressively lighter/darker shades. No borders, no shadows.
176
+
177
+ ## 8. Accessibility Constraints & Accepted Debt
178
+
179
+ ### Constraints
180
+ - WCAG target: [e.g. 2.2 AA] — contrast floor [4.5:1 body / 3:1 large text], visible focus on every
181
+ interactive element, full keyboard reachability, `prefers-reduced-motion` respected (Section 6).
182
+
183
+ ### Accepted Debt
184
+ | Item | Location | Why accepted | Owner / Exit |
185
+ |------|----------|--------------|--------------|
186
+ | [debt] | [file/screen] | [reason + user sign-off] | [when it gets fixed] |
187
+
188
+ New debt is recorded here at the moment it is accepted — never silently.
168
189
  ```
169
190
 
170
191
  ## Creation Workflow
@@ -173,7 +194,7 @@ Surfaces use progressively lighter/darker shades. No borders, no shadows.
173
194
 
174
195
  1. **Select references before taste** — no visual reference means `_INDEX.md` shortlist of 2-3 Layer B candidates, then exactly one Layer A style skill and one Layer B brand/design-system reference. Use `open-design` only when the curated set has no fit.
175
196
  2. **Assemble from references** — extract tokens, layout grammar, component anatomy, states, motion, and taste decisions, then recombine them into project-specific primitives. Customize for the user's product; never copy logos, trademarked assets, or brand-specific copy.
176
- 3. **Define the system** — atmosphere, palette, typography, spacing, and one depth strategy, grounded in the selected references and product semantics.
197
+ 3. **Define the system** — atmosphere, palette, typography, spacing, and one depth strategy, grounded in the selected references and product semantics. Sanity-check the palette and type pairing with one `ui-ux-db` domain search (CLI in `references/ui-ux-db/README.md`).
177
198
  4. **Document initial primitives** — only components you are about to build, including variants and states.
178
199
  5. **Write it to `DESIGN.md`** at project root.
179
200
  6. **Build a primitive showcase first** — exercise each primitive's default, hover, active, focus, disabled, loading, empty, and error states at mobile/tablet/desktop widths before composing product screens.
@@ -199,6 +220,7 @@ After every component implementation, check:
199
220
  - [ ] Component reused 2+ times? Documented in Section 5.
200
221
  - [ ] Motion follows the timing table. No arbitrary durations.
201
222
  - [ ] Component visual QA passed for each primitive and required state before product screens were composed.
223
+ - [ ] Section 8 accessibility constraints hold for the new component; any new debt is recorded in Section 8, not silently accepted.
202
224
 
203
225
  ## Memory Management
204
226
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  This is an internal frontend ruleset, not a standalone skill. `/frontend` remains the only public activation point for web UI, UX, visual design, accessibility, design QA, and frontend implementation routing.
4
4
 
5
- Load this reference from the frontend router when a task needs design operating-layer guidance: personas, cognitive accessibility, critique, design debt, handoff, synthetic user testing, motion guidance, or designpowers-style role references.
5
+ Load this reference from the frontend router for EVERY implementation or redesign that creates or updates `DESIGN.md`, and whenever a task needs design operating-layer guidance: personas, cognitive accessibility, critique, design debt, handoff, synthetic user testing, motion guidance, or designpowers-style role references.
6
6
 
7
7
  The purpose of this ruleset is to enrich the existing frontend workflow while preserving its gates:
8
8
 
@@ -18,7 +18,7 @@ Read these files before applying designpowers guidance:
18
18
  1. `README.md` - this frontend integration contract.
19
19
  2. `routing.md` - how designpowers context feeds existing frontend, planning, execution, visual QA, and review routes.
20
20
  3. `orchestration.md` - shared state, Direct/Auto prompt semantics, safeguards, and role-reference rules.
21
- 4. Phase lane docs, loaded only when relevant:
21
+ 4. Phase lane docs `lane-c-review.md` loads with this README for every implementation or redesign heading into Phase Final review (it is the flatness/critique reviewer); the other lanes load only when their phase applies:
22
22
  - `lane-a-direction.md` for planning, direction, discovery, personas, taste, and accessibility constraints.
23
23
  - `lane-b-execution.md` for execution, UI build prompts, frontend handoff, and implementation evidence.
24
24
  - `lane-c-review.md` for visual QA, design critique, review gates, and objective evidence before judgment.
@@ -44,7 +44,7 @@ Lane B worker DoneClaims must include:
44
44
 
45
45
  - Exact changed files and the `frontend` references loaded.
46
46
  - The real-surface QA invocation required by `start-work` for the UI surface, with captured artifact path.
47
- - Screenshot, browser, HTTP, or tmux artifacts appropriate to the visible surface.
47
+ - Screenshot, browser, HTTP, or xterm.js web-terminal artifacts appropriate to the visible surface.
48
48
  - Accessibility evidence from the existing OpenAgent frontend path, such as Lighthouse, react-doctor, keyboard checks, or other plan-required checks.
49
49
  - A short design trace: which persona, design principle, token, or state requirement each major UI decision satisfies.
50
50
  - Cleanup receipts for any browser session, server, tmux session, temporary artifact, or process used during QA.
@@ -16,7 +16,9 @@ This skill may include examples copied from the OpenCode harness. In Codex, do n
16
16
  | `background_output(task_id="...")` | `multi_agent_v1.wait_agent(...)` for mailbox signals |
17
17
  | `team_*(...)` | Use Codex native subagents via `multi_agent_v1.spawn_agent`, `multi_agent_v1.send_input`, `multi_agent_v1.wait_agent`, and `multi_agent_v1.close_agent` |
18
18
 
19
- Role-specific behavior must be described in a self-contained `message`. Use `fork_context: false` to start the child with only the initial prompt (no parent history); use `fork_context: true` only when full parent history is truly required. Include any required conversation context, files, diffs, constraints, and requested skill names directly in the spawned agent's `message`. OMO installs these selectable agent roles into `~/.codex/agents/`: `explorer`, `librarian`, `plan`, `momus`, `metis`, `lazycodex-code-reviewer`, `lazycodex-qa-executor`, and `lazycodex-gate-reviewer` — pass the matching name as `agent_type` so the child gets that role's model and instructions. On `multi_agent_v2` sessions the same `agent_type` applies (the OMO installer exposes it) with `fork_turns` instead of `fork_context`. If the spawn tool exposes no `agent_type` parameter, omit it and describe the role inside `message`. If a code block below conflicts with this section, this section wins.
19
+ Role-specific behavior must be described in a self-contained `message`. Use `fork_context: false` to start the child with only the initial prompt (no parent history); use `fork_context: true` only when full parent history is truly required. Include any required conversation context, files, diffs, constraints, and requested skill names directly in the spawned agent's `message`. OMO installs these selectable agent roles into `~/.codex/agents/`: `explorer`, `librarian`, `plan`, `momus`, `metis`, `lazycodex-code-reviewer`, `lazycodex-qa-executor`, and `lazycodex-gate-reviewer` — pass the matching name as `agent_type` so the child gets that role's model and instructions. If the spawn tool exposes no `agent_type` parameter, omit it and describe the role inside `message`. If a code block below conflicts with this section, this section wins.
20
+
21
+ Codex exposes ONE of two subagent tool surfaces per session; check your own tool list and route accordingly. If `multi_agent_v1.*` tools exist, use the table above as written. If instead a flat `spawn_agent` with a required `task_name` exists (`multi_agent_v2`), rewrite every `multi_agent_v1.*` example: `multi_agent_v1.spawn_agent({...,"fork_context":false})` becomes `spawn_agent({"task_name":"<lowercase_digits_underscores>","message":...,"agent_type":...,"fork_turns":"none"})` (`"all"` only when full parent history is truly required); `send_input` becomes `send_message`; do not call `close_agent`/`resume_agent` (finished agents end on their own; `followup_task` re-tasks one, `interrupt_agent` stops one); `wait_agent` takes only `timeout_ms` and returns on any child mailbox activity. `agent_type` works the same on both surfaces. If a code block below conflicts with this section, this section wins.
20
22
 
21
23
  For work likely to exceed one wait cycle, require the child to send `WORKING: <task> - <current phase>` before long passes and `BLOCKED: <reason>` only when progress stops. A `multi_agent_v1.wait_agent` timeout only means no new mailbox update arrived. Treat a running child as alive. Fallback only when the child is completed without the deliverable, ack-only after followup, explicitly `BLOCKED:`, or no longer running.
22
24
 
@@ -20,6 +20,8 @@ Translate any OpenCode-only tool name in an inherited example to its Codex equiv
20
20
 
21
21
  When translating `load_skills=[...]`, name the skills inside the spawned agent's `message`. If a code block below conflicts with this section, this section wins.
22
22
 
23
+ Codex exposes ONE of two subagent tool surfaces per session; check your own tool list and route accordingly. If `multi_agent_v1.*` tools exist, use the table above as written. If instead a flat `spawn_agent` with a required `task_name` exists (`multi_agent_v2`), rewrite every `multi_agent_v1.*` example: `multi_agent_v1.spawn_agent({...,"fork_context":false})` becomes `spawn_agent({"task_name":"<lowercase_digits_underscores>","message":...,"agent_type":...,"fork_turns":"none"})` (`"all"` only when full parent history is truly required); `send_input` becomes `send_message`; do not call `close_agent`/`resume_agent` (finished agents end on their own; `followup_task` re-tasks one, `interrupt_agent` stops one); `wait_agent` takes only `timeout_ms` and returns on any child mailbox activity. `agent_type` works the same on both surfaces. If a code block below conflicts with this section, this section wins.
24
+
23
25
  ## Codex Subagent Reliability
24
26
 
25
27
  Every `multi_agent_v1.spawn_agent` message is a self-contained executable assignment: `TASK: <imperative assignment>`, then `DELIVERABLE`, `SCOPE`, and `VERIFY`, with role instructions inside `message`. Use `fork_context: false` unless full history is truly required; paste only the context the child needs.
@@ -99,10 +101,10 @@ Each sub-task message must include:
99
101
  4. Automated verification commands to run.
100
102
  5. One Manual-QA channel, named with the exact tool and exact invocation (the literal `curl`, `send-keys`, `browser:control-in-app-browser` action, `page.click`, payload, selectors, and the binary observable that decides PASS/FAIL), not "verify it works". A LIGHT checkbox needs one real-surface proof of its deliverable, and auxiliary surfaces (CLI stdout, DB state diff, parsed config dump) are first-class when the surface is CLI- or data-shaped:
101
103
  - HTTP call: `curl -i` against the live endpoint.
102
- - tmux: a `tmux` session driven with `send-keys`, dumped via `capture-pane`.
104
+ - Terminal / TUI: drive a real pty; `tmux send-keys` is fine for a boot/behavior smoke, but color/layout/CJK evidence goes through the xterm.js web terminal below, NEVER `tmux capture-pane`.
103
105
  - Browser use: in Codex, use `browser:control-in-app-browser` first when available and the scenario does not need an authenticated or persistent user browser profile; otherwise drive the real page with Chrome, or agent-browser (https://github.com/vercel-labs/agent-browser) when Chrome is unavailable.
104
106
  - Computer use: OS-level GUI automation against the running desktop app when the surface is not a page.
105
- - TUI visual evidence: when a tmux/TUI claim needs visual QA or PR proof, run `node script/qa/web-terminal-visual-qa.mjs --from-file <capture.txt> --evidence-dir <dir>` and attach `terminal.png` plus `metadata.json`.
107
+ - TUI visual evidence: when a TUI claim needs visual QA or PR proof, run `node script/qa/web-terminal-visual-qa.mjs --command "<cmd>" --input "{Enter}" --evidence-dir <dir>` (real pty rendered through xterm.js in Chrome) and attach `terminal.png` plus `metadata.json`.
106
108
  6. The adversarial classes that apply to this sub-task (from the 9 ultraqa classes) and how each is probed.
107
109
  7. Required artifact path and cleanup receipt.
108
110
 
@@ -17,7 +17,9 @@ This skill may include examples copied from the OpenCode harness. In Codex, do n
17
17
  | `background_output(task_id="...")` | `multi_agent_v1.wait_agent(...)` for mailbox signals |
18
18
  | `team_*(...)` | Use Codex native subagents via `multi_agent_v1.spawn_agent`, `multi_agent_v1.send_input`, `multi_agent_v1.wait_agent`, and `multi_agent_v1.close_agent` |
19
19
 
20
- Role-specific behavior must be described in a self-contained `message`. Use `fork_context: false` to start the child with only the initial prompt (no parent history); use `fork_context: true` only when full parent history is truly required. Include any required conversation context, files, diffs, constraints, and requested skill names directly in the spawned agent's `message`. OMO installs these selectable agent roles into `~/.codex/agents/`: `explorer`, `librarian`, `plan`, `momus`, `metis`, `lazycodex-code-reviewer`, `lazycodex-qa-executor`, and `lazycodex-gate-reviewer` — pass the matching name as `agent_type` so the child gets that role's model and instructions. On `multi_agent_v2` sessions the same `agent_type` applies (the OMO installer exposes it) with `fork_turns` instead of `fork_context`. If the spawn tool exposes no `agent_type` parameter, omit it and describe the role inside `message`. If a code block below conflicts with this section, this section wins.
20
+ Role-specific behavior must be described in a self-contained `message`. Use `fork_context: false` to start the child with only the initial prompt (no parent history); use `fork_context: true` only when full parent history is truly required. Include any required conversation context, files, diffs, constraints, and requested skill names directly in the spawned agent's `message`. OMO installs these selectable agent roles into `~/.codex/agents/`: `explorer`, `librarian`, `plan`, `momus`, `metis`, `lazycodex-code-reviewer`, `lazycodex-qa-executor`, and `lazycodex-gate-reviewer` — pass the matching name as `agent_type` so the child gets that role's model and instructions. If the spawn tool exposes no `agent_type` parameter, omit it and describe the role inside `message`. If a code block below conflicts with this section, this section wins.
21
+
22
+ Codex exposes ONE of two subagent tool surfaces per session; check your own tool list and route accordingly. If `multi_agent_v1.*` tools exist, use the table above as written. If instead a flat `spawn_agent` with a required `task_name` exists (`multi_agent_v2`), rewrite every `multi_agent_v1.*` example: `multi_agent_v1.spawn_agent({...,"fork_context":false})` becomes `spawn_agent({"task_name":"<lowercase_digits_underscores>","message":...,"agent_type":...,"fork_turns":"none"})` (`"all"` only when full parent history is truly required); `send_input` becomes `send_message`; do not call `close_agent`/`resume_agent` (finished agents end on their own; `followup_task` re-tasks one, `interrupt_agent` stops one); `wait_agent` takes only `timeout_ms` and returns on any child mailbox activity. `agent_type` works the same on both surfaces. If a code block below conflicts with this section, this section wins.
21
23
 
22
24
  For work likely to exceed one wait cycle, require the child to send `WORKING: <task> - <current phase>` before long passes and `BLOCKED: <reason>` only when progress stops. A `multi_agent_v1.wait_agent` timeout only means no new mailbox update arrived. Treat a running child as alive. Fallback only when the child is completed without the deliverable, ack-only after followup, explicitly `BLOCKED:`, or no longer running.
23
25