oh-my-opencode 4.18.2 → 4.19.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 (164) hide show
  1. package/README.ja.md +2 -2
  2. package/README.ko.md +2 -2
  3. package/README.md +4 -4
  4. package/README.ru.md +2 -2
  5. package/README.zh-cn.md +2 -2
  6. package/dist/agents/atlas/agent.d.ts +6 -5
  7. package/dist/agents/sisyphus/index.d.ts +5 -0
  8. package/dist/agents/sisyphus/kimi-k3.d.ts +19 -0
  9. package/dist/agents/sisyphus-agent-factory.d.ts +1 -1
  10. package/dist/agents/sisyphus-junior/agent.d.ts +8 -4
  11. package/dist/agents/sisyphus-junior/index.d.ts +2 -0
  12. package/dist/agents/sisyphus-junior/kimi-k3.d.ts +12 -0
  13. package/dist/agents/types.d.ts +2 -2
  14. package/dist/cli/index.js +648 -136
  15. package/dist/cli-node/index.js +648 -136
  16. package/dist/config/index.d.ts +1 -1
  17. package/dist/config/schema/browser-automation.d.ts +1 -0
  18. package/dist/config/schema/commands.d.ts +1 -3
  19. package/dist/config/schema/default-mode.d.ts +1 -1
  20. package/dist/config/schema/goal.d.ts +7 -0
  21. package/dist/config/schema/hooks.d.ts +1 -1
  22. package/dist/config/schema/oh-my-opencode-config.d.ts +6 -10
  23. package/dist/config/schema/ralph-loop.d.ts +1 -1
  24. package/dist/config/schema.d.ts +1 -1
  25. package/dist/create-hooks.d.ts +1 -1
  26. package/dist/features/builtin-commands/templates/goal.d.ts +1 -0
  27. package/dist/features/builtin-commands/templates/stop-continuation.d.ts +1 -1
  28. package/dist/features/builtin-commands/types.d.ts +1 -1
  29. package/dist/hooks/auto-slash-command/executor.d.ts +1 -0
  30. package/dist/hooks/goal/command-arguments.d.ts +13 -0
  31. package/dist/hooks/goal/controller.d.ts +26 -0
  32. package/dist/hooks/goal/index.d.ts +23 -0
  33. package/dist/hooks/goal/prompt.d.ts +3 -0
  34. package/dist/hooks/goal/store.d.ts +8 -0
  35. package/dist/hooks/goal/tools.d.ts +10 -0
  36. package/dist/hooks/goal/types.d.ts +93 -0
  37. package/dist/hooks/goal/validation.d.ts +4 -0
  38. package/dist/hooks/index.d.ts +1 -0
  39. package/dist/hooks/keyword-detector/hook.d.ts +1 -2
  40. package/dist/hooks/ralph-loop/types.d.ts +1 -1
  41. package/dist/index.js +3515 -4365
  42. package/dist/oh-my-opencode.schema.json +23 -19
  43. package/dist/plugin/chat-message/loop-commands.d.ts +1 -1
  44. package/dist/plugin/chat-message/types.d.ts +23 -10
  45. package/dist/plugin/hooks/create-core-hooks.d.ts +1 -1
  46. package/dist/plugin/hooks/create-session-hooks.d.ts +3 -2
  47. package/dist/plugin/hooks/create-transform-hooks.d.ts +0 -2
  48. package/dist/plugin/stop-continuation.d.ts +2 -2
  49. package/dist/shared/system-directive.d.ts +0 -1
  50. package/dist/skills/ulw-plan/SKILL.md +11 -7
  51. package/dist/skills/ulw-plan/references/full-workflow.md +117 -6
  52. package/dist/skills/ulw-plan/scripts/scaffold-plan.mjs +46 -10
  53. package/dist/skills/ulw-research/SKILL.md +3 -3
  54. package/dist/tools/delegate-task/types.d.ts +0 -1
  55. package/dist/tui.js +73 -25
  56. package/package.json +14 -14
  57. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  58. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +352 -17
  59. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  60. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  61. package/packages/omo-codex/plugin/components/codegraph/AGENTS.md +7 -6
  62. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +97 -30
  63. package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
  64. package/packages/omo-codex/plugin/components/codegraph/test/hook-exclusion.test.ts +1 -1
  65. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  66. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  67. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  68. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  69. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  70. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  71. package/packages/omo-codex/plugin/components/lsp/AGENTS.md +1 -0
  72. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
  73. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  74. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  75. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  76. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  77. package/packages/omo-codex/plugin/components/start-work-continuation/AGENTS.md +8 -0
  78. package/packages/omo-codex/plugin/components/start-work-continuation/dist/cli.js +147 -60
  79. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  80. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  81. package/packages/omo-codex/plugin/components/start-work-continuation/src/boulder-reader.ts +3 -71
  82. package/packages/omo-codex/plugin/components/start-work-continuation/src/plan-checklist.ts +171 -0
  83. package/packages/omo-codex/plugin/components/start-work-continuation/test/boulder-reader.test.ts +198 -23
  84. package/packages/omo-codex/plugin/components/start-work-continuation/test/cli.test.ts +4 -3
  85. package/packages/omo-codex/plugin/components/start-work-continuation/test/codex-hook.test.ts +6 -5
  86. package/packages/omo-codex/plugin/components/start-work-continuation/test/fixtures/plan-scaffold.md +15 -0
  87. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  88. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  89. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  90. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  91. package/packages/omo-codex/plugin/components/ultrawork/AGENTS.md +10 -10
  92. package/packages/omo-codex/plugin/components/ultrawork/agents/momus.toml +3 -3
  93. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  94. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  95. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +11 -7
  96. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +117 -6
  97. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/scripts/scaffold-plan.mjs +46 -10
  98. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  99. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  100. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  101. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  102. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  103. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  104. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  105. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  106. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  107. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  108. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  109. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  110. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  111. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  112. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  113. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  114. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  115. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  116. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
  117. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  118. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
  119. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  120. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  121. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  122. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  123. package/packages/omo-codex/plugin/package-lock.json +13 -13
  124. package/packages/omo-codex/plugin/package.json +1 -1
  125. package/packages/omo-codex/plugin/scripts/migrate-codex-config/multi-agent-v2-guard.mjs +32 -28
  126. package/packages/omo-codex/plugin/scripts/migrate-codex-config/subagent-limit-guard.mjs +17 -45
  127. package/packages/omo-codex/plugin/scripts/migrate-codex-config/toml-section-editor.mjs +455 -0
  128. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +3 -18
  129. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +11 -7
  130. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +117 -6
  131. package/packages/omo-codex/plugin/skills/ulw-plan/scripts/scaffold-plan.mjs +46 -10
  132. package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +2 -2
  133. package/packages/omo-codex/plugin/test/lcx-bug-skills.test.mjs +2 -2
  134. package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +6 -6
  135. package/packages/omo-codex/plugin/test/multi-agent-v2-regression.test.mjs +3 -3
  136. package/packages/omo-codex/plugin/test/scaffold-plan.test.mjs +62 -0
  137. package/packages/omo-codex/plugin/test/subagent-limit-migration.test.mjs +271 -14
  138. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +3 -18
  139. package/packages/omo-codex/plugin/test/sync-skills.test.mjs +0 -5
  140. package/packages/omo-codex/plugin/test/ulw-plan-review-state-contract.test.mjs +293 -0
  141. package/packages/omo-codex/scripts/install-config.test.mjs +10 -10
  142. package/packages/omo-codex/scripts/install-dist/install-local.mjs +353 -18
  143. package/packages/omo-codex/scripts/install-generated-bundle.test.mjs +39 -2
  144. package/packages/shared-skills/skills/ulw-plan/SKILL.md +11 -7
  145. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +117 -6
  146. package/packages/shared-skills/skills/ulw-plan/scripts/scaffold-plan.mjs +46 -10
  147. package/packages/shared-skills/skills/ulw-research/SKILL.md +3 -3
  148. package/dist/features/builtin-commands/templates/ralph-loop.d.ts +0 -3
  149. package/dist/skills/ultraresearch/SKILL.md +0 -10
  150. package/packages/shared-skills/skills/lcx-contribute-bug-fix/SKILL.md +0 -273
  151. package/packages/shared-skills/skills/lcx-contribute-bug-fix/agents/openai.yaml +0 -12
  152. package/packages/shared-skills/skills/lcx-contribute-bug-fix/scripts/create-pr-body.mjs +0 -107
  153. package/packages/shared-skills/skills/lcx-doctor/SKILL.md +0 -128
  154. package/packages/shared-skills/skills/lcx-doctor/agents/openai.yaml +0 -11
  155. package/packages/shared-skills/skills/lcx-report-bug/SKILL.md +0 -268
  156. package/packages/shared-skills/skills/lcx-report-bug/agents/openai.yaml +0 -11
  157. package/packages/shared-skills/skills/ultraresearch/SKILL.md +0 -10
  158. /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-contribute-bug-fix/SKILL.md +0 -0
  159. /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-contribute-bug-fix/agents/openai.yaml +0 -0
  160. /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-contribute-bug-fix/scripts/create-pr-body.mjs +0 -0
  161. /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-doctor/SKILL.md +0 -0
  162. /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-doctor/agents/openai.yaml +0 -0
  163. /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-report-bug/SKILL.md +0 -0
  164. /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-report-bug/agents/openai.yaml +0 -0
