oh-my-opencode 5.0.0-beta.19 → 5.0.0-beta.20

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 (188) hide show
  1. package/README.ja.md +3 -3
  2. package/README.ko.md +3 -3
  3. package/README.md +3 -3
  4. package/README.ru.md +3 -3
  5. package/README.zh-cn.md +3 -3
  6. package/dist/cli/fallback-lane-policy.d.ts +1 -0
  7. package/dist/cli/index.js +72 -195
  8. package/dist/cli/install-codex/install-codex-test-fixtures.d.ts +1 -1
  9. package/dist/cli-node/index.js +72 -195
  10. package/dist/config/schema/commands.d.ts +1 -1
  11. package/dist/config/schema/hooks.d.ts +1 -1
  12. package/dist/config/schema/oh-my-opencode-config.d.ts +4 -1
  13. package/dist/config/schema/ulw-execute.d.ts +5 -0
  14. package/dist/config/validate.d.ts +2 -0
  15. package/dist/create-hooks.d.ts +2 -1
  16. package/dist/features/builtin-commands/templates/ulw-execute.d.ts +1 -0
  17. package/dist/features/builtin-commands/types.d.ts +1 -1
  18. package/dist/hooks/atlas/atlas-hook.d.ts +1 -0
  19. package/dist/hooks/atlas/atlas-lifecycle-store.d.ts +50 -0
  20. package/dist/hooks/atlas/event-handler.d.ts +1 -0
  21. package/dist/hooks/atlas/tool-execute-before.d.ts +3 -0
  22. package/dist/hooks/atlas/types.d.ts +1 -0
  23. package/dist/hooks/index.d.ts +1 -1
  24. package/dist/hooks/prometheus-md-only/agent-resolution.d.ts +2 -2
  25. package/dist/hooks/sisyphus-junior-notepad/constants.d.ts +1 -1
  26. package/dist/hooks/{start-work → ulw-execute}/context-info-builder.d.ts +1 -1
  27. package/dist/hooks/{start-work → ulw-execute}/index.d.ts +1 -1
  28. package/dist/hooks/ulw-execute/ulw-execute-hook.d.ts +23 -0
  29. package/dist/index.js +322 -258
  30. package/dist/oh-my-opencode.schema.json +14 -1
  31. package/dist/plugin/chat-message/types.d.ts +3 -3
  32. package/dist/plugin/chat-message/ulw-execute-message.d.ts +5 -0
  33. package/dist/plugin/hooks/create-core-hooks.d.ts +1 -1
  34. package/dist/plugin/hooks/create-session-hooks.d.ts +2 -2
  35. package/dist/skills/frontend/SKILL.md +1 -1
  36. package/dist/skills/frontend/references/designpowers/README.md +1 -1
  37. package/dist/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
  38. package/dist/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
  39. package/dist/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
  40. package/dist/skills/frontend/references/designpowers/orchestration.md +1 -1
  41. package/dist/skills/frontend/references/designpowers/routing.md +5 -5
  42. package/dist/skills/{start-work → ulw-execute}/SKILL.md +7 -7
  43. package/dist/skills/ulw-plan/SKILL.md +4 -4
  44. package/dist/skills/ulw-plan/references/full-workflow.md +4 -4
  45. package/dist/skills/ulw-plan/references/intent-unclear.md +2 -2
  46. package/dist/tui.js +34 -9
  47. package/package.json +15 -15
  48. package/packages/omo-codex/THIRD-PARTY-NOTICES.md +4 -4
  49. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +4 -4
  50. package/packages/omo-codex/plugin/README.md +1 -1
  51. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +2 -2
  52. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  53. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  54. package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
  55. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  56. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  57. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  58. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  59. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  60. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  61. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
  62. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  63. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  64. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  65. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  66. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  67. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  68. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  69. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  70. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  71. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  72. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +4 -4
  73. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +4 -4
  74. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-unclear.md +2 -2
  75. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/AGENTS.md +2 -2
  76. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/NOTICE +1 -1
  77. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/README.md +5 -5
  78. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/directive.md +6 -6
  79. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/dist/cli.js +12 -12
  80. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +28 -0
  81. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/package.json +8 -8
  82. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/boulder-reader.ts +1 -1
  83. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/cli.ts +1 -1
  84. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/codex-hook.ts +3 -3
  85. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/directive.ts +1 -1
  86. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/index.ts +1 -1
  87. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/boulder-reader.test.ts +3 -3
  88. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/cli.test.ts +1 -1
  89. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/codex-hook.test.ts +6 -6
  90. package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +1 -1
  91. package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +3 -3
  92. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  93. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  94. package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +3 -3
  95. package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +1 -1
  96. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  97. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  98. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  99. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  100. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  101. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  102. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  103. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  104. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  105. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  106. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  107. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  108. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  109. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  110. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  111. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  112. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +17 -0
  113. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  114. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-ulw-execute-continuation.json +17 -0
  115. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  116. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  117. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  118. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  119. package/packages/omo-codex/plugin/package-lock.json +34 -34
  120. package/packages/omo-codex/plugin/package.json +2 -2
  121. package/packages/omo-codex/plugin/scripts/auto-update-plan.mjs +1 -1
  122. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +11 -11
  123. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +1 -1
  124. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/README.md +1 -1
  125. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
  126. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
  127. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
  128. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/orchestration.md +1 -1
  129. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/routing.md +5 -5
  130. package/packages/omo-codex/plugin/skills/review-work/SKILL.md +1 -1
  131. package/packages/omo-codex/plugin/skills/{start-work → ulw-execute}/SKILL.md +10 -10
  132. package/packages/omo-codex/plugin/skills/ulw-execute/agents/openai.yaml +2 -0
  133. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +4 -4
  134. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +4 -4
  135. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-unclear.md +2 -2
  136. package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +4 -4
  137. package/packages/omo-codex/plugin/test/aggregate-manifest.test.mjs +1 -1
  138. package/packages/omo-codex/plugin/test/component-bin-names.test.mjs +2 -2
  139. package/packages/omo-codex/plugin/test/component-bundled-cli.test.mjs +1 -1
  140. package/packages/omo-codex/plugin/test/component-hook-contract-cases.mjs +2 -2
  141. package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +4 -4
  142. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +12 -12
  143. package/packages/omo-codex/scripts/install-dist/install-local.mjs +4 -4
  144. package/packages/shared-skills/skills/frontend/SKILL.md +1 -1
  145. package/packages/shared-skills/skills/frontend/references/designpowers/README.md +1 -1
  146. package/packages/shared-skills/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
  147. package/packages/shared-skills/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
  148. package/packages/shared-skills/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
  149. package/packages/shared-skills/skills/frontend/references/designpowers/orchestration.md +1 -1
  150. package/packages/shared-skills/skills/frontend/references/designpowers/routing.md +5 -5
  151. package/packages/shared-skills/skills/{start-work → ulw-execute}/SKILL.md +7 -7
  152. package/packages/shared-skills/skills/ulw-plan/SKILL.md +4 -4
  153. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +4 -4
  154. package/packages/shared-skills/skills/ulw-plan/references/intent-unclear.md +2 -2
  155. package/dist/config/schema/start-work.d.ts +0 -5
  156. package/dist/features/builtin-commands/templates/start-work.d.ts +0 -1
  157. package/dist/hooks/start-work/start-work-hook.d.ts +0 -23
  158. package/dist/plugin/chat-message/start-work-message.d.ts +0 -5
  159. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +0 -28
  160. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +0 -17
  161. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +0 -17
  162. package/packages/omo-codex/plugin/skills/start-work/agents/openai.yaml +0 -2
  163. /package/dist/hooks/{start-work → ulw-execute}/context-info-formatters.d.ts +0 -0
  164. /package/dist/hooks/{start-work → ulw-execute}/explicit-plan-context.d.ts +0 -0
  165. /package/dist/hooks/{start-work → ulw-execute}/notepad-scaffold.d.ts +0 -0
  166. /package/dist/hooks/{start-work → ulw-execute}/parse-user-request.d.ts +0 -0
  167. /package/dist/hooks/{start-work → ulw-execute}/plan-discovery-context.d.ts +0 -0
  168. /package/dist/hooks/{start-work → ulw-execute}/plan-selection.d.ts +0 -0
  169. /package/dist/hooks/{start-work → ulw-execute}/session-plan-affinity.d.ts +0 -0
  170. /package/dist/hooks/{start-work → ulw-execute}/work-initializer.d.ts +0 -0
  171. /package/dist/hooks/{start-work → ulw-execute}/worktree-block.d.ts +0 -0
  172. /package/dist/hooks/{start-work → ulw-execute}/worktree-detector.d.ts +0 -0
  173. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/.gitattributes +0 -0
  174. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/CHANGELOG.md +0 -0
  175. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/LICENSE +0 -0
  176. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/biome.json +0 -0
  177. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/plan-checklist.ts +0 -0
  178. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/types.ts +0 -0
  179. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-completed.json +0 -0
  180. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-mixed-platforms.json +0 -0
  181. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-single-codex-work.json +0 -0
  182. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-all-done.md +0 -0
  183. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-scaffold.md +0 -0
  184. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-nested-checkboxes.md +0 -0
  185. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-unchecked.md +0 -0
  186. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.build.json +0 -0
  187. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.json +0 -0
  188. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/vitest.config.ts +0 -0
package/dist/index.js CHANGED
@@ -10353,18 +10353,6 @@ var init_internal_initiator_marker = __esm(() => {
10353
10353
  });
10354
10354
 
10355
10355
  // packages/utils/src/migration/agent-names.ts
10356
- function migrateAgentNames(agents) {
10357
- const migrated = {};
10358
- let changed = false;
10359
- for (const [key, value] of Object.entries(agents)) {
10360
- const newKey = AGENT_NAME_MAP[key.toLowerCase()] ?? AGENT_NAME_MAP[key] ?? key;
10361
- if (newKey !== key) {
10362
- changed = true;
10363
- }
10364
- migrated[newKey] = value;
10365
- }
10366
- return { migrated, changed };
10367
- }
10368
10356
  var AGENT_NAME_MAP, BUILTIN_AGENT_NAMES;
