oh-my-opencode 5.1.30 → 5.1.32

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 (83) hide show
  1. package/dist/cli/index.js +25 -19
  2. package/dist/cli/service-auth/commands.d.ts +11 -0
  3. package/dist/cli-node/index.js +25 -19
  4. package/dist/features/background-agent/task-poller.d.ts +3 -0
  5. package/dist/features/team-mode/tools/lifecycle-inline-spec.d.ts +1 -0
  6. package/dist/hooks/keyword-detector/constants.d.ts +1 -0
  7. package/dist/index.js +172 -60
  8. package/dist/skills/browser/runtime/omowright/manifest.json +1 -1
  9. package/dist/skills/ulw-execute/SKILL.md +2 -2
  10. package/dist/tools/delegate-task/executor-types.d.ts +1 -0
  11. package/dist/tools/delegate-task/sync-session-creator.d.ts +1 -0
  12. package/dist/tools/delegate-task/types.d.ts +2 -0
  13. package/dist/tools/session-manager/session-error.d.ts +7 -0
  14. package/dist/tui.js +18 -16
  15. package/package.json +14 -14
  16. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  17. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +4 -2
  18. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  19. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  20. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  21. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  22. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  23. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  24. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  25. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  26. package/packages/omo-codex/plugin/components/lcx/skills/lcx-contribute-bug-fix/SKILL.md +7 -4
  27. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
  28. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  29. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  30. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  31. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  32. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  33. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  34. package/packages/omo-codex/plugin/components/teammode/skills/teammode/SKILL.md +3 -3
  35. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  36. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  37. package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +18 -15
  38. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  39. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  40. package/packages/omo-codex/plugin/components/ultrawork/src/directive-content.ts +1 -1
  41. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +1 -1
  42. package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
  43. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +18 -15
  44. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
  45. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  46. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +2 -2
  47. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +2 -2
  48. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  49. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  50. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  51. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  52. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  53. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  54. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  55. package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +1 -1
  56. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  57. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  58. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  59. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  60. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  61. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  62. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  63. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
  64. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  65. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  66. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  67. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  68. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  69. package/packages/omo-codex/plugin/package-lock.json +12 -12
  70. package/packages/omo-codex/plugin/package.json +1 -1
  71. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +2 -2
  72. package/packages/omo-codex/plugin/skills/browser/runtime/omowright/manifest.json +1 -1
  73. package/packages/omo-codex/plugin/skills/lcx-contribute-bug-fix/SKILL.md +7 -4
  74. package/packages/omo-codex/plugin/skills/teammode/SKILL.md +3 -3
  75. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +18 -15
  76. package/packages/omo-codex/plugin/skills/ulw-execute/SKILL.md +2 -2
  77. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +2 -2
  78. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +2 -2
  79. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +2 -2
  80. package/packages/omo-codex/scripts/install-dist/install-local.mjs +6 -4
  81. package/packages/prompts-core/prompts/ultrawork/codex.md +18 -15
  82. package/packages/shared-skills/skills/browser/runtime/omowright/manifest.json +1 -1
  83. package/packages/shared-skills/skills/ulw-execute/SKILL.md +2 -2
package/dist/index.js CHANGED
@@ -20393,7 +20393,8 @@ var OmoMemoryNudgeSchema = z8.object({
20393
20393
  }).strict();
20394
20394
  var OmoMemoryFactsSchema = z8.object({
20395
20395
  enabled: z8.boolean().default(true),
20396
- debounce_settles: z8.number().int().min(1).default(4)
20396
+ debounce_settles: z8.number().int().min(1).default(4),
20397
+ model: z8.string().min(1).optional()
20397
20398
  }).strict();
