oh-my-opencode 5.0.0-beta.21 → 5.0.0-beta.23

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 (151) hide show
  1. package/dist/cli/index.js +290 -288
  2. package/dist/cli-node/index.js +290 -288
  3. package/dist/index.js +1675 -1657
  4. package/dist/skills/debugging/SKILL.md +2 -0
  5. package/dist/skills/debugging/references/methodology/00-setup.md +12 -0
  6. package/dist/skills/debugging/references/methodology/02-investigate.md +21 -0
  7. package/dist/skills/debugging/references/runtimes/go.md +15 -1
  8. package/dist/skills/debugging/references/runtimes/native-binary.md +38 -0
  9. package/dist/skills/debugging/references/runtimes/node.md +25 -0
  10. package/dist/skills/debugging/references/runtimes/python.md +13 -0
  11. package/dist/skills/debugging/references/runtimes/rust.md +41 -0
  12. package/dist/skills/debugging/references/scripts/dap.mjs +267 -0
  13. package/dist/skills/debugging/references/scripts/dap.test.ts +86 -0
  14. package/dist/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  15. package/dist/skills/debugging/references/tools/dap.md +103 -0
  16. package/dist/skills/debugging/references/tools/frida.md +193 -0
  17. package/dist/tools/delegate-task/types.d.ts +3 -0
  18. package/dist/tui.js +131 -147
  19. package/package.json +18 -15
  20. package/packages/lsp-core/src/index.ts +1 -0
  21. package/packages/lsp-core/src/lsp/client-wrapper.ts +25 -5
  22. package/packages/lsp-core/src/lsp/client.ts +26 -0
  23. package/packages/lsp-core/src/lsp/connection.ts +16 -0
  24. package/packages/lsp-core/src/lsp/constants.ts +1 -0
  25. package/packages/lsp-core/src/lsp/format-document.test.ts +143 -0
  26. package/packages/lsp-core/src/lsp/format-document.ts +90 -0
  27. package/packages/lsp-core/src/lsp/manager-max-clients.test.ts +151 -0
  28. package/packages/lsp-core/src/lsp/manager.ts +34 -1
  29. package/packages/lsp-core/src/lsp/server-definitions.ts +29 -0
  30. package/packages/lsp-core/src/lsp/server-installation.test.ts +376 -0
  31. package/packages/lsp-core/src/lsp/server-installation.ts +200 -27
  32. package/packages/lsp-core/src/lsp/server-resolution-local-binary.test.ts +170 -0
  33. package/packages/lsp-core/src/lsp/server-resolution.ts +18 -5
  34. package/packages/lsp-core/src/lsp/transport.ts +9 -0
  35. package/packages/lsp-core/src/lsp/types.ts +8 -0
  36. package/packages/lsp-core/src/tool-surface.test.ts +13 -1
  37. package/packages/lsp-core/src/tools/definitions.ts +14 -0
  38. package/packages/lsp-core/src/tools/format.test.ts +56 -0
  39. package/packages/lsp-core/src/tools/format.ts +56 -0
  40. package/packages/lsp-core/src/tools/index.ts +1 -0
  41. package/packages/lsp-core/src/tools/types.ts +10 -0
  42. package/packages/lsp-daemon/dist/cli.js +432 -144
  43. package/packages/lsp-daemon/dist/client.d.ts +10 -0
  44. package/packages/lsp-daemon/dist/client.js +401 -107
  45. package/packages/lsp-daemon/dist/daemon-client.d.ts +1 -0
  46. package/packages/lsp-daemon/dist/daemon-client.js +3 -0
  47. package/packages/lsp-daemon/dist/index.js +395 -107
  48. package/packages/lsp-daemon/package.json +1 -1
  49. package/packages/lsp-tools-mcp/dist/cli.js +384 -99
  50. package/packages/lsp-tools-mcp/dist/lsp/manager.js +53 -0
  51. package/packages/lsp-tools-mcp/dist/mcp.js +384 -99
  52. package/packages/lsp-tools-mcp/dist/tools.js +385 -99
  53. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  54. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +2 -2
  55. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  56. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  57. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +69 -35
  58. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +21 -2
  59. package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
  60. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  61. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  62. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  63. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  64. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  65. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  66. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
  67. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +404 -121
  68. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  69. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  70. package/packages/omo-codex/plugin/components/rules/dist/cli.js +3 -3
  71. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  72. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  73. package/packages/omo-codex/plugin/components/rules/src/post-compact-budget.ts +3 -3
  74. package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +4 -4
  75. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  76. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  77. package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +30 -15
  78. package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +30 -15
  79. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  80. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  81. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  82. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  83. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +2 -2
  84. package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
  85. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +5 -1
  86. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +2 -1
  87. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +11 -1
  88. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +22 -10
  89. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  90. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  91. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +5 -1
  92. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +13 -1
  93. package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +3 -5
  94. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-entrypoint.test.ts +26 -2
  95. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  96. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  97. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  98. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  99. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  100. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  101. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  102. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  103. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  104. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  105. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  106. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  107. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  108. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  109. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  110. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  111. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
  112. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  113. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-ulw-execute-continuation.json +1 -1
  114. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  115. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  116. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  117. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  118. package/packages/omo-codex/plugin/model-catalog.json +3 -3
  119. package/packages/omo-codex/plugin/package-lock.json +13 -13
  120. package/packages/omo-codex/plugin/package.json +1 -1
  121. package/packages/omo-codex/plugin/scripts/migrate-codex-config/catalog.mjs +3 -3
  122. package/packages/omo-codex/plugin/skills/debugging/SKILL.md +2 -0
  123. package/packages/omo-codex/plugin/skills/debugging/references/methodology/00-setup.md +12 -0
  124. package/packages/omo-codex/plugin/skills/debugging/references/methodology/02-investigate.md +21 -0
  125. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/go.md +15 -1
  126. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/native-binary.md +38 -0
  127. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/node.md +25 -0
  128. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/python.md +13 -0
  129. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/rust.md +41 -0
  130. package/packages/omo-codex/plugin/skills/debugging/references/scripts/dap.mjs +267 -0
  131. package/packages/omo-codex/plugin/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  132. package/packages/omo-codex/plugin/skills/debugging/references/tools/dap.md +103 -0
  133. package/packages/omo-codex/plugin/skills/debugging/references/tools/frida.md +193 -0
  134. package/packages/omo-codex/plugin/test/aggregate-model-catalog.test.mjs +1 -1
  135. package/packages/omo-codex/plugin/test/auto-update.test.mjs +2 -2
  136. package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +8 -8
  137. package/packages/omo-codex/scripts/install-config-reasoning.test.mjs +2 -2
  138. package/packages/omo-codex/scripts/install-dist/install-local.mjs +38 -23
  139. package/packages/shared-skills/skills/debugging/SKILL.md +2 -0
  140. package/packages/shared-skills/skills/debugging/references/methodology/00-setup.md +12 -0
  141. package/packages/shared-skills/skills/debugging/references/methodology/02-investigate.md +21 -0
  142. package/packages/shared-skills/skills/debugging/references/runtimes/go.md +15 -1
  143. package/packages/shared-skills/skills/debugging/references/runtimes/native-binary.md +38 -0
  144. package/packages/shared-skills/skills/debugging/references/runtimes/node.md +25 -0
  145. package/packages/shared-skills/skills/debugging/references/runtimes/python.md +13 -0
  146. package/packages/shared-skills/skills/debugging/references/runtimes/rust.md +41 -0
  147. package/packages/shared-skills/skills/debugging/references/scripts/dap.mjs +267 -0
  148. package/packages/shared-skills/skills/debugging/references/scripts/dap.test.ts +86 -0
  149. package/packages/shared-skills/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  150. package/packages/shared-skills/skills/debugging/references/tools/dap.md +103 -0
  151. package/packages/shared-skills/skills/debugging/references/tools/frida.md +193 -0