@@ -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.18.2",
2149
+ version: "4.19.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",
@@ -2256,7 +2256,7 @@ var init_package = __esm(() => {
2256
2256
  "install:codex-dev": "bun run script/build-codex-install.ts && bun run script/install-codex-dev.ts",
2257
2257
  "build:codex-plugin": "npm --prefix packages/omo-codex/plugin ci && bun run --cwd packages/omo-codex/plugin build",
2258
2258
  "build:senpi-plugin": "bun run build:lsp-daemon && bun run build:senpi-plugin:stage",
2259
- "build:senpi-plugin:stage": "node packages/omo-senpi/plugin/scripts/stage-lsp-daemon-runtime.mjs && 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 && node packages/omo-senpi/plugin/scripts/build-install.mjs",
2259
+ "build:senpi-plugin:stage": "bun run build:materialize-frontend && node packages/omo-senpi/plugin/scripts/stage-lsp-daemon-runtime.mjs && 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 && node packages/omo-senpi/plugin/scripts/build-install.mjs",
2260
2260
  "build:materialize-frontend": "node packages/omo-codex/plugin/scripts/materialize-shared-upstreams.mjs --strict",
2261
2261
  "build:shared-skills-assets": "bun run build:materialize-frontend && rm -rf dist/skills && cp -R packages/shared-skills/skills dist/skills",
2262
2262
  "build:lsp-tools-mcp": "npm --prefix packages/lsp-tools-mcp ci && npm --prefix packages/lsp-tools-mcp run build",
@@ -2358,18 +2358,18 @@ var init_package = __esm(() => {
2358
2358
  typescript: "^6.0.3"
2359
2359
  },
2360
2360
  optionalDependencies: {
2361
- "oh-my-opencode-darwin-arm64": "4.18.2",
2362
- "oh-my-opencode-darwin-x64": "4.18.2",
2363
- "oh-my-opencode-darwin-x64-baseline": "4.18.2",
2364
- "oh-my-opencode-linux-arm64": "4.18.2",
2365
- "oh-my-opencode-linux-arm64-musl": "4.18.2",
2366
- "oh-my-opencode-linux-x64": "4.18.2",
2367
- "oh-my-opencode-linux-x64-baseline": "4.18.2",
2368
- "oh-my-opencode-linux-x64-musl": "4.18.2",
2369
- "oh-my-opencode-linux-x64-musl-baseline": "4.18.2",
2370
- "oh-my-opencode-windows-arm64": "4.18.2",
2371
- "oh-my-opencode-windows-x64": "4.18.2",
2372
- "oh-my-opencode-windows-x64-baseline": "4.18.2"
2361
+ "oh-my-opencode-darwin-arm64": "4.19.0",
2362
+ "oh-my-opencode-darwin-x64": "4.19.0",
2363
+ "oh-my-opencode-darwin-x64-baseline": "4.19.0",
2364
+ "oh-my-opencode-linux-arm64": "4.19.0",
2365
+ "oh-my-opencode-linux-arm64-musl": "4.19.0",
2366
+ "oh-my-opencode-linux-x64": "4.19.0",
2367
+ "oh-my-opencode-linux-x64-baseline": "4.19.0",
2368
+ "oh-my-opencode-linux-x64-musl": "4.19.0",
2369
+ "oh-my-opencode-linux-x64-musl-baseline": "4.19.0",
2370
+ "oh-my-opencode-windows-arm64": "4.19.0",
2371
+ "oh-my-opencode-windows-x64": "4.19.0",
2372
+ "oh-my-opencode-windows-x64-baseline": "4.19.0"
2373
2373
  },
2374
2374
  overrides: {
2375
2375
  "@earendil-works/pi-agent-core": "0.80.3",
@@ -9199,6 +9199,7 @@ var init_agent_model_requirements = __esm(() => {
9199
9199
  model: "claude-opus-4-7",
9200
9200
  variant: "max"
9201
9201
  },
9202
+ { providers: ["opencode-go", "kimi-for-coding", "moonshotai", "opencode", "vercel"], model: "kimi-k3" },
9202
9203
  { providers: ["opencode-go", "vercel"], model: "kimi-k2.6" },
9203
9204
  { providers: ["kimi-for-coding"], model: "k2p5" },
9204
9205
  {
@@ -9331,12 +9332,12 @@ var init_agent_model_requirements = __esm(() => {
9331
9332
  fallbackChain: [
9332
9333
  {
9333
9334
  providers: ["openai", "vercel"],
9334
- model: "gpt-5.6-sol",
9335
- variant: "xhigh"
9335
+ model: "gpt-5.6-terra",
9336
+ variant: "high"
9336
9337
  },
9337
9338
  {
9338
9339
  providers: ["github-copilot"],
9339
- model: "gpt-5.6-sol",
9340
+ model: "gpt-5.6-terra",
9340
9341
  variant: "high"
9341
9342
  },
9342
9343
  {
@@ -10099,6 +10100,21 @@ var init_runtime_fallback_model = () => {};
10099
10100
  var SUPPLEMENTAL_MODEL_CAPABILITIES;
10100
10101
  var init_supplemental_entries = __esm(() => {
10101
10102
  SUPPLEMENTAL_MODEL_CAPABILITIES = {
10103
+ "kimi-k3": {
10104
+ id: "kimi-k3",
10105
+ family: "kimi",
10106
+ reasoning: true,
10107
+ temperature: true,
10108
+ toolCall: true,
10109
+ modalities: {
10110
+ input: ["text", "image", "video"],
10111
+ output: ["text"]
10112
+ },
10113
+ limit: {
10114
+ context: 262144,
10115
+ output: 262144
10116
+ }
10117
+ },
10102
10118
  "kimi-k2.6": {
10103
10119
  id: "kimi-k2.6",
10104
10120
  family: "kimi",
@@ -72697,7 +72713,7 @@ var package_default2;
72697
72713
  var init_package2 = __esm(() => {
72698
72714
  package_default2 = {
72699
72715
  name: "@oh-my-opencode/omo-codex",
72700
- version: "4.18.2",
72716
+ version: "4.19.0",
72701
72717
  type: "module",
72702
72718
  private: true,
72703
72719
  description: "Codex harness adapter for oh-my-openagent. Vendored Codex plugin namespace (omo) + TypeScript installer + telemetry.",
@@ -75739,9 +75755,16 @@ function findTomlSection(config, header) {
75739
75755
  const lines = config.match(/[^\n]*\n?|$/g) ?? [];
75740
75756
  let offset = 0;
75741
75757
  let start = -1;
75758
+ let multilineQuote = null;
75742
75759
  for (const line of lines) {
75743
75760
  if (line.length === 0)
75744
75761
  break;
75762
+ const multilineScan = scanTomlMultilineLine(line, multilineQuote);
75763
+ multilineQuote = multilineScan.nextQuote;
75764
+ if (multilineScan.wasInside) {
75765
+ offset += line.length;
75766
+ continue;
75767
+ }
75745
75768
  const trimmed = line.trim();
75746
75769
  if (start === -1) {
75747
75770
  if (tomlTableHeaderMatches(trimmed, headerLine, targetHeaderPath))
@@ -75756,8 +75779,37 @@ function findTomlSection(config, header) {
75756
75779
  return { start, end: config.length, text: config.slice(start) };
75757
75780
  }
75758
75781
  function replaceOrInsertSetting(config, section, key, value) {
75759
- const linePattern = new RegExp(`^[ \\t]*${escapeRegExp(key)}[ \\t]*=.*$`, "m");
75760
- const replacement = linePattern.test(section.text) ? section.text.replace(linePattern, `${key} = ${value}`) : insertSetting(section.text, key, value);
75782
+ const targetPath = parseTomlDottedKey(key);
75783
+ if (!targetPath)
75784
+ return config;
75785
+ const lines = section.text.match(/[^\n]*\n?|$/g) ?? [];
75786
+ let offset = 0;
75787
+ let multilineQuote = null;
75788
+ for (const line of lines) {
75789
+ if (line.length === 0)
75790
+ break;
75791
+ const multilineScan = scanTomlMultilineLine(line, multilineQuote);
75792
+ multilineQuote = multilineScan.nextQuote;
75793
+ if (multilineScan.wasInside) {
75794
+ offset += line.length;
75795
+ continue;
75796
+ }
75797
+ const assignmentIndex = findUnquotedAssignment(line);
75798
+ if (assignmentIndex < 0) {
75799
+ offset += line.length;
75800
+ continue;
75801
+ }
75802
+ const settingPath = parseTomlDottedKey(line.slice(0, assignmentIndex).trim());
75803
+ if (!settingPath || !tomlPathMatches(settingPath, targetPath)) {
75804
+ offset += line.length;
75805
+ continue;
75806
+ }
75807
+ const replacement2 = replaceTomlAssignmentValue(line, assignmentIndex, value);
75808
+ const assignmentEnd = multilineScan.nextQuote ? findTomlMultilineValueEnd(section.text, offset + line.length, multilineScan.nextQuote) : offset + line.length;
75809
+ const sectionReplacement = section.text.slice(0, offset) + replacement2 + section.text.slice(assignmentEnd);
75810
+ return config.slice(0, section.start) + sectionReplacement + config.slice(section.end);
75811
+ }
75812
+ const replacement = insertSetting(section.text, key, value);
75761
75813
  return config.slice(0, section.start) + replacement + config.slice(section.end);
75762
75814
  }
75763
75815
  function removeSetting(config, section, key) {
@@ -75777,6 +75829,50 @@ function replaceOrInsertRootSetting(config, key, value) {
75777
75829
  return replacement;
75778
75830
  return `${replacement.trimEnd()}
75779
75831
 
75832
+ ${suffix.trimStart()}`;
75833
+ }
75834
+ function replaceOrInsertRootDottedSetting(config, keyPath, value) {
75835
+ const targetPath = parseTomlDottedKey(keyPath);
75836
+ if (!targetPath)
75837
+ return config;
75838
+ const lines = config.match(/[^\n]*\n?|$/g) ?? [];
75839
+ let offset = 0;
75840
+ let multilineQuote = null;
75841
+ for (const line of lines) {
75842
+ if (line.length === 0)
75843
+ break;
75844
+ const multilineScan = scanTomlMultilineLine(line, multilineQuote);
75845
+ multilineQuote = multilineScan.nextQuote;
75846
+ if (multilineScan.wasInside) {
75847
+ offset += line.length;
75848
+ continue;
75849
+ }
75850
+ if (isTomlTableHeaderLine(line))
75851
+ break;
75852
+ const assignmentIndex = findUnquotedAssignment(line);
75853
+ if (assignmentIndex < 0) {
75854
+ offset += line.length;
75855
+ continue;
75856
+ }
75857
+ const settingPath = parseTomlDottedKey(line.slice(0, assignmentIndex).trim());
75858
+ if (!settingPath || !tomlPathMatches(settingPath, targetPath)) {
75859
+ offset += line.length;
75860
+ continue;
75861
+ }
75862
+ const replacement2 = replaceTomlAssignmentValue(line, assignmentIndex, value);
75863
+ const assignmentEnd = multilineScan.nextQuote ? findTomlMultilineValueEnd(config, offset + line.length, multilineScan.nextQuote) : offset + line.length;
75864
+ return config.slice(0, offset) + replacement2 + config.slice(assignmentEnd);
75865
+ }
75866
+ const sectionStart = findFirstTableStart(config);
75867
+ const root = config.slice(0, sectionStart).trimEnd();
75868
+ const suffix = config.slice(sectionStart);
75869
+ const replacement = `${root}${root.length > 0 ? `
75870
+ ` : ""}${keyPath} = ${value}
75871
+ `;
75872
+ if (suffix.length === 0)
75873
+ return replacement;
75874
+ return `${replacement.trimEnd()}
75875
+
75780
75876
  ${suffix.trimStart()}`;
75781
75877
  }
75782
75878
  function appendBlock(config, block) {
@@ -75789,9 +75885,16 @@ function appendBlock(config, block) {
75789
75885
  function findFirstTableStart(config) {
75790
75886
  const lines = config.match(/[^\n]*\n?|$/g) ?? [];
75791
75887
  let offset = 0;
75888
+ let multilineQuote = null;
75792
75889
  for (const line of lines) {
75793
75890
  if (line.length === 0)
75794
75891
  break;
75892
+ const multilineScan = scanTomlMultilineLine(line, multilineQuote);
75893
+ multilineQuote = multilineScan.nextQuote;
75894
+ if (multilineScan.wasInside) {
75895
+ offset += line.length;
75896
+ continue;
75897
+ }
75795
75898
  if (isTomlTableHeaderLine(line))
75796
75899
  return offset;
75797
75900
  offset += line.length;
@@ -75829,6 +75932,131 @@ function isTomlTableHeaderLine(line) {
75829
75932
  const normalizedLine = stripUnquotedInlineComment(line).trim();
75830
75933
  return normalizedLine.startsWith("[") && normalizedLine.endsWith("]");
75831
75934
  }
75935
+ function scanTomlMultilineLine(line, currentQuote) {
75936
+ if (currentQuote) {
75937
+ return {
75938
+ wasInside: true,
75939
+ nextQuote: findTomlMultilineDelimiter(line, currentQuote, 0) === -1 ? currentQuote : null
75940
+ };
75941
+ }
75942
+ let quote = null;
75943
+ let index = 0;
75944
+ while (index < line.length) {
75945
+ const char = line[index];
75946
+ if (quote === '"') {
75947
+ if (char === "\\") {
75948
+ index += 2;
75949
+ continue;
75950
+ }
75951
+ if (char === '"')
75952
+ quote = null;
75953
+ index += 1;
75954
+ continue;
75955
+ }
75956
+ if (quote === "'") {
75957
+ if (char === "'")
75958
+ quote = null;
75959
+ index += 1;
75960
+ continue;
75961
+ }
75962
+ if (char === "#")
75963
+ break;
75964
+ const delimiter2 = line.startsWith('"""', index) ? '"""' : line.startsWith("'''", index) ? "'''" : null;
75965
+ if (delimiter2) {
75966
+ const closingIndex = findTomlMultilineDelimiter(line, delimiter2, index + delimiter2.length);
75967
+ return { wasInside: false, nextQuote: closingIndex === -1 ? delimiter2 : null };
75968
+ }
75969
+ if (char === '"' || char === "'")
75970
+ quote = char;
75971
+ index += 1;
75972
+ }
75973
+ return { wasInside: false, nextQuote: null };
75974
+ }
75975
+ function findTomlMultilineDelimiter(line, delimiter2, startIndex) {
75976
+ let index = line.indexOf(delimiter2, startIndex);
75977
+ while (index !== -1) {
75978
+ if (delimiter2 === "'''" || countPrecedingBackslashes(line, index) % 2 === 0)
75979
+ return index;
75980
+ index = line.indexOf(delimiter2, index + 1);
75981
+ }
75982
+ return -1;
75983
+ }
75984
+ function countPrecedingBackslashes(line, index) {
75985
+ let count = 0;
75986
+ let cursor = index - 1;
75987
+ while (cursor >= 0 && line[cursor] === "\\") {
75988
+ count += 1;
75989
+ cursor -= 1;
75990
+ }
75991
+ return count;
75992
+ }
75993
+ function findUnquotedAssignment(line) {
75994
+ return findUnquotedCharacter(line, "=", 0);
75995
+ }
75996
+ function findUnquotedComment(line, startIndex) {
75997
+ return findUnquotedCharacter(line, "#", startIndex);
75998
+ }
75999
+ function findUnquotedCharacter(line, target, startIndex) {
76000
+ let quote = null;
76001
+ let index = startIndex;
76002
+ while (index < line.length) {
76003
+ const char = line[index];
76004
+ if (quote === '"') {
76005
+ if (char === "\\") {
76006
+ index += 2;
76007
+ continue;
76008
+ }
76009
+ if (char === '"')
76010
+ quote = null;
76011
+ index += 1;
76012
+ continue;
76013
+ }
76014
+ if (quote === "'") {
76015
+ if (char === "'")
76016
+ quote = null;
76017
+ index += 1;
76018
+ continue;
76019
+ }
76020
+ if (char === '"' || char === "'") {
76021
+ quote = char;
76022
+ index += 1;
76023
+ continue;
76024
+ }
76025
+ if (char === target)
76026
+ return index;
76027
+ if (char === "#")
76028
+ return -1;
76029
+ index += 1;
76030
+ }
76031
+ return -1;
76032
+ }
76033
+ function tomlPathMatches(candidate, target) {
76034
+ return candidate.length === target.length && candidate.every((part, index) => part === target[index]);
76035
+ }
76036
+ function replaceTomlAssignmentValue(line, assignmentIndex, value) {
76037
+ const newline = line.endsWith(`
76038
+ `) ? `
76039
+ ` : "";
76040
+ const lineBody = newline ? line.slice(0, -1) : line;
76041
+ const commentIndex = findUnquotedComment(lineBody, assignmentIndex + 1);
76042
+ const comment = commentIndex === -1 ? "" : ` ${lineBody.slice(commentIndex).trimStart()}`;
76043
+ return `${lineBody.slice(0, assignmentIndex + 1)} ${value}${comment}${newline}`;
76044
+ }
76045
+ function findTomlMultilineValueEnd(text, startOffset, quote) {
76046
+ const lines = text.slice(startOffset).match(/[^\n]*\n?|$/g) ?? [];
76047
+ let offset = startOffset;
76048
+ let currentQuote = quote;
76049
+ for (const line of lines) {
76050
+ if (line.length === 0)
76051
+ break;
76052
+ const scan = scanTomlMultilineLine(line, currentQuote);
76053
+ currentQuote = scan.nextQuote;
76054
+ offset += line.length;
76055
+ if (currentQuote === null)
76056
+ return offset;
76057
+ }
76058
+ return text.length;
76059
+ }
75832
76060
  function stripUnquotedInlineComment(line) {
75833
76061
  let quote = null;
75834
76062
  let index = 0;
@@ -76159,13 +76387,137 @@ function delay(milliseconds) {
76159
76387
  return new Promise((resolveDelay) => setTimeout(resolveDelay, milliseconds));
76160
76388
  }
76161
76389
 
76390
+ // packages/omo-codex/src/install/toml-setting-reader.ts
76391
+ function hasTomlSetting(config, keyPath) {
76392
+ const targetPath = parseTomlDottedKey(keyPath);
76393
+ if (!targetPath)
76394
+ return false;
76395
+ return hasTomlAssignment(config, (tablePath, settingPath) => {
76396
+ const fullPath = [...tablePath, ...settingPath];
76397
+ return fullPath.length === targetPath.length && fullPath.every((part, index) => part === targetPath[index]);
76398
+ });
76399
+ }
76400
+ function hasTomlRootDottedKeyPrefix(config, rootKey) {
76401
+ return hasTomlAssignment(config, (tablePath, settingPath) => tablePath.length === 0 && settingPath.length > 1 && settingPath[0] === rootKey);
76402
+ }
76403
+ function hasTomlAssignment(config, predicate) {
76404
+ let tablePath = [];
76405
+ let multilineQuote = null;
76406
+ for (const line of config.split(`
76407
+ `)) {
76408
+ const multilineScan = scanTomlMultilineLine(line, multilineQuote);
76409
+ multilineQuote = multilineScan.nextQuote;
76410
+ if (multilineScan.wasInside)
76411
+ continue;
76412
+ const normalizedLine = stripUnquotedInlineComment2(line).trim();
76413
+ if (normalizedLine.length === 0)
76414
+ continue;
76415
+ const headerPath = parseTomlTableHeader2(normalizedLine);
76416
+ if (headerPath) {
76417
+ tablePath = headerPath;
76418
+ continue;
76419
+ }
76420
+ if (isTomlTableHeaderLine2(normalizedLine)) {
76421
+ tablePath = null;
76422
+ continue;
76423
+ }
76424
+ if (!tablePath)
76425
+ continue;
76426
+ const assignmentIndex = findUnquotedAssignment2(normalizedLine);
76427
+ if (assignmentIndex < 0)
76428
+ continue;
76429
+ const settingPath = parseTomlDottedKey(normalizedLine.slice(0, assignmentIndex).trim());
76430
+ if (!settingPath)
76431
+ continue;
76432
+ if (predicate(tablePath, settingPath))
76433
+ return true;
76434
+ }
76435
+ return false;
76436
+ }
76437
+ function parseTomlTableHeader2(line) {
76438
+ if (!line.startsWith("[") || !line.endsWith("]") || line.startsWith("[["))
76439
+ return null;
76440
+ return parseTomlDottedKey(line.slice(1, -1).trim());
76441
+ }
76442
+ function isTomlTableHeaderLine2(line) {
76443
+ return line.startsWith("[") && line.endsWith("]");
76444
+ }
76445
+ function stripUnquotedInlineComment2(line) {
76446
+ let quote = null;
76447
+ let index = 0;
76448
+ while (index < line.length) {
76449
+ const char = line[index];
76450
+ if (quote === '"') {
76451
+ if (char === "\\") {
76452
+ index += 2;
76453
+ continue;
76454
+ }
76455
+ if (char === '"')
76456
+ quote = null;
76457
+ index += 1;
76458
+ continue;
76459
+ }
76460
+ if (quote === "'") {
76461
+ if (char === "'")
76462
+ quote = null;
76463
+ index += 1;
76464
+ continue;
76465
+ }
76466
+ if (char === '"' || char === "'") {
76467
+ quote = char;
76468
+ index += 1;
76469
+ continue;
76470
+ }
76471
+ if (char === "#")
76472
+ return line.slice(0, index);
76473
+ index += 1;
76474
+ }
76475
+ return line;
76476
+ }
76477
+ function findUnquotedAssignment2(line) {
76478
+ let quote = null;
76479
+ let index = 0;
76480
+ while (index < line.length) {
76481
+ const char = line[index];
76482
+ if (quote === '"') {
76483
+ if (char === "\\") {
76484
+ index += 2;
76485
+ continue;
76486
+ }
76487
+ if (char === '"')
76488
+ quote = null;
76489
+ index += 1;
76490
+ continue;
76491
+ }
76492
+ if (quote === "'") {
76493
+ if (char === "'")
76494
+ quote = null;
76495
+ index += 1;
76496
+ continue;
76497
+ }
76498
+ if (char === '"' || char === "'") {
76499
+ quote = char;
76500
+ index += 1;
76501
+ continue;
76502
+ }
76503
+ if (char === "=")
76504
+ return index;
76505
+ index += 1;
76506
+ }
76507
+ return -1;
76508
+ }
76509
+
76162
76510
  // packages/omo-codex/src/install/codex-config-features.ts
76163
76511
  function ensureFeatureEnabled(config, featureName) {
76164
76512
  const section = findTomlSection(config, "features");
76165
- if (!section)
76513
+ if (!section) {
76514
+ if (hasTomlRootDottedKeyPrefix(config, "features")) {
76515
+ return replaceOrInsertRootDottedSetting(config, `features.${featureName}`, "true");
76516
+ }
76166
76517
  return appendBlock(config, `[features]
76167
76518
  ${featureName} = true
76168
76519
  `);
76520
+ }
76169
76521
  return replaceOrInsertSetting(config, section, featureName, "true");
76170
76522
  }
76171
76523
 
@@ -76233,7 +76585,7 @@ function ensureAutonomousPermissions(config) {
76233
76585
  next = replaceOrInsertRootSetting(next, "sandbox_mode", JSON.stringify("danger-full-access"));
76234
76586
  next = replaceOrInsertRootSetting(next, "network_access", JSON.stringify("enabled"));
76235
76587
  for (const featureName of AUTONOMOUS_FEATURES) {
76236
- next = ensureFeatureEnabled2(next, featureName);
76588
+ next = ensureFeatureEnabled(next, featureName);
76237
76589
  }
76238
76590
  next = removeWindowsSandboxSetting(next);
76239
76591
  next = ensureNoticeEnabled(next, "hide_full_access_warning");
@@ -76251,14 +76603,6 @@ function ensureNoticeEnabled(config, key) {
76251
76603
  return appendNoticeBlock(config, key);
76252
76604
  return replaceOrInsertSetting(config, section, key, "true");
76253
76605
  }
76254
- function ensureFeatureEnabled2(config, key) {
76255
- const section = findTomlSection(config, "features");
76256
- if (section === null)
76257
- return appendBlock(config, `[features]
76258
- ${key} = true
76259
- `);
76260
- return replaceOrInsertSetting(config, section, key, "true");
76261
- }
76262
76606
  function appendNoticeBlock(config, key) {
76263
76607
  return appendBlock(config, `[notice]
76264
76608
  ${key} = true
@@ -76330,7 +76674,7 @@ function readStringArraySetting(sectionText, key) {
76330
76674
  const assignmentIndex = line.indexOf("=");
76331
76675
  if (assignmentIndex === -1)
76332
76676
  return null;
76333
- return parseTomlStringArray(stripUnquotedInlineComment2(line.slice(assignmentIndex + 1)).trim());
76677
+ return parseTomlStringArray(stripUnquotedInlineComment3(line.slice(assignmentIndex + 1)).trim());
76334
76678
  }
76335
76679
  return null;
76336
76680
  }
@@ -76374,7 +76718,7 @@ function parseTomlString(input, startIndex) {
76374
76718
  }
76375
76719
  return null;
76376
76720
  }
76377
- function stripUnquotedInlineComment2(line) {
76721
+ function stripUnquotedInlineComment3(line) {
76378
76722
  let quote = null;
76379
76723
  let index = 0;
76380
76724
  while (index < line.length) {
@@ -76588,24 +76932,27 @@ import { readFileSync as readFileSync13 } from "node:fs";
76588
76932
  import { dirname as dirname15, isAbsolute as isAbsolute8, join as join39 } from "node:path";
76589
76933
  var CODEX_AGENTS_HEADER = "agents";
76590
76934
  var CODEX_MULTI_AGENT_V2_HEADER = "features.multi_agent_v2";
76935
+ var CODEX_MULTI_AGENT_V2_THREAD_LIMIT_KEY = `${CODEX_MULTI_AGENT_V2_HEADER}.max_concurrent_threads_per_session`;
76591
76936
  var CODEX_SUBAGENT_THREAD_LIMIT = 1000;
76937
+ var CODEX_MULTI_AGENT_V2_THREAD_LIMIT = 16;
76592
76938
  function ensureCodexMultiAgentV2Config(config, options = {}) {
76593
76939
  const featureFlag = removeFeatureFlagSetting(config, "multi_agent_v2");
76594
76940
  const v2Preferred = options.multiAgentVersion === "v2";
76595
76941
  const modelKnown = options.multiAgentVersion != null || readRootModel(featureFlag.config) !== null;
76596
76942
  const agentsConfig = v2Preferred ? removeAgentsMaxThreads(featureFlag.config) : modelKnown ? ensureAgentsMaxThreads(featureFlag.config) : raiseExistingAgentsMaxThreads(featureFlag.config);
76597
- const maxThreadsValue = CODEX_SUBAGENT_THREAD_LIMIT.toString();
76598
76943
  const preserveDisable = featureFlag.value === false && !v2Preferred;
76599
76944
  const featureConfig = preserveDisable ? setMultiAgentV2Disable(agentsConfig) : v2Preferred ? removeMultiAgentV2Disable(agentsConfig) : agentsConfig;
76945
+ if (hasTomlSetting(featureConfig, CODEX_MULTI_AGENT_V2_THREAD_LIMIT_KEY))
76946
+ return featureConfig;
76600
76947
  const section = findTomlSection(featureConfig, CODEX_MULTI_AGENT_V2_HEADER);
76601
76948
  if (!section) {
76602
76949
  const enabledSetting = preserveDisable ? `enabled = false
76603
76950
  ` : "";
76604
76951
  return appendBlock(featureConfig, `[${CODEX_MULTI_AGENT_V2_HEADER}]
76605
- ${enabledSetting}max_concurrent_threads_per_session = ${maxThreadsValue}
76952
+ ${enabledSetting}max_concurrent_threads_per_session = ${CODEX_MULTI_AGENT_V2_THREAD_LIMIT}
76606
76953
  `);
76607
76954
  }
76608
- return replaceOrInsertSetting(featureConfig, section, "max_concurrent_threads_per_session", maxThreadsValue);
76955
+ return replaceOrInsertSetting(featureConfig, section, "max_concurrent_threads_per_session", CODEX_MULTI_AGENT_V2_THREAD_LIMIT.toString());
76609
76956
  }
76610
76957
  function resolveCodexMultiAgentVersion(config, configPath) {
76611
76958
  const model = readRootModel(config);
@@ -76964,6 +77311,10 @@ var MANAGED_REASONING_DEFAULT_UPGRADES = new Map([
76964
77311
  {
76965
77312
  previous: { model: "gpt-5.5", effort: "xhigh" },
76966
77313
  current: { model: "gpt-5.6-sol", effort: "ultra" }
77314
+ },
77315
+ {
77316
+ previous: { model: "gpt-5.6-sol", effort: "ultra" },
77317
+ current: { model: "gpt-5.6-terra", effort: "high" }
76967
77318
  }
76968
77319
  ]
76969
77320
  ],
@@ -79026,8 +79377,24 @@ import { promisify as promisify2 } from "node:util";
79026
79377
  var execFileAsync2 = promisify2(execFile4);
79027
79378
  var REQUIRED_PLUGIN_ARTIFACTS = [
79028
79379
  join58("extensions", "omo.js"),
79380
+ join58("skills", "ast-grep", "SKILL.md"),
79381
+ join58("skills", "coding-agent-sessions", "SKILL.md"),
79382
+ join58("skills", "debugging", "SKILL.md"),
79383
+ join58("skills", "frontend", "SKILL.md"),
79384
+ join58("skills", "git-master", "SKILL.md"),
79385
+ join58("skills", "init-deep", "SKILL.md"),
79386
+ join58("skills", "lsp-setup", "SKILL.md"),
79387
+ join58("skills", "programming", "SKILL.md"),
79388
+ join58("skills", "refactor", "SKILL.md"),
79389
+ join58("skills", "remove-ai-slops", "SKILL.md"),
79390
+ join58("skills", "review-work", "SKILL.md"),
79391
+ join58("skills", "start-work", "SKILL.md"),
79392
+ join58("skills", "ultimate-browsing", "SKILL.md"),
79029
79393
  join58("skills", "ultrawork", "SKILL.md"),
79030
79394
  join58("skills", "ulw-loop", "SKILL.md"),
79395
+ join58("skills", "ulw-plan", "SKILL.md"),
79396
+ join58("skills", "ulw-research", "SKILL.md"),
79397
+ join58("skills", "visual-qa", "SKILL.md"),
79031
79398
  join58("runtime", "lsp-daemon", "dist", "cli.js"),
79032
79399
  join58("runtime", "lsp-daemon", "dist", "index.js"),
79033
79400
  join58("runtime", "lsp-daemon", "dist", "index.d.ts"),
@@ -79081,6 +79448,7 @@ async function ensurePluginArtifacts(context) {
79081
79448
  throw new Error(`Packed omo-senpi plugin is missing required runtime artifacts at ${context.pluginPath}`);
79082
79449
  }
79083
79450
  await context.runCommand("node", [join58(context.pluginPath, "scripts", "build-extension.mjs")], { cwd: context.repoRoot });
79451
+ await context.runCommand("node", [join58("packages", "omo-codex", "plugin", "scripts", "materialize-shared-upstreams.mjs")], { cwd: context.repoRoot });
79084
79452
  await context.runCommand("node", [join58(context.pluginPath, "scripts", "sync-skills.mjs")], { cwd: context.repoRoot });
79085
79453
  await context.runCommand("node", [join58(context.pluginPath, "scripts", "build-install.mjs")], { cwd: context.repoRoot });
79086
79454
  await context.runCommand("node", [join58(context.pluginPath, "scripts", "stage-lsp-daemon-runtime.mjs")], { cwd: context.repoRoot });
@@ -96710,7 +97078,8 @@ var BrowserAutomationProviderSchema = exports_external.enum([
96710
97078
  "playwright-cli"
96711
97079
  ]);
96712
97080
  var BrowserAutomationConfigSchema = exports_external.object({
96713
- provider: BrowserAutomationProviderSchema.default("playwright")
97081
+ provider: BrowserAutomationProviderSchema.default("playwright"),
97082
+ playwright_mcp_args: exports_external.array(exports_external.string()).optional()
96714
97083
  });
96715
97084
  // packages/omo-opencode/src/config/schema/categories.ts
96716
97085
  var CategoryConfigSchema = exports_external.object({
@@ -96772,9 +97141,7 @@ var CommentCheckerConfigSchema = exports_external.object({
96772
97141
  });
96773
97142
  // packages/omo-opencode/src/config/schema/commands.ts
96774
97143
  var BuiltinCommandNameSchema = exports_external.enum([
96775
- "ralph-loop",
96776
- "ulw-loop",
96777
- "cancel-ralph",
97144
+ "goal",
96778
97145
  "refactor",
96779
97146
  "start-work",
96780
97147
  "stop-continuation",
@@ -96784,7 +97151,7 @@ var BuiltinCommandNameSchema = exports_external.enum([
96784
97151
  // packages/omo-opencode/src/config/schema/default-mode.ts
96785
97152
  var DefaultModeConfigSchema = exports_external.object({
96786
97153
  ultrawork: exports_external.boolean().default(false),
96787
- ralph_loop: exports_external.boolean().default(false)
97154
+ goal: exports_external.boolean().default(false)
96788
97155
  });
96789
97156
  // packages/omo-opencode/src/config/schema/dynamic-context-pruning.ts
96790
97157
  var DynamicContextPruningConfigSchema = exports_external.object({
@@ -96832,6 +97199,12 @@ var ExperimentalConfigSchema = exports_external.object({
96832
97199
  max_tools: exports_external.number().int().min(1).optional(),
96833
97200
  disable_live_parent_wake_routing: exports_external.boolean().optional()
96834
97201
  });
97202
+ // packages/omo-opencode/src/config/schema/goal.ts
97203
+ var GoalConfigSchema = exports_external.object({
97204
+ enabled: exports_external.boolean().default(false),
97205
+ auto_start: exports_external.boolean().default(false),
97206
+ default_max_iterations: exports_external.number().min(1).max(1000).default(100)
97207
+ });
96835
97208
  // packages/skills-loader-core/src/config/git-env-prefix.ts
96836
97209
  var GIT_ENV_ASSIGNMENT_PATTERN = /^(?:[A-Za-z_][A-Za-z0-9_]*=[A-Za-z0-9_-]*)(?: [A-Za-z_][A-Za-z0-9_]*=[A-Za-z0-9_-]*)*$/;
96837
97210
  var GIT_ENV_PREFIX_VALIDATION_MESSAGE = 'git_env_prefix must be empty or use shell-safe env assignments like "GIT_MASTER=1"';
@@ -96874,7 +97247,7 @@ var HookNameSchema = exports_external.enum([
96874
97247
  "interactive-bash-session",
96875
97248
  "tool-pair-validator",
96876
97249
  "monitor-status-injector",
96877
- "ralph-loop",
97250
+ "goal",
96878
97251
  "category-skill-reminder",
96879
97252
  "compaction-context-injector",
96880
97253
  "compaction-todo-preserver",
@@ -96984,14 +97357,6 @@ var MonitorConfigSchema = exports_external.object({
96984
97357
  pattern_max_length: exports_external.number().int().min(1).default(512)
96985
97358
  });
96986
97359
 
96987
- // packages/omo-opencode/src/config/schema/ralph-loop.ts
96988
- var RalphLoopConfigSchema = exports_external.object({
96989
- enabled: exports_external.boolean().default(false),
96990
- default_max_iterations: exports_external.number().min(1).max(1000).default(100),
96991
- state_dir: exports_external.string().optional(),
96992
- default_strategy: exports_external.enum(["reset", "continue"]).default("continue")
96993
- });
96994
-
96995
97360
  // packages/omo-opencode/src/config/schema/runtime-fallback.ts
96996
97361
  var RuntimeFallbackConfigSchema = exports_external.object({
96997
97362
  enabled: exports_external.boolean().optional(),
@@ -97127,7 +97492,8 @@ var OhMyOpenCodeConfigSchema = exports_external.object({
97127
97492
  experimental: ExperimentalConfigSchema.optional(),
97128
97493
  auto_update: exports_external.boolean().optional(),
97129
97494
  skills: SkillsConfigSchema.optional(),
97130
- ralph_loop: RalphLoopConfigSchema.optional(),
97495
+ goal: GoalConfigSchema.optional(),
97496
+ ralph_loop: exports_external.record(exports_external.string(), exports_external.unknown()).optional(),
97131
97497
  runtime_fallback: exports_external.union([exports_external.boolean(), RuntimeFallbackConfigSchema]).optional(),
97132
97498
  background_task: BackgroundTaskConfigSchema.optional(),
97133
97499
  notification: NotificationConfigSchema.optional(),
@@ -97510,6 +97876,7 @@ function loadPluginConfig(directory, ctx) {
97510
97876
  }
97511
97877
  }
97512
97878
  const userMcpEnvAllowlist = config3.mcp_env_allowlist ?? [];
97879
+ const userPlaywrightMcpArgs = config3.browser_automation_engine?.playwright_mcp_args;
97513
97880
  const canonicalAncestorPathsFarthestFirst = [...canonicalAncestorPathsNearestFirst].reverse();
97514
97881
  const defaultGitMaster = OhMyOpenCodeConfigSchema.parse({}).git_master;
97515
97882
  const ancestorGitMasterOverridesFarthestFirst = [];
@@ -97542,6 +97909,16 @@ function loadPluginConfig(directory, ctx) {
97542
97909
  ...config3,
97543
97910
  mcp_env_allowlist: userMcpEnvAllowlist
97544
97911
  };
97912
+ if (config3.browser_automation_engine) {
97913
+ const {
97914
+ playwright_mcp_args: _ancestorPlaywrightMcpArgs,
97915
+ ...browserAutomationEngine
97916
+ } = config3.browser_automation_engine;
97917
+ config3 = {
97918
+ ...config3,
97919
+ browser_automation_engine: userPlaywrightMcpArgs !== undefined ? { ...browserAutomationEngine, playwright_mcp_args: userPlaywrightMcpArgs } : browserAutomationEngine
97920
+ };
97921
+ }
97545
97922
  applyDisabledProviders(config3);
97546
97923
  log2("Final merged config", {
97547
97924
  agents: config3.agents,
@@ -98013,22 +98390,170 @@ var BOULDER_FILE = "boulder.json";
98013
98390
  var BOULDER_STATE_PATH = `${BOULDER_DIR}/${BOULDER_FILE}`;
98014
98391
  var NOTEPAD_DIR = "notepads";
98015
98392
  var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
98016
- // packages/boulder-state/src/top-level-task.ts
98017
- import { existsSync as existsSync37, readFileSync as readFileSync19 } from "node:fs";
98018
- var TODO_HEADING_PATTERN = /^##\s+TODOs\b/i;
98019
- var FINAL_VERIFICATION_HEADING_PATTERN = /^##\s+Final Verification Wave\b/i;
98020
- var SECOND_LEVEL_HEADING_PATTERN = /^##\s+/;
98021
- var UNCHECKED_CHECKBOX_PATTERN = /^(\s*)[-*]\s*\[\s*\]\s*(.+)$/;
98022
- var TODO_TASK_PATTERN = /^(\d+)\.\s+(.+)$/;
98023
- var FINAL_WAVE_TASK_PATTERN = /^(F\d+)\.\s+(.+)$/i;
98024
- function buildTaskRef(section, taskLabel) {
98025
- const pattern = section === "todo" ? TODO_TASK_PATTERN : FINAL_WAVE_TASK_PATTERN;
98026
- const match = taskLabel.match(pattern);
98027
- if (!match) {
98393
+ // packages/boulder-state/src/plan-checklist.ts
98394
+ var SIMPLE_CHECKBOX_PATTERN = /^[-*][ \t]*\[[ \t]*([xX]?)[ \t]*\][ \t]+(.+)$/;
98395
+ var TODO_HEADING_PATTERN = /^##[ \t]+TODOs(?:[ \t]+#+)?[ \t]*$/i;
98396
+ var FINAL_VERIFICATION_HEADING_PATTERN = /^##[ \t]+Final Verification Wave(?:[ \t]+#+)?[ \t]*$/i;
98397
+ var SECTION_BOUNDARY_HEADING_PATTERN = /^#{1,2}(?:[ \t]+|$)/;
98398
+ var FENCE_PATTERN = /^[ \t]{0,3}(`{3,}|~{3,})(.*)$/;
98399
+ var TODO_CHECKBOX_PATTERN = /^- \[([ xX])\] ([1-9]\d*\. .+)$/;
98400
+ var FINAL_WAVE_CHECKBOX_PATTERN = /^- \[([ xX])\] (F[1-9]\d*\. .+)$/i;
98401
+ function parsePlanChecklist(markdown) {
98402
+ const lines = markdown.split(/\r?\n/);
98403
+ if (!hasStructuredSection(lines)) {
98404
+ return parseSimpleChecklist(lines);
98405
+ }
98406
+ return parseStructuredPlan(lines).checklist;
98407
+ }
98408
+ function parseCurrentTopLevelTask(markdown) {
98409
+ const lines = markdown.split(/\r?\n/);
98410
+ if (!hasStructuredSection(lines)) {
98411
+ return null;
98412
+ }
98413
+ return parseStructuredPlan(lines).nextTask;
98414
+ }
98415
+ function parseStructuredPlan(lines) {
98416
+ let remaining = 0;
98417
+ let total = 0;
98418
+ let nextTaskLabel = null;
98419
+ let nextTask = null;
98420
+ let section = "other";
98421
+ let fence = null;
98422
+ for (const line of lines) {
98423
+ if (fence !== null) {
98424
+ if (isClosingFence(line, fence)) {
98425
+ fence = null;
98426
+ }
98427
+ continue;
98428
+ }
98429
+ const openingFence = parseOpeningFence(line);
98430
+ if (openingFence !== null) {
98431
+ fence = openingFence;
98432
+ continue;
98433
+ }
98434
+ if (SECTION_BOUNDARY_HEADING_PATTERN.test(line)) {
98435
+ section = parseStructuredSectionHeading(line);
98436
+ continue;
98437
+ }
98438
+ if (section === "other") {
98439
+ continue;
98440
+ }
98441
+ const checkbox = parseStructuredTopLevelCheckbox(line, section);
98442
+ if (checkbox === null) {
98443
+ continue;
98444
+ }
98445
+ total += 1;
98446
+ if (checkbox.checked) {
98447
+ continue;
98448
+ }
98449
+ remaining += 1;
98450
+ if (nextTaskLabel === null) {
98451
+ nextTaskLabel = checkbox.label;
98452
+ nextTask = checkbox.task;
98453
+ }
98454
+ }
98455
+ return {
98456
+ checklist: {
98457
+ completed: total - remaining,
98458
+ remaining,
98459
+ total,
98460
+ nextTaskLabel
98461
+ },
98462
+ nextTask
98463
+ };
98464
+ }
98465
+ function parseSimpleChecklist(lines) {
98466
+ let remaining = 0;
98467
+ let total = 0;
98468
+ let nextTaskLabel = null;
98469
+ let fence = null;
98470
+ for (const line of lines) {
98471
+ if (fence !== null) {
98472
+ if (isClosingFence(line, fence)) {
98473
+ fence = null;
98474
+ }
98475
+ continue;
98476
+ }
98477
+ const openingFence = parseOpeningFence(line);
98478
+ if (openingFence !== null) {
98479
+ fence = openingFence;
98480
+ continue;
98481
+ }
98482
+ const checkbox = parseSimpleTopLevelCheckbox(line);
98483
+ if (checkbox === null) {
98484
+ continue;
98485
+ }
98486
+ total += 1;
98487
+ if (checkbox.checked) {
98488
+ continue;
98489
+ }
98490
+ remaining += 1;
98491
+ if (nextTaskLabel === null) {
98492
+ nextTaskLabel = checkbox.label;
98493
+ }
98494
+ }
98495
+ return { completed: total - remaining, remaining, total, nextTaskLabel };
98496
+ }
98497
+ function parseSimpleTopLevelCheckbox(line) {
98498
+ const match = line.match(SIMPLE_CHECKBOX_PATTERN);
98499
+ const marker = match?.[1];
98500
+ const label = match?.[2];
98501
+ if (marker === undefined || label === undefined) {
98502
+ return null;
98503
+ }
98504
+ return { checked: marker.toLowerCase() === "x", label };
98505
+ }
98506
+ function hasStructuredSection(lines) {
98507
+ let fence = null;
98508
+ for (const line of lines) {
98509
+ if (fence !== null) {
98510
+ if (isClosingFence(line, fence)) {
98511
+ fence = null;
98512
+ }
98513
+ continue;
98514
+ }
98515
+ const openingFence = parseOpeningFence(line);
98516
+ if (openingFence !== null) {
98517
+ fence = openingFence;
98518
+ continue;
98519
+ }
98520
+ if (parseStructuredSectionHeading(line) !== "other") {
98521
+ return true;
98522
+ }
98523
+ }
98524
+ return false;
98525
+ }
98526
+ function parseStructuredSectionHeading(line) {
98527
+ if (TODO_HEADING_PATTERN.test(line)) {
98528
+ return "todo";
98529
+ }
98530
+ if (FINAL_VERIFICATION_HEADING_PATTERN.test(line)) {
98531
+ return "final-wave";
98532
+ }
98533
+ return "other";
98534
+ }
98535
+ function parseStructuredTopLevelCheckbox(line, section) {
98536
+ const pattern = section === "todo" ? TODO_CHECKBOX_PATTERN : FINAL_WAVE_CHECKBOX_PATTERN;
98537
+ const match = line.match(pattern);
98538
+ const marker = match?.[1];
98539
+ const label = match?.[2];
98540
+ if (marker === undefined || label === undefined) {
98541
+ return null;
98542
+ }
98543
+ const task = buildTaskRef(section, label);
98544
+ if (task === null) {
98545
+ return null;
98546
+ }
98547
+ return { checked: marker.toLowerCase() === "x", label, task };
98548
+ }
98549
+ function buildTaskRef(section, label) {
98550
+ const pattern = section === "todo" ? /^([1-9]\d*)\. (.+)$/ : /^(F[1-9]\d*)\. (.+)$/i;
98551
+ const match = label.match(pattern);
98552
+ const rawLabel = match?.[1];
98553
+ const title = match?.[2];
98554
+ if (rawLabel === undefined || title === undefined) {
98028
98555
  return null;
98029
98556
  }
98030
- const rawLabel = match[1];
98031
- const title = match[2].trim();
98032
98557
  return {
98033
98558
  key: `${section}:${rawLabel.toLowerCase()}`,
98034
98559
  section,
@@ -98036,31 +98561,29 @@ function buildTaskRef(section, taskLabel) {
98036
98561
  title
98037
98562
  };
98038
98563
  }
98564
+ function parseOpeningFence(line) {
98565
+ const match = line.match(FENCE_PATTERN);
98566
+ const run = match?.[1];
98567
+ const info = match?.[2];
98568
+ const marker = run?.charAt(0);
98569
+ if (run === undefined || info === undefined || marker !== "`" && marker !== "~" || marker === "`" && info.includes("`")) {
98570
+ return null;
98571
+ }
98572
+ return { marker, length: run.length };
98573
+ }
98574
+ function isClosingFence(line, fence) {
98575
+ const run = line.match(/^[ \t]{0,3}(`{3,}|~{3,})[ \t]*$/)?.[1];
98576
+ return run?.charAt(0) === fence.marker && run.length >= fence.length;
98577
+ }
98578
+ // packages/boulder-state/src/top-level-task.ts
98579
+ import { existsSync as existsSync37, readFileSync as readFileSync19 } from "node:fs";
98039
98580
  function readCurrentTopLevelTask(planPath) {
98040
98581
  if (!existsSync37(planPath)) {
98041
98582
  return null;
98042
98583
  }
98043
98584
  try {
98044
98585
  const content = readFileSync19(planPath, "utf-8");
98045
- const lines = content.split(/\r?\n/);
98046
- let section = "other";
98047
- for (const line of lines) {
98048
- if (SECOND_LEVEL_HEADING_PATTERN.test(line)) {
98049
- section = TODO_HEADING_PATTERN.test(line) ? "todo" : FINAL_VERIFICATION_HEADING_PATTERN.test(line) ? "final-wave" : "other";
98050
- }
98051
- const uncheckedTaskMatch = line.match(UNCHECKED_CHECKBOX_PATTERN);
98052
- if (!uncheckedTaskMatch || uncheckedTaskMatch[1].length > 0) {
98053
- continue;
98054
- }
98055
- if (section !== "todo" && section !== "final-wave") {
98056
- continue;
98057
- }
98058
- const taskRef = buildTaskRef(section, uncheckedTaskMatch[2].trim());
98059
- if (taskRef) {
98060
- return taskRef;
98061
- }
98062
- }
98063
- return null;
98586
+ return parseCurrentTopLevelTask(content);
98064
98587
  } catch {
98065
98588
  return null;
98066
98589
  }
@@ -98094,69 +98617,25 @@ function resolveBoulderPlanPathForWork(directory, work) {
98094
98617
  }
98095
98618
  // packages/boulder-state/src/storage/plan-progress.ts
98096
98619
  import { existsSync as existsSync39, readFileSync as readFileSync20, readdirSync as readdirSync5, statSync as statSync5 } from "node:fs";
98097
- var TODO_HEADING_PATTERN2 = /^##\s+TODOs\b/i;
98098
- var FINAL_VERIFICATION_HEADING_PATTERN2 = /^##\s+Final Verification Wave\b/i;
98099
- var SECOND_LEVEL_HEADING_PATTERN2 = /^##\s+/;
98100
- var UNCHECKED_CHECKBOX_PATTERN2 = /^(\s*)[-*]\s*\[\s*\]\s*(.+)$/;
98101
- var CHECKED_CHECKBOX_PATTERN = /^(\s*)[-*]\s*\[[xX]\]\s*(.+)$/;
98102
- var TODO_TASK_PATTERN2 = /^\d+\.\s+/;
98103
- var FINAL_WAVE_TASK_PATTERN2 = /^F\d+\.\s+/i;
98104
98620
  function getPlanProgress(planPath) {
98105
98621
  if (!existsSync39(planPath)) {
98106
98622
  return { total: 0, completed: 0, isComplete: false };
98107
98623
  }
98108
98624
  try {
98109
98625
  const content = readFileSync20(planPath, "utf-8");
98110
- const lines = content.split(/\r?\n/);
98111
- const hasStructuredSections = lines.some((line) => TODO_HEADING_PATTERN2.test(line) || FINAL_VERIFICATION_HEADING_PATTERN2.test(line));
98112
- if (hasStructuredSections) {
98113
- return getStructuredPlanProgress(lines);
98114
- }
98115
- return getSimplePlanProgress(content);
98626
+ const checklist = parsePlanChecklist(content);
98627
+ return {
98628
+ total: checklist.total,
98629
+ completed: checklist.completed,
98630
+ isComplete: checklist.total > 0 && checklist.remaining === 0
98631
+ };
98116
98632
  } catch {
98117
98633
  return { total: 0, completed: 0, isComplete: false };
98118
98634
  }
98119
98635
  }
98120
- function getStructuredPlanProgress(lines) {
98121
- let section = "other";
98122
- let total = 0;
98123
- let completed = 0;
98124
- for (const line of lines) {
98125
- if (SECOND_LEVEL_HEADING_PATTERN2.test(line)) {
98126
- section = TODO_HEADING_PATTERN2.test(line) ? "todo" : FINAL_VERIFICATION_HEADING_PATTERN2.test(line) ? "final-wave" : "other";
98127
- continue;
98128
- }
98129
- if (section !== "todo" && section !== "final-wave") {
98130
- continue;
98131
- }
98132
- const checkedMatch = line.match(CHECKED_CHECKBOX_PATTERN);
98133
- const uncheckedMatch = checkedMatch ? null : line.match(UNCHECKED_CHECKBOX_PATTERN2);
98134
- const match = checkedMatch ?? uncheckedMatch;
98135
- if (!match || match[1].length > 0) {
98136
- continue;
98137
- }
98138
- const taskBody = match[2].trim();
98139
- const labelPattern = section === "todo" ? TODO_TASK_PATTERN2 : FINAL_WAVE_TASK_PATTERN2;
98140
- if (!labelPattern.test(taskBody)) {
98141
- continue;
98142
- }
98143
- total += 1;
98144
- if (checkedMatch) {
98145
- completed += 1;
98146
- }
98147
- }
98148
- return { total, completed, isComplete: total > 0 && completed === total };
98149
- }
98150
- function getSimplePlanProgress(content) {
98151
- const uncheckedMatches = content.match(/^[-*]\s*\[\s*\]/gm) ?? [];
98152
- const checkedMatches = content.match(/^[-*]\s*\[[xX]\]/gm) ?? [];
98153
- const total = uncheckedMatches.length + checkedMatches.length;
98154
- const completed = checkedMatches.length;
98155
- return { total, completed, isComplete: total > 0 && completed === total };
98156
- }
98157
98636
  // packages/boulder-state/src/storage/shared.ts
98158
98637
  var RESERVED_KEYS = new Set(["__proto__", "prototype", "constructor"]);
98159
- var SESSION_ID_PREFIX_PATTERN = /^(codex|opencode):/;
98638
+ var SESSION_ID_PREFIX_PATTERN = /^(codex|opencode|senpi):/;
98160
98639
  function normalizeSessionId(sessionId, platform = "opencode") {
98161
98640
  if (SESSION_ID_PREFIX_PATTERN.test(sessionId)) {
98162
98641
  return sessionId;
@@ -98231,7 +98710,7 @@ function readBoulderState(directory) {
98231
98710
  try {
98232
98711
  const content = readFileSync21(filePath, "utf-8");
98233
98712
  const parsed = JSON.parse(content);
98234
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
98713
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed) || Object.keys(parsed).length === 0) {
98235
98714
  return null;
98236
98715
  }
98237
98716
  normalizeState(parsed);
@@ -100188,6 +100667,7 @@ import { readFileSync as readFileSync35 } from "node:fs";
100188
100667
  import { homedir as homedir16 } from "node:os";
100189
100668
  import { dirname as dirname29, relative as relative9 } from "node:path";
100190
100669
  init_shared();
100670
+ init_logger2();
100191
100671
  init_plugin_identity();
100192
100672
  function resolveHomeDirectory2() {
100193
100673
  return process.env.HOME ?? process.env.USERPROFILE ?? homedir16();
@@ -100276,13 +100756,45 @@ function mergeLoadedConfig(userLayersNearestFirst, projectLayersNearestFirst) {
100276
100756
  config3 = mergeConfigs2(config3, layer.config);
100277
100757
  }
100278
100758
  const userMcpEnvAllowlist = config3.mcp_env_allowlist ?? [];
100759
+ const userPlaywrightMcpArgs = config3.browser_automation_engine?.playwright_mcp_args;
100279
100760
  for (const layer of [...projectLayersNearestFirst].reverse()) {
100280
100761
  if (layer.config)
100281
100762
  config3 = mergeConfigs2(config3, layer.config);
100282
100763
  }
100283
100764
  config3 = { ...config3, mcp_env_allowlist: userMcpEnvAllowlist };
100765
+ if (config3.browser_automation_engine) {
100766
+ const {
100767
+ playwright_mcp_args: _projectPlaywrightMcpArgs,
100768
+ ...browserAutomationEngine
100769
+ } = config3.browser_automation_engine;
100770
+ config3 = {
100771
+ ...config3,
100772
+ browser_automation_engine: userPlaywrightMcpArgs !== undefined ? { ...browserAutomationEngine, playwright_mcp_args: userPlaywrightMcpArgs } : browserAutomationEngine
100773
+ };
100774
+ }
100284
100775
  return applyDisabledProviders(config3);
100285
100776
  }
100777
+ function migrateRalphLoopConfig(config3) {
100778
+ const legacy = config3.ralph_loop;
100779
+ if (legacy === undefined) {
100780
+ return config3;
100781
+ }
100782
+ const enabled = typeof legacy.enabled === "boolean" ? legacy.enabled : undefined;
100783
+ const defaultMaxIterations = typeof legacy.default_max_iterations === "number" ? legacy.default_max_iterations : undefined;
100784
+ if (enabled === undefined && defaultMaxIterations === undefined) {
100785
+ return config3;
100786
+ }
100787
+ log2("[config] ralph_loop is deprecated and will be removed in a future release. Use goal instead.");
100788
+ const existingGoal = config3.goal;
100789
+ return {
100790
+ ...config3,
100791
+ goal: {
100792
+ enabled: existingGoal?.enabled ?? enabled ?? false,
100793
+ auto_start: existingGoal?.auto_start ?? false,
100794
+ default_max_iterations: existingGoal?.default_max_iterations ?? defaultMaxIterations ?? 100
100795
+ }
100796
+ };
100797
+ }
100286
100798
  function validatePluginConfig(directory) {
100287
100799
  const userLayersNearestFirst = discoverUserLayers().map((layer) => parseLayerConfig(layer.path));
100288
100800
  const projectLayersNearestFirst = discoverProjectLayersNearestFirst(directory).map((layer) => parseLayerConfig(layer.path));
@@ -100292,7 +100804,7 @@ function validatePluginConfig(directory) {
100292
100804
  valid: messages.length === 0,
100293
100805
  messages,
100294
100806
  path: firstFailingPath(layers) ?? firstPath(layers),
100295
- config: mergeLoadedConfig(userLayersNearestFirst, projectLayersNearestFirst)
100807
+ config: migrateRalphLoopConfig(mergeLoadedConfig(userLayersNearestFirst, projectLayersNearestFirst))
100296
100808
  };
100297
100809
  }
100298
100810