10369
10357
  var init_agent_names = __esm(() => {
10370
10358
  AGENT_NAME_MAP = {
@@ -10414,62 +10402,6 @@ var init_agent_names = __esm(() => {
10414
10402
  ]);
10415
10403
  });
10416
10404
 
10417
- // packages/utils/src/migration/hook-names.ts
10418
- var HOOK_NAME_MAP;
10419
- var init_hook_names = __esm(() => {
10420
- HOOK_NAME_MAP = {
10421
- "anthropic-auto-compact": "anthropic-context-window-limit-recovery",
10422
- "sisyphus-orchestrator": "atlas",
10423
- "sisyphus-gpt-hephaestus-reminder": "no-sisyphus-gpt",
10424
- "empty-message-sanitizer": null,
10425
- "delegate-task-english-directive": null,
10426
- "gpt-permission-continuation": null,
10427
- "thinking-block-validator": null,
10428
- "session-recovery": null
10429
- };
10430
- });
10431
-
10432
- // packages/utils/src/migration/model-versions.ts
10433
- function migrationKey(oldModel, newModel) {
10434
- return `model-version:${oldModel}->${newModel}`;
10435
- }
10436
- function migrateModelVersions(configs, appliedMigrations) {
10437
- const migrated = {};
10438
- let changed = false;
10439
- const newMigrations = [];
10440
- for (const [key, value] of Object.entries(configs)) {
10441
- if (value && typeof value === "object" && !Array.isArray(value)) {
10442
- const config2 = value;
10443
- if (typeof config2.model === "string" && !CURRENT_USER_SELECTABLE_MODELS.has(config2.model) && MODEL_VERSION_MAP[config2.model]) {
10444
- const oldModel = config2.model;
10445
- const newModel = MODEL_VERSION_MAP[oldModel];
10446
- const mKey = migrationKey(oldModel, newModel);
10447
- if (appliedMigrations?.has(mKey)) {
10448
- migrated[key] = value;
10449
- continue;
10450
- }
10451
- migrated[key] = { ...config2, model: newModel };
10452
- changed = true;
10453
- newMigrations.push(mKey);
10454
- continue;
10455
- }
10456
- }
10457
- migrated[key] = value;
10458
- }
10459
- return { migrated, changed, newMigrations };
10460
- }
10461
- var MODEL_VERSION_MAP, CURRENT_USER_SELECTABLE_MODELS;
10462
- var init_model_versions = __esm(() => {
10463
- MODEL_VERSION_MAP = {
10464
- "anthropic/claude-opus-4-4": "anthropic/claude-opus-4-8"
10465
- };
10466
- CURRENT_USER_SELECTABLE_MODELS = new Set([
10467
- "anthropic/claude-opus-4-5",
10468
- "anthropic/claude-opus-4-6",
10469
- "anthropic/claude-sonnet-4-5"
10470
- ]);
10471
- });
10472
-
10473
10405
  // packages/utils/src/migration/agent-category.ts
10474
10406
  function configureMigrationCategoryDefaults(defaults) {
10475
10407
  categoryDefaults = defaults ?? {};
@@ -27455,7 +27387,7 @@ import { z as z25 } from "zod";
27455
27387
  var BuiltinCommandNameSchema = z25.enum([
27456
27388
  "goal",
27457
27389
  "refactor",
27458
- "start-work",
27390
+ "ulw-execute",
27459
27391
  "stop-continuation",
27460
27392
  "remove-ai-slops",
27461
27393
  "hyperplan"
@@ -27587,7 +27519,7 @@ var HookNameSchema = z32.enum([
27587
27519
  "no-sisyphus-gpt",
27588
27520
  "no-hephaestus-non-gpt",
27589
27521
  "hephaestus-agents-md-injector",
27590
- "start-work",
27522
+ "ulw-execute",
27591
27523
  "atlas",
27592
27524
  "unstable-agent-babysitter",
27593
27525
  "task-resume-info",
@@ -27798,9 +27730,9 @@ var TuiConfigSchema = z47.object({
27798
27730
  sidebar: TuiSidebarConfigSchema.default({ enabled: true })
27799
27731
  });
27800
27732
 
27801
- // packages/omo-opencode/src/config/schema/start-work.ts
27733
+ // packages/omo-opencode/src/config/schema/ulw-execute.ts
27802
27734
  import { z as z48 } from "zod";
27803
- var StartWorkConfigSchema = z48.object({
27735
+ var UlwExecuteConfigSchema = z48.object({
27804
27736
  auto_commit: z48.boolean().default(true)
27805
27737
  });
27806
27738
 
@@ -27860,7 +27792,8 @@ var OhMyOpenCodeConfigSchema = z50.object({
27860
27792
  tmux: TmuxConfigSchema.optional(),
27861
27793
  tui: TuiConfigSchema.default({ sidebar: { enabled: true } }).optional(),
27862
27794
  sisyphus: SisyphusConfigSchema.optional(),
27863
- start_work: StartWorkConfigSchema.optional(),
27795
+ ulw_execute: UlwExecuteConfigSchema.optional(),
27796
+ start_work: UlwExecuteConfigSchema.optional(),
27864
27797
  default_mode: DefaultModeConfigSchema.optional(),
27865
27798
  _migrations: z50.array(z50.string()).optional()
27866
27799
  });
@@ -27951,6 +27884,21 @@ function materializeAgentModelChains(config3) {
27951
27884
  }));
27952
27885
  return changed ? { ...config3, agents } : config3;
27953
27886
  }
27887
+ var START_WORK_DEPRECATION_MESSAGE = 'config key "start_work" is deprecated, rename to "ulw_execute" - will be removed next release';
27888
+ var deprecationWarningSink = log2;
27889
+ function warnLegacyUlwExecuteKey(views) {
27890
+ for (const view of views) {
27891
+ if (!Object.hasOwn(view.config, "start_work"))
27892
+ continue;
27893
+ deprecationWarningSink(`[config] ${shortPath(view.path)}: ${START_WORK_DEPRECATION_MESSAGE}`);
27894
+ }
27895
+ }
27896
+ function migrateLegacyUlwExecuteKey(config3) {
27897
+ const legacy = config3.start_work;
27898
+ if (legacy === undefined || config3.ulw_execute !== undefined)
27899
+ return config3;
27900
+ return { ...config3, ulw_execute: legacy };
27901
+ }
27954
27902
  function migrateRalphLoopConfig(config3) {
27955
27903
  const legacy = config3.ralph_loop;
27956
27904
  if (legacy === undefined)
@@ -27979,11 +27927,12 @@ function validatePluginConfig(directory, environment2 = process.env) {
27979
27927
  const firstView = views[0];
27980
27928
  const userConfig = parseConfig(chain.protectedUserView);
27981
27929
  const config3 = applyDisabledProviders(materializeAgentModelChains(protectUserFields(mergeViews(views), userConfig)));
27930
+ warnLegacyUlwExecuteKey(chain.views);
27982
27931
  return {
27983
27932
  valid: messages.length === 0,
27984
27933
  messages,
27985
27934
  path: chainMessages.length > 0 ? chain.diagnostics[0]?.path ?? null : firstFailingView?.path ?? firstView?.path ?? null,
27986
- config: migrateRalphLoopConfig(config3)
27935
+ config: migrateRalphLoopConfig(migrateLegacyUlwExecuteKey(config3))
27987
27936
  };
27988
27937
  }
27989
27938
 
@@ -98681,7 +98630,7 @@ function getCachedVersion(options = {}) {
98681
98630
  // package.json
98682
98631
  var package_default = {
98683
98632
  name: "oh-my-opencode",
98684
- version: "5.0.0-beta.19",
98633
+ version: "5.0.0-beta.20",
98685
98634
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
98686
98635
  main: "./dist/index.js",
98687
98636
  types: "dist/index.d.ts",
@@ -98766,7 +98715,7 @@ var package_default = {
98766
98715
  "packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/cli.js",
98767
98716
  "packages/omo-codex/plugin/components/lsp/dist/cli.js",
98768
98717
  "packages/omo-codex/plugin/components/rules/dist/cli.js",
98769
- "packages/omo-codex/plugin/components/start-work-continuation/dist/cli.js",
98718
+ "packages/omo-codex/plugin/components/ulw-execute-continuation/dist/cli.js",
98770
98719
  "packages/omo-codex/plugin/components/teammode/dist/cli.js",
98771
98720
  "packages/omo-codex/plugin/components/telemetry/dist/cli.js",
98772
98721
  "packages/omo-codex/plugin/components/ultrawork/dist/cli.js",
@@ -98862,7 +98811,7 @@ var package_default = {
98862
98811
  zod: "^4.4.3"
98863
98812
  },
98864
98813
  devDependencies: {
98865
- "@code-yeongyu/senpi": "2026.8.24",
98814
+ "@code-yeongyu/senpi": "2026.8.25",
98866
98815
  "@oh-my-opencode/agents-md-core": "workspace:*",
98867
98816
  "@oh-my-opencode/ast-grep-mcp": "workspace:*",
98868
98817
  "@oh-my-opencode/boulder-state": "workspace:*",
@@ -98903,18 +98852,18 @@ var package_default = {
98903
98852
  typescript: "^7.0.2"
98904
98853
  },
98905
98854
  optionalDependencies: {
98906
- "oh-my-opencode-darwin-arm64": "5.0.0-beta.19",
98907
- "oh-my-opencode-darwin-x64": "5.0.0-beta.19",
98908
- "oh-my-opencode-darwin-x64-baseline": "5.0.0-beta.19",
98909
- "oh-my-opencode-linux-arm64": "5.0.0-beta.19",
98910
- "oh-my-opencode-linux-arm64-musl": "5.0.0-beta.19",
98911
- "oh-my-opencode-linux-x64": "5.0.0-beta.19",
98912
- "oh-my-opencode-linux-x64-baseline": "5.0.0-beta.19",
98913
- "oh-my-opencode-linux-x64-musl": "5.0.0-beta.19",
98914
- "oh-my-opencode-linux-x64-musl-baseline": "5.0.0-beta.19",
98915
- "oh-my-opencode-windows-arm64": "5.0.0-beta.19",
98916
- "oh-my-opencode-windows-x64": "5.0.0-beta.19",
98917
- "oh-my-opencode-windows-x64-baseline": "5.0.0-beta.19"
98855
+ "oh-my-opencode-darwin-arm64": "5.0.0-beta.20",
98856
+ "oh-my-opencode-darwin-x64": "5.0.0-beta.20",
98857
+ "oh-my-opencode-darwin-x64-baseline": "5.0.0-beta.20",
98858
+ "oh-my-opencode-linux-arm64": "5.0.0-beta.20",
98859
+ "oh-my-opencode-linux-arm64-musl": "5.0.0-beta.20",
98860
+ "oh-my-opencode-linux-x64": "5.0.0-beta.20",
98861
+ "oh-my-opencode-linux-x64-baseline": "5.0.0-beta.20",
98862
+ "oh-my-opencode-linux-x64-musl": "5.0.0-beta.20",
98863
+ "oh-my-opencode-linux-x64-musl-baseline": "5.0.0-beta.20",
98864
+ "oh-my-opencode-windows-arm64": "5.0.0-beta.20",
98865
+ "oh-my-opencode-windows-x64": "5.0.0-beta.20",
98866
+ "oh-my-opencode-windows-x64-baseline": "5.0.0-beta.20"
98918
98867
  },
98919
98868
  overrides: {
98920
98869
  "@earendil-works/pi-agent-core": "0.84.2",
@@ -99099,6 +99048,8 @@ function syncCachePackageJsonToIntent(pluginInfo) {
99099
99048
  import { existsSync as existsSync73 } from "fs";
99100
99049
  import { dirname as dirname28, join as join89 } from "path";
99101
99050
  import { fileURLToPath as fileURLToPath4 } from "url";
99051
+ // packages/omo-opencode/src/cli/fallback-lane-policy.ts
99052
+ var EXCLUDED_FALLBACK_PROVIDERS = new Set(["openrouter", "opencode", "vercel"]);
99102
99053
  // packages/omo-opencode/src/startup-migration.ts
99103
99054
  init_src();
99104
99055
  import { posix as posix8 } from "path";
@@ -99450,11 +99401,6 @@ function transformConfigJsoncSources(input) {
99450
99401
  };
99451
99402
  }
99452
99403
 
99453
- // packages/omo-opencode/src/config-migration/transform-opencode.ts
99454
- init_agent_names();
99455
- init_hook_names();
99456
- init_model_versions();
99457
-
99458
99404
  // packages/omo-opencode/src/config-migration/deep-diff.ts
99459
99405
  function equalValues(left, right) {
99460
99406
  if (Object.is(left, right))
@@ -99486,58 +99432,24 @@ function deepDifference(base, profile2) {
99486
99432
  }
99487
99433
 
99488
99434
  // packages/omo-opencode/src/config-migration/transform-opencode.ts
99489
- function replaceDisabledAgents(value) {
99490
- if (!Array.isArray(value))
99491
- return value;
99492
- return value.map((entry) => {
99493
- if (typeof entry !== "string")
99494
- return entry;
99495
- return AGENT_NAME_MAP[entry.toLowerCase()] ?? AGENT_NAME_MAP[entry] ?? entry;
99496
- });
99497
- }
99498
- function replaceDisabledHooks(value) {
99499
- if (!Array.isArray(value))
99500
- return value;
99501
- return value.flatMap((entry) => {
99502
- if (typeof entry !== "string")
99503
- return [entry];
99504
- const replacement = HOOK_NAME_MAP[entry];
99505
- return replacement === null ? [] : [replacement ?? entry];
99506
- });
99507
- }
99508
- function transformLegacyKeys(value, history) {
99435
+ var MIGRATED_OPENCODE_FIELDS = new Set([
99436
+ "disabled_providers",
99437
+ "model_fallback",
99438
+ "models",
99439
+ "sisyphus_agent"
99440
+ ]);
99441
+ function transformLegacyKeys(value) {
99509
99442
  const config3 = withoutLegacyMetadata(value);
99510
- const appliedMigrations = new Set(history);
99511
- const agents = config3.agents;
99512
- if (isPlainRecord4(agents)) {
99513
- const namedAgents = migrateAgentNames(agents).migrated;
99514
- config3.agents = migrateModelVersions(namedAgents, appliedMigrations).migrated;
99515
- }
99516
- const categories2 = config3.categories;
99517
- if (isPlainRecord4(categories2)) {
99518
- config3.categories = migrateModelVersions(categories2, appliedMigrations).migrated;
99519
- }
99443
+ delete config3.agents;
99444
+ delete config3.categories;
99520
99445
  if (config3.omo_agent !== undefined) {
99521
99446
  config3.sisyphus_agent = config3.omo_agent;
99522
99447
  delete config3.omo_agent;
99523
99448
  }
99524
- delete config3.lsp;
99525
- if (isPlainRecord4(config3.experimental) && Object.hasOwn(config3.experimental, "hashline_edit")) {
99526
- if (config3.hashline_edit === undefined)
99527
- config3.hashline_edit = config3.experimental.hashline_edit;
99528
- delete config3.experimental.hashline_edit;
99529
- if (Object.keys(config3.experimental).length === 0)
99530
- delete config3.experimental;
99531
- }
99532
- if (config3.disabled_agents !== undefined)
99533
- config3.disabled_agents = replaceDisabledAgents(config3.disabled_agents);
99534
- if (config3.disabled_hooks !== undefined)
99535
- config3.disabled_hooks = replaceDisabledHooks(config3.disabled_hooks);
99536
- return config3;
99449
+ return Object.fromEntries(Object.entries(config3).filter(([key]) => MIGRATED_OPENCODE_FIELDS.has(key)));
99537
99450
  }
99538
99451
  function loadedConfigs(discovered, sources) {
99539
99452
  const metadataByPath = new Map(discovered.map((source) => [source.path, source]));
99540
- const historyByConfigPath = legacyMigrationHistory(discovered, sources);
99541
99453
  const configs = [];
99542
99454
  for (const source of sources) {
99543
99455
  const metadata = metadataByPath.get(source.path);
@@ -99545,7 +99457,7 @@ function loadedConfigs(discovered, sources) {
99545
99457
  continue;
99546
99458
  configs.push({
99547
99459
  metadata,
99548
- value: transformLegacyKeys(source.value, historyByConfigPath[metadata.configPath] ?? [])
99460
+ value: transformLegacyKeys(source.value)
99549
99461
  });
99550
99462
  }
99551
99463
  return configs;
@@ -101425,7 +101337,7 @@ TASK ANALYSIS:
101425
101337
 
101426
101338
  ## Step 2: Notepad (auto-scaffolded)
101427
101339
 
101428
- \`/start-work\` creates \`.omo/notepads/{plan-name}/\` with these files automatically:
101340
+ \`/ulw-execute\` creates \`.omo/notepads/{plan-name}/\` with these files automatically:
101429
101341
  - \`learnings.md\` - Conventions, patterns
101430
101342
  - \`decisions.md\` - Architectural choices
101431
101343
  - \`issues.md\` - Problems, gotchas
@@ -101958,7 +101870,7 @@ TASK ANALYSIS:
101958
101870
 
101959
101871
  ## Step 2: Notepad (auto-scaffolded)
101960
101872
 
101961
- \`/start-work\` creates \`.omo/notepads/{plan-name}/\` with these files automatically:
101873
+ \`/ulw-execute\` creates \`.omo/notepads/{plan-name}/\` with these files automatically:
101962
101874
  - \`learnings.md\` - Conventions, patterns
101963
101875
  - \`decisions.md\` - Architectural choices
101964
101876
  - \`issues.md\` - Problems, gotchas
@@ -102439,7 +102351,7 @@ TASK ANALYSIS:
102439
102351
 
102440
102352
  ## Step 2: Notepad (auto-scaffolded)
102441
102353
 
102442
- \`/start-work\` creates \`.omo/notepads/{plan-name}/\` with these files automatically:
102354
+ \`/ulw-execute\` creates \`.omo/notepads/{plan-name}/\` with these files automatically:
102443
102355
  - \`learnings.md\` - Conventions, patterns
102444
102356
  - \`decisions.md\` - Architectural choices
102445
102357
  - \`issues.md\` - Problems, gotchas
@@ -102870,7 +102782,7 @@ TASK ANALYSIS:
102870
102782
 
102871
102783
  ## Step 2: Notepad (auto-scaffolded)
102872
102784
 
102873
- \`/start-work\` creates \`.omo/notepads/{plan-name}/\` with these files automatically:
102785
+ \`/ulw-execute\` creates \`.omo/notepads/{plan-name}/\` with these files automatically:
102874
102786
  - \`learnings.md\` - Conventions, patterns
102875
102787
  - \`decisions.md\` - Architectural choices
102876
102788
  - \`issues.md\` - Problems, gotchas
@@ -103349,7 +103261,7 @@ TASK ANALYSIS:
103349
103261
 
103350
103262
  ## Step 2: Notepad (auto-scaffolded)
103351
103263
 
103352
- \`/start-work\` creates \`.omo/notepads/{plan-name}/\` with these files automatically:
103264
+ \`/ulw-execute\` creates \`.omo/notepads/{plan-name}/\` with these files automatically:
103353
103265
  - \`learnings.md\` - Conventions, patterns
103354
103266
  - \`decisions.md\` - Architectural choices
103355
103267
  - \`issues.md\` - Problems, gotchas
@@ -103743,7 +103655,7 @@ TASK ANALYSIS:
103743
103655
 
103744
103656
  ## Step 2: Notepad (auto-scaffolded)
103745
103657
 
103746
- \`/start-work\` creates \`.omo/notepads/{plan-name}/\` with these files automatically:
103658
+ \`/ulw-execute\` creates \`.omo/notepads/{plan-name}/\` with these files automatically:
103747
103659
  - \`learnings.md\` - Conventions, patterns
103748
103660
  - \`decisions.md\` - Architectural choices
103749
103661
  - \`issues.md\` - Problems, gotchas
@@ -104073,7 +103985,7 @@ TASK ANALYSIS:
104073
103985
 
104074
103986
  ## Step 2: Notepad (auto-scaffolded)
104075
103987
 
104076
- \`/start-work\` creates \`.omo/notepads/{plan-name}/\` with these files automatically:
103988
+ \`/ulw-execute\` creates \`.omo/notepads/{plan-name}/\` with these files automatically:
104077
103989
  - \`learnings.md\` - Conventions, patterns
104078
103990
  - \`decisions.md\` - Architectural choices
104079
103991
  - \`issues.md\` - Problems, gotchas
@@ -104484,7 +104396,7 @@ TASK ANALYSIS:
104484
104396
 
104485
104397
  ## Step 2: Notepad (auto-scaffolded)
104486
104398
 
104487
- \`/start-work\` creates \`.omo/notepads/{plan-name}/\` with these files automatically:
104399
+ \`/ulw-execute\` creates \`.omo/notepads/{plan-name}/\` with these files automatically:
104488
104400
  - \`learnings.md\` - Conventions, patterns
104489
104401
  - \`decisions.md\` - Architectural choices
104490
104402
  - \`issues.md\` - Problems, gotchas
@@ -104777,7 +104689,7 @@ var atlasPromptVariants = {
104777
104689
  }
104778
104690
  };
104779
104691
  // packages/prompts-core/prompts/prometheus/default.md
104780
- var default_default2 = 'You are Prometheus, a planning consultant. Your only job: gather the MAXIMUM relevant information about the request and the codebase, give the user the appropriate best practice for their situation, and ALWAYS act in dependence on the ulw-plan skill.\n\nYou are a PLANNER. You read, search, and write only plan artifacts under `.omo/`; you never implement - not directly and not by proxy: a subagent you spawn that edits product code is you implementing. Plan mode is sticky: "do X" / "fix X" / "just do it" all mean "plan X" - execution belongs to a separate worker session that only the user starts (e.g. `/start-work`), and no subagent you dispatch is ever that worker.\n\nYour FIRST action in every planning session is to LOAD the ulw-plan skill - call the `skill` tool with `skill(name="ulw-plan")` - and read it before anything else. For everything else - how to explore, when to ask versus adopt a best-practice default, the clear/unclear intent routing, the approval gate, the plan template, the scaffold script, and the high-accuracy review - follow the ulw-plan skill exactly. Do not restate or override it here.\n';
104692
+ var default_default2 = 'You are Prometheus, a planning consultant. Your only job: gather the MAXIMUM relevant information about the request and the codebase, give the user the appropriate best practice for their situation, and ALWAYS act in dependence on the ulw-plan skill.\n\nYou are a PLANNER. You read, search, and write only plan artifacts under `.omo/`; you never implement - not directly and not by proxy: a subagent you spawn that edits product code is you implementing. Plan mode is sticky: "do X" / "fix X" / "just do it" all mean "plan X" - execution belongs to a separate worker session that only the user starts (e.g. `/ulw-execute`), and no subagent you dispatch is ever that worker.\n\nYour FIRST action in every planning session is to LOAD the ulw-plan skill - call the `skill` tool with `skill(name="ulw-plan")` - and read it before anything else. For everything else - how to explore, when to ask versus adopt a best-practice default, the clear/unclear intent routing, the approval gate, the plan template, the scaffold script, and the high-accuracy review - follow the ulw-plan skill exactly. Do not restate or override it here.\n';
104781
104693
 
104782
104694
  // packages/prompts-core/src/prometheus-prompts.ts
104783
104695
  var prometheusPromptVariants = {
@@ -113099,12 +113011,12 @@ Append to the 6.6 summary a "Dispatch path" line and, when team path was used, t
113099
113011
  // packages/omo-opencode/src/features/builtin-commands/templates/refactor.ts
113100
113012
  var REFACTOR_TEMPLATE = REFACTOR_INTRO_AND_ANALYSIS + REFACTOR_CODEMAP_AND_TESTS + REFACTOR_PLAN_AND_EXECUTION + REFACTOR_VERIFICATION_AND_TOOLING;
113101
113013
 
113102
- // packages/omo-opencode/src/features/builtin-commands/templates/start-work.ts
113103
- var START_WORK_TEMPLATE = `You are starting an Atlas work session.
113014
+ // packages/omo-opencode/src/features/builtin-commands/templates/ulw-execute.ts
113015
+ var ULW_EXECUTE_TEMPLATE = `You are starting an Atlas work session.
113104
113016
 
113105
113017
  ## ARGUMENTS
113106
113018
 
113107
- - \`/start-work [plan-name] [--worktree <path>] [--make-pr] [--ship]\`
113019
+ - \`/ulw-execute [plan-name] [--worktree <path>] [--make-pr] [--ship]\`
113108
113020
  - \`plan-name\` (optional): name or partial match of the plan to start
113109
113021
  - \`--worktree <path>\` (optional): absolute path to an existing git worktree to work in
113110
113022
  - If specified and valid: hook pre-sets worktree_path in boulder.json
@@ -113123,7 +113035,7 @@ var START_WORK_TEMPLATE = `You are starting an Atlas work session.
113123
113035
  - If multiple active works are listed in your context:
113124
113036
  - This means boulder.json has more than one work with status: \`active\` or \`paused\`
113125
113037
  - Use the Question tool to ask the user which plan to resume
113126
- - Resume by running \`/start-work {plan-name}\` for the selected plan
113038
+ - Resume by running \`/ulw-execute {plan-name}\` for the selected plan
113127
113039
  - If the user says "start a new plan", continue with cold-start auto-selection logic
113128
113040
  - If exactly one active work is listed and the user did not name a plan:
113129
113041
  - Auto-resume that single active work
@@ -113202,7 +113114,7 @@ Reading plan and beginning execution...
113202
113114
 
113203
113115
  Do BOTH of these immediately after reading the plan file, BEFORE starting any work. Skipping either is a defect.
113204
113116
 
113205
- **1. Set the goal, in detail.** When a goal tool is available (\`create_goal\`), call it with a DETAILED objective: the plan name and path, the concrete end state, the phase/task counts, the delivery mode (direct, \`--make-pr\`, or \`--ship\`), and how completion will be verified. One work session = one goal. No goal tool -> record the same objective as the first \`.omo/start-work/ledger.jsonl\` entry.
113117
+ **1. Set the goal, in detail.** When a goal tool is available (\`create_goal\`), call it with a DETAILED objective: the plan name and path, the concrete end state, the phase/task counts, the delivery mode (direct, \`--make-pr\`, or \`--ship\`), and how completion will be verified. One work session = one goal. No goal tool -> record the same objective as the first \`.omo/ulw-execute/ledger.jsonl\` entry.
113206
113118
 
113207
113119
  **2. Register every phase and task as todos.** Decompose every plan task into granular, implementation-level sub-steps and register ALL of them as task/todo items, grouped phase by phase (one phase per plan wave), BEFORE starting any work. Keep them current at every moment: mark in_progress when work dispatches and done immediately after its verification passes - never batch-complete at the end, never execute work that is not a registered todo. Discovered work is appended as a todo before it runs.
113208
113120
 
@@ -113674,7 +113586,7 @@ $ARGUMENTS
113674
113586
  If team-mode is unavailable (\`team_*\` tools missing), instruct the user to set \`team_mode.enabled: true\` in \`~/.omo/omo.jsonc\` and restart opencode.`;
113675
113587
 
113676
113588
  // packages/omo-opencode/src/features/builtin-commands/commands.ts
113677
- function resolveStartWorkAgent(options) {
113589
+ function resolveUlwExecuteAgent(options) {
113678
113590
  if (options?.useRegisteredAgents) {
113679
113591
  return isAgentRegistered("atlas") ? "atlas" : "sisyphus";
113680
113592
  }
@@ -113707,11 +113619,11 @@ ${refactorContent}
113707
113619
  </command-instruction>`,
113708
113620
  argumentHint: "<refactoring-target> [--scope=<file|module|project>] [--strategy=<safe|aggressive>]"
113709
113621
  },
113710
- "start-work": {
113711
- description: "(builtin) Start Atlas work session from Prometheus plan",
113712
- agent: resolveStartWorkAgent(options),
113622
+ "ulw-execute": {
113623
+ description: "(builtin) Execute an Atlas work session from a Prometheus plan",
113624
+ agent: resolveUlwExecuteAgent(options),
113713
113625
  template: `<command-instruction>
113714
- ${START_WORK_TEMPLATE}
113626
+ ${ULW_EXECUTE_TEMPLATE}
113715
113627
  </command-instruction>
113716
113628
 
113717
113629
  <session-context>
@@ -114356,7 +114268,7 @@ ${createSystemDirective(SystemDirectiveTypes.PROMETHEUS_READ_ONLY)}
114356
114268
  \u2502 \u2502 - Key decisions made \u2502
114357
114269
  \u2502 \u2502 - Scope IN/OUT \u2502
114358
114270
  \u2502 \u2502 - Offer: "Start Work" vs "High Accuracy Review" \u2502
114359
- \u2502 \u2502 - Guide to /start-work \u2502
114271
+ \u2502 \u2502 - Guide to /ulw-execute \u2502
114360
114272
  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518
114361
114273
 
114362
114274
  **DID YOU COMPLETE STEPS 1-2 BEFORE WRITING THIS PLAN?**
@@ -114465,7 +114377,7 @@ function createPrometheusMdOnlyHook(ctx) {
114465
114377
  filePath,
114466
114378
  agent: agentName
114467
114379
  });
114468
- throw new Error(`[${HOOK_NAME6}] Prometheus is a planning agent. File operations restricted to .omo/*.md plan files only. ` + `Do NOT route this change through a subagent either - delegated implementation is still implementation. ` + `Record the intended change as a todo in the plan; implementation starts only when the user runs /start-work. ` + `Attempted to modify: ${filePath}.`);
114380
+ throw new Error(`[${HOOK_NAME6}] Prometheus is a planning agent. File operations restricted to .omo/*.md plan files only. ` + `Do NOT route this change through a subagent either - delegated implementation is still implementation. ` + `Record the intended change as a todo in the plan; implementation starts only when the user runs /ulw-execute. ` + `Attempted to modify: ${filePath}.`);
114469
114381
  }
114470
114382
  const normalizedPath = filePath.toLowerCase().replace(/\\/g, "/");
114471
114383
  if (normalizedPath.includes(".omo/plans/") || normalizedPath.includes(".omo\\plans\\")) {
@@ -114498,7 +114410,7 @@ NOTEPAD PATH: .omo/notepads/{plan-name}/
114498
114410
  - problems.md: Record unresolved issues, technical debt
114499
114411
 
114500
114412
  You SHOULD append findings to notepad files after completing work.
114501
- Notepad files are auto-scaffolded by /start-work. APPEND only - use the \`edit\` tool (match-and-insert after the last line) or \`bash\` \`>>\`. Never use the \`write\` tool (blocked by notepad-write-guard) and never overwrite.
114413
+ Notepad files are auto-scaffolded by /ulw-execute. APPEND only - use the \`edit\` tool (match-and-insert after the last line) or \`bash\` \`>>\`. Never use the \`write\` tool (blocked by notepad-write-guard) and never overwrite.
114502
114414
 
114503
114415
  ## Plan Location (subagent: READ ONLY)
114504
114416
  PLAN PATH: .omo/plans/{plan-name}.md
@@ -114559,10 +114471,10 @@ to continue: task(task_id="${taskId}", load_skills=[], run_in_background=false,
114559
114471
  "tool.execute.after": toolExecuteAfter
114560
114472
  };
114561
114473
  }
114562
- // packages/omo-opencode/src/hooks/start-work/start-work-hook.ts
114474
+ // packages/omo-opencode/src/hooks/ulw-execute/ulw-execute-hook.ts
114563
114475
  init_logger2();
114564
114476
 
114565
- // packages/omo-opencode/src/hooks/start-work/worktree-detector.ts
114477
+ // packages/omo-opencode/src/hooks/ulw-execute/worktree-detector.ts
114566
114478
  import { execFileSync as execFileSync6 } from "child_process";
114567
114479
  import { existsSync as existsSync84, realpathSync as realpathSync19 } from "fs";
114568
114480
  import { resolve as resolve29, win32 as win3210 } from "path";
@@ -114604,7 +114516,7 @@ function detectWorktreePath3(directory) {
114604
114516
  }
114605
114517
  }
114606
114518
 
114607
- // packages/omo-opencode/src/hooks/start-work/parse-user-request.ts
114519
+ // packages/omo-opencode/src/hooks/ulw-execute/parse-user-request.ts
114608
114520
  var KEYWORD_PATTERN = /\b(ultrawork|ulw)\b/gi;
114609
114521
  var WORKTREE_FLAG_PATTERN = /--worktree(?:\s+(\S+))?/;
114610
114522
  var MAKE_PR_FLAG_PATTERN = /--make-pr\b/;
@@ -114642,10 +114554,10 @@ function parseUserRequest(promptText) {
114642
114554
  };
114643
114555
  }
114644
114556
 
114645
- // packages/omo-opencode/src/hooks/start-work/context-info-builder.ts
114557
+ // packages/omo-opencode/src/hooks/ulw-execute/context-info-builder.ts
114646
114558
  init_logger2();
114647
114559
 
114648
- // packages/omo-opencode/src/hooks/start-work/worktree-block.ts
114560
+ // packages/omo-opencode/src/hooks/ulw-execute/worktree-block.ts
114649
114561
  function createWorktreeActiveBlock(worktreePath) {
114650
114562
  return `
114651
114563
  ## Worktree Active
@@ -114672,7 +114584,7 @@ ${worktreeInstruction}
114672
114584
  ${completionInstruction}`;
114673
114585
  }
114674
114586
 
114675
- // packages/omo-opencode/src/hooks/start-work/notepad-scaffold.ts
114587
+ // packages/omo-opencode/src/hooks/ulw-execute/notepad-scaffold.ts
114676
114588
  init_logger2();
114677
114589
  import { mkdirSync as mkdirSync21, writeFileSync as writeFileSync22 } from "fs";
114678
114590
  import { join as join111 } from "path";
@@ -114694,7 +114606,7 @@ var NOTEPAD_LABELS = {
114694
114606
  "issues.md": "Issues",
114695
114607
  "problems.md": "Problems"
114696
114608
  };
114697
- var NOTEPAD_FOOTER = "_Auto-scaffolded by /start-work. Append new entries below - never overwrite._";
114609
+ var NOTEPAD_FOOTER = "_Auto-scaffolded by /ulw-execute. Append new entries below - never overwrite._";
114698
114610
  function buildHeader(fileName, planName, timestamp) {
114699
114611
  const label = NOTEPAD_LABELS[fileName];
114700
114612
  const purpose = NOTEPAD_PURPOSES[fileName];
@@ -114730,7 +114642,7 @@ function ensureNotepadScaffold(params) {
114730
114642
  return { created, skipped };
114731
114643
  }
114732
114644
 
114733
- // packages/omo-opencode/src/hooks/start-work/context-info-formatters.ts
114645
+ // packages/omo-opencode/src/hooks/ulw-execute/context-info-formatters.ts
114734
114646
  function buildAutoSelectedPlanContextInfoOnly(params) {
114735
114647
  const { planPath, sessionId, timestamp, worktreeBlock, reason } = params;
114736
114648
  const progress = getPlanProgress(planPath);
@@ -114782,7 +114694,7 @@ Session ID: ${sessionId}
114782
114694
  ${optionList}
114783
114695
 
114784
114696
  Use the Question tool to ask the user which plan to resume.
114785
- - If the user chooses one option, run /start-work {plan-name} for that plan.
114697
+ - If the user chooses one option, run /ulw-execute {plan-name} for that plan.
114786
114698
  - If the user chooses to start a new plan, proceed with cold-start auto-selection flow.
114787
114699
  </system-reminder>`;
114788
114700
  }
@@ -114828,10 +114740,10 @@ The current session (${sessionId}) has been added to session_ids.
114828
114740
  Read the plan file and continue from the first unchecked task.`;
114829
114741
  }
114830
114742
 
114831
- // packages/omo-opencode/src/hooks/start-work/explicit-plan-context.ts
114743
+ // packages/omo-opencode/src/hooks/ulw-execute/explicit-plan-context.ts
114832
114744
  init_logger2();
114833
114745
 
114834
- // packages/omo-opencode/src/hooks/start-work/plan-selection.ts
114746
+ // packages/omo-opencode/src/hooks/ulw-execute/plan-selection.ts
114835
114747
  import { statSync as statSync14 } from "fs";
114836
114748
  function normalizePlanLookupValue(value) {
114837
114749
  return value.trim().replace(/^["'`]+|["'`]+$/g, "").toLowerCase().replace(/[\s_]+/g, "-").replace(/[^\p{L}\p{N}-]+/gu, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
@@ -114884,7 +114796,7 @@ Ask the user which plan to work on.`;
114884
114796
  No incomplete plans available. Create a new plan using the Prometheus agent.`;
114885
114797
  }
114886
114798
 
114887
- // packages/omo-opencode/src/hooks/start-work/work-initializer.ts
114799
+ // packages/omo-opencode/src/hooks/ulw-execute/work-initializer.ts
114888
114800
  function createNewWorkOrInitialize(params) {
114889
114801
  const { directory, planPath, sessionId, activeAgent, worktreePath } = params;
114890
114802
  const created = addBoulderWork(directory, {
@@ -114913,7 +114825,7 @@ function buildAutoSelectedPlanContextWithStateInit(params) {
114913
114825
  });
114914
114826
  }
114915
114827
 
114916
- // packages/omo-opencode/src/hooks/start-work/explicit-plan-context.ts
114828
+ // packages/omo-opencode/src/hooks/ulw-execute/explicit-plan-context.ts
114917
114829
  function buildExplicitPlanContext(params) {
114918
114830
  const { explicitPlanName, sessionId, timestamp, activeAgent, worktreePath, worktreeBlock, directory } = params;
114919
114831
  log2(`[${HOOK_NAME8}] Explicit plan name requested: ${explicitPlanName}`, { sessionID: sessionId });
@@ -114990,7 +114902,7 @@ function buildPlanAlreadyCompleteContext(params) {
114990
114902
  All ${totalTasks} tasks are done. Create a new plan using the Prometheus agent.`;
114991
114903
  }
114992
114904
 
114993
- // packages/omo-opencode/src/hooks/start-work/plan-discovery-context.ts
114905
+ // packages/omo-opencode/src/hooks/ulw-execute/plan-discovery-context.ts
114994
114906
  function shouldResumeExistingState(input) {
114995
114907
  const { existingState, preferredPlanPath } = input;
114996
114908
  if (!existingState) {
@@ -115081,8 +114993,8 @@ ${worktreeBlock}
115081
114993
  </system-reminder>`;
115082
114994
  }
115083
114995
 
115084
- // packages/omo-opencode/src/hooks/start-work/context-info-builder.ts
115085
- function buildStartWorkContextInfo(params) {
114996
+ // packages/omo-opencode/src/hooks/ulw-execute/context-info-builder.ts
114997
+ function buildUlwExecuteContextInfo(params) {
115086
114998
  const {
115087
114999
  ctx,
115088
115000
  explicitPlanName,
@@ -115199,7 +115111,7 @@ function buildSelectedContextInfo(params) {
115199
115111
  return "";
115200
115112
  }
115201
115113
 
115202
- // packages/omo-opencode/src/hooks/start-work/session-plan-affinity.ts
115114
+ // packages/omo-opencode/src/hooks/ulw-execute/session-plan-affinity.ts
115203
115115
  import { posix as posix10, win32 as win3211 } from "path";
115204
115116
  init_logger2();
115205
115117
  var PLAN_PATH_PATTERN = /[A-Za-z0-9_./\\:~-]*\.(?:sisyphus|omo)[\\/]plans[\\/][A-Za-z0-9._/\\~-]+\.md/gi;
@@ -115274,7 +115186,7 @@ async function findRecentSessionPlanPath(input) {
115274
115186
  }
115275
115187
  }
115276
115188
  } catch (error) {
115277
- log2("[start-work] Failed to inspect session history for preferred plan", {
115189
+ log2("[ulw-execute] Failed to inspect session history for preferred plan", {
115278
115190
  sessionID: input.sessionID,
115279
115191
  error: String(error)
115280
115192
  });
@@ -115282,10 +115194,10 @@ async function findRecentSessionPlanPath(input) {
115282
115194
  return null;
115283
115195
  }
115284
115196
 
115285
- // packages/omo-opencode/src/hooks/start-work/start-work-hook.ts
115286
- var HOOK_NAME8 = "start-work";
115287
- var START_WORK_TEMPLATE_MARKER = "You are starting an Atlas work session.";
115288
- var CONTEXT_INFO_MARKER = "<!-- omo-start-work-context -->";
115197
+ // packages/omo-opencode/src/hooks/ulw-execute/ulw-execute-hook.ts
115198
+ var HOOK_NAME8 = "ulw-execute";
115199
+ var ULW_EXECUTE_TEMPLATE_MARKER = "You are starting an Atlas work session.";
115200
+ var CONTEXT_INFO_MARKER = "<!-- omo-ulw-execute-context -->";
115289
115201
  var COMMAND_INSTRUCTION_OPEN = "<command-instruction>";
115290
115202
  var COMMAND_INSTRUCTION_CLOSE = "</command-instruction>";
115291
115203
  var SESSION_CONTEXT_OPEN = "<session-context>";
@@ -115295,14 +115207,14 @@ function findFrameworkSessionContextRanges(text) {
115295
115207
  const ranges = [];
115296
115208
  let searchFrom = 0;
115297
115209
  while (searchFrom < text.length) {
115298
- const markerIndex = text.indexOf(START_WORK_TEMPLATE_MARKER, searchFrom);
115210
+ const markerIndex = text.indexOf(ULW_EXECUTE_TEMPLATE_MARKER, searchFrom);
115299
115211
  if (markerIndex < 0)
115300
115212
  break;
115301
115213
  const instructionOpen = text.lastIndexOf(COMMAND_INSTRUCTION_OPEN, markerIndex);
115302
115214
  const instructionBodyStart = instructionOpen + COMMAND_INSTRUCTION_OPEN.length;
115303
- const instructionClose = text.indexOf(COMMAND_INSTRUCTION_CLOSE, markerIndex + START_WORK_TEMPLATE_MARKER.length);
115215
+ const instructionClose = text.indexOf(COMMAND_INSTRUCTION_CLOSE, markerIndex + ULW_EXECUTE_TEMPLATE_MARKER.length);
115304
115216
  if (instructionOpen < searchFrom || instructionClose < 0 || text.slice(instructionBodyStart, markerIndex).trim() !== "") {
115305
- searchFrom = markerIndex + START_WORK_TEMPLATE_MARKER.length;
115217
+ searchFrom = markerIndex + ULW_EXECUTE_TEMPLATE_MARKER.length;
115306
115218
  continue;
115307
115219
  }
115308
115220
  const instructionEnd = instructionClose + COMMAND_INSTRUCTION_CLOSE.length;
@@ -115364,15 +115276,15 @@ function resolveWorktreeContext(explicitWorktreePath) {
115364
115276
  **Worktree** (needs setup): \`git worktree add ${explicitWorktreePath} <branch>\`, then add \`"worktree_path"\` to boulder.json`
115365
115277
  };
115366
115278
  }
115367
- function createStartWorkHook(ctx) {
115368
- const processStartWork = async (input, output) => {
115279
+ function createUlwExecuteHook(ctx) {
115280
+ const processUlwExecute = async (input, output) => {
115369
115281
  const parts = output.parts;
115370
115282
  const promptText = parts?.filter((p) => p.type === "text" && p.text).map((p) => p.text).join(`
115371
115283
  `).trim() || "";
115372
- if (!promptText.includes("<session-context>") || !promptText.includes(START_WORK_TEMPLATE_MARKER)) {
115284
+ if (!promptText.includes("<session-context>") || !promptText.includes(ULW_EXECUTE_TEMPLATE_MARKER)) {
115373
115285
  return;
115374
115286
  }
115375
- log2(`[${HOOK_NAME8}] Processing start-work command`, { sessionID: input.sessionID });
115287
+ log2(`[${HOOK_NAME8}] Processing ulw-execute command`, { sessionID: input.sessionID });
115376
115288
  const activeAgent = isAgentRegistered("atlas") ? "atlas" : "sisyphus";
115377
115289
  updateSessionAgent(input.sessionID, activeAgent);
115378
115290
  if (output.message) {
@@ -115390,7 +115302,7 @@ function createStartWorkHook(ctx) {
115390
115302
  sessionID: input.sessionID,
115391
115303
  availablePlans: findPrometheusPlans(ctx.directory)
115392
115304
  });
115393
- const contextInfo = buildStartWorkContextInfo({
115305
+ const contextInfo = buildUlwExecuteContextInfo({
115394
115306
  ctx,
115395
115307
  explicitPlanName,
115396
115308
  existingState,
@@ -115430,10 +115342,10 @@ ${contextInfo}`;
115430
115342
  };
115431
115343
  return {
115432
115344
  "chat.message": async (input, output) => {
115433
- await processStartWork(input, output);
115345
+ await processUlwExecute(input, output);
115434
115346
  },
115435
115347
  "command.execute.before": async (input, output) => {
115436
- await processStartWork(input, output);
115348
+ await processUlwExecute(input, output);
115437
115349
  }
115438
115350
  };
115439
115351
  }
@@ -116149,6 +116061,8 @@ function hasRunningBackgroundTasks(sessionID, options) {
116149
116061
  return backgroundManager ? backgroundManager.getTasksByParentSession(sessionID).some((task2) => ACTIVE_BACKGROUND_TASK_STATUSES2.has(task2.status)) : false;
116150
116062
  }
116151
116063
  async function injectContinuation2(input) {
116064
+ if (input.sessionState.lifecycleActive === false)
116065
+ return;
116152
116066
  const remaining = input.progress.total - input.progress.completed;
116153
116067
  if (input.sessionState.isInjectingContinuation) {
116154
116068
  scheduleRetry({
@@ -116248,12 +116162,16 @@ async function injectContinuation2(input) {
116248
116162
  }
116249
116163
  function scheduleRetry(input) {
116250
116164
  const { ctx, sessionID, sessionState, options } = input;
116165
+ if (sessionState.lifecycleActive === false)
116166
+ return;
116251
116167
  if (sessionState.pendingRetryTimer) {
116252
116168
  return;
116253
116169
  }
116254
116170
  sessionState.pendingRetryTimer = setTimeout(async () => {
116255
116171
  try {
116256
116172
  sessionState.pendingRetryTimer = undefined;
116173
+ if (sessionState.lifecycleActive === false)
116174
+ return;
116257
116175
  if (sessionState.promptFailureCount >= MAX_CONSECUTIVE_PROMPT_FAILURES)
116258
116176
  return;
116259
116177
  if (sessionState.stalledContinuationReason)
@@ -116359,7 +116277,6 @@ async function resolveActiveBoulderSession(input) {
116359
116277
  async function handleAtlasSessionIdle(input) {
116360
116278
  const { ctx, options, getState, sessionID } = input;
116361
116279
  const normalizedSessionID = normalizeSessionId(sessionID);
116362
- const sessionState = getState(sessionID);
116363
116280
  log2(`[${HOOK_NAME9}] session.idle`, { sessionID });
116364
116281
  const activeBoulderSession = await resolveActiveBoulderSession({
116365
116282
  client: ctx.client,
@@ -116370,6 +116287,7 @@ async function handleAtlasSessionIdle(input) {
116370
116287
  log2(`[${HOOK_NAME9}] Skipped: session not registered in active boulder`, { sessionID });
116371
116288
  return;
116372
116289
  }
116290
+ const sessionState = getState(sessionID);
116373
116291
  const { boulderState, progress, appendedSession } = activeBoulderSession;
116374
116292
  if (sessionState.waitingForFinalWaveApproval) {
116375
116293
  log2(`[${HOOK_NAME9}] Skipped: waiting for explicit final-wave approval`, { sessionID });
@@ -116484,21 +116402,28 @@ async function handleAtlasSessionIdle(input) {
116484
116402
 
116485
116403
  // packages/omo-opencode/src/hooks/atlas/event-handler.ts
116486
116404
  function createAtlasEventHandler(input) {
116487
- const { ctx, options, sessions, getState } = input;
116405
+ const { ctx, options, sessions, getState, cleanupSession } = input;
116488
116406
  return async ({ event }) => {
116489
116407
  const props = event.properties;
116490
116408
  if (event.type === "session.error") {
116491
116409
  const sessionID = resolveSessionEventID(props);
116492
116410
  if (!sessionID)
116493
116411
  return;
116494
- const state3 = getState(sessionID);
116495
116412
  const isAbort = isAbortError2(props?.error);
116496
- state3.lastEventWasAbortError = isAbort;
116497
116413
  log2(`[${HOOK_NAME9}] session.error`, { sessionID, isAbort });
116498
- if (!isAbort) {
116499
- const previousInjectedAt = state3.lastContinuationInjectedAt;
116414
+ if (isAbort) {
116415
+ const activeBoulderSession = await resolveActiveBoulderSession({
116416
+ client: ctx.client,
116417
+ directory: ctx.directory,
116418
+ sessionID
116419
+ });
116420
+ if (activeBoulderSession)
116421
+ getState(sessionID).lastEventWasAbortError = true;
116422
+ } else {
116423
+ const previousInjectedAt = sessions.get(sessionID)?.lastContinuationInjectedAt;
116500
116424
  await handleAtlasSessionIdle({ ctx, options, getState, sessionID });
116501
- if (state3.lastContinuationInjectedAt !== undefined && state3.lastContinuationInjectedAt !== previousInjectedAt) {
116425
+ const state3 = sessions.get(sessionID);
116426
+ if (state3 && state3.lastContinuationInjectedAt !== undefined && state3.lastContinuationInjectedAt !== previousInjectedAt) {
116502
116427
  state3.skipNextIdleAfterRuntimeErrorRetry = true;
116503
116428
  }
116504
116429
  }
@@ -116554,12 +116479,7 @@ function createAtlasEventHandler(input) {
116554
116479
  if (event.type === "session.deleted") {
116555
116480
  const sessionID = resolveSessionEventID(props);
116556
116481
  if (sessionID) {
116557
- const deletedState = sessions.get(sessionID);
116558
- if (deletedState?.pendingRetryTimer) {
116559
- clearTimeout(deletedState.pendingRetryTimer);
116560
- deletedState.pendingRetryTimer = undefined;
116561
- }
116562
- sessions.delete(sessionID);
116482
+ cleanupSession(sessionID);
116563
116483
  log2(`[${HOOK_NAME9}] Session deleted: cleaned up`, { sessionID });
116564
116484
  }
116565
116485
  return;
@@ -116567,18 +116487,148 @@ function createAtlasEventHandler(input) {
116567
116487
  if (event.type === "session.compacted") {
116568
116488
  const sessionID = resolveSessionEventID(props);
116569
116489
  if (sessionID) {
116570
- const compactedState = sessions.get(sessionID);
116571
- if (compactedState?.pendingRetryTimer) {
116572
- clearTimeout(compactedState.pendingRetryTimer);
116573
- compactedState.pendingRetryTimer = undefined;
116574
- }
116575
- sessions.delete(sessionID);
116490
+ cleanupSession(sessionID);
116576
116491
  log2(`[${HOOK_NAME9}] Session compacted: cleaned up`, { sessionID });
116577
116492
  }
116578
116493
  }
116579
116494
  };
116580
116495
  }
116581
116496
 
116497
+ // packages/omo-opencode/src/hooks/atlas/atlas-lifecycle-store.ts
116498
+ var ATLAS_SESSION_STATE_TTL_MS = 10 * 60 * 1000;
116499
+ var ATLAS_SESSION_PRUNE_INTERVAL_MS = 2 * 60 * 1000;
116500
+
116501
+ class AtlasLifecycleStore {
116502
+ sessions = new Map;
116503
+ pendingFilePaths = new Map;
116504
+ pendingTaskRefs = new Map;
116505
+ pendingPlanSnapshots = new Map;
116506
+ pendingCalls = new Map;
116507
+ sessionCallIDs = new Map;
116508
+ lastAccessedAt = new Map;
116509
+ pruneInterval;
116510
+ disposed = false;
116511
+ disposedState = { promptFailureCount: 0 };
116512
+ getExistingState(sessionID) {
116513
+ const tracked = this.sessions.get(sessionID);
116514
+ if (!tracked)
116515
+ return;
116516
+ this.lastAccessedAt.set(sessionID, Date.now());
116517
+ return tracked;
116518
+ }
116519
+ getOrCreateState(sessionID) {
116520
+ if (this.disposed)
116521
+ return this.disposedState;
116522
+ const existing = this.getExistingState(sessionID);
116523
+ if (existing)
116524
+ return existing;
116525
+ const state3 = { promptFailureCount: 0, lifecycleActive: true };
116526
+ this.sessions.set(sessionID, state3);
116527
+ this.lastAccessedAt.set(sessionID, Date.now());
116528
+ this.ensurePruneInterval();
116529
+ return state3;
116530
+ }
116531
+ trackFileCall(callID, sessionID, filePath) {
116532
+ this.pendingFilePaths.set(callID, filePath);
116533
+ this.replaceCall(callID, { kind: "file", sessionID, filePath });
116534
+ }
116535
+ trackTaskCall(callID, sessionID, task2) {
116536
+ this.pendingTaskRefs.set(callID, task2);
116537
+ this.replaceCall(callID, { kind: "task", sessionID, task: task2 });
116538
+ }
116539
+ trackPlanSnapshot(callID, snapshot) {
116540
+ this.pendingPlanSnapshots.set(callID, snapshot);
116541
+ }
116542
+ consumeFileCall(callID) {
116543
+ const pending = this.pendingCalls.get(callID ?? "");
116544
+ if (!pending || pending.kind !== "file")
116545
+ return;
116546
+ this.clearPendingCall(callID);
116547
+ return pending;
116548
+ }
116549
+ consumeTaskCall(callID) {
116550
+ const pending = this.pendingCalls.get(callID ?? "");
116551
+ if (!pending || pending.kind !== "task")
116552
+ return;
116553
+ this.clearPendingCall(callID);
116554
+ return pending;
116555
+ }
116556
+ clearPendingCall(callID) {
116557
+ if (!callID)
116558
+ return;
116559
+ const pending = this.pendingCalls.get(callID);
116560
+ if (!pending)
116561
+ return;
116562
+ this.pendingCalls.delete(callID);
116563
+ this.pendingFilePaths.delete(callID);
116564
+ this.pendingTaskRefs.delete(callID);
116565
+ this.pendingPlanSnapshots.delete(callID);
116566
+ if (pending.sessionID)
116567
+ this.removeSessionCallID(pending.sessionID, callID);
116568
+ }
116569
+ cleanupSession(sessionID) {
116570
+ const state3 = this.sessions.get(sessionID);
116571
+ if (state3)
116572
+ state3.lifecycleActive = false;
116573
+ if (state3?.pendingRetryTimer)
116574
+ clearTimeout(state3.pendingRetryTimer);
116575
+ this.sessions.delete(sessionID);
116576
+ this.lastAccessedAt.delete(sessionID);
116577
+ for (const callID of this.sessionCallIDs.get(sessionID) ?? [])
116578
+ this.clearPendingCall(callID);
116579
+ this.sessionCallIDs.delete(sessionID);
116580
+ }
116581
+ dispose() {
116582
+ if (this.disposed)
116583
+ return;
116584
+ this.disposed = true;
116585
+ if (this.pruneInterval)
116586
+ clearInterval(this.pruneInterval);
116587
+ this.pruneInterval = undefined;
116588
+ for (const sessionID of this.sessions.keys())
116589
+ this.cleanupSession(sessionID);
116590
+ this.pendingCalls.clear();
116591
+ this.pendingFilePaths.clear();
116592
+ this.pendingTaskRefs.clear();
116593
+ this.pendingPlanSnapshots.clear();
116594
+ this.sessionCallIDs.clear();
116595
+ }
116596
+ get sizes() {
116597
+ return { sessions: this.sessions.size, pendingCalls: this.pendingCalls.size, sessionIndexes: this.sessionCallIDs.size, hasPruneInterval: this.pruneInterval !== undefined };
116598
+ }
116599
+ replaceCall(callID, call) {
116600
+ this.clearPendingCall(callID);
116601
+ this.pendingCalls.set(callID, call);
116602
+ if (!call.sessionID)
116603
+ return;
116604
+ const callIDs = this.sessionCallIDs.get(call.sessionID) ?? new Set;
116605
+ callIDs.add(callID);
116606
+ this.sessionCallIDs.set(call.sessionID, callIDs);
116607
+ }
116608
+ removeSessionCallID(sessionID, callID) {
116609
+ const callIDs = this.sessionCallIDs.get(sessionID);
116610
+ if (!callIDs)
116611
+ return;
116612
+ callIDs.delete(callID);
116613
+ if (callIDs.size === 0)
116614
+ this.sessionCallIDs.delete(sessionID);
116615
+ }
116616
+ ensurePruneInterval() {
116617
+ if (this.pruneInterval || this.disposed)
116618
+ return;
116619
+ this.pruneInterval = setInterval(() => this.prune(), ATLAS_SESSION_PRUNE_INTERVAL_MS);
116620
+ this.pruneInterval.unref();
116621
+ }
116622
+ prune() {
116623
+ const now = Date.now();
116624
+ for (const sessionID of this.sessions.keys()) {
116625
+ const lastAccessedAt = this.lastAccessedAt.get(sessionID);
116626
+ if (lastAccessedAt !== undefined && now - lastAccessedAt > ATLAS_SESSION_STATE_TTL_MS)
116627
+ this.cleanupSession(sessionID);
116628
+ }
116629
+ }
116630
+ }
116631
+
116582
116632
  // packages/omo-opencode/src/hooks/atlas/subagent-session-id.ts
116583
116633
  init_logger2();
116584
116634
  function extractSessionIdFromMetadata(metadata) {
@@ -117430,13 +117480,22 @@ function createToolExecuteAfterHandler2(input) {
117430
117480
  const collectGitDiffStatsImpl = input.collectGitDiffStats ?? collectGitDiffStats;
117431
117481
  const formatFileChangesImpl = input.formatFileChanges ?? formatFileChanges;
117432
117482
  return async (toolInput, toolOutput) => {
117483
+ const clearPendingCall = () => {
117484
+ if (!toolInput.callID)
117485
+ return;
117486
+ pendingFilePaths.delete(toolInput.callID);
117487
+ pendingPlanSnapshots?.delete(toolInput.callID);
117488
+ pendingTaskRefs.delete(toolInput.callID);
117489
+ };
117433
117490
  if (!toolOutput) {
117491
+ clearPendingCall();
117434
117492
  return;
117435
117493
  }
117436
117494
  if (toolInput.sessionID && isTangibleProgressTool(toolInput.tool) && didToolMakeProgress(toolOutput)) {
117437
117495
  recordToolProgress(getState(toolInput.sessionID));
117438
117496
  }
117439
117497
  if (!await resolveIsCallerOrchestrator(toolInput.sessionID)) {
117498
+ clearPendingCall();
117440
117499
  return;
117441
117500
  }
117442
117501
  if (await handleDirectWorkToolAfter({
@@ -117509,10 +117568,12 @@ function parseTrackedTaskFromPrompt(prompt) {
117509
117568
  return null;
117510
117569
  }
117511
117570
  function createToolExecuteBeforeHandler2(input) {
117512
- const { ctx, pendingFilePaths, pendingTaskRefs, pendingPlanSnapshots } = input;
117571
+ const { ctx, pendingFilePaths, pendingTaskRefs, pendingPlanSnapshots, trackFileCall, trackTaskCall, trackPlanSnapshot } = input;
117513
117572
  const resolveIsCallerOrchestrator = input.isCallerOrchestrator ?? ((sessionID) => isCallerOrchestrator(sessionID, ctx.client));
117514
- function trackTask(callID, task2) {
117515
- pendingTaskRefs.set(callID, { kind: "track", task: task2 });
117573
+ function trackTask(callID, sessionID, task2) {
117574
+ const pending = { kind: "track", task: task2 };
117575
+ pendingTaskRefs.set(callID, pending);
117576
+ trackTaskCall?.(callID, sessionID, pending);
117516
117577
  }
117517
117578
  return async (toolInput, toolOutput) => {
117518
117579
  if (!await resolveIsCallerOrchestrator(toolInput.sessionID)) {
@@ -117524,6 +117585,7 @@ function createToolExecuteBeforeHandler2(input) {
117524
117585
  return;
117525
117586
  }
117526
117587
  pendingFilePaths.set(toolInput.callID, filePath);
117588
+ trackFileCall?.(toolInput.callID, toolInput.sessionID, filePath);
117527
117589
  const sessionID = toolInput.sessionID;
117528
117590
  const sessionWork = sessionID ? getWorkForSession(ctx.directory, sessionID) : null;
117529
117591
  const state3 = sessionWork ? null : readBoulderState(ctx.directory);
@@ -117532,6 +117594,7 @@ function createToolExecuteBeforeHandler2(input) {
117532
117594
  try {
117533
117595
  if (existsSync87(planPath)) {
117534
117596
  pendingPlanSnapshots.set(toolInput.callID, readFileSync59(planPath, "utf-8"));
117597
+ trackPlanSnapshot?.(toolInput.callID, readFileSync59(planPath, "utf-8"));
117535
117598
  }
117536
117599
  } catch (error) {
117537
117600
  if (!(error instanceof Error)) {
@@ -117555,10 +117618,12 @@ function createToolExecuteBeforeHandler2(input) {
117555
117618
  if (toolInput.callID) {
117556
117619
  const requestedSessionId = toolOutput.args.session_id;
117557
117620
  if (requestedSessionId) {
117558
- pendingTaskRefs.set(toolInput.callID, {
117621
+ const pending = {
117559
117622
  kind: "skip",
117560
117623
  reason: "explicit_resume"
117561
- });
117624
+ };
117625
+ pendingTaskRefs.set(toolInput.callID, pending);
117626
+ trackTaskCall?.(toolInput.callID, toolInput.sessionID, pending);
117562
117627
  } else {
117563
117628
  const prompt2 = typeof toolOutput.args.prompt === "string" ? toolOutput.args.prompt : "";
117564
117629
  const taskFromPrompt = parseTrackedTaskFromPrompt(prompt2);
@@ -117583,18 +117648,20 @@ function createToolExecuteBeforeHandler2(input) {
117583
117648
  };
117584
117649
  const hasExistingClaim = [...pendingTaskRefs.values()].some((pendingTaskRef) => pendingTaskRef.kind === "track" && pendingTaskRef.task.key === trackedTask.key);
117585
117650
  if (hasExistingClaim) {
117586
- pendingTaskRefs.set(toolInput.callID, {
117651
+ const pending = {
117587
117652
  kind: "skip",
117588
117653
  reason: "ambiguous_task_key",
117589
117654
  task: trackedTask
117590
- });
117655
+ };
117656
+ pendingTaskRefs.set(toolInput.callID, pending);
117657
+ trackTaskCall?.(toolInput.callID, toolInput.sessionID, pending);
117591
117658
  log2(`[${HOOK_NAME9}] Skipping task session persistence for ambiguous task key`, {
117592
117659
  sessionID: toolInput.sessionID,
117593
117660
  callID: toolInput.callID,
117594
117661
  taskKey: trackedTask.key
117595
117662
  });
117596
117663
  } else {
117597
- trackTask(toolInput.callID, trackedTask);
117664
+ trackTask(toolInput.callID, toolInput.sessionID, trackedTask);
117598
117665
  }
117599
117666
  }
117600
117667
  }
@@ -117613,37 +117680,33 @@ function createToolExecuteBeforeHandler2(input) {
117613
117680
 
117614
117681
  // packages/omo-opencode/src/hooks/atlas/atlas-hook.ts
117615
117682
  function createAtlasHook(ctx, options) {
117616
- const sessions = new Map;
117617
- const pendingFilePaths = new Map;
117618
- const pendingTaskRefs = new Map;
117619
- const pendingPlanSnapshots = new Map;
117683
+ const lifecycle = new AtlasLifecycleStore;
117620
117684
  const autoCommit = options?.autoCommit ?? true;
117621
117685
  function getState(sessionID) {
117622
- let state3 = sessions.get(sessionID);
117623
- if (!state3) {
117624
- state3 = { promptFailureCount: 0 };
117625
- sessions.set(sessionID, state3);
117626
- }
117627
- return state3;
117686
+ return lifecycle.getOrCreateState(sessionID);
117628
117687
  }
117629
117688
  return {
117630
- handler: createAtlasEventHandler({ ctx, options, sessions, getState }),
117689
+ handler: createAtlasEventHandler({ ctx, options, sessions: lifecycle.sessions, getState, cleanupSession: (sessionID) => lifecycle.cleanupSession(sessionID) }),
117631
117690
  "tool.execute.before": createToolExecuteBeforeHandler2({
117632
117691
  ctx,
117633
- pendingFilePaths,
117634
- pendingTaskRefs,
117635
- pendingPlanSnapshots,
117692
+ pendingFilePaths: lifecycle.pendingFilePaths,
117693
+ pendingTaskRefs: lifecycle.pendingTaskRefs,
117694
+ pendingPlanSnapshots: lifecycle.pendingPlanSnapshots,
117695
+ trackFileCall: (callID, sessionID, filePath) => lifecycle.trackFileCall(callID, sessionID, filePath),
117696
+ trackTaskCall: (callID, sessionID, task2) => lifecycle.trackTaskCall(callID, sessionID, task2),
117697
+ trackPlanSnapshot: (callID, snapshot) => lifecycle.trackPlanSnapshot(callID, snapshot),
117636
117698
  isCallerOrchestrator: options?.isCallerOrchestrator
117637
117699
  }),
117638
117700
  "tool.execute.after": createToolExecuteAfterHandler2({
117639
117701
  ctx,
117640
- pendingFilePaths,
117641
- pendingTaskRefs,
117642
- pendingPlanSnapshots,
117702
+ pendingFilePaths: lifecycle.pendingFilePaths,
117703
+ pendingTaskRefs: lifecycle.pendingTaskRefs,
117704
+ pendingPlanSnapshots: lifecycle.pendingPlanSnapshots,
117643
117705
  autoCommit,
117644
117706
  getState,
117645
117707
  isCallerOrchestrator: options?.isCallerOrchestrator
117646
- })
117708
+ }),
117709
+ dispose: () => lifecycle.dispose()
117647
117710
  };
117648
117711
  }
117649
117712
  // packages/omo-opencode/src/hooks/team-tool-gating/hook.ts
@@ -124779,7 +124842,7 @@ function buildWarning(rawCount, parsedCount, hasEmptySection) {
124779
124842
  "",
124780
124843
  "<plan-format-warning>",
124781
124844
  summary,
124782
- "Those sections will contribute no tasks to `/start-work` progress.",
124845
+ "Those sections will contribute no tasks to `/ulw-execute` progress.",
124783
124846
  "",
124784
124847
  "**Fix**: Every task checkbox under `## TODOs` MUST start with a bare number",
124785
124848
  "followed by dot + space: `1.`, `2.`, `3.` \u2014 NOT `T1.`, `Phase 1:`, `Task-1.` etc.",
@@ -124794,7 +124857,7 @@ function buildWarning(rawCount, parsedCount, hasEmptySection) {
124794
124857
  "<plan-format-warning>",
124795
124858
  `Plan has **${rawCount} task checkbox(es)** but \`getPlanProgress()\` only parsed **${parsedCount}**. `,
124796
124859
  `**${skipped} task(s)** have malformed labels and will be SKIPPED by the progress counter.`,
124797
- `\`/start-work\` will show "Progress: ${parsedCount} tasks" \u2014 missing ${skipped} task(s).`,
124860
+ `\`/ulw-execute\` will show "Progress: ${parsedCount} tasks" \u2014 missing ${skipped} task(s).`,
124798
124861
  "",
124799
124862
  "**Fix**: Ensure every skipped task checkbox uses bare-number format:",
124800
124863
  " `## TODOs` \u2192 `1.`, `2.`, `3.` (NOT `T1.`, `Phase 1:`, `Task-1.`)",
@@ -135534,7 +135597,7 @@ function createSessionHooks(args) {
135534
135597
  })) : null;
135535
135598
  const editErrorRecovery = isHookEnabled("edit-error-recovery") ? safeHook("edit-error-recovery", () => createEditErrorRecoveryHook(ctx)) : null;
135536
135599
  const delegateTaskRetry = isHookEnabled("delegate-task-retry") ? safeHook("delegate-task-retry", () => createDelegateTaskRetryHook(ctx)) : null;
135537
- const startWork = isHookEnabled("start-work") ? safeHook("start-work", () => createStartWorkHook(ctx)) : null;
135600
+ const ulwExecute = isHookEnabled("ulw-execute") ? safeHook("ulw-execute", () => createUlwExecuteHook(ctx)) : null;
135538
135601
  const prometheusMdOnly = isHookEnabled("prometheus-md-only") ? safeHook("prometheus-md-only", () => createPrometheusMdOnlyHook(ctx)) : null;
135539
135602
  const sisyphusJuniorNotepad = isHookEnabled("sisyphus-junior-notepad") ? safeHook("sisyphus-junior-notepad", () => createSisyphusJuniorNotepadHook(ctx)) : null;
135540
135603
  const noSisyphusGpt = isHookEnabled("no-sisyphus-gpt") ? safeHook("no-sisyphus-gpt", () => createNoSisyphusGptHook(ctx)) : null;
@@ -135565,7 +135628,7 @@ function createSessionHooks(args) {
135565
135628
  goal: goal2,
135566
135629
  editErrorRecovery,
135567
135630
  delegateTaskRetry,
135568
- startWork,
135631
+ ulwExecute,
135569
135632
  prometheusMdOnly,
135570
135633
  sisyphusJuniorNotepad,
135571
135634
  noSisyphusGpt,
@@ -136190,7 +136253,7 @@ function createContinuationHooks(args) {
136190
136253
  backgroundManager,
136191
136254
  isContinuationStopped: (sessionID) => stopContinuationGuard?.isStopped(sessionID) ?? false,
136192
136255
  agentOverrides: pluginConfig.agents,
136193
- autoCommit: pluginConfig.start_work?.auto_commit
136256
+ autoCommit: pluginConfig.ulw_execute?.auto_commit
136194
136257
  })) : null;
136195
136258
  return {
136196
136259
  stopContinuationGuard,
@@ -136229,6 +136292,7 @@ function disposeCreatedHooks(hooks2) {
136229
136292
  hooks2.claudeCodeHooks?.dispose?.();
136230
136293
  hooks2.commentChecker?.dispose?.();
136231
136294
  hooks2.runtimeFallback?.dispose?.();
136295
+ hooks2.atlasHook?.dispose?.();
136232
136296
  hooks2.todoContinuationEnforcer?.dispose?.();
136233
136297
  hooks2.autoSlashCommand?.dispose?.();
136234
136298
  hooks2.anthropicContextWindowLimitRecovery?.dispose?.();
@@ -173615,9 +173679,9 @@ function recordSessionModel(input, output) {
173615
173679
  }
173616
173680
  }
173617
173681
 
173618
- // packages/omo-opencode/src/plugin/chat-message/start-work-message.ts
173619
- var START_WORK_TEMPLATE_MARKER2 = "You are starting an Atlas work session.";
173620
- function isStartWorkHookOutput(value) {
173682
+ // packages/omo-opencode/src/plugin/chat-message/ulw-execute-message.ts
173683
+ var ULW_EXECUTE_TEMPLATE_MARKER2 = "You are starting an Atlas work session.";
173684
+ function isUlwExecuteHookOutput(value) {
173621
173685
  if (typeof value !== "object" || value === null)
173622
173686
  return false;
173623
173687
  const record13 = value;
@@ -173631,10 +173695,10 @@ function isStartWorkHookOutput(value) {
173631
173695
  return typeof partRecord.type === "string";
173632
173696
  });
173633
173697
  }
173634
- function isStartWorkFallbackTemplate(promptText) {
173635
- return promptText.includes("<session-context>") && promptText.includes(START_WORK_TEMPLATE_MARKER2);
173698
+ function isUlwExecuteFallbackTemplate(promptText) {
173699
+ return promptText.includes("<session-context>") && promptText.includes(ULW_EXECUTE_TEMPLATE_MARKER2);
173636
173700
  }
173637
- function clearStoppedContinuationBeforeWorkStart(hooks2, sessionID, command) {
173701
+ function clearStoppedContinuationBeforeUlwExecute(hooks2, sessionID, command) {
173638
173702
  if (hooks2.stopContinuationGuard?.isStopped(sessionID)) {
173639
173703
  hooks2.stopContinuationGuard.clear(sessionID);
173640
173704
  log2("[stop-continuation] Stop state cleared by chat.message work-starting command", {
@@ -173643,15 +173707,15 @@ function clearStoppedContinuationBeforeWorkStart(hooks2, sessionID, command) {
173643
173707
  });
173644
173708
  }
173645
173709
  }
173646
- async function runStartWorkHookIfApplicable(hooks2, input, output) {
173647
- if (!hooks2.startWork || !isStartWorkHookOutput(output)) {
173710
+ async function runUlwExecuteHookIfApplicable(hooks2, input, output) {
173711
+ if (!hooks2.ulwExecute || !isUlwExecuteHookOutput(output)) {
173648
173712
  return;
173649
173713
  }
173650
173714
  const promptText = extractPromptText5(output.parts);
173651
- if (isStartWorkFallbackTemplate(promptText)) {
173652
- clearStoppedContinuationBeforeWorkStart(hooks2, input.sessionID, "start-work");
173715
+ if (isUlwExecuteFallbackTemplate(promptText)) {
173716
+ clearStoppedContinuationBeforeUlwExecute(hooks2, input.sessionID, "ulw-execute");
173653
173717
  }
173654
- await hooks2.startWork["chat.message"]?.(input, output);
173718
+ await hooks2.ulwExecute["chat.message"]?.(input, output);
173655
173719
  }
173656
173720
 
173657
173721
  // packages/omo-opencode/src/plugin/command-execute-before.ts
@@ -173723,8 +173787,8 @@ function createCommandExecuteBeforeHandler(args) {
173723
173787
  }
173724
173788
  markNativeGoalCommand(output.parts);
173725
173789
  }
173726
- if (hooks2.startWork && normalizedCommand === "start-work" && hasPartsOutput(output)) {
173727
- await hooks2.startWork["command.execute.before"]?.(input, output);
173790
+ if (hooks2.ulwExecute && normalizedCommand === "ulw-execute" && hasPartsOutput(output)) {
173791
+ await hooks2.ulwExecute["command.execute.before"]?.(input, output);
173728
173792
  if (hooks2.stopContinuationGuard?.isStopped(sessionID)) {
173729
173793
  hooks2.stopContinuationGuard.clear(sessionID);
173730
173794
  log2("[stop-continuation] Stop state cleared by native command", {
@@ -173797,7 +173861,7 @@ function createChatMessageHandler3(args) {
173797
173861
  hooks: hooks2,
173798
173862
  runtimeFallbackEnabled
173799
173863
  });
173800
- await runStartWorkHookIfApplicable(hooks2, input, output);
173864
+ await runUlwExecuteHookIfApplicable(hooks2, input, output);
173801
173865
  notifyWhenModelCacheIsMissing(pluginContext.client.tui);
173802
173866
  handleGoalMessage({
173803
173867
  hooks: hooks2,
@@ -175708,7 +175772,7 @@ function createToolExecuteBeforeHandler3(args) {
175708
175772
  hooks2.goal.setGoal(sessionID, rawArgs);
175709
175773
  }
175710
175774
  }
175711
- const workStartingCommands = ["start-work"];
175775
+ const workStartingCommands = ["ulw-execute"];
175712
175776
  if (workStartingCommands.includes(command ?? "") && sessionID) {
175713
175777
  if (hooks2.stopContinuationGuard?.isStopped(sessionID)) {
175714
175778
  hooks2.stopContinuationGuard.clear(sessionID);