@@ -8,7 +8,7 @@
8
8
  "type": "command",
9
9
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-tool-use",
10
10
  "timeout": 60,
11
- "statusMessage": "(OmO 5.0.0-beta.21) Checking LSP Diagnostics"
11
+ "statusMessage": "(OmO 5.0.0-beta.23) Checking LSP Diagnostics"
12
12
  }
13
13
  ]
14
14
  }
@@ -21,7 +21,7 @@
21
21
  "type": "command",
22
22
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-compact",
23
23
  "timeout": 5,
24
- "statusMessage": "(OmO 5.0.0-beta.21) Resetting LSP Diagnostics Cache"
24
+ "statusMessage": "(OmO 5.0.0-beta.23) Resetting LSP Diagnostics Cache"
25
25
  }
26
26
  ]
27
27
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-yeongyu/codex-lsp",
3
- "version": "5.0.0-beta.21",
3
+ "version": "5.0.0-beta.23",
4
4
  "description": "Codex plugin that exposes Language Server Protocol tools and post-edit diagnostics.",
5
5
  "type": "module",
6
6
  "packageManager": "npm@11.12.1",
@@ -3882,15 +3882,15 @@ var POST_COMPACT_MIN_RESERVED_TOKENS = 8000;
3882
3882
  var POST_COMPACT_MIN_GUIDE_CHARS = 500;
3883
3883
  var FALLBACK_CONTEXT_WINDOW_TOKENS = 200000;
3884
3884
  var MODEL_CONTEXT_BUDGETS = [
3885
- { slug: "gpt-5.6-sol", contextWindowTokens: 372000, effectivePercent: DEFAULT_EFFECTIVE_CONTEXT_WINDOW_PERCENT },
3885
+ { slug: "gpt-5.6-sol", contextWindowTokens: 650000, effectivePercent: DEFAULT_EFFECTIVE_CONTEXT_WINDOW_PERCENT },
3886
3886
  {
3887
3887
  slug: "gpt-5.6-terra",
3888
- contextWindowTokens: 372000,
3888
+ contextWindowTokens: 650000,
3889
3889
  effectivePercent: DEFAULT_EFFECTIVE_CONTEXT_WINDOW_PERCENT
3890
3890
  },
3891
3891
  {
3892
3892
  slug: "gpt-5.6-luna",
3893
- contextWindowTokens: 372000,
3893
+ contextWindowTokens: 650000,
3894
3894
  effectivePercent: DEFAULT_EFFECTIVE_CONTEXT_WINDOW_PERCENT
3895
3895
  },
3896
3896
  { slug: "gpt-5.5", contextWindowTokens: 272000, effectivePercent: DEFAULT_EFFECTIVE_CONTEXT_WINDOW_PERCENT },
@@ -7,7 +7,7 @@
7
7
  "type": "command",
8
8
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook session-start",
9
9
  "timeout": 10,
10
- "statusMessage": "(OmO 5.0.0-beta.21) Loading Project Rules"
10
+ "statusMessage": "(OmO 5.0.0-beta.23) Loading Project Rules"
11
11
  }
12
12
  ]
13
13
  }
@@ -19,7 +19,7 @@
19
19
  "type": "command",
20
20
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook user-prompt-submit",
21
21
  "timeout": 10,