20398
20399
  var OmoMemoryDreamSchema = z8.object({
20399
20400
  enabled: z8.boolean().default(true),
@@ -20455,7 +20456,8 @@ var OmoMemoryNudgeLayerSchema = z8.object({
20455
20456
  }).strict();
20456
20457
  var OmoMemoryFactsLayerSchema = z8.object({
20457
20458
  enabled: z8.boolean().optional(),
20458
- debounce_settles: z8.number().int().min(1).optional()
20459
+ debounce_settles: z8.number().int().min(1).optional(),
20460
+ model: z8.string().min(1).optional()
20459
20461
  }).strict();
20460
20462
  var OmoMemoryDreamLayerSchema = z8.object({
20461
20463
  enabled: z8.boolean().optional(),
@@ -24643,6 +24645,9 @@ function isRuntimeFallbackRetryableError(error, retryOnErrors, options = {}) {
24643
24645
  const errorType = classifyRuntimeFallbackError(error);
24644
24646
  if (errorType === "abort" || errorType === "context_overflow")
24645
24647
  return false;
24648
+ if (getRuntimeFallbackErrorName(error)?.toLowerCase().replace(/[_-]/g, "") === "contentfiltererror") {
24649
+ return true;
24650
+ }
24646
24651
  if (errorType === "missing_api_key" || errorType === "model_not_found" || errorType === "quota_exceeded") {
24647
24652
  return true;
24648
24653
  }
@@ -99132,7 +99137,7 @@ function getCachedVersion(options = {}) {
99132
99137
  // package.json
99133
99138
  var package_default = {
99134
99139
  name: "oh-my-opencode",
99135
- version: "5.1.30",
99140
+ version: "5.1.32",
99136
99141
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
99137
99142
  main: "./dist/index.js",
99138
99143
  types: "dist/index.d.ts",
@@ -99309,7 +99314,7 @@ var package_default = {
99309
99314
  },
99310
99315
  devDependencies: {
99311
99316
  "@clack/prompts": "^1.8.1",
99312
- "@code-yeongyu/senpi": "2026.10.11",
99317
+ "@code-yeongyu/senpi": "2026.10.12",
99313
99318
  "@modelcontextprotocol/sdk": "^1.30.0",
99314
99319
  "@oh-my-opencode/agents-md-core": "workspace:*",
99315
99320
  "@oh-my-opencode/ast-grep-mcp": "workspace:*",
@@ -99368,18 +99373,18 @@ var package_default = {
99368
99373
  typescript: "^7.0.2"
99369
99374
  },
99370
99375
  optionalDependencies: {
99371
- "oh-my-opencode-darwin-arm64": "5.1.30",
99372
- "oh-my-opencode-darwin-x64": "5.1.30",
99373
- "oh-my-opencode-darwin-x64-baseline": "5.1.30",
99374
- "oh-my-opencode-linux-arm64": "5.1.30",
99375
- "oh-my-opencode-linux-arm64-musl": "5.1.30",
99376
- "oh-my-opencode-linux-x64": "5.1.30",
99377
- "oh-my-opencode-linux-x64-baseline": "5.1.30",
99378
- "oh-my-opencode-linux-x64-musl": "5.1.30",
99379
- "oh-my-opencode-linux-x64-musl-baseline": "5.1.30",
99380
- "oh-my-opencode-windows-arm64": "5.1.30",
99381
- "oh-my-opencode-windows-x64": "5.1.30",
99382
- "oh-my-opencode-windows-x64-baseline": "5.1.30"
99376
+ "oh-my-opencode-darwin-arm64": "5.1.32",
99377
+ "oh-my-opencode-darwin-x64": "5.1.32",
99378
+ "oh-my-opencode-darwin-x64-baseline": "5.1.32",
99379
+ "oh-my-opencode-linux-arm64": "5.1.32",
99380
+ "oh-my-opencode-linux-arm64-musl": "5.1.32",
99381
+ "oh-my-opencode-linux-x64": "5.1.32",
99382
+ "oh-my-opencode-linux-x64-baseline": "5.1.32",
99383
+ "oh-my-opencode-linux-x64-musl": "5.1.32",
99384
+ "oh-my-opencode-linux-x64-musl-baseline": "5.1.32",
99385
+ "oh-my-opencode-windows-arm64": "5.1.32",
99386
+ "oh-my-opencode-windows-x64": "5.1.32",
99387
+ "oh-my-opencode-windows-x64-baseline": "5.1.32"
99383
99388
  },
99384
99389
  overrides: {
99385
99390
  hono: "^4.13.8",
@@ -105362,7 +105367,13 @@ task(category="quick", load_skills=["git-master"], run_in_background=true)
105362
105367
 
105363
105368
  ---
105364
105369
 
105370
+ ## Task resources
105371
+ Before the first task command, create and record one \`RUN_TMP=$(mktemp -d)\` per task. Export \`TMPDIR="$RUN_TMP" NODE_COMPILE_CACHE="$RUN_TMP/node-compile-cache" BUN_RUNTIME_TRANSPILER_CACHE_PATH="$RUN_TMP/bun-transpiler"\` for every command; pass the same environment explicitly to children that do not inherit it. Give independent child tasks their own run roots.
105372
+ At task end, after owned processes exit, remove only owned directories, including runtime caches. Never wipe shared caches; retain worktrees still needed by open PRs and any parent directory containing them.
105373
+ ALWAYS add a cleanup todo AT CREATION for each worktree, cache directory (including the run root), and QA resource (PID, tmux session, browser context, port, container, script or temp path); complete it only after a read-back teardown receipt.
105374
+
105365
105375
  ## EXECUTION RULES
105376
+
105366
105377
  - **TODO format**: \`path: <action> for <scenario-id> \u2014 verify by <check>\` encoding WHERE / WHY (which scenario it advances) / HOW / VERIFY. Exactly ONE in_progress at a time. Mark completed IMMEDIATELY \u2014 never batch.
105367
105378
  - GOOD pair (ordered): \`test/module.test: read the validateEmail cases for S2 - verify by noting intent / coverage / pass in the notepad\` \u2192 \`src/module: Implement validateEmail() for S2 - verify by curl 400 body + module.test green\`
105368
105379
  - BAD: "Implement feature" / "Fix bug" / "Add tests later" \u2192 rewrite.
@@ -105462,7 +105473,7 @@ The real-surface artifact is always required. A new test only where the reposito
105462
105473
 
105463
105474
  **NAME THE EXACT TOOL + EXACT INVOCATION** for every scenario \u2014 the literal \`curl ...\`, \`tmux send-keys ...\`, \`page.click(...)\` with concrete inputs and the binary observable. "run it" / "open the page" is not a scenario.
105464
105475
 
105465
- **CLEANUP IS PART OF QA \u2014 TRACK IT AS TODOS.** The moment a QA scenario spawns any resource, add a teardown todo for it (QA scripts, tmux assets, browser contexts, PIDs, ports, containers, temp dirs). Execute every teardown todo and capture the receipt before declaring done. A leftover process / tmux session / browser context / bound port / temp dir = NOT done.
105476
+ **CLEANUP IS PART OF THE TASK \u2014 TRACK IT AS TODOS.** Tear down QA scripts, tmux assets, browser contexts, PIDs, ports, containers and QA temp paths inside \`$RUN_TMP\` before recording QA; leftover QA resources mean NOT done. Remove the run root and eligible worktrees at task end under Task resources.
105466
105477
  </MANUAL_QA_MANDATE>
105467
105478
 
105468
105479
  ### Test Decision (every production code change)
@@ -105710,7 +105721,13 @@ task(subagent_type="plan", load_skills=[], run_in_background=false, prompt="<gat
105710
105721
 
105711
105722
  ---
105712
105723
 
105724
+ ## Task resources
105725
+ Before the first task command, create and record one \`RUN_TMP=$(mktemp -d)\` per task. Export \`TMPDIR="$RUN_TMP" NODE_COMPILE_CACHE="$RUN_TMP/node-compile-cache" BUN_RUNTIME_TRANSPILER_CACHE_PATH="$RUN_TMP/bun-transpiler"\` for every command; pass the same environment explicitly to children that do not inherit it. Give independent child tasks their own run roots.
105726
+ At task end, after owned processes exit, remove only owned directories, including runtime caches. Never wipe shared caches; retain worktrees still needed by open PRs and any parent directory containing them.
105727
+ ALWAYS add a cleanup todo AT CREATION for each worktree, cache directory (including the run root), and QA resource (PID, tmux session, browser context, port, container, script or temp path); complete it only after a read-back teardown receipt.
105728
+
105713
105729
  ## EXECUTION RULES
105730
+
105714
105731
  - **TODO**: Track EVERY step. Mark complete IMMEDIATELY after each.
105715
105732
  - **PARALLEL**: Fire independent agent calls simultaneously via task(run_in_background=true) - NEVER wait sequentially.
105716
105733
  - **BACKGROUND FIRST**: Use task for exploration/research agents (10+ concurrent if needed).
@@ -105810,7 +105827,7 @@ Trigger if user said "\uC5C4\uBC00"/"strictly"/"rigorously"/"properly review", o
105810
105827
  | Adds a new tool/hook/feature | Test it end-to-end in a real scenario. |
105811
105828
  | Modifies config handling | Load the config. Verify it parses correctly. |
105812
105829
 
105813
- **NAME THE EXACT TOOL + EXACT INVOCATION** per scenario \u2014 the literal \`curl\` / \`send-keys\` / \`page.click\` with inputs and the binary observable. **REGISTER EVERY QA-SPAWNED RESOURCE TEARDOWN AS ITS OWN TODO** (scripts, tmux assets, browser contexts, PIDs, ports, temp dirs), execute it, capture the receipt. A leftover process / tmux session / browser context = NOT done.
105830
+ **NAME THE EXACT TOOL + INVOCATION** per scenario. Tear down QA scripts, tmux assets, browser contexts, PIDs, ports, containers and QA temp paths inside \`$RUN_TMP\` before recording QA; leftover QA resources mean NOT done. Remove the run root and eligible worktrees at task end under Task resources.
105814
105831
 
105815
105832
  **UNACCEPTABLE (WILL BE REJECTED):**
105816
105833
  - "This should work" - DID YOU RUN IT? NO? THEN RUN IT.
@@ -105995,6 +106012,11 @@ If a verification command is unavailable or not applicable, state the exact reas
105995
106012
 
105996
106013
  When a \`create_goal\` tool exists, check \`get_goal\` first (continue a matching active goal; never duplicate), then register the run's goal before implementation with exactly \`objective\`, written outcome-first: the concrete outcome that will be true (never an activity), the named deliverable surfaces, the scenario contract as success criteria that can fail, scope bounds, and one WHEN TO STOP line naming the observable end state. Never invent a budget or deadline the user did not state. Without the tool, record the same contract in your working notes and treat it as binding.
105997
106014
 
106015
+ ## Task resources
106016
+ Before the first task command, create and record one \`RUN_TMP=$(mktemp -d)\` per task. Export \`TMPDIR="$RUN_TMP" NODE_COMPILE_CACHE="$RUN_TMP/node-compile-cache" BUN_RUNTIME_TRANSPILER_CACHE_PATH="$RUN_TMP/bun-transpiler"\` for every command; pass the same environment explicitly to children that do not inherit it. Give independent child tasks their own run roots.
106017
+ At task end, after owned processes exit, remove only owned directories, including runtime caches. Never wipe shared caches; retain worktrees still needed by open PRs and any parent directory containing them.
106018
+ ALWAYS add a cleanup todo AT CREATION for each worktree, cache directory (including the run root), and QA resource (PID, tmux session, browser context, port, container, script or temp path); complete it only after a read-back teardown receipt.
106019
+
105998
106020
  ## TODO DISCIPLINE
105999
106021
 
106000
106022
  Track every multi-step task in a live todo list: one atomic item per action with its verification, exactly one item in progress, status updated the instant it changes, newly discovered work added immediately. Never batch completions.
@@ -106038,7 +106060,7 @@ Tests are necessary and insufficient. Exercise the real surface.
106038
106060
  | Prompt or mode | Verify the prompt loads or the registry resolves it. |
106039
106061
  | Build output | Run build and verify exit code 0. |
106040
106062
 
106041
- If QA starts a server, browser, tmux session, port, temp dir, or background process, clean it up and record the cleanup.
106063
+ Tear down QA scripts, tmux assets, browser contexts, PIDs, ports, containers and QA temp paths inside \`$RUN_TMP\` before recording QA; leftover QA resources mean NOT done. Remove the run root and eligible worktrees at task end under Task resources.
106042
106064
 
106043
106065
  ## REVIEWER GATE
106044
106066
 
@@ -106193,6 +106215,11 @@ At start, run \`NOTE=$(mktemp -t ulw-$(date +%Y%m%d-%H%M%S).XXXXXX.md)\` and ech
106193
106215
 
106194
106216
  When a \`create_goal\` tool exists, check \`get_goal\` first (continue a matching active goal; never duplicate), then register the run's goal before implementation with exactly \`objective\`, outcome-first: the concrete outcome that will be true (never an activity), named deliverable surfaces, the scenario contract as criteria that can fail, scope bounds, and the WHEN TO STOP line. No invented budgets or deadlines. No tool \u2192 record the same contract in the notepad and treat it as binding.
106195
106217
 
106218
+ ## Task resources
106219
+ Before the first task command, create and record one \`RUN_TMP=$(mktemp -d)\` per task. Export \`TMPDIR="$RUN_TMP" NODE_COMPILE_CACHE="$RUN_TMP/node-compile-cache" BUN_RUNTIME_TRANSPILER_CACHE_PATH="$RUN_TMP/bun-transpiler"\` for every command; pass the same environment explicitly to children that do not inherit it. Give independent child tasks their own run roots.
106220
+ At task end, after owned processes exit, remove only owned directories, including runtime caches. Never wipe shared caches; retain worktrees still needed by open PRs and any parent directory containing them.
106221
+ ALWAYS add a cleanup todo AT CREATION for each worktree, cache directory (including the run root), and QA resource (PID, tmux session, browser context, port, container, script or temp path); complete it only after a read-back teardown receipt.
106222
+
106196
106223
  ## TODO DISCIPLINE
106197
106224
 
106198
106225
  Maintain a live todo list for every multi-step task: one atomic item per action (\`path: <action> for <scenario> \u2014 verify by <check>\`), exactly one in_progress, transitions marked the instant they happen, discovered work inserted immediately. Never batch completions.
@@ -106241,7 +106268,7 @@ lsp_diagnostics catches type errors only. Logic bugs, missing behavior, broken f
106241
106268
  | Adds tool/hook/feature | Test end-to-end in a real scenario. |
106242
106269
  | Modifies config handling | Load config. Verify parsed shape. |
106243
106270
 
106244
- Name the exact tool + exact invocation per scenario (literal \`curl\` / \`send-keys\` / \`page.click\` + inputs + binary observable). Register every QA-spawned resource teardown as its own todo (scripts, tmux, browser contexts, PIDs, ports, temp dirs), execute it, capture the receipt. "This should work" / "tests pass" / "lsp clean" / a leftover process are NOT done \u2014 the surface artifact + clean teardown are.
106271
+ Name the exact tool and invocation per scenario. Tear down QA scripts, tmux assets, browser contexts, PIDs, ports, containers and QA temp paths inside \`$RUN_TMP\` before recording QA; leftover QA resources mean NOT done. Remove the run root and eligible worktrees at task end under Task resources.
106245
106272
  </MANUAL_QA_MANDATE>
106246
106273
 
106247
106274
  ## REVIEWER GATE (triggered)
@@ -106431,7 +106458,8 @@ var HYPERPLAN_MESSAGE = HYPERPLAN_MODE_PROMPT;
106431
106458
  // packages/omo-opencode/src/hooks/keyword-detector/constants.ts
106432
106459
  var CODE_BLOCK_PATTERN2 = /```[\s\S]*?```/g;
106433
106460
  var INLINE_CODE_PATTERN2 = /`[^`]+`/g;
106434
- var HYPERPLAN_ULTRAWORK_PATTERN = /\b(?:hpp|hyperplan)\s+(?:ulw|ultrawork)\b|\b(?:ulw|ultrawork)\s+(?:hpp|hyperplan)\b/i;
106461
+ var ULTRAWORK_PATTERN = /\b(?:ultrawork|ulw(?!-\w))\b/i;
106462
+ var HYPERPLAN_ULTRAWORK_PATTERN = /\b(?:hpp|hyperplan)\s+(?:ultrawork|ulw(?!-\w))\b|\b(?:ultrawork|ulw(?!-\w))\s+(?:hpp|hyperplan)\b/i;
106435
106463
  var HYPERPLAN_ULTRAWORK_BANNER = `<hyperplan-ultrawork-mode>
106436
106464
  **MANDATORY**: Say "HYPERPLAN ULTRAWORK MODE ENABLED!" exactly once as your first response. Do NOT say the standalone "ULTRAWORK MODE ENABLED!" or "HYPERPLAN MODE ENABLED!" banners.
106437
106465
 
@@ -106445,7 +106473,7 @@ ${getUltraworkMessage(agentName, modelID)}`;
106445
106473
  var KEYWORD_DETECTORS = [
106446
106474
  {
106447
106475
  type: "ultrawork",
106448
- pattern: /\b(ultrawork|ulw)\b/i,
106476
+ pattern: ULTRAWORK_PATTERN,
106449
106477
  message: getUltraworkMessage
106450
106478
  },
106451
106479
  {
@@ -121776,6 +121804,8 @@ function createMessageUpdateHandler(deps, helpers) {
121776
121804
  return;
121777
121805
  }
121778
121806
  if (sessionID && role === "assistant" && error) {
121807
+ const isContentFilterError = extractErrorName(error)?.toLowerCase().replace(/[_-]/g, "") === "contentfiltererror";
121808
+ const shouldOverrideRetry = Boolean(retrySignal && timeoutEnabled) || isContentFilterError;
121779
121809
  let state = sessionStates.get(sessionID);
121780
121810
  const pendingFallbackModel = state?.pendingFallbackModel;
121781
121811
  const wasAwaitingFallbackResult = sessionAwaitingFallbackResult.has(sessionID);
@@ -121790,12 +121820,12 @@ function createMessageUpdateHandler(deps, helpers) {
121790
121820
  if (wasAwaitingFallbackResult) {
121791
121821
  sessionAwaitingFallbackResult.delete(sessionID);
121792
121822
  }
121793
- if (sessionRetryInFlight.has(sessionID) && !retrySignal) {
121823
+ if (sessionRetryInFlight.has(sessionID) && !retrySignal && !isContentFilterError) {
121794
121824
  log2(`[${HOOK_NAME13}] message.updated fallback skipped (retry in flight)`, { sessionID });
121795
121825
  return;
121796
121826
  }
121797
- if (retrySignal && timeoutEnabled && (sessionRetryInFlight.has(sessionID) || wasAwaitingFallbackResult)) {
121798
- log2(`[${HOOK_NAME13}] Overriding active retry due to provider auto-retry signal`, {
121827
+ if (shouldOverrideRetry && (sessionRetryInFlight.has(sessionID) || wasAwaitingFallbackResult)) {
121828
+ log2(`[${HOOK_NAME13}] Overriding active retry due to provider retry signal or content-filter error`, {
121799
121829
  sessionID,
121800
121830
  model
121801
121831
  });
@@ -121868,8 +121898,8 @@ function createMessageUpdateHandler(deps, helpers) {
121868
121898
  } else {
121869
121899
  sessionLastAccess.set(sessionID, Date.now());
121870
121900
  if (state.pendingFallbackModel) {
121871
- if (retrySignal && timeoutEnabled) {
121872
- log2(`[${HOOK_NAME13}] Clearing pending fallback due to provider auto-retry signal`, {
121901
+ if (shouldOverrideRetry) {
121902
+ log2(`[${HOOK_NAME13}] Clearing pending fallback due to provider retry signal or content-filter error`, {
121873
121903
  sessionID,
121874
121904
  pendingFallbackModel: state.pendingFallbackModel
121875
121905
  });
@@ -131918,6 +131948,58 @@ function isSessionSdkUnavailableError(value) {
131918
131948
  return SDK_UNAVAILABLE_PATTERNS.some((pattern) => haystack.includes(pattern));
131919
131949
  }
131920
131950
 
131951
+ // packages/omo-opencode/src/tools/session-manager/session-error.ts
131952
+ function textField(record, key) {
131953
+ const value = record[key];
131954
+ return typeof value === "string" && value.length > 0 ? value : undefined;
131955
+ }
131956
+ function describeSessionError(error) {
131957
+ if (error instanceof Error)
131958
+ return error.message;
131959
+ if (typeof error === "string")
131960
+ return error;
131961
+ if (!error || typeof error !== "object")
131962
+ return String(error);
131963
+ const record = error;
131964
+ const data = record.data && typeof record.data === "object" ? record.data : undefined;
131965
+ const message = textField(record, "message") ?? (data ? textField(data, "message") : undefined);
131966
+ const name = textField(record, "name");
131967
+ const code = textField(record, "code");
131968
+ if (message) {
131969
+ if (name)
131970
+ return `${name}: ${message}`;
131971
+ return code ? `${message} (${code})` : message;
131972
+ }
131973
+ if (name)
131974
+ return name;
131975
+ try {
131976
+ return JSON.stringify(error);
131977
+ } catch {
131978
+ return Object.prototype.toString.call(error);
131979
+ }
131980
+ }
131981
+ function toSessionError(error) {
131982
+ if (error instanceof Error)
131983
+ return error;
131984
+ const wrapped = new Error(describeSessionError(error), { cause: error });
131985
+ const name = error && typeof error === "object" ? textField(error, "name") : undefined;
131986
+ if (name)
131987
+ wrapped.name = name;
131988
+ return wrapped;
131989
+ }
131990
+ var SKIPPED_SESSIONS_SHOWN = 5;
131991
+ function formatSkippedSessions(skipped) {
131992
+ if (skipped.length === 0)
131993
+ return "";
131994
+ const noun = skipped.length === 1 ? "session" : "sessions";
131995
+ const shown = skipped.slice(0, SKIPPED_SESSIONS_SHOWN).map((entry) => `${entry.id} (${entry.reason})`);
131996
+ const hidden = skipped.length - shown.length;
131997
+ const entries = hidden > 0 ? [...shown, `and ${hidden} more`] : shown;
131998
+ return `
131999
+
132000
+ Skipped ${skipped.length} ${noun} that could not be read: ${entries.join(", ")}`;
132001
+ }
132002
+
131921
132003
  // packages/omo-opencode/src/tools/session-manager/sdk-storage.ts
131922
132004
  function unwrapSdkResponseError(response) {
131923
132005
  if (!response || typeof response !== "object" || !("error" in response)) {
@@ -131929,7 +132011,7 @@ function throwOnNonFallbackableSdkError(response) {
131929
132011
  const error = unwrapSdkResponseError(response);
131930
132012
  if (!error)
131931
132013
  return;
131932
- throw error;
132014
+ throw toSessionError(error);
131933
132015
  }
131934
132016
  var SDK_TRANSIENT_RETRY_ATTEMPTS = 3;
131935
132017
  var GLOBAL_SESSION_PAGE_SIZE = 100;
@@ -132062,6 +132144,12 @@ function shouldFallbackFromSdkError(error) {
132062
132144
  }
132063
132145
 
132064
132146
  // packages/omo-opencode/src/tools/session-manager/storage.ts
132147
+ function isSdkSessionNotFound(error) {
132148
+ return error instanceof Error && error.name === "NotFoundError";
132149
+ }
132150
+ function shouldReadFileSession(error) {
132151
+ return shouldFallbackFromSdkError(error) || isSdkSessionNotFound(error);
132152
+ }
132065
132153
  function normalizeProjectFilter(directory) {
132066
132154
  if (directory === "/")
132067
132155
  return;
@@ -132096,7 +132184,7 @@ async function getMainSessions(options) {
132096
132184
  } catch (error) {
132097
132185
  if (!shouldFallbackFromSdkError(error))
132098
132186
  throw error;
132099
- log2("[session-manager] falling back to file session list after SDK unavailable error", { error: String(error) });
132187
+ log2("[session-manager] falling back to file session list after SDK unavailable error", { error: describeSessionError(error) });
132100
132188
  }
132101
132189
  }
132102
132190
  return getFileMainSessions(directory);
@@ -132110,7 +132198,7 @@ async function getAllSessions(limit) {
132110
132198
  } catch (error) {
132111
132199
  if (!shouldFallbackFromSdkError(error))
132112
132200
  throw error;
132113
- log2("[session-manager] falling back to file session ids after SDK unavailable error", { error: String(error) });
132201
+ log2("[session-manager] falling back to file session ids after SDK unavailable error", { error: describeSessionError(error) });
132114
132202
  }
132115
132203
  }
132116
132204
  return getFileAllSessions();
@@ -132122,9 +132210,9 @@ async function sessionExists2(sessionID) {
132122
132210
  if (existsInSdk)
132123
132211
  return true;
132124
132212
  } catch (error) {
132125
- if (!shouldFallbackFromSdkError(error))
132213
+ if (!shouldReadFileSession(error))
132126
132214
  throw error;
132127
- log2("[session-manager] falling back to file sessionExists after SDK unavailable error", { error: String(error), sessionID });
132215
+ log2("[session-manager] reading file sessionExists after SDK error", { error: describeSessionError(error), sessionID });
132128
132216
  }
132129
132217
  }
132130
132218
  return fileSessionExists(sessionID);
@@ -132136,9 +132224,9 @@ async function readSessionMessages2(sessionID) {
132136
132224
  if (sdkMessages.length > 0)
132137
132225
  return sdkMessages;
132138
132226
  } catch (error) {
132139
- if (!shouldFallbackFromSdkError(error))
132227
+ if (!shouldReadFileSession(error))
132140
132228
  throw error;
132141
- log2("[session-manager] falling back to file session messages after SDK unavailable error", { error: String(error), sessionID });
132229
+ log2("[session-manager] reading file session messages after SDK error", { error: describeSessionError(error), sessionID });
132142
132230
  }
132143
132231
  }
132144
132232
  return getFileSessionMessages(sessionID);
@@ -132150,9 +132238,9 @@ async function readSessionTodos(sessionID) {
132150
132238
  if (sdkTodos.length > 0)
132151
132239
  return sdkTodos;
132152
132240
  } catch (error) {
132153
- if (!shouldFallbackFromSdkError(error))
132241
+ if (!shouldReadFileSession(error))
132154
132242
  throw error;
132155
- log2("[session-manager] falling back to file session todos after SDK unavailable error", { error: String(error), sessionID });
132243
+ log2("[session-manager] reading file session todos after SDK error", { error: describeSessionError(error), sessionID });
132156
132244
  }
132157
132245
  }
132158
132246
  return getFileSessionTodos(sessionID);
@@ -132194,9 +132282,9 @@ async function getSessionInfo(sessionID) {
132194
132282
  };
132195
132283
  }
132196
132284
  } catch (error) {
132197
- if (!shouldFallbackFromSdkError(error))
132285
+ if (!shouldReadFileSession(error))
132198
132286
  throw error;
132199
- log2("[session-manager] falling back to file session info after SDK unavailable error", { error: String(error), sessionID });
132287
+ log2("[session-manager] reading file session info after SDK error", { error: describeSessionError(error), sessionID });
132200
132288
  }
132201
132289
  }
132202
132290
  return getFileSessionInfo(sessionID);
@@ -132207,9 +132295,14 @@ async function formatSessionList(sessionIDs) {
132207
132295
  if (sessionIDs.length === 0) {
132208
132296
  return "No sessions found.";
132209
132297
  }
132210
- const infos = (await Promise.all(sessionIDs.map((id) => getSessionInfo(id)))).filter((info) => info !== null);
132298
+ const skipped = [];
132299
+ const reads = await Promise.all(sessionIDs.map((id) => getSessionInfo(id).catch((error) => {
132300
+ skipped.push({ id, reason: describeSessionError(error) });
132301
+ return null;
132302
+ })));
132303
+ const infos = reads.filter((info) => info !== null);
132211
132304
  if (infos.length === 0) {
132212
- return "No valid sessions found.";
132305
+ return `No valid sessions found.${formatSkippedSessions(skipped)}`;
132213
132306
  }
132214
132307
  const headers = ["Session ID", "Messages", "First", "Last", "Agents"];
132215
132308
  const rows = infos.map((info) => [
@@ -132225,7 +132318,7 @@ async function formatSessionList(sessionIDs) {
132225
132318
  };
132226
132319
  const separator = "|" + colWidths.map((w) => "-".repeat(w + 2)).join("|") + "|";
132227
132320
  return [formatRow(headers), separator, ...rows.map(formatRow)].join(`
132228
- `);
132321
+ `) + formatSkippedSessions(skipped);
132229
132322
  }
132230
132323
  function formatSessionMessages(messages, includeTodos, todos) {
132231
132324
  if (messages.length === 0) {
@@ -132421,7 +132514,7 @@ function createSessionManagerTools(ctx, deps = {}) {
132421
132514
  }
132422
132515
  return await resolvedDeps.formatSessionList(sessionIDs);
132423
132516
  } catch (e) {
132424
- return `Error: ${e instanceof Error ? e.message : String(e)}`;
132517
+ return `Error: ${describeSessionError(e)}`;
132425
132518
  }
132426
132519
  }
132427
132520
  });
@@ -132449,7 +132542,7 @@ function createSessionManagerTools(ctx, deps = {}) {
132449
132542
  const todos = args.include_todos ? await resolvedDeps.readSessionTodos(args.session_id) : undefined;
132450
132543
  return resolvedDeps.formatSessionMessages(messages, args.include_todos, todos);
132451
132544
  } catch (e) {
132452
- return `Error: ${e instanceof Error ? e.message : String(e)}`;
132545
+ return `Error: ${describeSessionError(e)}`;
132453
132546
  }
132454
132547
  }
132455
132548
  });
@@ -132464,6 +132557,7 @@ function createSessionManagerTools(ctx, deps = {}) {
132464
132557
  execute: async (args, _context) => {
132465
132558
  try {
132466
132559
  const resultLimit = args.limit && args.limit > 0 ? args.limit : 20;
132560
+ const skipped = [];
132467
132561
  const searchOperation = async () => {
132468
132562
  if (args.session_id) {
132469
132563
  return resolvedDeps.searchInSession(args.session_id, args.query, args.case_sensitive, resultLimit);
@@ -132475,15 +132569,19 @@ function createSessionManagerTools(ctx, deps = {}) {
132475
132569
  if (allResults.length >= resultLimit)
132476
132570
  break;
132477
132571
  const remaining = resultLimit - allResults.length;
132478
- const sessionResults = await resolvedDeps.searchInSession(sid, args.query, args.case_sensitive, remaining);
132479
- allResults.push(...sessionResults);
132572
+ try {
132573
+ const sessionResults = await resolvedDeps.searchInSession(sid, args.query, args.case_sensitive, remaining);
132574
+ allResults.push(...sessionResults);
132575
+ } catch (error) {
132576
+ skipped.push({ id: sid, reason: describeSessionError(error) });
132577
+ }
132480
132578
  }
132481
132579
  return allResults.slice(0, resultLimit);
132482
132580
  };
132483
132581
  const results = await withTimeout4(searchOperation(), SEARCH_TIMEOUT_MS, "Search");
132484
- return resolvedDeps.formatSearchResults(results);
132582
+ return resolvedDeps.formatSearchResults(results) + formatSkippedSessions(skipped);
132485
132583
  } catch (e) {
132486
- return `Error: ${e instanceof Error ? e.message : String(e)}`;
132584
+ return `Error: ${describeSessionError(e)}`;
132487
132585
  }
132488
132586
  }
132489
132587
  });
@@ -132500,7 +132598,7 @@ function createSessionManagerTools(ctx, deps = {}) {
132500
132598
  }
132501
132599
  return resolvedDeps.formatSessionInfo(info);
132502
132600
  } catch (e) {
132503
- return `Error: ${e instanceof Error ? e.message : String(e)}`;
132601
+ return `Error: ${describeSessionError(e)}`;
132504
132602
  }
132505
132603
  }
132506
132604
  });
@@ -137865,7 +137963,7 @@ async function createSyncSession(client, input) {
137865
137963
  const createResult = await client.session.create({
137866
137964
  body: {
137867
137965
  parentID: input.parentSessionID,
137868
- title: `${input.description} (@${input.agentToUse} subagent)`,
137966
+ title: `${input.category ? `[${input.category}] ` : ""}${input.description} (@${input.agentToUse} subagent)`,
137869
137967
  permission: QUESTION_DENIED_SESSION_PERMISSION,
137870
137968
  ...input.categoryModel ? {
137871
137969
  model: {
@@ -138297,6 +138395,7 @@ async function runSyncTaskLoop(input) {
138297
138395
  agentToUse,
138298
138396
  description: args.description,
138299
138397
  defaultDirectory: directory,
138398
+ category: args.category,
138300
138399
  categoryModel: nextFallbackModel
138301
138400
  });
138302
138401
  if (!retrySessionResult.ok) {
@@ -138397,6 +138496,7 @@ async function executeSyncTask(args, ctx, executorCtx, parentContext, agentToUse
138397
138496
  agentToUse,
138398
138497
  description: args.description,
138399
138498
  defaultDirectory: directory,
138499
+ category: args.category,
138400
138500
  categoryModel
138401
138501
  });
138402
138502
  if (!createSessionResult.ok) {
@@ -138915,7 +139015,7 @@ async function resolveSubagentAgentMatch(requestedAgent, executorCtx, options) {
138915
139015
  const hasDemotedPlan = agents.some(isDemotedPlanAgent);
138916
139016
  const serverPrimaryAgent = findPrimaryAgentMatch(agents, requestedAgent);
138917
139017
  const serverMatchedAgent = findCallableAgentMatch(agents, requestedAgent);
138918
- const mergedAgents = mergeWithClaudeCodeAgents(agents, executorCtx.directory);
139018
+ const mergedAgents = executorCtx.claudeCodeAgentsEnabled === false ? agents : mergeWithClaudeCodeAgents(agents, executorCtx.directory);
138919
139019
  const matchedPrimaryAgent = findPrimaryAgentMatch(mergedAgents, requestedAgent);
138920
139020
  const useHiddenPlanFallback = shouldUseHiddenPlanAgent(requestedAgent, serverPrimaryAgent, serverMatchedAgent, executorCtx.sisyphusAgentConfig, hasDemotedPlan);
138921
139021
  if (isReservedHiddenNativeAgent(requestedAgent) && !serverPrimaryAgent && !serverMatchedAgent) {
@@ -144199,7 +144299,7 @@ async function verifySessionExists(client, sessionID, directory) {
144199
144299
 
144200
144300
  // packages/omo-opencode/src/features/background-agent/session-stopped-on-error.ts
144201
144301
  var MIN_ERRORED_IDLE_POLLS = 10;
144202
- function describeSessionError(error) {
144302
+ function describeSessionError2(error) {
144203
144303
  if (!isRecord9(error)) {
144204
144304
  return String(error);
144205
144305
  }
@@ -144217,7 +144317,7 @@ function getStoppedSessionError(messages) {
144217
144317
  if (error === undefined || error === null) {
144218
144318
  return;
144219
144319
  }
144220
- return describeSessionError(error);
144320
+ return describeSessionError2(error);
144221
144321
  }
144222
144322
 
144223
144323
  // packages/omo-opencode/src/features/background-agent/session-idle-event-handler.ts
@@ -144773,6 +144873,7 @@ var TERMINAL_TASK_STATUSES = new Set([
144773
144873
  function pruneStaleTasksAndNotifications(args) {
144774
144874
  const { tasks, notifications, onTaskPruned } = args;
144775
144875
  const effectiveTtl = args.taskTtlMs ?? TASK_TTL_MS;
144876
+ const terminalTtl = Math.max(TERMINAL_TASK_TTL_MS, args.taskCleanupDelayMs ?? 0);
144776
144877
  const now = Date.now();
144777
144878
  const tasksWithPendingNotifications = new Set;
144778
144879
  for (const queued of notifications.values()) {
@@ -144784,11 +144885,15 @@ function pruneStaleTasksAndNotifications(args) {
144784
144885
  if (TERMINAL_TASK_STATUSES.has(task.status)) {
144785
144886
  if (tasksWithPendingNotifications.has(taskId))
144786
144887
  continue;
144888
+ if (args.hasPendingRemovalTimer?.(taskId))
144889
+ continue;
144890
+ if (task.sessionId && args.hasAttachedSyncSession?.(task.sessionId))
144891
+ continue;
144787
144892
  const completedAt = task.completedAt?.getTime();
144788
144893
  if (!completedAt)
144789
144894
  continue;
144790
144895
  const age = now - completedAt;
144791
- if (age <= TERMINAL_TASK_TTL_MS)
144896
+ if (age <= terminalTtl)
144792
144897
  continue;
144793
144898
  removeTaskToastTracking(taskId);
144794
144899
  tasks.delete(taskId);
@@ -145621,7 +145726,7 @@ class BackgroundManager {
145621
145726
  const createResult = await this.client.session.create({
145622
145727
  body: {
145623
145728
  parentID: input.parentSessionId,
145624
- title: `${input.description} (@${input.agent} subagent)`,
145729
+ title: `${input.category ? `[${input.category}] ` : ""}${input.description} (@${input.agent} subagent)`,
145625
145730
  ...input.sessionPermission ? { permission: input.sessionPermission } : {},
145626
145731
  ...input.model ? {
145627
145732
  model: {
@@ -147257,7 +147362,10 @@ The task was re-queued on a fallback model after a retryable failure.
147257
147362
  tasks: this.tasks,
147258
147363
  notifications: this.notifications,
147259
147364
  taskTtlMs: this.config?.taskTtlMs,
147365
+ taskCleanupDelayMs: this.config?.taskCleanupDelayMs,
147260
147366
  sessionStatuses: allStatuses,
147367
+ hasPendingRemovalTimer: (taskId) => this.completionTimers.has(taskId),
147368
+ hasAttachedSyncSession: (sessionID) => this.syncAttachedSessions.has(sessionID),
147261
147369
  onTaskPruned: (taskId, task, errorMessage) => {
147262
147370
  const wasPending = task.status === "pending";
147263
147371
  log2("[background-agent] Pruning stale task:", { taskId, status: task.status, age: Math.round(((wasPending ? task.queuedAt?.getTime() : task.startedAt?.getTime()) ? Date.now() - (wasPending ? task.queuedAt.getTime() : task.startedAt.getTime()) : 0) / 1000) + "s" });
@@ -172359,7 +172467,8 @@ function createTeamModeToolsRecord(args) {
172359
172467
  team_create: factories.createTeamCreateTool(pluginConfig.team_mode, ctx.client, managers.backgroundManager, managers.tmuxSessionManager, {
172360
172468
  userCategories: pluginConfig.categories,
172361
172469
  sisyphusJuniorModel: getSisyphusJuniorModelOverride(pluginConfig.agents?.["sisyphus-junior"]),
172362
- agentOverrides: pluginConfig.agents
172470
+ agentOverrides: pluginConfig.agents,
172471
+ claudeCodeAgentsEnabled: pluginConfig.claude_code?.agents ?? true
172363
172472
  }),
172364
172473
  team_delete: factories.createTeamDeleteTool(pluginConfig.team_mode, ctx.client, managers.backgroundManager, managers.tmuxSessionManager),
172365
172474
  team_shutdown_request: factories.createTeamShutdownRequestTool(pluginConfig.team_mode, ctx.client),
@@ -172505,6 +172614,7 @@ function createCoreTools(args) {
172505
172614
  nativeSkills,
172506
172615
  getLoadedSkills,
172507
172616
  sisyphusAgentConfig: pluginConfig.sisyphus_agent,
172617
+ claudeCodeAgentsEnabled: pluginConfig.claude_code?.agents ?? true,
172508
172618
  syncPollTimeoutMs: pluginConfig.background_task?.syncPollTimeoutMs,
172509
172619
  modelFallbackControllerAccessor: managers.modelFallbackControllerAccessor,
172510
172620
  onSyncSessionCreated: async (event) => {
@@ -173657,7 +173767,8 @@ function createTeamCreateTool(config, client, bgMgr, tmuxMgr, executorConfig, de
173657
173767
  directory: projectRoot,
173658
173768
  userCategories: executorConfig?.userCategories,
173659
173769
  sisyphusJuniorModel: executorConfig?.sisyphusJuniorModel,
173660
- agentOverrides: executorConfig?.agentOverrides
173770
+ agentOverrides: executorConfig?.agentOverrides,
173771
+ claudeCodeAgentsEnabled: executorConfig?.claudeCodeAgentsEnabled
173661
173772
  }, config, bgMgr, tmuxMgr, {
173662
173773
  callerAgentTypeId: callerTeamLead.agentTypeId,
173663
173774
  parentMessageID: runtimeContext.messageID
@@ -174565,7 +174676,7 @@ function buildChatParamsInput(raw) {
174565
174676
  return null;
174566
174677
  const providerID = model.providerID;
174567
174678
  const modelID = typeof model.modelID === "string" ? model.modelID : typeof model.id === "string" ? model.id : undefined;
174568
- const providerId = provider.id;
174679
+ const providerId = isRecord9(provider.info) ? provider.info.id : provider.id;
174569
174680
  if (typeof providerID !== "string")
174570
174681
  return null;
174571
174682
  if (typeof modelID !== "string")
@@ -174578,7 +174689,8 @@ function buildChatParamsInput(raw) {
174578
174689
  model: { providerID, modelID },
174579
174690
  provider: { id: providerId },
174580
174691
  message,
174581
- rawMessage: message
174692
+ rawMessage: message,
174693
+ runtimeModel: isRecord9(model.capabilities) ? model : undefined
174582
174694
  };
174583
174695
  }
174584
174696
  function isChatParamsOutput(raw) {
@@ -174616,7 +174728,8 @@ function createChatParamsHandler(_args = {}) {
174616
174728
  }
174617
174729
  const capabilities = getModelCapabilities2({
174618
174730
  providerID: normalizedInput.model.providerID,
174619
- modelID: normalizedInput.model.modelID
174731
+ modelID: normalizedInput.model.modelID,
174732
+ runtimeModel: normalizedInput.runtimeModel
174620
174733
  });
174621
174734
  const compatibility = resolveCompatibleModelSettings({
174622
174735
  providerID: normalizedInput.model.providerID,
@@ -174950,7 +175063,6 @@ async function resolveValidUltraworkVariant(client, model, variant) {
174950
175063
  // packages/omo-opencode/src/plugin/ultrawork-model-override.ts
174951
175064
  var CODE_BLOCK = /```[\s\S]*?```/g;
174952
175065
  var INLINE_CODE = /`[^`]+`/g;
174953
- var ULTRAWORK_PATTERN = /\b(ultrawork|ulw)\b/i;
174954
175066
  function detectUltrawork(text) {
174955
175067
  const clean = text.replace(CODE_BLOCK, "").replace(INLINE_CODE, "");
174956
175068
  return ULTRAWORK_PATTERN.test(clean);
@@ -5,5 +5,5 @@
5
5
  "index.js": "b6b064fab277031c6c51f5a58b84b31040f9960bf767bf646adc0540c1d25c1b",
6
6
  "page-bundle.js": "bfd51e8383cf47200d57387bbbed258bce5a3a3d00c38fc108034d2888e23f0c"
7
7
  },
8
- "stagedAtUtc": "2026-10-11T14:42:51.925Z"
8
+ "stagedAtUtc": "2026-10-13T00:11:24.408Z"
9
9
  }
@@ -96,7 +96,7 @@ Write `.omo/boulder.json` before implementation starts. Prefix session ids with
96
96
  }
97
97
  ```
98
98
 
99
- Every phase (plan wave) runs in its own task-owned worktree with its own goal: before the wave's first dispatch, record the wave's goal — its checkboxes and their acceptance criteria — as a ledger entry, then `git worktree add <repo>-wt/<plan>-<wave> <branch off the integration base>` (or verify a `--worktree` path with `git worktree list --porcelain`), store the absolute path as `worktree_path`, run every edit, command, test, and evidence capture inside it; the wave lands on the integration base once its checkboxes are verified (direct merge, or the PR under `--make-pr`/`--ship`), and the next wave branches from that landed base.
99
+ Every phase (plan wave) runs in its own task-owned worktree with its own goal: before the wave's first dispatch, record the wave's goal — its checkboxes and their acceptance criteria — as a ledger entry, then `git worktree add <repo>-wt/<plan>-<wave> <branch off the integration base>` (or verify a `--worktree` path with `git worktree list --porcelain`), store the absolute path as `worktree_path`, run every edit, command, test, and evidence capture inside it; the wave lands on the integration base once its checkboxes are verified (direct merge, or the PR under `--make-pr`/`--ship`), and the next wave branches from that landed base. Use the bundled ultrawork directive’s Task resources and todo rules at wave/worktree creation; read those sections if absent from context.
100
100
 
101
101
  ## Parallel delivery lanes (teams and worktrees)
102
102
 
@@ -227,7 +227,7 @@ Only after verification passes:
227
227
  When all top-level checkboxes in `## TODOs` and `## Final Verification Wave` are complete:
228
228
 
229
229
  1. Run the plan's final verification commands.
230
- 2. For PR/branch work, finish the lifecycle from the last phase's worktree: sync `.omo/` state back to the main repo, create or update the PR, wait for review/verification gates, merge by default unless explicitly opted out, and remove the worktree only after successful merge or explicit handoff.
230
+ 2. For PR/branch work, finish the lifecycle from the last phase's worktree: sync `.omo/` state back to the main repo, create or update the PR, wait for review/verification gates, merge by default unless explicitly opted out, and remove the worktree only after successful merge or explicit handoff. Finish directory teardown per Task resources and record its receipts.
231
231
  3. Remove or mark the Boulder work as completed.
232
232
  4. Print an `ORCHESTRATION COMPLETE` block with the plan path, verification commands, artifacts, and cleanup receipts.
233
233
 
@@ -12,6 +12,7 @@ export interface ExecutorContext {
12
12
  browserProvider?: BrowserAutomationProvider;
13
13
  agentOverrides?: AgentOverrides;
14
14
  sisyphusAgentConfig?: SisyphusAgentConfig;
15
+ claudeCodeAgentsEnabled?: boolean;
15
16
  modelFallbackControllerAccessor?: ModelFallbackControllerAccessor;
16
17
  onSyncSessionCreated?: (event: {
17
18
  sessionID: string;