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
package/dist/cli/index.js CHANGED
@@ -2145,7 +2145,7 @@ var package_default;
2145
2145
  var init_package = __esm(() => {
2146
2146
  package_default = {
2147
2147
  name: "oh-my-opencode",
2148
- version: "4.18.2",
2148
+ version: "4.19.0",
2149
2149
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
2150
2150
  main: "./dist/index.js",
2151
2151
  types: "dist/index.d.ts",
@@ -2255,7 +2255,7 @@ var init_package = __esm(() => {
2255
2255
  "install:codex-dev": "bun run script/build-codex-install.ts && bun run script/install-codex-dev.ts",
2256
2256
  "build:codex-plugin": "npm --prefix packages/omo-codex/plugin ci && bun run --cwd packages/omo-codex/plugin build",
2257
2257
  "build:senpi-plugin": "bun run build:lsp-daemon && bun run build:senpi-plugin:stage",
2258
- "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",
2258
+ "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",
2259
2259
  "build:materialize-frontend": "node packages/omo-codex/plugin/scripts/materialize-shared-upstreams.mjs --strict",
2260
2260
  "build:shared-skills-assets": "bun run build:materialize-frontend && rm -rf dist/skills && cp -R packages/shared-skills/skills dist/skills",
2261
2261
  "build:lsp-tools-mcp": "npm --prefix packages/lsp-tools-mcp ci && npm --prefix packages/lsp-tools-mcp run build",
@@ -2357,18 +2357,18 @@ var init_package = __esm(() => {
2357
2357
  typescript: "^6.0.3"
2358
2358
  },
2359
2359
  optionalDependencies: {
2360
- "oh-my-opencode-darwin-arm64": "4.18.2",
2361
- "oh-my-opencode-darwin-x64": "4.18.2",
2362
- "oh-my-opencode-darwin-x64-baseline": "4.18.2",
2363
- "oh-my-opencode-linux-arm64": "4.18.2",
2364
- "oh-my-opencode-linux-arm64-musl": "4.18.2",
2365
- "oh-my-opencode-linux-x64": "4.18.2",
2366
- "oh-my-opencode-linux-x64-baseline": "4.18.2",
2367
- "oh-my-opencode-linux-x64-musl": "4.18.2",
2368
- "oh-my-opencode-linux-x64-musl-baseline": "4.18.2",
2369
- "oh-my-opencode-windows-arm64": "4.18.2",
2370
- "oh-my-opencode-windows-x64": "4.18.2",
2371
- "oh-my-opencode-windows-x64-baseline": "4.18.2"
2360
+ "oh-my-opencode-darwin-arm64": "4.19.0",
2361
+ "oh-my-opencode-darwin-x64": "4.19.0",
2362
+ "oh-my-opencode-darwin-x64-baseline": "4.19.0",
2363
+ "oh-my-opencode-linux-arm64": "4.19.0",
2364
+ "oh-my-opencode-linux-arm64-musl": "4.19.0",
2365
+ "oh-my-opencode-linux-x64": "4.19.0",
2366
+ "oh-my-opencode-linux-x64-baseline": "4.19.0",
2367
+ "oh-my-opencode-linux-x64-musl": "4.19.0",
2368
+ "oh-my-opencode-linux-x64-musl-baseline": "4.19.0",
2369
+ "oh-my-opencode-windows-arm64": "4.19.0",
2370
+ "oh-my-opencode-windows-x64": "4.19.0",
2371
+ "oh-my-opencode-windows-x64-baseline": "4.19.0"
2372
2372
  },
2373
2373
  overrides: {
2374
2374
  "@earendil-works/pi-agent-core": "0.80.3",
@@ -9198,6 +9198,7 @@ var init_agent_model_requirements = __esm(() => {
9198
9198
  model: "claude-opus-4-7",
9199
9199
  variant: "max"
9200
9200
  },
9201
+ { providers: ["opencode-go", "kimi-for-coding", "moonshotai", "opencode", "vercel"], model: "kimi-k3" },
9201
9202
  { providers: ["opencode-go", "vercel"], model: "kimi-k2.6" },
9202
9203
  { providers: ["kimi-for-coding"], model: "k2p5" },
9203
9204
  {
@@ -9330,12 +9331,12 @@ var init_agent_model_requirements = __esm(() => {
9330
9331
  fallbackChain: [
9331
9332
  {
9332
9333
  providers: ["openai", "vercel"],
9333
- model: "gpt-5.6-sol",
9334
- variant: "xhigh"
9334
+ model: "gpt-5.6-terra",
9335
+ variant: "high"
9335
9336
  },
9336
9337
  {
9337
9338
  providers: ["github-copilot"],
9338
- model: "gpt-5.6-sol",
9339
+ model: "gpt-5.6-terra",
9339
9340
  variant: "high"
9340
9341
  },
9341
9342
  {
@@ -10098,6 +10099,21 @@ var init_runtime_fallback_model = () => {};
10098
10099
  var SUPPLEMENTAL_MODEL_CAPABILITIES;
10099
10100
  var init_supplemental_entries = __esm(() => {
10100
10101
  SUPPLEMENTAL_MODEL_CAPABILITIES = {
10102
+ "kimi-k3": {
10103
+ id: "kimi-k3",
10104
+ family: "kimi",
10105
+ reasoning: true,
10106
+ temperature: true,
10107
+ toolCall: true,
10108
+ modalities: {
10109
+ input: ["text", "image", "video"],
10110
+ output: ["text"]
10111
+ },
10112
+ limit: {
10113
+ context: 262144,
10114
+ output: 262144
10115
+ }
10116
+ },
10101
10117
  "kimi-k2.6": {
10102
10118
  id: "kimi-k2.6",
10103
10119
  family: "kimi",
@@ -72641,7 +72657,7 @@ var package_default2;
72641
72657
  var init_package2 = __esm(() => {
72642
72658
  package_default2 = {
72643
72659
  name: "@oh-my-opencode/omo-codex",
72644
- version: "4.18.2",
72660
+ version: "4.19.0",
72645
72661
  type: "module",
72646
72662
  private: true,
72647
72663
  description: "Codex harness adapter for oh-my-openagent. Vendored Codex plugin namespace (omo) + TypeScript installer + telemetry.",
@@ -75683,9 +75699,16 @@ function findTomlSection(config, header) {
75683
75699
  const lines = config.match(/[^\n]*\n?|$/g) ?? [];
75684
75700
  let offset = 0;
75685
75701
  let start = -1;
75702
+ let multilineQuote = null;
75686
75703
  for (const line of lines) {
75687
75704
  if (line.length === 0)
75688
75705
  break;
75706
+ const multilineScan = scanTomlMultilineLine(line, multilineQuote);
75707
+ multilineQuote = multilineScan.nextQuote;
75708
+ if (multilineScan.wasInside) {
75709
+ offset += line.length;
75710
+ continue;
75711
+ }
75689
75712
  const trimmed = line.trim();
75690
75713
  if (start === -1) {
75691
75714
  if (tomlTableHeaderMatches(trimmed, headerLine, targetHeaderPath))
@@ -75700,8 +75723,37 @@ function findTomlSection(config, header) {
75700
75723
  return { start, end: config.length, text: config.slice(start) };
75701
75724
  }
75702
75725
  function replaceOrInsertSetting(config, section, key, value) {
75703
- const linePattern = new RegExp(`^[ \\t]*${escapeRegExp(key)}[ \\t]*=.*$`, "m");
75704
- const replacement = linePattern.test(section.text) ? section.text.replace(linePattern, `${key} = ${value}`) : insertSetting(section.text, key, value);
75726
+ const targetPath = parseTomlDottedKey(key);
75727
+ if (!targetPath)
75728
+ return config;
75729
+ const lines = section.text.match(/[^\n]*\n?|$/g) ?? [];
75730
+ let offset = 0;
75731
+ let multilineQuote = null;
75732
+ for (const line of lines) {
75733
+ if (line.length === 0)
75734
+ break;
75735
+ const multilineScan = scanTomlMultilineLine(line, multilineQuote);
75736
+ multilineQuote = multilineScan.nextQuote;
75737
+ if (multilineScan.wasInside) {
75738
+ offset += line.length;
75739
+ continue;
75740
+ }
75741
+ const assignmentIndex = findUnquotedAssignment(line);
75742
+ if (assignmentIndex < 0) {
75743
+ offset += line.length;
75744
+ continue;
75745
+ }
75746
+ const settingPath = parseTomlDottedKey(line.slice(0, assignmentIndex).trim());
75747
+ if (!settingPath || !tomlPathMatches(settingPath, targetPath)) {
75748
+ offset += line.length;
75749
+ continue;
75750
+ }
75751
+ const replacement2 = replaceTomlAssignmentValue(line, assignmentIndex, value);
75752
+ const assignmentEnd = multilineScan.nextQuote ? findTomlMultilineValueEnd(section.text, offset + line.length, multilineScan.nextQuote) : offset + line.length;
75753
+ const sectionReplacement = section.text.slice(0, offset) + replacement2 + section.text.slice(assignmentEnd);
75754
+ return config.slice(0, section.start) + sectionReplacement + config.slice(section.end);
75755
+ }
75756
+ const replacement = insertSetting(section.text, key, value);
75705
75757
  return config.slice(0, section.start) + replacement + config.slice(section.end);
75706
75758
  }
75707
75759
  function removeSetting(config, section, key) {
@@ -75721,6 +75773,50 @@ function replaceOrInsertRootSetting(config, key, value) {
75721
75773
  return replacement;
75722
75774
  return `${replacement.trimEnd()}
75723
75775
 
75776
+ ${suffix.trimStart()}`;
75777
+ }
75778
+ function replaceOrInsertRootDottedSetting(config, keyPath, value) {
75779
+ const targetPath = parseTomlDottedKey(keyPath);
75780
+ if (!targetPath)
75781
+ return config;
75782
+ const lines = config.match(/[^\n]*\n?|$/g) ?? [];
75783
+ let offset = 0;
75784
+ let multilineQuote = null;
75785
+ for (const line of lines) {
75786
+ if (line.length === 0)
75787
+ break;
75788
+ const multilineScan = scanTomlMultilineLine(line, multilineQuote);
75789
+ multilineQuote = multilineScan.nextQuote;
75790
+ if (multilineScan.wasInside) {
75791
+ offset += line.length;
75792
+ continue;
75793
+ }
75794
+ if (isTomlTableHeaderLine(line))
75795
+ break;
75796
+ const assignmentIndex = findUnquotedAssignment(line);
75797
+ if (assignmentIndex < 0) {
75798
+ offset += line.length;
75799
+ continue;
75800
+ }
75801
+ const settingPath = parseTomlDottedKey(line.slice(0, assignmentIndex).trim());
75802
+ if (!settingPath || !tomlPathMatches(settingPath, targetPath)) {
75803
+ offset += line.length;
75804
+ continue;
75805
+ }
75806
+ const replacement2 = replaceTomlAssignmentValue(line, assignmentIndex, value);
75807
+ const assignmentEnd = multilineScan.nextQuote ? findTomlMultilineValueEnd(config, offset + line.length, multilineScan.nextQuote) : offset + line.length;
75808
+ return config.slice(0, offset) + replacement2 + config.slice(assignmentEnd);
75809
+ }
75810
+ const sectionStart = findFirstTableStart(config);
75811
+ const root = config.slice(0, sectionStart).trimEnd();
75812
+ const suffix = config.slice(sectionStart);
75813
+ const replacement = `${root}${root.length > 0 ? `
75814
+ ` : ""}${keyPath} = ${value}
75815
+ `;
75816
+ if (suffix.length === 0)
75817
+ return replacement;
75818
+ return `${replacement.trimEnd()}
75819
+
75724
75820
  ${suffix.trimStart()}`;
75725
75821
  }
75726
75822
  function appendBlock(config, block) {
@@ -75733,9 +75829,16 @@ function appendBlock(config, block) {
75733
75829
  function findFirstTableStart(config) {
75734
75830
  const lines = config.match(/[^\n]*\n?|$/g) ?? [];
75735
75831
  let offset = 0;
75832
+ let multilineQuote = null;
75736
75833
  for (const line of lines) {
75737
75834
  if (line.length === 0)
75738
75835
  break;
75836
+ const multilineScan = scanTomlMultilineLine(line, multilineQuote);
75837
+ multilineQuote = multilineScan.nextQuote;
75838
+ if (multilineScan.wasInside) {
75839
+ offset += line.length;
75840
+ continue;
75841
+ }
75739
75842
  if (isTomlTableHeaderLine(line))
75740
75843
  return offset;
75741
75844
  offset += line.length;
@@ -75773,6 +75876,131 @@ function isTomlTableHeaderLine(line) {
75773
75876
  const normalizedLine = stripUnquotedInlineComment(line).trim();
75774
75877
  return normalizedLine.startsWith("[") && normalizedLine.endsWith("]");
75775
75878
  }
75879
+ function scanTomlMultilineLine(line, currentQuote) {
75880
+ if (currentQuote) {
75881
+ return {
75882
+ wasInside: true,
75883
+ nextQuote: findTomlMultilineDelimiter(line, currentQuote, 0) === -1 ? currentQuote : null
75884
+ };
75885
+ }
75886
+ let quote = null;
75887
+ let index = 0;
75888
+ while (index < line.length) {
75889
+ const char = line[index];
75890
+ if (quote === '"') {
75891
+ if (char === "\\") {
75892
+ index += 2;
75893
+ continue;
75894
+ }
75895
+ if (char === '"')
75896
+ quote = null;
75897
+ index += 1;
75898
+ continue;
75899
+ }
75900
+ if (quote === "'") {
75901
+ if (char === "'")
75902
+ quote = null;
75903
+ index += 1;
75904
+ continue;
75905
+ }
75906
+ if (char === "#")
75907
+ break;
75908
+ const delimiter2 = line.startsWith('"""', index) ? '"""' : line.startsWith("'''", index) ? "'''" : null;
75909
+ if (delimiter2) {
75910
+ const closingIndex = findTomlMultilineDelimiter(line, delimiter2, index + delimiter2.length);
75911
+ return { wasInside: false, nextQuote: closingIndex === -1 ? delimiter2 : null };
75912
+ }
75913
+ if (char === '"' || char === "'")
75914
+ quote = char;
75915
+ index += 1;
75916
+ }
75917
+ return { wasInside: false, nextQuote: null };
75918
+ }
75919
+ function findTomlMultilineDelimiter(line, delimiter2, startIndex) {
75920
+ let index = line.indexOf(delimiter2, startIndex);
75921
+ while (index !== -1) {
75922
+ if (delimiter2 === "'''" || countPrecedingBackslashes(line, index) % 2 === 0)
75923
+ return index;
75924
+ index = line.indexOf(delimiter2, index + 1);
75925
+ }
75926
+ return -1;
75927
+ }
75928
+ function countPrecedingBackslashes(line, index) {
75929
+ let count = 0;
75930
+ let cursor = index - 1;
75931
+ while (cursor >= 0 && line[cursor] === "\\") {
75932
+ count += 1;
75933
+ cursor -= 1;
75934
+ }
75935
+ return count;
75936
+ }
75937
+ function findUnquotedAssignment(line) {
75938
+ return findUnquotedCharacter(line, "=", 0);
75939
+ }
75940
+ function findUnquotedComment(line, startIndex) {
75941
+ return findUnquotedCharacter(line, "#", startIndex);
75942
+ }
75943
+ function findUnquotedCharacter(line, target, startIndex) {
75944
+ let quote = null;
75945
+ let index = startIndex;
75946
+ while (index < line.length) {
75947
+ const char = line[index];
75948
+ if (quote === '"') {
75949
+ if (char === "\\") {
75950
+ index += 2;
75951
+ continue;
75952
+ }
75953
+ if (char === '"')
75954
+ quote = null;
75955
+ index += 1;
75956
+ continue;
75957
+ }
75958
+ if (quote === "'") {
75959
+ if (char === "'")
75960
+ quote = null;
75961
+ index += 1;
75962
+ continue;
75963
+ }
75964
+ if (char === '"' || char === "'") {
75965
+ quote = char;
75966
+ index += 1;
75967
+ continue;
75968
+ }
75969
+ if (char === target)
75970
+ return index;
75971
+ if (char === "#")
75972
+ return -1;
75973
+ index += 1;
75974
+ }
75975
+ return -1;
75976
+ }
75977
+ function tomlPathMatches(candidate, target) {
75978
+ return candidate.length === target.length && candidate.every((part, index) => part === target[index]);
75979
+ }
75980
+ function replaceTomlAssignmentValue(line, assignmentIndex, value) {
75981
+ const newline = line.endsWith(`
75982
+ `) ? `
75983
+ ` : "";
75984
+ const lineBody = newline ? line.slice(0, -1) : line;
75985
+ const commentIndex = findUnquotedComment(lineBody, assignmentIndex + 1);
75986
+ const comment = commentIndex === -1 ? "" : ` ${lineBody.slice(commentIndex).trimStart()}`;
75987
+ return `${lineBody.slice(0, assignmentIndex + 1)} ${value}${comment}${newline}`;
75988
+ }
75989
+ function findTomlMultilineValueEnd(text, startOffset, quote) {
75990
+ const lines = text.slice(startOffset).match(/[^\n]*\n?|$/g) ?? [];
75991
+ let offset = startOffset;
75992
+ let currentQuote = quote;
75993
+ for (const line of lines) {
75994
+ if (line.length === 0)
75995
+ break;
75996
+ const scan = scanTomlMultilineLine(line, currentQuote);
75997
+ currentQuote = scan.nextQuote;
75998
+ offset += line.length;
75999
+ if (currentQuote === null)
76000
+ return offset;
76001
+ }
76002
+ return text.length;
76003
+ }
75776
76004
  function stripUnquotedInlineComment(line) {
75777
76005
  let quote = null;
75778
76006
  let index = 0;
@@ -76103,13 +76331,137 @@ function delay(milliseconds) {
76103
76331
  return new Promise((resolveDelay) => setTimeout(resolveDelay, milliseconds));
76104
76332
  }
76105
76333
 
76334
+ // packages/omo-codex/src/install/toml-setting-reader.ts
76335
+ function hasTomlSetting(config, keyPath) {
76336
+ const targetPath = parseTomlDottedKey(keyPath);
76337
+ if (!targetPath)
76338
+ return false;
76339
+ return hasTomlAssignment(config, (tablePath, settingPath) => {
76340
+ const fullPath = [...tablePath, ...settingPath];
76341
+ return fullPath.length === targetPath.length && fullPath.every((part, index) => part === targetPath[index]);
76342
+ });
76343
+ }
76344
+ function hasTomlRootDottedKeyPrefix(config, rootKey) {
76345
+ return hasTomlAssignment(config, (tablePath, settingPath) => tablePath.length === 0 && settingPath.length > 1 && settingPath[0] === rootKey);
76346
+ }
76347
+ function hasTomlAssignment(config, predicate) {
76348
+ let tablePath = [];
76349
+ let multilineQuote = null;
76350
+ for (const line of config.split(`
76351
+ `)) {
76352
+ const multilineScan = scanTomlMultilineLine(line, multilineQuote);
76353
+ multilineQuote = multilineScan.nextQuote;
76354
+ if (multilineScan.wasInside)
76355
+ continue;
76356
+ const normalizedLine = stripUnquotedInlineComment2(line).trim();
76357
+ if (normalizedLine.length === 0)
76358
+ continue;
76359
+ const headerPath = parseTomlTableHeader2(normalizedLine);
76360
+ if (headerPath) {
76361
+ tablePath = headerPath;
76362
+ continue;
76363
+ }
76364
+ if (isTomlTableHeaderLine2(normalizedLine)) {
76365
+ tablePath = null;
76366
+ continue;
76367
+ }
76368
+ if (!tablePath)
76369
+ continue;
76370
+ const assignmentIndex = findUnquotedAssignment2(normalizedLine);
76371
+ if (assignmentIndex < 0)
76372
+ continue;
76373
+ const settingPath = parseTomlDottedKey(normalizedLine.slice(0, assignmentIndex).trim());
76374
+ if (!settingPath)
76375
+ continue;
76376
+ if (predicate(tablePath, settingPath))
76377
+ return true;
76378
+ }
76379
+ return false;
76380
+ }
76381
+ function parseTomlTableHeader2(line) {
76382
+ if (!line.startsWith("[") || !line.endsWith("]") || line.startsWith("[["))
76383
+ return null;
76384
+ return parseTomlDottedKey(line.slice(1, -1).trim());
76385
+ }
76386
+ function isTomlTableHeaderLine2(line) {
76387
+ return line.startsWith("[") && line.endsWith("]");
76388
+ }
76389
+ function stripUnquotedInlineComment2(line) {
76390
+ let quote = null;
76391
+ let index = 0;
76392
+ while (index < line.length) {
76393
+ const char = line[index];
76394
+ if (quote === '"') {
76395
+ if (char === "\\") {
76396
+ index += 2;
76397
+ continue;
76398
+ }
76399
+ if (char === '"')
76400
+ quote = null;
76401
+ index += 1;
76402
+ continue;
76403
+ }
76404
+ if (quote === "'") {
76405
+ if (char === "'")
76406
+ quote = null;
76407
+ index += 1;
76408
+ continue;
76409
+ }
76410
+ if (char === '"' || char === "'") {
76411
+ quote = char;
76412
+ index += 1;
76413
+ continue;
76414
+ }
76415
+ if (char === "#")
76416
+ return line.slice(0, index);
76417
+ index += 1;
76418
+ }
76419
+ return line;
76420
+ }
76421
+ function findUnquotedAssignment2(line) {
76422
+ let quote = null;
76423
+ let index = 0;
76424
+ while (index < line.length) {
76425
+ const char = line[index];
76426
+ if (quote === '"') {
76427
+ if (char === "\\") {
76428
+ index += 2;
76429
+ continue;
76430
+ }
76431
+ if (char === '"')
76432
+ quote = null;
76433
+ index += 1;
76434
+ continue;
76435
+ }
76436
+ if (quote === "'") {
76437
+ if (char === "'")
76438
+ quote = null;
76439
+ index += 1;
76440
+ continue;
76441
+ }
76442
+ if (char === '"' || char === "'") {
76443
+ quote = char;
76444
+ index += 1;
76445
+ continue;
76446
+ }
76447
+ if (char === "=")
76448
+ return index;
76449
+ index += 1;
76450
+ }
76451
+ return -1;
76452
+ }
76453
+
76106
76454
  // packages/omo-codex/src/install/codex-config-features.ts
76107
76455
  function ensureFeatureEnabled(config, featureName) {
76108
76456
  const section = findTomlSection(config, "features");
76109
- if (!section)
76457
+ if (!section) {
76458
+ if (hasTomlRootDottedKeyPrefix(config, "features")) {
76459
+ return replaceOrInsertRootDottedSetting(config, `features.${featureName}`, "true");
76460
+ }
76110
76461
  return appendBlock(config, `[features]
76111
76462
  ${featureName} = true
76112
76463
  `);
76464
+ }
76113
76465
  return replaceOrInsertSetting(config, section, featureName, "true");
76114
76466
  }
76115
76467
 
@@ -76177,7 +76529,7 @@ function ensureAutonomousPermissions(config) {
76177
76529
  next = replaceOrInsertRootSetting(next, "sandbox_mode", JSON.stringify("danger-full-access"));
76178
76530
  next = replaceOrInsertRootSetting(next, "network_access", JSON.stringify("enabled"));
76179
76531
  for (const featureName of AUTONOMOUS_FEATURES) {
76180
- next = ensureFeatureEnabled2(next, featureName);
76532
+ next = ensureFeatureEnabled(next, featureName);
76181
76533
  }
76182
76534
  next = removeWindowsSandboxSetting(next);
76183
76535
  next = ensureNoticeEnabled(next, "hide_full_access_warning");
@@ -76195,14 +76547,6 @@ function ensureNoticeEnabled(config, key) {
76195
76547
  return appendNoticeBlock(config, key);
76196
76548
  return replaceOrInsertSetting(config, section, key, "true");
76197
76549
  }
76198
- function ensureFeatureEnabled2(config, key) {
76199
- const section = findTomlSection(config, "features");
76200
- if (section === null)
76201
- return appendBlock(config, `[features]
76202
- ${key} = true
76203
- `);
76204
- return replaceOrInsertSetting(config, section, key, "true");
76205
- }
76206
76550
  function appendNoticeBlock(config, key) {
76207
76551
  return appendBlock(config, `[notice]
76208
76552
  ${key} = true
@@ -76274,7 +76618,7 @@ function readStringArraySetting(sectionText, key) {
76274
76618
  const assignmentIndex = line.indexOf("=");
76275
76619
  if (assignmentIndex === -1)
76276
76620
  return null;
76277
- return parseTomlStringArray(stripUnquotedInlineComment2(line.slice(assignmentIndex + 1)).trim());
76621
+ return parseTomlStringArray(stripUnquotedInlineComment3(line.slice(assignmentIndex + 1)).trim());
76278
76622
  }
76279
76623
  return null;
76280
76624
  }
@@ -76318,7 +76662,7 @@ function parseTomlString(input, startIndex) {
76318
76662
  }
76319
76663
  return null;
76320
76664
  }
76321
- function stripUnquotedInlineComment2(line) {
76665
+ function stripUnquotedInlineComment3(line) {
76322
76666
  let quote = null;
76323
76667
  let index = 0;
76324
76668
  while (index < line.length) {
@@ -76532,24 +76876,27 @@ import { readFileSync as readFileSync13 } from "fs";
76532
76876
  import { dirname as dirname15, isAbsolute as isAbsolute8, join as join39 } from "path";
76533
76877
  var CODEX_AGENTS_HEADER = "agents";
76534
76878
  var CODEX_MULTI_AGENT_V2_HEADER = "features.multi_agent_v2";
76879
+ var CODEX_MULTI_AGENT_V2_THREAD_LIMIT_KEY = `${CODEX_MULTI_AGENT_V2_HEADER}.max_concurrent_threads_per_session`;
76535
76880
  var CODEX_SUBAGENT_THREAD_LIMIT = 1000;
76881
+ var CODEX_MULTI_AGENT_V2_THREAD_LIMIT = 16;
76536
76882
  function ensureCodexMultiAgentV2Config(config, options = {}) {
76537
76883
  const featureFlag = removeFeatureFlagSetting(config, "multi_agent_v2");
76538
76884
  const v2Preferred = options.multiAgentVersion === "v2";
76539
76885
  const modelKnown = options.multiAgentVersion != null || readRootModel(featureFlag.config) !== null;
76540
76886
  const agentsConfig = v2Preferred ? removeAgentsMaxThreads(featureFlag.config) : modelKnown ? ensureAgentsMaxThreads(featureFlag.config) : raiseExistingAgentsMaxThreads(featureFlag.config);
76541
- const maxThreadsValue = CODEX_SUBAGENT_THREAD_LIMIT.toString();
76542
76887
  const preserveDisable = featureFlag.value === false && !v2Preferred;
76543
76888
  const featureConfig = preserveDisable ? setMultiAgentV2Disable(agentsConfig) : v2Preferred ? removeMultiAgentV2Disable(agentsConfig) : agentsConfig;
76889
+ if (hasTomlSetting(featureConfig, CODEX_MULTI_AGENT_V2_THREAD_LIMIT_KEY))
76890
+ return featureConfig;
76544
76891
  const section = findTomlSection(featureConfig, CODEX_MULTI_AGENT_V2_HEADER);
76545
76892
  if (!section) {
76546
76893
  const enabledSetting = preserveDisable ? `enabled = false
76547
76894
  ` : "";
76548
76895
  return appendBlock(featureConfig, `[${CODEX_MULTI_AGENT_V2_HEADER}]
76549
- ${enabledSetting}max_concurrent_threads_per_session = ${maxThreadsValue}
76896
+ ${enabledSetting}max_concurrent_threads_per_session = ${CODEX_MULTI_AGENT_V2_THREAD_LIMIT}
76550
76897
  `);
76551
76898
  }
76552
- return replaceOrInsertSetting(featureConfig, section, "max_concurrent_threads_per_session", maxThreadsValue);
76899
+ return replaceOrInsertSetting(featureConfig, section, "max_concurrent_threads_per_session", CODEX_MULTI_AGENT_V2_THREAD_LIMIT.toString());
76553
76900
  }
76554
76901
  function resolveCodexMultiAgentVersion(config, configPath) {
76555
76902
  const model = readRootModel(config);
@@ -76908,6 +77255,10 @@ var MANAGED_REASONING_DEFAULT_UPGRADES = new Map([
76908
77255
  {
76909
77256
  previous: { model: "gpt-5.5", effort: "xhigh" },
76910
77257
  current: { model: "gpt-5.6-sol", effort: "ultra" }
77258
+ },
77259
+ {
77260
+ previous: { model: "gpt-5.6-sol", effort: "ultra" },
77261
+ current: { model: "gpt-5.6-terra", effort: "high" }
76911
77262
  }
76912
77263
  ]
76913
77264
  ],
@@ -78970,8 +79321,24 @@ import { promisify as promisify2 } from "util";
78970
79321
  var execFileAsync2 = promisify2(execFile4);
78971
79322
  var REQUIRED_PLUGIN_ARTIFACTS = [
78972
79323
  join58("extensions", "omo.js"),
79324
+ join58("skills", "ast-grep", "SKILL.md"),
79325
+ join58("skills", "coding-agent-sessions", "SKILL.md"),
79326
+ join58("skills", "debugging", "SKILL.md"),
79327
+ join58("skills", "frontend", "SKILL.md"),
79328
+ join58("skills", "git-master", "SKILL.md"),
79329
+ join58("skills", "init-deep", "SKILL.md"),
79330
+ join58("skills", "lsp-setup", "SKILL.md"),
79331
+ join58("skills", "programming", "SKILL.md"),
79332
+ join58("skills", "refactor", "SKILL.md"),
79333
+ join58("skills", "remove-ai-slops", "SKILL.md"),
79334
+ join58("skills", "review-work", "SKILL.md"),
79335
+ join58("skills", "start-work", "SKILL.md"),
79336
+ join58("skills", "ultimate-browsing", "SKILL.md"),
78973
79337
  join58("skills", "ultrawork", "SKILL.md"),
78974
79338
  join58("skills", "ulw-loop", "SKILL.md"),
79339
+ join58("skills", "ulw-plan", "SKILL.md"),
79340
+ join58("skills", "ulw-research", "SKILL.md"),
79341
+ join58("skills", "visual-qa", "SKILL.md"),
78975
79342
  join58("runtime", "lsp-daemon", "dist", "cli.js"),
78976
79343
  join58("runtime", "lsp-daemon", "dist", "index.js"),
78977
79344
  join58("runtime", "lsp-daemon", "dist", "index.d.ts"),
@@ -79025,6 +79392,7 @@ async function ensurePluginArtifacts(context) {
79025
79392
  throw new Error(`Packed omo-senpi plugin is missing required runtime artifacts at ${context.pluginPath}`);
79026
79393
  }
79027
79394
  await context.runCommand("node", [join58(context.pluginPath, "scripts", "build-extension.mjs")], { cwd: context.repoRoot });
79395
+ await context.runCommand("node", [join58("packages", "omo-codex", "plugin", "scripts", "materialize-shared-upstreams.mjs")], { cwd: context.repoRoot });
79028
79396
  await context.runCommand("node", [join58(context.pluginPath, "scripts", "sync-skills.mjs")], { cwd: context.repoRoot });
79029
79397
  await context.runCommand("node", [join58(context.pluginPath, "scripts", "build-install.mjs")], { cwd: context.repoRoot });
79030
79398
  await context.runCommand("node", [join58(context.pluginPath, "scripts", "stage-lsp-daemon-runtime.mjs")], { cwd: context.repoRoot });
@@ -96654,7 +97022,8 @@ var BrowserAutomationProviderSchema = exports_external.enum([
96654
97022
  "playwright-cli"
96655
97023
  ]);
96656
97024
  var BrowserAutomationConfigSchema = exports_external.object({
96657
- provider: BrowserAutomationProviderSchema.default("playwright")
97025
+ provider: BrowserAutomationProviderSchema.default("playwright"),
97026
+ playwright_mcp_args: exports_external.array(exports_external.string()).optional()
96658
97027
  });
96659
97028
  // packages/omo-opencode/src/config/schema/categories.ts
96660
97029
  var CategoryConfigSchema = exports_external.object({
@@ -96716,9 +97085,7 @@ var CommentCheckerConfigSchema = exports_external.object({
96716
97085
  });
96717
97086
  // packages/omo-opencode/src/config/schema/commands.ts
96718
97087
  var BuiltinCommandNameSchema = exports_external.enum([
96719
- "ralph-loop",
96720
- "ulw-loop",
96721
- "cancel-ralph",
97088
+ "goal",
96722
97089
  "refactor",
96723
97090
  "start-work",
96724
97091
  "stop-continuation",
@@ -96728,7 +97095,7 @@ var BuiltinCommandNameSchema = exports_external.enum([
96728
97095
  // packages/omo-opencode/src/config/schema/default-mode.ts
96729
97096
  var DefaultModeConfigSchema = exports_external.object({
96730
97097
  ultrawork: exports_external.boolean().default(false),
96731
- ralph_loop: exports_external.boolean().default(false)
97098
+ goal: exports_external.boolean().default(false)
96732
97099
  });
96733
97100
  // packages/omo-opencode/src/config/schema/dynamic-context-pruning.ts
96734
97101
  var DynamicContextPruningConfigSchema = exports_external.object({
@@ -96776,6 +97143,12 @@ var ExperimentalConfigSchema = exports_external.object({
96776
97143
  max_tools: exports_external.number().int().min(1).optional(),
96777
97144
  disable_live_parent_wake_routing: exports_external.boolean().optional()
96778
97145
  });
97146
+ // packages/omo-opencode/src/config/schema/goal.ts
97147
+ var GoalConfigSchema = exports_external.object({
97148
+ enabled: exports_external.boolean().default(false),
97149
+ auto_start: exports_external.boolean().default(false),
97150
+ default_max_iterations: exports_external.number().min(1).max(1000).default(100)
97151
+ });
96779
97152
  // packages/skills-loader-core/src/config/git-env-prefix.ts
96780
97153
  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_-]*)*$/;
96781
97154
  var GIT_ENV_PREFIX_VALIDATION_MESSAGE = 'git_env_prefix must be empty or use shell-safe env assignments like "GIT_MASTER=1"';
@@ -96818,7 +97191,7 @@ var HookNameSchema = exports_external.enum([
96818
97191
  "interactive-bash-session",
96819
97192
  "tool-pair-validator",
96820
97193
  "monitor-status-injector",
96821
- "ralph-loop",
97194
+ "goal",
96822
97195
  "category-skill-reminder",
96823
97196
  "compaction-context-injector",
96824
97197
  "compaction-todo-preserver",
@@ -96928,14 +97301,6 @@ var MonitorConfigSchema = exports_external.object({
96928
97301
  pattern_max_length: exports_external.number().int().min(1).default(512)
96929
97302
  });
96930
97303
 
96931
- // packages/omo-opencode/src/config/schema/ralph-loop.ts
96932
- var RalphLoopConfigSchema = exports_external.object({
96933
- enabled: exports_external.boolean().default(false),
96934
- default_max_iterations: exports_external.number().min(1).max(1000).default(100),
96935
- state_dir: exports_external.string().optional(),
96936
- default_strategy: exports_external.enum(["reset", "continue"]).default("continue")
96937
- });
96938
-
96939
97304
  // packages/omo-opencode/src/config/schema/runtime-fallback.ts
96940
97305
  var RuntimeFallbackConfigSchema = exports_external.object({
96941
97306
  enabled: exports_external.boolean().optional(),
@@ -97071,7 +97436,8 @@ var OhMyOpenCodeConfigSchema = exports_external.object({
97071
97436
  experimental: ExperimentalConfigSchema.optional(),
97072
97437
  auto_update: exports_external.boolean().optional(),
97073
97438
  skills: SkillsConfigSchema.optional(),
97074
- ralph_loop: RalphLoopConfigSchema.optional(),
97439
+ goal: GoalConfigSchema.optional(),
97440
+ ralph_loop: exports_external.record(exports_external.string(), exports_external.unknown()).optional(),
97075
97441
  runtime_fallback: exports_external.union([exports_external.boolean(), RuntimeFallbackConfigSchema]).optional(),
97076
97442
  background_task: BackgroundTaskConfigSchema.optional(),
97077
97443
  notification: NotificationConfigSchema.optional(),
@@ -97454,6 +97820,7 @@ function loadPluginConfig(directory, ctx) {
97454
97820
  }
97455
97821
  }
97456
97822
  const userMcpEnvAllowlist = config3.mcp_env_allowlist ?? [];
97823
+ const userPlaywrightMcpArgs = config3.browser_automation_engine?.playwright_mcp_args;
97457
97824
  const canonicalAncestorPathsFarthestFirst = [...canonicalAncestorPathsNearestFirst].reverse();
97458
97825
  const defaultGitMaster = OhMyOpenCodeConfigSchema.parse({}).git_master;
97459
97826
  const ancestorGitMasterOverridesFarthestFirst = [];
@@ -97486,6 +97853,16 @@ function loadPluginConfig(directory, ctx) {
97486
97853
  ...config3,
97487
97854
  mcp_env_allowlist: userMcpEnvAllowlist
97488
97855
  };
97856
+ if (config3.browser_automation_engine) {
97857
+ const {
97858
+ playwright_mcp_args: _ancestorPlaywrightMcpArgs,
97859
+ ...browserAutomationEngine
97860
+ } = config3.browser_automation_engine;
97861
+ config3 = {
97862
+ ...config3,
97863
+ browser_automation_engine: userPlaywrightMcpArgs !== undefined ? { ...browserAutomationEngine, playwright_mcp_args: userPlaywrightMcpArgs } : browserAutomationEngine
97864
+ };
97865
+ }
97489
97866
  applyDisabledProviders(config3);
97490
97867
  log2("Final merged config", {
97491
97868
  agents: config3.agents,
@@ -97957,22 +98334,170 @@ var BOULDER_FILE = "boulder.json";
97957
98334
  var BOULDER_STATE_PATH = `${BOULDER_DIR}/${BOULDER_FILE}`;
97958
98335
  var NOTEPAD_DIR = "notepads";
97959
98336
  var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
97960
- // packages/boulder-state/src/top-level-task.ts
97961
- import { existsSync as existsSync37, readFileSync as readFileSync19 } from "fs";
97962
- var TODO_HEADING_PATTERN = /^##\s+TODOs\b/i;
97963
- var FINAL_VERIFICATION_HEADING_PATTERN = /^##\s+Final Verification Wave\b/i;
97964
- var SECOND_LEVEL_HEADING_PATTERN = /^##\s+/;
97965
- var UNCHECKED_CHECKBOX_PATTERN = /^(\s*)[-*]\s*\[\s*\]\s*(.+)$/;
97966
- var TODO_TASK_PATTERN = /^(\d+)\.\s+(.+)$/;
97967
- var FINAL_WAVE_TASK_PATTERN = /^(F\d+)\.\s+(.+)$/i;
97968
- function buildTaskRef(section, taskLabel) {
97969
- const pattern = section === "todo" ? TODO_TASK_PATTERN : FINAL_WAVE_TASK_PATTERN;
97970
- const match = taskLabel.match(pattern);
97971
- if (!match) {
98337
+ // packages/boulder-state/src/plan-checklist.ts
98338
+ var SIMPLE_CHECKBOX_PATTERN = /^[-*][ \t]*\[[ \t]*([xX]?)[ \t]*\][ \t]+(.+)$/;
98339
+ var TODO_HEADING_PATTERN = /^##[ \t]+TODOs(?:[ \t]+#+)?[ \t]*$/i;
98340
+ var FINAL_VERIFICATION_HEADING_PATTERN = /^##[ \t]+Final Verification Wave(?:[ \t]+#+)?[ \t]*$/i;
98341
+ var SECTION_BOUNDARY_HEADING_PATTERN = /^#{1,2}(?:[ \t]+|$)/;
98342
+ var FENCE_PATTERN = /^[ \t]{0,3}(`{3,}|~{3,})(.*)$/;
98343
+ var TODO_CHECKBOX_PATTERN = /^- \[([ xX])\] ([1-9]\d*\. .+)$/;
98344
+ var FINAL_WAVE_CHECKBOX_PATTERN = /^- \[([ xX])\] (F[1-9]\d*\. .+)$/i;
98345
+ function parsePlanChecklist(markdown) {
98346
+ const lines = markdown.split(/\r?\n/);
98347
+ if (!hasStructuredSection(lines)) {
98348
+ return parseSimpleChecklist(lines);
98349
+ }
98350
+ return parseStructuredPlan(lines).checklist;
98351
+ }
98352
+ function parseCurrentTopLevelTask(markdown) {
98353
+ const lines = markdown.split(/\r?\n/);
98354
+ if (!hasStructuredSection(lines)) {
98355
+ return null;
98356
+ }
98357
+ return parseStructuredPlan(lines).nextTask;
98358
+ }
98359
+ function parseStructuredPlan(lines) {
98360
+ let remaining = 0;
98361
+ let total = 0;
98362
+ let nextTaskLabel = null;
98363
+ let nextTask = null;
98364
+ let section = "other";
98365
+ let fence = null;
98366
+ for (const line of lines) {
98367
+ if (fence !== null) {
98368
+ if (isClosingFence(line, fence)) {
98369
+ fence = null;
98370
+ }
98371
+ continue;
98372
+ }
98373
+ const openingFence = parseOpeningFence(line);
98374
+ if (openingFence !== null) {
98375
+ fence = openingFence;
98376
+ continue;
98377
+ }
98378
+ if (SECTION_BOUNDARY_HEADING_PATTERN.test(line)) {
98379
+ section = parseStructuredSectionHeading(line);
98380
+ continue;
98381
+ }
98382
+ if (section === "other") {
98383
+ continue;
98384
+ }
98385
+ const checkbox = parseStructuredTopLevelCheckbox(line, section);
98386
+ if (checkbox === null) {
98387
+ continue;
98388
+ }
98389
+ total += 1;
98390
+ if (checkbox.checked) {
98391
+ continue;
98392
+ }
98393
+ remaining += 1;
98394
+ if (nextTaskLabel === null) {
98395
+ nextTaskLabel = checkbox.label;
98396
+ nextTask = checkbox.task;
98397
+ }
98398
+ }
98399
+ return {
98400
+ checklist: {
98401
+ completed: total - remaining,
98402
+ remaining,
98403
+ total,
98404
+ nextTaskLabel
98405
+ },
98406
+ nextTask
98407
+ };
98408
+ }
98409
+ function parseSimpleChecklist(lines) {
98410
+ let remaining = 0;
98411
+ let total = 0;
98412
+ let nextTaskLabel = null;
98413
+ let fence = null;
98414
+ for (const line of lines) {
98415
+ if (fence !== null) {
98416
+ if (isClosingFence(line, fence)) {
98417
+ fence = null;
98418
+ }
98419
+ continue;
98420
+ }
98421
+ const openingFence = parseOpeningFence(line);
98422
+ if (openingFence !== null) {
98423
+ fence = openingFence;
98424
+ continue;
98425
+ }
98426
+ const checkbox = parseSimpleTopLevelCheckbox(line);
98427
+ if (checkbox === null) {
98428
+ continue;
98429
+ }
98430
+ total += 1;
98431
+ if (checkbox.checked) {
98432
+ continue;
98433
+ }
98434
+ remaining += 1;
98435
+ if (nextTaskLabel === null) {
98436
+ nextTaskLabel = checkbox.label;
98437
+ }
98438
+ }
98439
+ return { completed: total - remaining, remaining, total, nextTaskLabel };
98440
+ }
98441
+ function parseSimpleTopLevelCheckbox(line) {
98442
+ const match = line.match(SIMPLE_CHECKBOX_PATTERN);
98443
+ const marker = match?.[1];
98444
+ const label = match?.[2];
98445
+ if (marker === undefined || label === undefined) {
98446
+ return null;
98447
+ }
98448
+ return { checked: marker.toLowerCase() === "x", label };
98449
+ }
98450
+ function hasStructuredSection(lines) {
98451
+ let fence = null;
98452
+ for (const line of lines) {
98453
+ if (fence !== null) {
98454
+ if (isClosingFence(line, fence)) {
98455
+ fence = null;
98456
+ }
98457
+ continue;
98458
+ }
98459
+ const openingFence = parseOpeningFence(line);
98460
+ if (openingFence !== null) {
98461
+ fence = openingFence;
98462
+ continue;
98463
+ }
98464
+ if (parseStructuredSectionHeading(line) !== "other") {
98465
+ return true;
98466
+ }
98467
+ }
98468
+ return false;
98469
+ }
98470
+ function parseStructuredSectionHeading(line) {
98471
+ if (TODO_HEADING_PATTERN.test(line)) {
98472
+ return "todo";
98473
+ }
98474
+ if (FINAL_VERIFICATION_HEADING_PATTERN.test(line)) {
98475
+ return "final-wave";
98476
+ }
98477
+ return "other";
98478
+ }
98479
+ function parseStructuredTopLevelCheckbox(line, section) {
98480
+ const pattern = section === "todo" ? TODO_CHECKBOX_PATTERN : FINAL_WAVE_CHECKBOX_PATTERN;
98481
+ const match = line.match(pattern);
98482
+ const marker = match?.[1];
98483
+ const label = match?.[2];
98484
+ if (marker === undefined || label === undefined) {
98485
+ return null;
98486
+ }
98487
+ const task = buildTaskRef(section, label);
98488
+ if (task === null) {
98489
+ return null;
98490
+ }
98491
+ return { checked: marker.toLowerCase() === "x", label, task };
98492
+ }
98493
+ function buildTaskRef(section, label) {
98494
+ const pattern = section === "todo" ? /^([1-9]\d*)\. (.+)$/ : /^(F[1-9]\d*)\. (.+)$/i;
98495
+ const match = label.match(pattern);
98496
+ const rawLabel = match?.[1];
98497
+ const title = match?.[2];
98498
+ if (rawLabel === undefined || title === undefined) {
97972
98499
  return null;
97973
98500
  }
97974
- const rawLabel = match[1];
97975
- const title = match[2].trim();
97976
98501
  return {
97977
98502
  key: `${section}:${rawLabel.toLowerCase()}`,
97978
98503
  section,
@@ -97980,31 +98505,29 @@ function buildTaskRef(section, taskLabel) {
97980
98505
  title
97981
98506
  };
97982
98507
  }
98508
+ function parseOpeningFence(line) {
98509
+ const match = line.match(FENCE_PATTERN);
98510
+ const run = match?.[1];
98511
+ const info = match?.[2];
98512
+ const marker = run?.charAt(0);
98513
+ if (run === undefined || info === undefined || marker !== "`" && marker !== "~" || marker === "`" && info.includes("`")) {
98514
+ return null;
98515
+ }
98516
+ return { marker, length: run.length };
98517
+ }
98518
+ function isClosingFence(line, fence) {
98519
+ const run = line.match(/^[ \t]{0,3}(`{3,}|~{3,})[ \t]*$/)?.[1];
98520
+ return run?.charAt(0) === fence.marker && run.length >= fence.length;
98521
+ }
98522
+ // packages/boulder-state/src/top-level-task.ts
98523
+ import { existsSync as existsSync37, readFileSync as readFileSync19 } from "fs";
97983
98524
  function readCurrentTopLevelTask(planPath) {
97984
98525
  if (!existsSync37(planPath)) {
97985
98526
  return null;
97986
98527
  }
97987
98528
  try {
97988
98529
  const content = readFileSync19(planPath, "utf-8");
97989
- const lines = content.split(/\r?\n/);
97990
- let section = "other";
97991
- for (const line of lines) {
97992
- if (SECOND_LEVEL_HEADING_PATTERN.test(line)) {
97993
- section = TODO_HEADING_PATTERN.test(line) ? "todo" : FINAL_VERIFICATION_HEADING_PATTERN.test(line) ? "final-wave" : "other";
97994
- }
97995
- const uncheckedTaskMatch = line.match(UNCHECKED_CHECKBOX_PATTERN);
97996
- if (!uncheckedTaskMatch || uncheckedTaskMatch[1].length > 0) {
97997
- continue;
97998
- }
97999
- if (section !== "todo" && section !== "final-wave") {
98000
- continue;
98001
- }
98002
- const taskRef = buildTaskRef(section, uncheckedTaskMatch[2].trim());
98003
- if (taskRef) {
98004
- return taskRef;
98005
- }
98006
- }
98007
- return null;
98530
+ return parseCurrentTopLevelTask(content);
98008
98531
  } catch {
98009
98532
  return null;
98010
98533
  }
@@ -98038,69 +98561,25 @@ function resolveBoulderPlanPathForWork(directory, work) {
98038
98561
  }
98039
98562
  // packages/boulder-state/src/storage/plan-progress.ts
98040
98563
  import { existsSync as existsSync39, readFileSync as readFileSync20, readdirSync as readdirSync5, statSync as statSync5 } from "fs";
98041
- var TODO_HEADING_PATTERN2 = /^##\s+TODOs\b/i;
98042
- var FINAL_VERIFICATION_HEADING_PATTERN2 = /^##\s+Final Verification Wave\b/i;
98043
- var SECOND_LEVEL_HEADING_PATTERN2 = /^##\s+/;
98044
- var UNCHECKED_CHECKBOX_PATTERN2 = /^(\s*)[-*]\s*\[\s*\]\s*(.+)$/;
98045
- var CHECKED_CHECKBOX_PATTERN = /^(\s*)[-*]\s*\[[xX]\]\s*(.+)$/;
98046
- var TODO_TASK_PATTERN2 = /^\d+\.\s+/;
98047
- var FINAL_WAVE_TASK_PATTERN2 = /^F\d+\.\s+/i;
98048
98564
  function getPlanProgress(planPath) {
98049
98565
  if (!existsSync39(planPath)) {
98050
98566
  return { total: 0, completed: 0, isComplete: false };
98051
98567
  }
98052
98568
  try {
98053
98569
  const content = readFileSync20(planPath, "utf-8");
98054
- const lines = content.split(/\r?\n/);
98055
- const hasStructuredSections = lines.some((line) => TODO_HEADING_PATTERN2.test(line) || FINAL_VERIFICATION_HEADING_PATTERN2.test(line));
98056
- if (hasStructuredSections) {
98057
- return getStructuredPlanProgress(lines);
98058
- }
98059
- return getSimplePlanProgress(content);
98570
+ const checklist = parsePlanChecklist(content);
98571
+ return {
98572
+ total: checklist.total,
98573
+ completed: checklist.completed,
98574
+ isComplete: checklist.total > 0 && checklist.remaining === 0
98575
+ };
98060
98576
  } catch {
98061
98577
  return { total: 0, completed: 0, isComplete: false };
98062
98578
  }
98063
98579
  }
98064
- function getStructuredPlanProgress(lines) {
98065
- let section = "other";
98066
- let total = 0;
98067
- let completed = 0;
98068
- for (const line of lines) {
98069
- if (SECOND_LEVEL_HEADING_PATTERN2.test(line)) {
98070
- section = TODO_HEADING_PATTERN2.test(line) ? "todo" : FINAL_VERIFICATION_HEADING_PATTERN2.test(line) ? "final-wave" : "other";
98071
- continue;
98072
- }
98073
- if (section !== "todo" && section !== "final-wave") {
98074
- continue;
98075
- }
98076
- const checkedMatch = line.match(CHECKED_CHECKBOX_PATTERN);
98077
- const uncheckedMatch = checkedMatch ? null : line.match(UNCHECKED_CHECKBOX_PATTERN2);
98078
- const match = checkedMatch ?? uncheckedMatch;
98079
- if (!match || match[1].length > 0) {
98080
- continue;
98081
- }
98082
- const taskBody = match[2].trim();
98083
- const labelPattern = section === "todo" ? TODO_TASK_PATTERN2 : FINAL_WAVE_TASK_PATTERN2;
98084
- if (!labelPattern.test(taskBody)) {
98085
- continue;
98086
- }
98087
- total += 1;
98088
- if (checkedMatch) {
98089
- completed += 1;
98090
- }
98091
- }
98092
- return { total, completed, isComplete: total > 0 && completed === total };
98093
- }
98094
- function getSimplePlanProgress(content) {
98095
- const uncheckedMatches = content.match(/^[-*]\s*\[\s*\]/gm) ?? [];
98096
- const checkedMatches = content.match(/^[-*]\s*\[[xX]\]/gm) ?? [];
98097
- const total = uncheckedMatches.length + checkedMatches.length;
98098
- const completed = checkedMatches.length;
98099
- return { total, completed, isComplete: total > 0 && completed === total };
98100
- }
98101
98580
  // packages/boulder-state/src/storage/shared.ts
98102
98581
  var RESERVED_KEYS = new Set(["__proto__", "prototype", "constructor"]);
98103
- var SESSION_ID_PREFIX_PATTERN = /^(codex|opencode):/;
98582
+ var SESSION_ID_PREFIX_PATTERN = /^(codex|opencode|senpi):/;
98104
98583
  function normalizeSessionId(sessionId, platform = "opencode") {
98105
98584
  if (SESSION_ID_PREFIX_PATTERN.test(sessionId)) {
98106
98585
  return sessionId;
@@ -98175,7 +98654,7 @@ function readBoulderState(directory) {
98175
98654
  try {
98176
98655
  const content = readFileSync21(filePath, "utf-8");
98177
98656
  const parsed = JSON.parse(content);
98178
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
98657
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed) || Object.keys(parsed).length === 0) {
98179
98658
  return null;
98180
98659
  }
98181
98660
  normalizeState(parsed);
@@ -100132,6 +100611,7 @@ import { readFileSync as readFileSync35 } from "fs";
100132
100611
  import { homedir as homedir16 } from "os";
100133
100612
  import { dirname as dirname29, relative as relative9 } from "path";
100134
100613
  init_shared();
100614
+ init_logger2();
100135
100615
  init_plugin_identity();
100136
100616
  function resolveHomeDirectory2() {
100137
100617
  return process.env.HOME ?? process.env.USERPROFILE ?? homedir16();
@@ -100220,13 +100700,45 @@ function mergeLoadedConfig(userLayersNearestFirst, projectLayersNearestFirst) {
100220
100700
  config3 = mergeConfigs2(config3, layer.config);
100221
100701
  }
100222
100702
  const userMcpEnvAllowlist = config3.mcp_env_allowlist ?? [];
100703
+ const userPlaywrightMcpArgs = config3.browser_automation_engine?.playwright_mcp_args;
100223
100704
  for (const layer of [...projectLayersNearestFirst].reverse()) {
100224
100705
  if (layer.config)
100225
100706
  config3 = mergeConfigs2(config3, layer.config);
100226
100707
  }
100227
100708
  config3 = { ...config3, mcp_env_allowlist: userMcpEnvAllowlist };
100709
+ if (config3.browser_automation_engine) {
100710
+ const {
100711
+ playwright_mcp_args: _projectPlaywrightMcpArgs,
100712
+ ...browserAutomationEngine
100713
+ } = config3.browser_automation_engine;
100714
+ config3 = {
100715
+ ...config3,
100716
+ browser_automation_engine: userPlaywrightMcpArgs !== undefined ? { ...browserAutomationEngine, playwright_mcp_args: userPlaywrightMcpArgs } : browserAutomationEngine
100717
+ };
100718
+ }
100228
100719
  return applyDisabledProviders(config3);
100229
100720
  }
100721
+ function migrateRalphLoopConfig(config3) {
100722
+ const legacy = config3.ralph_loop;
100723
+ if (legacy === undefined) {
100724
+ return config3;
100725
+ }
100726
+ const enabled = typeof legacy.enabled === "boolean" ? legacy.enabled : undefined;
100727
+ const defaultMaxIterations = typeof legacy.default_max_iterations === "number" ? legacy.default_max_iterations : undefined;
100728
+ if (enabled === undefined && defaultMaxIterations === undefined) {
100729
+ return config3;
100730
+ }
100731
+ log2("[config] ralph_loop is deprecated and will be removed in a future release. Use goal instead.");
100732
+ const existingGoal = config3.goal;
100733
+ return {
100734
+ ...config3,
100735
+ goal: {
100736
+ enabled: existingGoal?.enabled ?? enabled ?? false,
100737
+ auto_start: existingGoal?.auto_start ?? false,
100738
+ default_max_iterations: existingGoal?.default_max_iterations ?? defaultMaxIterations ?? 100
100739
+ }
100740
+ };
100741
+ }
100230
100742
  function validatePluginConfig(directory) {
100231
100743
  const userLayersNearestFirst = discoverUserLayers().map((layer) => parseLayerConfig(layer.path));
100232
100744
  const projectLayersNearestFirst = discoverProjectLayersNearestFirst(directory).map((layer) => parseLayerConfig(layer.path));
@@ -100236,7 +100748,7 @@ function validatePluginConfig(directory) {
100236
100748
  valid: messages.length === 0,
100237
100749
  messages,
100238
100750
  path: firstFailingPath(layers) ?? firstPath(layers),
100239
- config: mergeLoadedConfig(userLayersNearestFirst, projectLayersNearestFirst)
100751
+ config: migrateRalphLoopConfig(mergeLoadedConfig(userLayersNearestFirst, projectLayersNearestFirst))
100240
100752
  };
100241
100753
  }
100242
100754