22
- "statusMessage": "(OmO 5.0.0-beta.21) Loading Project Rules"
22
+ "statusMessage": "(OmO 5.0.0-beta.23) Loading Project Rules"
23
23
  }
24
24
  ]
25
25
  }
@@ -32,7 +32,7 @@
32
32
  "type": "command",
33
33
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-tool-use",
34
34
  "timeout": 10,
35
- "statusMessage": "(OmO 5.0.0-beta.21) Matching Project Rules"
35
+ "statusMessage": "(OmO 5.0.0-beta.23) Matching Project Rules"
36
36
  }
37
37
  ]
38
38
  }
@@ -45,7 +45,7 @@
45
45
  "type": "command",
46
46
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-compact",
47
47
  "timeout": 10,
48
- "statusMessage": "(OmO 5.0.0-beta.21) Resetting Project Rule Cache"
48
+ "statusMessage": "(OmO 5.0.0-beta.23) Resetting Project Rule Cache"
49
49
  }
50
50
  ]
51
51
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-yeongyu/codex-rules",
3
- "version": "5.0.0-beta.21",
3
+ "version": "5.0.0-beta.23",
4
4
  "description": "Codex plugin that injects project rule files into model context through lifecycle hooks.",
5
5
  "type": "module",
6
6
  "packageManager": "npm@11.12.1",
@@ -21,15 +21,15 @@ const POST_COMPACT_MIN_RESERVED_TOKENS = 8_000;
21
21
  const POST_COMPACT_MIN_GUIDE_CHARS = 500;
22
22
  const FALLBACK_CONTEXT_WINDOW_TOKENS = 200_000;
23
23
  const MODEL_CONTEXT_BUDGETS: readonly ModelContextBudget[] = [
24
- { slug: "gpt-5.6-sol", contextWindowTokens: 372_000, effectivePercent: DEFAULT_EFFECTIVE_CONTEXT_WINDOW_PERCENT },
24
+ { slug: "gpt-5.6-sol", contextWindowTokens: 650_000, effectivePercent: DEFAULT_EFFECTIVE_CONTEXT_WINDOW_PERCENT },
25
25
  {
26
26
  slug: "gpt-5.6-terra",
27
- contextWindowTokens: 372_000,
27
+ contextWindowTokens: 650_000,
28
28
  effectivePercent: DEFAULT_EFFECTIVE_CONTEXT_WINDOW_PERCENT,
29
29
  },
30
30
  {
31
31
  slug: "gpt-5.6-luna",
32
- contextWindowTokens: 372_000,
32
+ contextWindowTokens: 650_000,
33
33
  effectivePercent: DEFAULT_EFFECTIVE_CONTEXT_WINDOW_PERCENT,
34
34
  },
35
35
  { slug: "gpt-5.5", contextWindowTokens: 272_000, effectivePercent: DEFAULT_EFFECTIVE_CONTEXT_WINDOW_PERCENT },
@@ -75,7 +75,7 @@ describe("post-compact context budget", () => {
75
75
  expect(budget.maxRuleChars).toBeLessThanOrEqual(budget.maxResultChars);
76
76
  });
77
77
 
78
- it("#given gpt-5.6-sol within its 372k window #when resolving post-compact budget #then keeps configured post-compact cap", () => {
78
+ it("#given gpt-5.6-sol within its 650k window #when resolving post-compact budget #then keeps configured post-compact cap", () => {
79
79
  // given
80
80
  const transcriptPath = writeCompactedTranscript("A".repeat(541_500));
81
81
 
@@ -87,7 +87,7 @@ describe("post-compact context budget", () => {
87
87
  expect(budget.maxResultChars).toBe(CONFIG.postCompactMaxResultChars);
88
88
  });
89
89
 
90
- it("#given gpt-5.6-terra within its 372k window #when resolving post-compact budget #then keeps configured post-compact cap", () => {
90
+ it("#given gpt-5.6-terra within its 650k window #when resolving post-compact budget #then keeps configured post-compact cap", () => {
91
91
  // given
92
92
  const transcriptPath = writeCompactedTranscript("A".repeat(541_500));
93
93
 
@@ -99,7 +99,7 @@ describe("post-compact context budget", () => {
99
99
  expect(budget.maxResultChars).toBe(CONFIG.postCompactMaxResultChars);
100
100
  });
101
101
 
102
- it("#given gpt-5.6-luna within its 372k window #when resolving post-compact budget #then keeps configured post-compact cap", () => {
102
+ it("#given gpt-5.6-luna within its 650k window #when resolving post-compact budget #then keeps configured post-compact cap", () => {
103
103
  // given
104
104
  const transcriptPath = writeCompactedTranscript("A".repeat(541_500));
105
105
 
@@ -111,7 +111,7 @@ describe("post-compact context budget", () => {
111
111
  expect(budget.maxResultChars).toBe(CONFIG.postCompactMaxResultChars);
112
112
  });
113
113
 
114
- it("#given provider-prefixed gpt-5.6 variant within its 372k window #when resolving post-compact budget #then keeps configured post-compact cap", () => {
114
+ it("#given provider-prefixed gpt-5.6 variant within its 650k window #when resolving post-compact budget #then keeps configured post-compact cap", () => {
115
115
  // given
116
116
  const transcriptPath = writeCompactedTranscript("A".repeat(541_500));
117
117
 
@@ -8,7 +8,7 @@
8
8
  "type": "command",
9
9
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-tool-use",
10
10
  "timeout": 10,
11
- "statusMessage": "(OmO 5.0.0-beta.21) Checking Thread Title Hygiene"
11
+ "statusMessage": "(OmO 5.0.0-beta.23) Checking Thread Title Hygiene"
12
12
  }
13
13
  ]
14
14
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sisyphuslabs/codex-teammode",
3
- "version": "5.0.0-beta.21",
3
+ "version": "5.0.0-beta.23",
4
4
  "description": "Codex team-mode hook component that keeps background thread titles descriptive after create_thread.",
5
5
  "type": "module",
6
6
  "private": true,
@@ -27,9 +27,12 @@ import {
27
27
  fsyncSync,
28
28
  openSync,
29
29
  renameSync,
30
+ rmSync,
30
31
  unlinkSync,
31
32
  writeFileSync
32
33
  } from "node:fs";
34
+ import { randomUUID } from "node:crypto";
35
+ import { dirname } from "node:path";
33
36
  var TOLERATED_FSYNC_CODES = new Set([
34
37
  "EPERM",
35
38
  "EACCES",
@@ -51,24 +54,36 @@ function tolerantFsyncSync(fileDescriptor, fsyncImpl) {
51
54
  }
52
55
  }
53
56
  function writeFileAtomically(filePath, content, options = {}) {
54
- const tempPath = `${filePath}.tmp`;
55
- writeFileSync(tempPath, content, "utf-8");
56
- const tempFileDescriptor = openSync(tempPath, "r+");
57
+ const platform = options.platform ?? process.platform;
58
+ const fsyncImpl = options.fsyncSync ?? fsyncSync;
59
+ const tempPath = `${filePath}.${process.pid}.${randomUUID()}.tmp`;
57
60
  try {
58
- tolerantFsyncSync(tempFileDescriptor, options.fsyncSync ?? fsyncSync);
59
- } finally {
60
- closeSync(tempFileDescriptor);
61
- }
62
- try {
63
- renameSync(tempPath, filePath);
64
- } catch (error) {
65
- const isPermissionError = error instanceof Error && (error.message.includes("EPERM") || error.message.includes("EACCES"));
66
- if ((options.platform ?? process.platform) === "win32" && isPermissionError) {
61
+ writeFileSync(tempPath, content, "utf-8");
62
+ const tempFileDescriptor = openSync(tempPath, "r+");
63
+ try {
64
+ tolerantFsyncSync(tempFileDescriptor, fsyncImpl);
65
+ } finally {
66
+ closeSync(tempFileDescriptor);
67
+ }
68
+ try {
69
+ renameSync(tempPath, filePath);
70
+ } catch (error) {
71
+ const isPermissionError = error instanceof Error && (error.message.includes("EPERM") || error.message.includes("EACCES"));
72
+ if (platform !== "win32" || !isPermissionError)
73
+ throw error;
67
74
  unlinkSync(filePath);
68
75
  renameSync(tempPath, filePath);
76
+ }
77
+ if (platform === "win32")
69
78
  return;
79
+ const directoryFileDescriptor = openSync(dirname(filePath), "r");
80
+ try {
81
+ tolerantFsyncSync(directoryFileDescriptor, fsyncImpl);
82
+ } finally {
83
+ closeSync(directoryFileDescriptor);
70
84
  }
71
- throw error;
85
+ } finally {
86
+ rmSync(tempPath, { force: true });
72
87
  }
73
88
  }
74
89
 
@@ -339,7 +354,7 @@ function getTelemetryHost(env = process.env, defaultHost = DEFAULT_POSTHOG_HOST)
339
354
  }
340
355
 
341
356
  // ../../../node_modules/.bun/posthog-node@5.51.1/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
342
- import { dirname, posix, sep } from "node:path";
357
+ import { dirname as dirname2, posix, sep } from "node:path";
343
358
  function createModulerModifier() {
344
359
  const getModuleFromFileName = createGetModuleFromFilename();
345
360
  return async (frames) => {
@@ -348,7 +363,7 @@ function createModulerModifier() {
348
363
  return frames;
349
364
  };
350
365
  }
351
- function createGetModuleFromFilename(basePath = process.argv[1] ? dirname(process.argv[1]) : process.cwd(), isWindows = sep === "\\") {
366
+ function createGetModuleFromFilename(basePath = process.argv[1] ? dirname2(process.argv[1]) : process.cwd(), isWindows = sep === "\\") {
352
367
  const normalizedBase = isWindows ? normalizeWindowsPath(basePath) : basePath;
353
368
  return (filename) => {
354
369
  if (!filename)
@@ -23,9 +23,12 @@ import {
23
23
  fsyncSync,
24
24
  openSync,
25
25
  renameSync,
26
+ rmSync,
26
27
  unlinkSync,
27
28
  writeFileSync
28
29
  } from "node:fs";
30
+ import { randomUUID } from "node:crypto";
31
+ import { dirname } from "node:path";
29
32
  var TOLERATED_FSYNC_CODES = new Set([
30
33
  "EPERM",
31
34
  "EACCES",
@@ -47,24 +50,36 @@ function tolerantFsyncSync(fileDescriptor, fsyncImpl) {
47
50
  }
48
51
  }
49
52
  function writeFileAtomically(filePath, content, options = {}) {
50
- const tempPath = `${filePath}.tmp`;
51
- writeFileSync(tempPath, content, "utf-8");
52
- const tempFileDescriptor = openSync(tempPath, "r+");
53
+ const platform = options.platform ?? process.platform;
54
+ const fsyncImpl = options.fsyncSync ?? fsyncSync;
55
+ const tempPath = `${filePath}.${process.pid}.${randomUUID()}.tmp`;
53
56
  try {
54
- tolerantFsyncSync(tempFileDescriptor, options.fsyncSync ?? fsyncSync);
55
- } finally {
56
- closeSync(tempFileDescriptor);
57
- }
58
- try {
59
- renameSync(tempPath, filePath);
60
- } catch (error) {
61
- const isPermissionError = error instanceof Error && (error.message.includes("EPERM") || error.message.includes("EACCES"));
62
- if ((options.platform ?? process.platform) === "win32" && isPermissionError) {
57
+ writeFileSync(tempPath, content, "utf-8");
58
+ const tempFileDescriptor = openSync(tempPath, "r+");
59
+ try {
60
+ tolerantFsyncSync(tempFileDescriptor, fsyncImpl);
61
+ } finally {
62
+ closeSync(tempFileDescriptor);
63
+ }
64
+ try {
65
+ renameSync(tempPath, filePath);
66
+ } catch (error) {
67
+ const isPermissionError = error instanceof Error && (error.message.includes("EPERM") || error.message.includes("EACCES"));
68
+ if (platform !== "win32" || !isPermissionError)
69
+ throw error;
63
70
  unlinkSync(filePath);
64
71
  renameSync(tempPath, filePath);
72
+ }
73
+ if (platform === "win32")
65
74
  return;
75
+ const directoryFileDescriptor = openSync(dirname(filePath), "r");
76
+ try {
77
+ tolerantFsyncSync(directoryFileDescriptor, fsyncImpl);
78
+ } finally {
79
+ closeSync(directoryFileDescriptor);
66
80
  }
67
- throw error;
81
+ } finally {
82
+ rmSync(tempPath, { force: true });
68
83
  }
69
84
  }
70
85
 
@@ -335,7 +350,7 @@ function getTelemetryHost(env = process.env, defaultHost = DEFAULT_POSTHOG_HOST)
335
350
  }
336
351
 
337
352
  // ../../../../../node_modules/.bun/posthog-node@5.51.1/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
338
- import { dirname, posix, sep } from "path";
353
+ import { dirname as dirname2, posix, sep } from "path";
339
354
  function createModulerModifier() {
340
355
  const getModuleFromFileName = createGetModuleFromFilename();
341
356
  return async (frames) => {
@@ -344,7 +359,7 @@ function createModulerModifier() {
344
359
  return frames;
345
360
  };
346
361
  }
347
- function createGetModuleFromFilename(basePath = process.argv[1] ? dirname(process.argv[1]) : process.cwd(), isWindows = sep === "\\") {
362
+ function createGetModuleFromFilename(basePath = process.argv[1] ? dirname2(process.argv[1]) : process.cwd(), isWindows = sep === "\\") {
348
363
  const normalizedBase = isWindows ? normalizeWindowsPath(basePath) : basePath;
349
364
  return (filename) => {
350
365
  if (!filename)
@@ -7,7 +7,7 @@
7
7
  "type": "command",
8
8
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook session-start",
9
9
  "timeout": 5,
10
- "statusMessage": "(OmO 5.0.0-beta.21) Recording Session Telemetry"
10
+ "statusMessage": "(OmO 5.0.0-beta.23) Recording Session Telemetry"
11
11
  }
12
12
  ]
13
13
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-yeongyu/codex-telemetry",
3
- "version": "5.0.0-beta.21",
3
+ "version": "5.0.0-beta.23",
4
4
  "description": "Codex plugin component that emits omo-codex anonymous daily-active telemetry on SessionStart.",
5
5
  "type": "module",
6
6
  "packageManager": "npm@11.12.1",
@@ -7,7 +7,7 @@
7
7
  "type": "command",
8
8
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook user-prompt-submit",
9
9
  "timeout": 5,
10
- "statusMessage": "(OmO 5.0.0-beta.21) Checking Ultrawork Trigger"
10
+ "statusMessage": "(OmO 5.0.0-beta.23) Checking Ultrawork Trigger"
11
11
  }
12
12
  ]
13
13
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-yeongyu/codex-ultrawork",
3
- "version": "5.0.0-beta.21",
3
+ "version": "5.0.0-beta.23",
4
4
  "description": "Codex plugin that injects the ultrawork orchestration directive and ships LazyCodex planning, review, QA, and gate agent roles.",
5
5
  "type": "module",
6
6
  "packageManager": "npm@11.12.1",
@@ -7,7 +7,7 @@
7
7
  "type": "command",
8
8
  "command": "node \"${PLUGIN_ROOT}/components/ulw-execute-continuation/dist/cli.js\" hook stop",
9
9
  "timeout": 10,
10
- "statusMessage": "(OmO 5.0.0-beta.21) Checking Ulw-Execute Continuation"
10
+ "statusMessage": "(OmO 5.0.0-beta.23) Checking Ulw-Execute Continuation"
11
11
  }
12
12
  ]
13
13
  }
@@ -19,7 +19,7 @@
19
19
  "type": "command",
20
20
  "command": "node \"${PLUGIN_ROOT}/components/ulw-execute-continuation/dist/cli.js\" hook subagent-stop",
21
21
  "timeout": 10,
22
- "statusMessage": "(OmO 5.0.0-beta.21) Checking Ulw-Execute Continuation"
22
+ "statusMessage": "(OmO 5.0.0-beta.23) Checking Ulw-Execute Continuation"
23
23
  }
24
24
  ]
25
25
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-yeongyu/codex-ulw-execute-continuation",
3
- "version": "5.0.0-beta.21",
3
+ "version": "5.0.0-beta.23",
4
4
  "description": "Codex Stop hook continuation injector for omo-codex ulw-execute plans.",
5
5
  "type": "module",
6
6
  "packageManager": "npm@11.12.1",
@@ -1,6 +1,6 @@
1
1
  import { checkpoint } from "./checkpoint-continuation.js";
2
2
  import { hasFlag, readValue } from "./cli-arg-parser.js";
3
- import { printJsonError, ULW_LOOP_HELP } from "./cli-output.js";
3
+ import { printJsonError, subcommandHelp, ULW_LOOP_HELP } from "./cli-output.js";
4
4
  import { addGoal, captureEvidence, completeGoals, createGoals, criteria, reviewBlockers, status, steer, } from "./cli-subcommands.js";
5
5
  import { resolveUlwLoopSessionIdFromEnv } from "./paths.js";
6
6
  import { UlwLoopError } from "./types.js";
@@ -37,6 +37,10 @@ export async function ulwLoopCommand(argv) {
37
37
  process.stdout.write(`${ULW_LOOP_HELP}\n`);
38
38
  return 1;
39
39
  }
40
+ if (command !== "help" && (hasFlag(rest, "--help") || hasFlag(rest, "-h"))) {
41
+ process.stdout.write(`${subcommandHelp(command)}\n`);
42
+ return 0;
43
+ }
40
44
  switch (command) {
41
45
  case "help":
42
46
  process.stdout.write(`${ULW_LOOP_HELP}\n`);
@@ -1,5 +1,6 @@
1
1
  import type { UlwLoopCodexGoalMode, UlwLoopPlan } from "./types.js";
2
- export declare const ULW_LOOP_HELP = "Usage:\n omo-agent-toolkit ulw-loop create-goals --brief \"...\" [--brief-file <path>] [--from-stdin] [--codex-goal-mode aggregate|per_story] [--validation-batch-json <json-or-path>] [--force] [--json]\n omo-agent-toolkit ulw-loop status [--json]\n omo-agent-toolkit ulw-loop complete-goals [--retry-failed] [--json]\n omo-agent-toolkit ulw-loop criteria --goal-id <id> [--json]\n omo-agent-toolkit ulw-loop record-evidence --goal-id <id> --criterion-id <id> --status pass|fail|blocked --evidence \"...\" [--notes \"...\"] [--json]\n omo-agent-toolkit ulw-loop checkpoint --goal-id <id> --status complete|failed|blocked --evidence \"...\" --codex-goal-json <...> [--quality-gate-json <...>] [--no-advance] [--json]\n omo-agent-toolkit ulw-loop steer --kind <kind> ... --evidence \"...\" --rationale \"...\" [--proposals-json <json-or-path>] [--json]\n omo-agent-toolkit ulw-loop add-goal --title \"...\" --objective \"...\" [--json]\n omo-agent-toolkit ulw-loop record-review-blockers --goal-id <id> --title \"...\" --objective \"...\" --evidence \"...\" --codex-goal-json <...> [--json]\n\nAll subcommands accept [--session-id <id>] to isolate state under .omo/ulw-loop/<id>/; without it, Codex session env is used when present.";
2
+ export declare const ULW_LOOP_HELP = "Usage:\n omo-agent-toolkit hook user-prompt-submit [--with-ultrawork] (Codex UserPromptSubmit hook)\n omo-agent-toolkit help | --help | -h (this message)\n omo-agent-toolkit ulw-loop help\n omo-agent-toolkit ulw-loop create-goals --brief \"...\" [--brief-file <path>] [--from-stdin] [--codex-goal-mode aggregate|per_story] [--validation-batch-json <json-or-path>] [--force] [--json]\n omo-agent-toolkit ulw-loop status [--json]\n omo-agent-toolkit ulw-loop complete-goals [--retry-failed] [--json]\n omo-agent-toolkit ulw-loop criteria --goal-id <id> [--json]\n omo-agent-toolkit ulw-loop record-evidence --goal-id <id> --criterion-id <id> --status pass|fail|blocked --evidence \"...\" [--notes \"...\"] [--json]\n omo-agent-toolkit ulw-loop checkpoint --goal-id <id> --status complete|failed|blocked --evidence \"...\" --codex-goal-json <...> [--quality-gate-json <...>] [--no-advance] [--json]\n omo-agent-toolkit ulw-loop steer --kind <kind> ... --evidence \"...\" --rationale \"...\" [--proposals-json <json-or-path>] [--json]\n omo-agent-toolkit ulw-loop add-goal --title \"...\" --objective \"...\" [--json]\n omo-agent-toolkit ulw-loop record-review-blockers --goal-id <id> --title \"...\" --objective \"...\" --evidence \"...\" --codex-goal-json <...> [--json]\n\nAll subcommands accept [--session-id <id>] to isolate state under .omo/ulw-loop/<id>/; without it, Codex session env is used when present.\nEvery subcommand accepts --help | -h to print its own usage line.";
3
+ export declare function subcommandHelp(subcommand: string): string;
3
4
  export declare function printJson(value: unknown): void;
4
5
  export declare function printJsonError(error: unknown): void;
5
6
  export declare function printStatus(plan: UlwLoopPlan): void;
@@ -1,5 +1,8 @@
1
1
  import { UlwLoopError } from "./types.js";
2
2
  export const ULW_LOOP_HELP = `Usage:
3
+ omo-agent-toolkit hook user-prompt-submit [--with-ultrawork] (Codex UserPromptSubmit hook)
4
+ omo-agent-toolkit help | --help | -h (this message)
5
+ omo-agent-toolkit ulw-loop help
3
6
  omo-agent-toolkit ulw-loop create-goals --brief "..." [--brief-file <path>] [--from-stdin] [--codex-goal-mode aggregate|per_story] [--validation-batch-json <json-or-path>] [--force] [--json]
4
7
  omo-agent-toolkit ulw-loop status [--json]
5
8
  omo-agent-toolkit ulw-loop complete-goals [--retry-failed] [--json]
@@ -10,7 +13,14 @@ export const ULW_LOOP_HELP = `Usage:
10
13
  omo-agent-toolkit ulw-loop add-goal --title "..." --objective "..." [--json]
11
14
  omo-agent-toolkit ulw-loop record-review-blockers --goal-id <id> --title "..." --objective "..." --evidence "..." --codex-goal-json <...> [--json]
12
15
 
13
- All subcommands accept [--session-id <id>] to isolate state under .omo/ulw-loop/<id>/; without it, Codex session env is used when present.`;
16
+ All subcommands accept [--session-id <id>] to isolate state under .omo/ulw-loop/<id>/; without it, Codex session env is used when present.
17
+ Every subcommand accepts --help | -h to print its own usage line.`;
18
+ export function subcommandHelp(subcommand) {
19
+ const lines = ULW_LOOP_HELP.split("\n").filter((line) => line.trimStart().startsWith(`omo-agent-toolkit ulw-loop ${subcommand}`));
20
+ if (lines.length === 0)
21
+ return ULW_LOOP_HELP;
22
+ return ["Usage:", ...lines].join("\n");
23
+ }
14
24
  export function printJson(value) {
15
25
  process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
16
26
  }
@@ -1252,6 +1252,9 @@ async function checkpointUlwLoop(repoRoot, args, scope) {
1252
1252
 
1253
1253
  // packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts
1254
1254
  var ULW_LOOP_HELP = `Usage:
1255
+ omo-agent-toolkit hook user-prompt-submit [--with-ultrawork] (Codex UserPromptSubmit hook)
1256
+ omo-agent-toolkit help | --help | -h (this message)
1257
+ omo-agent-toolkit ulw-loop help
1255
1258
  omo-agent-toolkit ulw-loop create-goals --brief "..." [--brief-file <path>] [--from-stdin] [--codex-goal-mode aggregate|per_story] [--validation-batch-json <json-or-path>] [--force] [--json]
1256
1259
  omo-agent-toolkit ulw-loop status [--json]
1257
1260
  omo-agent-toolkit ulw-loop complete-goals [--retry-failed] [--json]
@@ -1262,7 +1265,16 @@ var ULW_LOOP_HELP = `Usage:
1262
1265
  omo-agent-toolkit ulw-loop add-goal --title "..." --objective "..." [--json]
1263
1266
  omo-agent-toolkit ulw-loop record-review-blockers --goal-id <id> --title "..." --objective "..." --evidence "..." --codex-goal-json <...> [--json]
1264
1267
 
1265
- All subcommands accept [--session-id <id>] to isolate state under .omo/ulw-loop/<id>/; without it, Codex session env is used when present.`;
1268
+ All subcommands accept [--session-id <id>] to isolate state under .omo/ulw-loop/<id>/; without it, Codex session env is used when present.
1269
+ Every subcommand accepts --help | -h to print its own usage line.`;
1270
+ function subcommandHelp(subcommand) {
1271
+ const lines = ULW_LOOP_HELP.split(`
1272
+ `).filter((line) => line.trimStart().startsWith(`omo-agent-toolkit ulw-loop ${subcommand}`));
1273
+ if (lines.length === 0)
1274
+ return ULW_LOOP_HELP;
1275
+ return ["Usage:", ...lines].join(`
1276
+ `);
1277
+ }
1266
1278
  function printJson(value) {
1267
1279
  process.stdout.write(`${JSON.stringify(value, null, 2)}
1268
1280
  `);
@@ -2720,6 +2732,11 @@ async function ulwLoopCommand(argv) {
2720
2732
  `);
2721
2733
  return 1;
2722
2734
  }
2735
+ if (command !== "help" && (hasFlag(rest, "--help") || hasFlag(rest, "-h"))) {
2736
+ process.stdout.write(`${subcommandHelp(command)}
2737
+ `);
2738
+ return 0;
2739
+ }
2723
2740
  switch (command) {
2724
2741
  case "help":
2725
2742
  process.stdout.write(`${ULW_LOOP_HELP}
@@ -3398,18 +3415,12 @@ function parseStopPayload(value) {
3398
3415
  }
3399
3416
 
3400
3417
  // packages/omo-codex/plugin/components/ulw-loop/src/cli.ts
3401
- var TOP_LEVEL_HELP = `Usage:
3402
- omo-agent-toolkit ulw-loop <subcommand> [args]
3403
- omo-agent-toolkit hook user-prompt-submit [--with-ultrawork] (Codex UserPromptSubmit hook)
3404
- omo-agent-toolkit help | --help | -h (this message)
3405
-
3406
- Run \`omo-agent-toolkit ulw-loop help\` for ulw-loop subcommands.
3407
- `;
3408
3418
  async function main() {
3409
3419
  const argv = process.argv.slice(2);
3410
3420
  const command = argv[0];
3411
3421
  if (command === undefined || command === "help" || command === "--help" || command === "-h") {
3412
- process.stdout.write(TOP_LEVEL_HELP);
3422
+ process.stdout.write(`${ULW_LOOP_HELP}
3423
+ `);
3413
3424
  return 0;
3414
3425
  }
3415
3426
  if (command === "ulw-loop")
@@ -3441,7 +3452,8 @@ async function main() {
3441
3452
  if (isUlwLoopSubcommand(command))
3442
3453
  return ulwLoopCommand(argv);
3443
3454
  process.stderr.write(`[omo] unknown command: ${command}
3444
- ${TOP_LEVEL_HELP}`);
3455
+ ${ULW_LOOP_HELP}
3456
+ `);
3445
3457
  return 1;
3446
3458
  }
3447
3459
  main().then((code) => {
@@ -7,7 +7,7 @@
7
7
  "type": "command",
8
8
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook user-prompt-submit --with-ultrawork",
9
9
  "timeout": 10,
10
- "statusMessage": "(OmO 5.0.0-beta.21) Checking Ulw-Loop Steering"
10
+ "statusMessage": "(OmO 5.0.0-beta.23) Checking Ulw-Loop Steering"
11
11
  }
12
12
  ]
13
13
  }
@@ -20,7 +20,7 @@
20
20
  "type": "command",
21
21
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook pre-tool-use",
22
22
  "timeout": 5,
23
- "statusMessage": "(OmO 5.0.0-beta.21) Enforcing Unlimited Ulw-Loop Budget"
23
+ "statusMessage": "(OmO 5.0.0-beta.23) Enforcing Unlimited Ulw-Loop Budget"
24
24
  }
25
25
  ]
26
26
  },
@@ -31,7 +31,7 @@
31
31
  "type": "command",
32
32
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook pre-tool-use-spawn",
33
33
  "timeout": 5,
34
- "statusMessage": "(OmO 5.0.0-beta.21) Guarding Ulw-Loop Spawns"
34
+ "statusMessage": "(OmO 5.0.0-beta.23) Guarding Ulw-Loop Spawns"
35
35
  }
36
36
  ]
37
37
  }
@@ -43,7 +43,7 @@
43
43
  "type": "command",
44
44
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook stop",
45
45
  "timeout": 10,
46
- "statusMessage": "(OmO 5.0.0-beta.21) Checking Ulw-Loop Resume"
46
+ "statusMessage": "(OmO 5.0.0-beta.23) Checking Ulw-Loop Resume"
47
47
  }
48
48
  ]
49
49
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-yeongyu/codex-ulw-loop",
3
- "version": "5.0.0-beta.21",
3
+ "version": "5.0.0-beta.23",
4
4
  "description": "Codex plugin: durable repo-native multi-goal orchestration with embedded success criteria and observable evidence audit.",
5
5
  "type": "module",
6
6
  "packageManager": "npm@11.12.1",
@@ -1,6 +1,6 @@
1
1
  import { checkpoint } from "./checkpoint-continuation.js";
2
2
  import { hasFlag, readValue } from "./cli-arg-parser.js";
3
- import { printJsonError, ULW_LOOP_HELP } from "./cli-output.js";
3
+ import { printJsonError, subcommandHelp, ULW_LOOP_HELP } from "./cli-output.js";
4
4
  import {
5
5
  addGoal,
6
6
  captureEvidence,
@@ -53,6 +53,10 @@ export async function ulwLoopCommand(argv: readonly string[]): Promise<number> {
53
53
  process.stdout.write(`${ULW_LOOP_HELP}\n`);
54
54
  return 1;
55
55
  }
56
+ if (command !== "help" && (hasFlag(rest, "--help") || hasFlag(rest, "-h"))) {
57
+ process.stdout.write(`${subcommandHelp(command)}\n`);
58
+ return 0;
59
+ }
56
60
  switch (command) {
57
61
  case "help":
58
62
  process.stdout.write(`${ULW_LOOP_HELP}\n`);
@@ -2,6 +2,9 @@ import type { UlwLoopCodexGoalMode, UlwLoopItem, UlwLoopPlan } from "./types.js"
2
2
  import { UlwLoopError } from "./types.js";
3
3
 
4
4
  export const ULW_LOOP_HELP = `Usage:
5
+ omo-agent-toolkit hook user-prompt-submit [--with-ultrawork] (Codex UserPromptSubmit hook)
6
+ omo-agent-toolkit help | --help | -h (this message)
7
+ omo-agent-toolkit ulw-loop help
5
8
  omo-agent-toolkit ulw-loop create-goals --brief "..." [--brief-file <path>] [--from-stdin] [--codex-goal-mode aggregate|per_story] [--validation-batch-json <json-or-path>] [--force] [--json]
6
9
  omo-agent-toolkit ulw-loop status [--json]
7
10
  omo-agent-toolkit ulw-loop complete-goals [--retry-failed] [--json]
@@ -12,7 +15,16 @@ export const ULW_LOOP_HELP = `Usage:
12
15
  omo-agent-toolkit ulw-loop add-goal --title "..." --objective "..." [--json]
13
16
  omo-agent-toolkit ulw-loop record-review-blockers --goal-id <id> --title "..." --objective "..." --evidence "..." --codex-goal-json <...> [--json]
14
17
 
15
- All subcommands accept [--session-id <id>] to isolate state under .omo/ulw-loop/<id>/; without it, Codex session env is used when present.`;
18
+ All subcommands accept [--session-id <id>] to isolate state under .omo/ulw-loop/<id>/; without it, Codex session env is used when present.
19
+ Every subcommand accepts --help | -h to print its own usage line.`;
20
+
21
+ export function subcommandHelp(subcommand: string): string {
22
+ const lines = ULW_LOOP_HELP.split("\n").filter((line) =>
23
+ line.trimStart().startsWith(`omo-agent-toolkit ulw-loop ${subcommand}`),
24
+ );
25
+ if (lines.length === 0) return ULW_LOOP_HELP;
26
+ return ["Usage:", ...lines].join("\n");
27
+ }
16
28
 
17
29
  type CriteriaCounts = { readonly pass: number; readonly total: number };
18
30