oh-my-opencode 5.0.0-beta.1 → 5.0.0-beta.10

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 (196) hide show
  1. package/.agents/command/publish.md +44 -16
  2. package/.agents/skills/publish/SKILL.md +44 -16
  3. package/.agents/skills/work-with-pr/SKILL.md +37 -23
  4. package/.opencode/command/publish.md +44 -16
  5. package/.opencode/skills/work-with-pr/SKILL.md +37 -23
  6. package/README.md +12 -1
  7. package/dist/agents/atlas/agent.d.ts +0 -1
  8. package/dist/agents/sisyphus/grok-4.d.ts +20 -0
  9. package/dist/agents/sisyphus/index.d.ts +2 -0
  10. package/dist/agents/sisyphus-agent-config.d.ts +6 -0
  11. package/dist/agents/sisyphus-agent-factory.d.ts +1 -1
  12. package/dist/agents/sisyphus-runtime-prompt-reconciler.d.ts +15 -4
  13. package/dist/agents/types.d.ts +2 -2
  14. package/dist/cli/index.js +797 -465
  15. package/dist/cli/run/on-complete-hook.d.ts +2 -0
  16. package/dist/cli-node/index.js +797 -465
  17. package/dist/hooks/atlas/final-wave-approval-gate.test-support.d.ts +50 -0
  18. package/dist/hooks/atlas/system-reminder-templates.d.ts +0 -1
  19. package/dist/index.js +1511 -1140
  20. package/dist/shared/normalize-sdk-response.d.ts +1 -0
  21. package/dist/shared/shell-env.d.ts +1 -1
  22. package/dist/skills/coding-agent-sessions/SKILL.md +3 -2
  23. package/dist/skills/coding-agent-sessions/references/all-platforms.md +1 -1
  24. package/dist/skills/coding-agent-sessions/references/senpi.md +4 -4
  25. package/dist/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
  26. package/dist/skills/frontend/SKILL.md +10 -7
  27. package/dist/skills/frontend/references/design/_INDEX.md +1 -0
  28. package/dist/skills/frontend/references/design/stylegallery.md +80 -0
  29. package/dist/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
  30. package/dist/skills/ultimate-browsing/engine/AGENTS.md +179 -0
  31. package/dist/skills/ultimate-browsing/engine/templates/package.json +1 -1
  32. package/dist/skills/ultimate-browsing/references/chrome-stealth.md +11 -11
  33. package/dist/skills/ulw-plan/SKILL.md +2 -2
  34. package/dist/skills/ulw-plan/references/full-workflow.md +27 -3
  35. package/dist/skills/ulw-plan/references/intent-clear.md +2 -1
  36. package/dist/skills/ulw-plan/references/intent-unclear.md +3 -3
  37. package/dist/tui.js +176 -14
  38. package/package.json +21 -19
  39. package/packages/lsp-core/src/lsp/client-diagnostics-concurrency.integration.test.ts +44 -0
  40. package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +0 -28
  41. package/packages/lsp-core/src/lsp/client-wrapper.test.ts +60 -7
  42. package/packages/lsp-core/src/lsp/client-wrapper.ts +69 -16
  43. package/packages/lsp-core/src/lsp/workspace-edit-adversarial.test.ts +20 -1
  44. package/packages/lsp-core/src/tools/diagnostics.ts +3 -3
  45. package/packages/lsp-core/src/tools/navigation.ts +4 -2
  46. package/packages/lsp-core/src/tools/rename.ts +4 -2
  47. package/packages/lsp-core/src/tools/symbols.ts +1 -1
  48. package/packages/lsp-daemon/dist/cli.js +83 -29
  49. package/packages/lsp-daemon/dist/client.js +76 -22
  50. package/packages/lsp-daemon/dist/index.js +81 -27
  51. package/packages/lsp-tools-mcp/dist/cli.js +76 -22
  52. package/packages/lsp-tools-mcp/dist/mcp.js +76 -22
  53. package/packages/lsp-tools-mcp/dist/tools.js +76 -22
  54. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  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 +118 -8
  58. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +118 -8
  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/lazycodex-executor-verify/test/codex-hook.test.ts +3 -17
  67. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
  68. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +83 -29
  69. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  70. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  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/test/bundled-rules-priority.test.ts +11 -16
  74. package/packages/omo-codex/plugin/components/rules/test/bundled-rules.test.ts +16 -23
  75. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-budget.test.ts +9 -7
  76. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-context.test.ts +0 -6
  77. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-dedup.test.ts +6 -4
  78. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-directive.test.ts +12 -9
  79. package/packages/omo-codex/plugin/components/rules/test/codex-hook.test.ts +28 -37
  80. package/packages/omo-codex/plugin/components/rules/test/formatter.test.ts +37 -69
  81. package/packages/omo-codex/plugin/components/rules/test/hook-output.test.ts +2 -3
  82. package/packages/omo-codex/plugin/components/rules/test/windows-git-bash-bundled-rule.test.ts +1 -15
  83. package/packages/omo-codex/plugin/components/start-work-continuation/AGENTS.md +3 -2
  84. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  85. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  86. package/packages/omo-codex/plugin/components/start-work-continuation/test/cli.test.ts +0 -3
  87. package/packages/omo-codex/plugin/components/start-work-continuation/test/codex-hook.test.ts +2 -16
  88. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  89. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  90. package/packages/omo-codex/plugin/components/teammode/test/thread-title-hook.test.ts +3 -9
  91. package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +24 -12
  92. package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +24 -12
  93. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  94. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  95. package/packages/omo-codex/plugin/components/ultrawork/directive.md +6 -0
  96. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  97. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  98. package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +6 -0
  99. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +2 -2
  100. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +27 -3
  101. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +2 -1
  102. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-unclear.md +3 -3
  103. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +0 -136
  104. package/packages/omo-codex/plugin/components/ultrawork/test/skill-pointer.test.ts +0 -2
  105. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +6 -0
  106. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  107. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  108. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +3 -2
  109. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/define-goal.md +108 -0
  110. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +1 -0
  111. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-continuation.test.ts +0 -1
  112. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-instruction.test.ts +2 -2
  113. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-hook.test.ts +0 -3
  114. package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +2 -35
  115. package/packages/omo-codex/plugin/components/ulw-loop/test/ultrawork-directive.test.ts +4 -5
  116. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  117. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  118. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  119. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  120. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  121. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  122. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  123. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  124. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  125. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  126. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  127. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  128. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  129. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  130. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  131. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  132. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
  133. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  134. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
  135. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  136. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  137. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  138. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  139. package/packages/omo-codex/plugin/package-lock.json +20 -20
  140. package/packages/omo-codex/plugin/package.json +1 -1
  141. package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +3 -2
  142. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +1 -1
  143. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/senpi.md +4 -4
  144. package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
  145. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +10 -7
  146. package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +1 -0
  147. package/packages/omo-codex/plugin/skills/frontend/references/design/stylegallery.md +80 -0
  148. package/packages/omo-codex/plugin/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
  149. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +179 -0
  150. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/package.json +1 -1
  151. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +11 -11
  152. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +6 -0
  153. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +3 -2
  154. package/packages/omo-codex/plugin/skills/ulw-loop/references/define-goal.md +108 -0
  155. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +1 -0
  156. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +2 -2
  157. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +27 -3
  158. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +2 -1
  159. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-unclear.md +3 -3
  160. package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +19 -173
  161. package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +4 -24
  162. package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +175 -13
  163. package/packages/omo-codex/plugin/test/aggregate.test.mjs +78 -2
  164. package/packages/omo-codex/plugin/test/auto-update-release-notes.test.mjs +19 -33
  165. package/packages/omo-codex/plugin/test/lcx-contribute-bug-fix-template.test.mjs +21 -27
  166. package/packages/omo-codex/plugin/test/scaffold-plan.test.mjs +0 -36
  167. package/packages/omo-codex/plugin/test/sync-skills-codex-compatibility.test.mjs +101 -0
  168. package/packages/omo-codex/plugin/test/sync-skills.test.mjs +1 -119
  169. package/packages/omo-codex/plugin/test/teammode-archive-ambiguity.test.mjs +0 -40
  170. package/packages/omo-codex/plugin/test/teammode-communication.test.mjs +6 -62
  171. package/packages/omo-codex/plugin/test/teammode-thread-links.test.mjs +3 -36
  172. package/packages/omo-codex/plugin/test/teammode-transport.test.mjs +0 -44
  173. package/packages/omo-codex/plugin/test/teammode-worktree.test.mjs +2 -6
  174. package/packages/omo-codex/plugin/test/ultrawork-skill-pointer.test.mjs +0 -3
  175. package/packages/omo-codex/plugin/test/ulw-plan-review-state-contract.test.mjs +0 -3
  176. package/packages/omo-codex/scripts/install-dist/install-local.mjs +57 -19
  177. package/packages/omo-codex/scripts/install-lazycodex-version-stamp.test.mjs +7 -2
  178. package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +3 -2
  179. package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +1 -1
  180. package/packages/shared-skills/skills/coding-agent-sessions/references/senpi.md +4 -4
  181. package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
  182. package/packages/shared-skills/skills/frontend/SKILL.md +10 -7
  183. package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +1 -0
  184. package/packages/shared-skills/skills/frontend/references/design/stylegallery.md +80 -0
  185. package/packages/shared-skills/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
  186. package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +179 -0
  187. package/packages/shared-skills/skills/ultimate-browsing/engine/templates/package.json +1 -1
  188. package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +11 -11
  189. package/packages/shared-skills/skills/ulw-plan/SKILL.md +2 -2
  190. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +27 -3
  191. package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +2 -1
  192. package/packages/shared-skills/skills/ulw-plan/references/intent-unclear.md +3 -3
  193. package/dist/tools/call-omo-agent/background-agent-executor.d.ts +0 -5
  194. package/packages/omo-codex/plugin/test/aggregate-skills.test.mjs +0 -92
  195. package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +0 -314
  196. package/packages/omo-codex/plugin/test/ulw-plan-scope-contract.test.mjs +0 -24
@@ -8,13 +8,18 @@ const FORMAT_OPTIONS = {
8
8
  maxResultChars: 10_000,
9
9
  };
10
10
 
11
+ // Runtime sentinel: the rules hook emits and re-greps this marker when
12
+ // deduplicating injected rules against the transcript (transcript-rule-filter.ts).
13
+ const INSTRUCTIONS_FROM = "Instructions from: ";
14
+
11
15
  describe("rules formatter hook context", () => {
12
16
  it("#given multiline dynamic rules #when formatting PostToolUse context #then labels and bodies render on separate lines", () => {
13
17
  // given
18
+ const body = "DYN_BODY_SENTINEL_LINE_1\n\nDYN_BODY_SENTINEL_LINE_2";
14
19
  const rule = loadedRule({
15
20
  path: "/repo/packages/CONTEXT.md",
16
21
  relativePath: "packages/CONTEXT.md",
17
- body: ["# packages", "", "## OVERVIEW", "23 sibling packages.", "", "## CONVENTIONS", "Use npm."].join("\n"),
22
+ body,
18
23
  });
19
24
 
20
25
  // when
@@ -25,124 +30,86 @@ describe("rules formatter hook context", () => {
25
30
  );
26
31
 
27
32
  // then
28
- expect(block).toBe(
29
- [
30
- "Additional project instructions matched for packages/omo-codex/plugin/components/ulw-loop/src/paths.ts:",
31
- "",
32
- "Instructions from: /repo/packages/CONTEXT.md",
33
- "",
34
- "# packages",
35
- "",
36
- "## OVERVIEW",
37
- "23 sibling packages.",
38
- "",
39
- "## CONVENTIONS",
40
- "Use npm.",
41
- ].join("\n"),
42
- );
33
+ expect(block).toContain(`${INSTRUCTIONS_FROM}/repo/packages/CONTEXT.md\n\n${body}`);
34
+ expect(occurrenceCount(block, INSTRUCTIONS_FROM)).toBe(1);
43
35
  });
44
36
 
45
37
  it("#given static rules #when formatting SessionStart context #then it injects rule bodies inline", () => {
46
38
  // given
39
+ const body = "STATIC_BODY_SENTINEL";
47
40
  const rule = loadedRule({
48
41
  path: "/repo/CONTEXT.md",
49
42
  relativePath: "CONTEXT.md",
50
- body: "Keep generated hook context readable.",
43
+ body,
51
44
  });
52
45
 
53
46
  // when
54
47
  const block = formatStaticBlock([rule], FORMAT_OPTIONS);
55
48
 
56
49
  // then
57
- expect(block).toBe(
58
- [
59
- "## Project Instructions",
60
- "",
61
- "Instructions from: /repo/CONTEXT.md",
62
- "",
63
- "Keep generated hook context readable.",
64
- ].join("\n"),
65
- );
50
+ expect(block).toContain(`${INSTRUCTIONS_FROM}/repo/CONTEXT.md\n\n${body}`);
66
51
  });
67
52
 
68
53
  it("#given CRLF and bare CR rule bodies #when formatting context #then it normalizes line endings", () => {
69
54
  // given
70
55
  const rule = loadedRule({
71
- body: "First line\r\n indented second line\rThird line",
56
+ body: "A1\r\n B2\rC3",
72
57
  });
73
58
 
74
59
  // when
75
60
  const block = formatDynamicBlock([rule], "src/app.ts", FORMAT_OPTIONS);
76
61
 
77
62
  // then
78
- expect(block).toContain("First line\n indented second line\nThird line");
63
+ expect(block).toContain("A1\n B2\nC3");
79
64
  expect(block).not.toContain("\r");
80
65
  });
81
66
 
82
67
  it("#given duplicate static rules with different line endings #when formatting context #then it injects one copy", () => {
83
68
  // given
69
+ const sharedBody = "SHARED_L1\r\nSHARED_L2";
70
+ const normalizedSharedBody = "SHARED_L1\nSHARED_L2";
84
71
  const lfRule = loadedRule({
85
72
  path: "/repo/CONTEXT.md",
86
73
  relativePath: "CONTEXT.md",
87
- body: "Shared rule\nKeep one copy.",
74
+ body: normalizedSharedBody,
88
75
  });
89
76
  const crlfRule = loadedRule({
90
77
  path: "/repo/packages/CONTEXT.md",
91
78
  relativePath: "packages/CONTEXT.md",
92
- body: "Shared rule\r\nKeep one copy.",
79
+ body: sharedBody,
93
80
  });
94
81
 
95
82
  // when
96
83
  const block = formatStaticBlock([lfRule, crlfRule], FORMAT_OPTIONS);
97
84
 
98
85
  // then
99
- expect(occurrenceCount(block, "Instructions from: /repo/CONTEXT.md")).toBe(1);
100
- expect(occurrenceCount(block, "Shared rule\nKeep one copy.")).toBe(1);
86
+ expect(occurrenceCount(block, `${INSTRUCTIONS_FROM}/repo/CONTEXT.md`)).toBe(1);
87
+ expect(occurrenceCount(block, normalizedSharedBody)).toBe(1);
101
88
  expect(block).not.toContain("/repo/packages/CONTEXT.md");
102
89
  });
103
90
 
104
91
  it("#given a Hephaestus static rule #when formatting SessionStart context #then it injects its body before other rule bodies", () => {
105
92
  // given
106
93
  const rules = [
107
- loadedRule({ path: "/repo/alpha.md", relativePath: "alpha.md", body: "Alpha guidance." }),
94
+ loadedRule({ path: "/repo/alpha.md", relativePath: "alpha.md", body: "ALPHA_BODY_SENTINEL" }),
108
95
  loadedRule({
109
96
  path: "/repo/bundled-rules/hephaestus.md",
110
97
  relativePath: "bundled-rules/hephaestus.md",
111
- body: "Hephaestus guidance.",
98
+ body: "HEPHAESTUS_BODY_SENTINEL",
112
99
  }),
113
- loadedRule({ path: "/repo/beta.md", relativePath: "beta.md", body: "Beta guidance." }),
100
+ loadedRule({ path: "/repo/beta.md", relativePath: "beta.md", body: "BETA_BODY_SENTINEL" }),
114
101
  ];
115
102
 
116
103
  // when
117
104
  const block = formatStaticBlock(rules, FORMAT_OPTIONS);
118
105
 
119
106
  // then
120
- expect(block).toContain("Instructions from: /repo/bundled-rules/hephaestus.md");
121
- expect(block).toContain("Hephaestus guidance.");
122
- expect(block).toContain("Alpha guidance.");
123
- expect(block).toContain("Beta guidance.");
124
- expect(block.indexOf("Hephaestus guidance.")).toBeLessThan(block.indexOf("Alpha guidance."));
125
- expect(block.indexOf("Alpha guidance.")).toBeLessThan(block.indexOf("Beta guidance."));
126
- expect(block).not.toContain("must read project rules:");
127
- expect(block).not.toContain("- [hephaestus.md]");
128
- });
129
-
130
- it("#given only a Hephaestus static rule #when formatting SessionStart context #then it emits no project rule link section", () => {
131
- // given
132
- const rule = loadedRule({
133
- path: "/repo/bundled-rules/hephaestus.md",
134
- relativePath: "bundled-rules/hephaestus.md",
135
- body: "Hephaestus guidance.",
136
- });
137
-
138
- // when
139
- const block = formatStaticBlock([rule], FORMAT_OPTIONS);
140
-
141
- // then
142
- expect(block).toContain("Instructions from: /repo/bundled-rules/hephaestus.md");
143
- expect(block).toContain("Hephaestus guidance.");
144
- expect(block).not.toContain("- [hephaestus.md]");
145
- expect(block).not.toContain("must read project rules:");
107
+ expect(block).toContain(`${INSTRUCTIONS_FROM}/repo/bundled-rules/hephaestus.md`);
108
+ expect(block).toContain("HEPHAESTUS_BODY_SENTINEL");
109
+ expect(block).toContain("ALPHA_BODY_SENTINEL");
110
+ expect(block).toContain("BETA_BODY_SENTINEL");
111
+ expect(block.indexOf("HEPHAESTUS_BODY_SENTINEL")).toBeLessThan(block.indexOf("ALPHA_BODY_SENTINEL"));
112
+ expect(block.indexOf("ALPHA_BODY_SENTINEL")).toBeLessThan(block.indexOf("BETA_BODY_SENTINEL"));
146
113
  });
147
114
 
148
115
  it("#given an oversized Hephaestus static rule #when formatting under a tight result budget #then its body is never truncated", () => {
@@ -162,7 +129,6 @@ describe("rules formatter hook context", () => {
162
129
 
163
130
  // then
164
131
  expect(block).toContain(tailMarker);
165
- expect(block).not.toContain("[Truncated. Full:");
166
132
  });
167
133
 
168
134
  it("#given multiple oversized rules #when formatting under a tight result budget #then every rule receives a fair truncated share with a read-full guide", () => {
@@ -180,13 +146,15 @@ describe("rules formatter hook context", () => {
180
146
  });
181
147
 
182
148
  // then
183
- expect(block).toContain("Instructions from: /repo/alpha.md");
184
- expect(block).toContain("Instructions from: /repo/beta.md");
185
- expect(block).toContain("Instructions from: /repo/gamma.md");
186
- expect(block).toContain("[Truncated. Full: alpha.md]");
187
- expect(block).toContain("[Truncated. Full: beta.md]");
188
- expect(block).toContain("[Truncated. Full: gamma.md]");
189
- expect(occurrenceCount(block, "[Truncated. Full:")).toBe(3);
149
+ expect(block).toContain(`${INSTRUCTIONS_FROM}/repo/alpha.md`);
150
+ expect(block).toContain(`${INSTRUCTIONS_FROM}/repo/beta.md`);
151
+ expect(block).toContain(`${INSTRUCTIONS_FROM}/repo/gamma.md`);
152
+ expect(block).toContain("alpha-");
153
+ expect(block).toContain("beta-");
154
+ expect(block).toContain("gamma-");
155
+ expect(block).not.toContain("A".repeat(400));
156
+ expect(block).not.toContain("B".repeat(400));
157
+ expect(block).not.toContain("C".repeat(400));
190
158
  });
191
159
 
192
160
  it("#given no matching rules #when formatting hook context #then it emits no context", () => {
@@ -5,14 +5,14 @@ import { formatAdditionalContextOutput } from "../src/hook-output.js";
5
5
  describe("formatAdditionalContextOutput", () => {
6
6
  it("#given context with outer whitespace and CRLF #when serializing hook JSON #then additional context is newline-normalized", () => {
7
7
  // given
8
- const context = "\r\n\r\nFirst line\r\nSecond line\rThird line\r\n";
8
+ const context = "\r\n\r\nA1\r\nB2\rC3\r\n";
9
9
 
10
10
  // when
11
11
  const output = formatAdditionalContextOutput("PostToolUse", context);
12
12
  const parsed: unknown = JSON.parse(output);
13
13
 
14
14
  // then
15
- expect(readAdditionalContext(parsed)).toBe("First line\nSecond line\nThird line");
15
+ expect(readAdditionalContext(parsed)).toBe("A1\nB2\nC3");
16
16
  expect(output.endsWith("\n")).toBe(true);
17
17
  });
18
18
 
@@ -40,7 +40,6 @@ describe("formatAdditionalContextOutput", () => {
40
40
  expect(additionalContext.length).toBeLessThanOrEqual(32_000);
41
41
  expect(additionalContext).toContain("first");
42
42
  expect(additionalContext).not.toContain("last");
43
- expect(additionalContext).toContain("[Truncated hook additional context to 32000 chars");
44
43
  });
45
44
  });
46
45
 
@@ -71,25 +71,11 @@ describe("Windows Git Bash bundled rule content", () => {
71
71
  expect(body).toContain("alwaysApply: true");
72
72
  });
73
73
 
74
- it('#given the bundled rule #when read #then it NEVER recommends bare shell:"bash"', () => {
75
- const body = readWindowsRuleBody();
76
-
77
- expect(body).not.toContain('shell: "bash"');
78
- });
79
-
80
- it("#given the bundled rule #when read #then it warns that bare bash often resolves to WSL System32", () => {
81
- const body = readWindowsRuleBody();
82
-
83
- expect(body).toMatch(/WSL/i);
84
- expect(body).toMatch(/System32/i);
85
- });
86
-
87
- it("#given the bundled rule #when read #then it prefers the git_bash MCP and the absolute Git Bash path", () => {
74
+ it("#given the bundled rule #when read #then it names the Git Bash runtime identifiers", () => {
88
75
  const body = readWindowsRuleBody();
89
76
 
90
77
  expect(body).toContain("git_bash");
91
78
  expect(body).toContain("OMO_CODEX_GIT_BASH_PATH");
92
- expect(body).toContain("C:\\Program Files\\Git\\bin\\bash.exe");
93
79
  });
94
80
  });
95
81
 
@@ -31,9 +31,10 @@ Conventions for human contributors and AI agents working on this repository.
31
31
 
32
32
  ## Layout
33
33
 
34
- - `src/boulder-reader.ts`: reads `.omo/boulder.json`, resolves the active work for the session, re-exports `getPlanChecklist`/`PlanChecklist` from `plan-checklist.ts`. `readContinuationState` returns null only when the plan has no readable top-level checklist (`total === 0`).
34
+ - `src/boulder-reader.ts`: reads `.omo/boulder.json`, resolves the active work for the session, re-exports `getPlanChecklist`/`PlanChecklist` from `plan-checklist.ts`. `readContinuationState` returns null in four cases: `boulder.json` is missing or unparseable, no work matches the session, the work status is not continuable (only `active` and `paused` continue - `completed`/`abandoned` stop), or `checklist.total === 0`.
35
35
  - `src/plan-checklist.ts`: `PlanChecklist` (`completed`/`remaining`/`total`/`nextTaskLabel`) and `getPlanChecklist`/`parsePlanChecklist`. Counts structured `## TODOs` rows (`N. <title>`) and `## Final Verification Wave` rows (`F<number>. <title>`); falls back to simple top-level `- [ ]`/`- [x]` checkboxes. Skips fenced blocks and respects `#`/`##` section boundaries.
36
- - `src/codex-hook.ts`: Stop/SubagentStop hook; fills `REMAINING_COUNT`/`TOTAL_COUNT`/`NEXT_TASK_LABEL` from the checklist into `directive.md`.
36
+ - `src/codex-hook.ts`: Stop/SubagentStop hook; fills nine placeholders into `directive.md` - `PLAN_NAME`, `PLAN_PATH`, `BOULDER_PATH`, `REMAINING_COUNT`, `TOTAL_COUNT`, `NEXT_TASK_LABEL`, `WORKTREE_BLOCK`, `LEDGER_PATH`, `SESSION_ID`. `WORKTREE_BLOCK` renders empty when the work has no worktree. When `remaining === 0`, `nextTaskLabel` is null and renders as "none (final gate pending)".
37
+ - **Context-pressure suppression:** the hook reads `input.transcript_path` through the injected `ReadonlyFileSystem` and returns `""` (no continuation) when the transcript carries any context-pressure marker (`context compacted`, `context_length_exceeded`, `context_too_large`, `codex ran out of room in the model's context window`, and related phrasings). This is the safety valve against an infinite continuation loop once the context window is exhausted; it is pinned by a `#given context-window pressure` test.
37
38
  - `directive.md`: directive template with placeholders, applied per invocation.
38
39
 
39
40
  ## Build and Hooks
@@ -7,7 +7,7 @@
7
7
  "type": "command",
8
8
  "command": "node \"${PLUGIN_ROOT}/components/start-work-continuation/dist/cli.js\" hook stop",
9
9
  "timeout": 10,
10
- "statusMessage": "(OmO 5.0.0-beta.1) Checking Start-Work Continuation"
10
+ "statusMessage": "(OmO 5.0.0-beta.10) Checking Start-Work Continuation"
11
11
  }
12
12
  ]
13
13
  }
@@ -19,7 +19,7 @@
19
19
  "type": "command",
20
20
  "command": "node \"${PLUGIN_ROOT}/components/start-work-continuation/dist/cli.js\" hook subagent-stop",
21
21
  "timeout": 10,
22
- "statusMessage": "(OmO 5.0.0-beta.1) Checking Start-Work Continuation"
22
+ "statusMessage": "(OmO 5.0.0-beta.10) Checking Start-Work Continuation"
23
23
  }
24
24
  ]
25
25
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-yeongyu/codex-start-work-continuation",
3
- "version": "5.0.0-beta.1",
3
+ "version": "5.0.0-beta.10",
4
4
  "description": "Codex Stop hook continuation injector for omo-codex start-work plans.",
5
5
  "type": "module",
6
6
  "packageManager": "npm@11.12.1",
@@ -26,9 +26,6 @@ describe("start-work continuation CLI", () => {
26
26
  expect(result.status).toBe(0);
27
27
  const output = parseStopHookOutput(result.stdout);
28
28
  expect(output.decision).toBe("block");
29
- expect(output.reason).toContain("Remaining top-level checkboxes: `2` of `4`");
30
- expect(output.reason).toContain("Next incomplete task: `1. Implement checklist parser parity`");
31
- expect(output.reason).toContain("Your session id in boulder.json: `codex:s1`");
32
29
  });
33
30
 
34
31
  it("#given valid SubagentStop stdin #when CLI runs #then stdout contains block JSON", () => {
@@ -58,16 +58,7 @@ describe("start-work Stop hook", () => {
58
58
  const output = runStopHook(createStopInput(workspace), fs);
59
59
 
60
60
  // then
61
- const parsed = parseBlockOutput(output);
62
- expect(parsed.decision).toBe("block");
63
- expect(parsed.reason).toContain("- Plan: `launch-plan`");
64
- expect(parsed.reason).toContain(`- Plan file: \`${join(workspace, ".omo", "plans", "plan.md")}\``);
65
- expect(parsed.reason).toContain(`- Boulder state: \`${join(workspace, ".omo", "boulder.json")}\``);
66
- expect(parsed.reason).toContain("- Remaining top-level checkboxes: `2` of `4`");
67
- expect(parsed.reason).toContain("- Next incomplete task: `1. Implement checklist parser parity`");
68
- expect(parsed.reason).toContain("- Worktree: `/tmp/worktree`");
69
- expect(parsed.reason).toContain(`- Ledger: \`${join(workspace, ".omo", "start-work", "ledger.jsonl")}\``);
70
- expect(parsed.reason).toContain("- Your session id in boulder.json: `codex:sess_abc`");
61
+ expect(parseBlockOutput(output).decision).toBe("block");
71
62
  });
72
63
 
73
64
  it("#given active codex work and an external-blocker marker #when hook runs #then returns empty output", () => {
@@ -187,12 +178,7 @@ describe("start-work Stop hook", () => {
187
178
  const output = runStopHook(createStopInput(workspace), fs);
188
179
 
189
180
  // then
190
- const parsed = parseBlockOutput(output);
191
- expect(parsed.decision).toBe("block");
192
- expect(parsed.reason).toContain("- Remaining top-level checkboxes: `0` of `1`");
193
- expect(parsed.reason).toContain("- Next incomplete task: `none (final gate pending)`");
194
- expect(parsed.reason).toContain("When the remaining count is `0`, skip checkbox execution");
195
- expect(parsed.reason).toContain("re-read the ledger record and verify the exact lane/SHA pair");
181
+ expect(parseBlockOutput(output).decision).toBe("block");
196
182
  });
197
183
 
198
184
  it("#given context-window pressure in transcript #when hook runs #then it does not inject continuation text", () => {
@@ -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.1) Checking Thread Title Hygiene"
11
+ "statusMessage": "(OmO 5.0.0-beta.10) 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.1",
3
+ "version": "5.0.0-beta.10",
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,
@@ -29,9 +29,7 @@ describe("thread title PostToolUse guidance", () => {
29
29
  expect(isHookOutput(parsed)).toBe(true);
30
30
  if (!isHookOutput(parsed)) return;
31
31
  expect(parsed.hookSpecificOutput.hookEventName).toBe("PostToolUse");
32
- expect(parsed.hookSpecificOutput.additionalContext).toBe(
33
- "THREAD ID thread-123: CALL codex_app.set_thread_title NOW. USE THE REAL TASK/ROLE.",
34
- );
32
+ expect(parsed.hookSpecificOutput.additionalContext).toContain("thread-123");
35
33
  });
36
34
 
37
35
  it("#given Codex reports create_thread output as a JSON string #when the hook runs #then it still extracts the thread id", () => {
@@ -59,9 +57,7 @@ describe("thread title PostToolUse guidance", () => {
59
57
  // then
60
58
  expect(isHookOutput(parsed)).toBe(true);
61
59
  if (!isHookOutput(parsed)) return;
62
- expect(parsed.hookSpecificOutput.additionalContext).toBe(
63
- "THREAD ID 019ef350-ee78-72a3-bd5e-e40cebc3d814: CALL codex_app.set_thread_title NOW. USE THE REAL TASK/ROLE.",
64
- );
60
+ expect(parsed.hookSpecificOutput.additionalContext).toContain("019ef350-ee78-72a3-bd5e-e40cebc3d814");
65
61
  });
66
62
 
67
63
  it("#given an unrelated tool completed #when the hook runs #then it stays silent", () => {
@@ -141,9 +137,7 @@ describe("thread title PostToolUse guidance", () => {
141
137
  // then
142
138
  expect(isHookOutput(parsed)).toBe(true);
143
139
  if (!isHookOutput(parsed)) return;
144
- expect(parsed.hookSpecificOutput.additionalContext).toBe(
145
- "PENDING WORKTREE ID remote-control:env:test-worktree: WORKTREE THREAD IS NOT READY YET. DO NOT bind-thread OR SEND THE MEMBER BOOTSTRAP UNTIL A REAL THREAD ID EXISTS. THEN CALL codex_app.set_thread_title USING THE REAL TASK/ROLE.",
146
- );
140
+ expect(parsed.hookSpecificOutput.additionalContext).toContain("remote-control:env:test-worktree");
147
141
  });
148
142
  });
149
143
 
@@ -174,6 +174,7 @@ function writePostHogActivityState(stateDir, nextState, diagnostics) {
174
174
  // ../../telemetry-core/src/constants.ts
175
175
  var DEFAULT_POSTHOG_HOST = "https://us.i.posthog.com";
176
176
  var DEFAULT_POSTHOG_API_KEY = "phc_CFJhj5HyvA62QPhvyaUCtaq23aUfznnijg5VaaGkNk74";
177
+ var UNCONFIGURED_POSTHOG_API_KEY = "phc_REPLACE_ME_OMO_NATIVE";
177
178
 
178
179
  // ../../telemetry-core/src/diagnostics.ts
179
180
  import { appendFileSync, existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync2 } from "node:fs";
@@ -310,6 +311,9 @@ function shouldDisableTelemetry(input) {
310
311
  const env = input.env ?? process.env;
311
312
  const globalPrefix = input.globalEnvPrefix ?? "OMO";
312
313
  const prefixes = Array.from(new Set([globalPrefix, input.productEnvPrefix]));
314
+ if (isDisableFlag(env["DO_NOT_TRACK"])) {
315
+ return true;
316
+ }
313
317
  for (const prefix of prefixes) {
314
318
  if (isDisableFlag(env[`${prefix}_DISABLE_POSTHOG`])) {
315
319
  return true;
@@ -323,18 +327,15 @@ function shouldDisableTelemetry(input) {
323
327
  function getTelemetryApiKey(env = process.env, defaultApiKey = DEFAULT_POSTHOG_API_KEY) {
324
328
  return env["POSTHOG_API_KEY"]?.trim() ?? defaultApiKey;
325
329
  }
326
- function getTelemetryHost(env = process.env, defaultHost = DEFAULT_POSTHOG_HOST) {
327
- return env["POSTHOG_HOST"]?.trim() || defaultHost;
330
+ function isConfiguredTelemetryApiKey(apiKey) {
331
+ const normalized = apiKey.trim();
332
+ return normalized.length > 0 && normalized !== UNCONFIGURED_POSTHOG_API_KEY;
328
333
  }
329
-
330
- // ../../telemetry-core/src/machine-id.ts
331
- import { createHash } from "node:crypto";
332
- import os2 from "node:os";
333
- function getDefaultTelemetryOsProvider() {
334
- return os2;
334
+ function hasTelemetryApiKey(env, defaultApiKey) {
335
+ return isConfiguredTelemetryApiKey(getTelemetryApiKey(env, defaultApiKey));
335
336
  }
336
- function getTelemetryDistinctId(machineIdPrefix, osProvider = getDefaultTelemetryOsProvider()) {
337
- return createHash("sha256").update(`${machineIdPrefix}${osProvider.hostname()}`).digest("hex");
337
+ function getTelemetryHost(env = process.env, defaultHost = DEFAULT_POSTHOG_HOST) {
338
+ return env["POSTHOG_HOST"]?.trim() || defaultHost;
338
339
  }
339
340
 
340
341
  // ../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
@@ -5504,6 +5505,16 @@ class PostHog extends PostHogBackendClient {
5504
5505
  }
5505
5506
  }
5506
5507
 
5508
+ // ../../telemetry-core/src/machine-id.ts
5509
+ import { createHash } from "node:crypto";
5510
+ import os2 from "node:os";
5511
+ function getDefaultTelemetryOsProvider() {
5512
+ return os2;
5513
+ }
5514
+ function getTelemetryDistinctId(machineIdPrefix, osProvider = getDefaultTelemetryOsProvider()) {
5515
+ return createHash("sha256").update(`${machineIdPrefix}${osProvider.hostname()}`).digest("hex");
5516
+ }
5517
+
5507
5518
  // ../../telemetry-core/src/posthog-client.ts
5508
5519
  var NO_OP_CLIENT = {
5509
5520
  enabled: false,
@@ -5538,7 +5549,7 @@ function createDefaultPostHogTransport(apiKey, options) {
5538
5549
  }
5539
5550
  function isTelemetryClientEnabled(input) {
5540
5551
  const env = input.env ?? process.env;
5541
- return !shouldDisableTelemetry({ env, productEnvPrefix: input.product.productEnvPrefix }) && getTelemetryApiKey(env, input.product.defaultApiKey).length > 0;
5552
+ return !shouldDisableTelemetry({ env, productEnvPrefix: input.product.productEnvPrefix }) && hasTelemetryApiKey(env, input.product.defaultApiKey);
5542
5553
  }
5543
5554
  function createTelemetryClient(input) {
5544
5555
  if (!isTelemetryClientEnabled(input)) {
@@ -5604,7 +5615,8 @@ function createTransport(input) {
5604
5615
  flushAt: 1,
5605
5616
  flushInterval: 0,
5606
5617
  host: getTelemetryHost(env, input.product.defaultHost),
5607
- disableGeoip: false
5618
+ disableGeoip: input.product.disableGeoip ?? false,
5619
+ ...input.product.transportOptions
5608
5620
  });
5609
5621
  } catch (error) {
5610
5622
  input.diagnostics?.({
@@ -170,6 +170,7 @@ function writePostHogActivityState(stateDir, nextState, diagnostics) {
170
170
  // ../../../../telemetry-core/src/constants.ts
171
171
  var DEFAULT_POSTHOG_HOST = "https://us.i.posthog.com";
172
172
  var DEFAULT_POSTHOG_API_KEY = "phc_CFJhj5HyvA62QPhvyaUCtaq23aUfznnijg5VaaGkNk74";
173
+ var UNCONFIGURED_POSTHOG_API_KEY = "phc_REPLACE_ME_OMO_NATIVE";
173
174
 
174
175
  // ../../../../telemetry-core/src/diagnostics.ts
175
176
  import { appendFileSync, existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync2 } from "node:fs";
@@ -306,6 +307,9 @@ function shouldDisableTelemetry(input) {
306
307
  const env = input.env ?? process.env;
307
308
  const globalPrefix = input.globalEnvPrefix ?? "OMO";
308
309
  const prefixes = Array.from(new Set([globalPrefix, input.productEnvPrefix]));
310
+ if (isDisableFlag(env["DO_NOT_TRACK"])) {
311
+ return true;
312
+ }
309
313
  for (const prefix of prefixes) {
310
314
  if (isDisableFlag(env[`${prefix}_DISABLE_POSTHOG`])) {
311
315
  return true;
@@ -319,18 +323,15 @@ function shouldDisableTelemetry(input) {
319
323
  function getTelemetryApiKey(env = process.env, defaultApiKey = DEFAULT_POSTHOG_API_KEY) {
320
324
  return env["POSTHOG_API_KEY"]?.trim() ?? defaultApiKey;
321
325
  }
322
- function getTelemetryHost(env = process.env, defaultHost = DEFAULT_POSTHOG_HOST) {
323
- return env["POSTHOG_HOST"]?.trim() || defaultHost;
326
+ function isConfiguredTelemetryApiKey(apiKey) {
327
+ const normalized = apiKey.trim();
328
+ return normalized.length > 0 && normalized !== UNCONFIGURED_POSTHOG_API_KEY;
324
329
  }
325
-
326
- // ../../../../telemetry-core/src/machine-id.ts
327
- import { createHash } from "node:crypto";
328
- import os2 from "node:os";
329
- function getDefaultTelemetryOsProvider() {
330
- return os2;
330
+ function hasTelemetryApiKey(env, defaultApiKey) {
331
+ return isConfiguredTelemetryApiKey(getTelemetryApiKey(env, defaultApiKey));
331
332
  }
332
- function getTelemetryDistinctId(machineIdPrefix, osProvider = getDefaultTelemetryOsProvider()) {
333
- return createHash("sha256").update(`${machineIdPrefix}${osProvider.hostname()}`).digest("hex");
333
+ function getTelemetryHost(env = process.env, defaultHost = DEFAULT_POSTHOG_HOST) {
334
+ return env["POSTHOG_HOST"]?.trim() || defaultHost;
334
335
  }
335
336
 
336
337
  // ../../../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
@@ -5500,6 +5501,16 @@ class PostHog extends PostHogBackendClient {
5500
5501
  }
5501
5502
  }
5502
5503
 
5504
+ // ../../../../telemetry-core/src/machine-id.ts
5505
+ import { createHash } from "node:crypto";
5506
+ import os2 from "node:os";
5507
+ function getDefaultTelemetryOsProvider() {
5508
+ return os2;
5509
+ }
5510
+ function getTelemetryDistinctId(machineIdPrefix, osProvider = getDefaultTelemetryOsProvider()) {
5511
+ return createHash("sha256").update(`${machineIdPrefix}${osProvider.hostname()}`).digest("hex");
5512
+ }
5513
+
5503
5514
  // ../../../../telemetry-core/src/posthog-client.ts
5504
5515
  var NO_OP_CLIENT = {
5505
5516
  enabled: false,
@@ -5534,7 +5545,7 @@ function createDefaultPostHogTransport(apiKey, options) {
5534
5545
  }
5535
5546
  function isTelemetryClientEnabled(input) {
5536
5547
  const env = input.env ?? process.env;
5537
- return !shouldDisableTelemetry({ env, productEnvPrefix: input.product.productEnvPrefix }) && getTelemetryApiKey(env, input.product.defaultApiKey).length > 0;
5548
+ return !shouldDisableTelemetry({ env, productEnvPrefix: input.product.productEnvPrefix }) && hasTelemetryApiKey(env, input.product.defaultApiKey);
5538
5549
  }
5539
5550
  function createTelemetryClient(input) {
5540
5551
  if (!isTelemetryClientEnabled(input)) {
@@ -5600,7 +5611,8 @@ function createTransport(input) {
5600
5611
  flushAt: 1,
5601
5612
  flushInterval: 0,
5602
5613
  host: getTelemetryHost(env, input.product.defaultHost),
5603
- disableGeoip: false
5614
+ disableGeoip: input.product.disableGeoip ?? false,
5615
+ ...input.product.transportOptions
5604
5616
  });
5605
5617
  } catch (error) {
5606
5618
  input.diagnostics?.({
@@ -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.1) Recording Session Telemetry"
10
+ "statusMessage": "(OmO 5.0.0-beta.10) 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.1",
3
+ "version": "5.0.0-beta.10",
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",
@@ -126,6 +126,12 @@ exactly `objective`; do not include `status`. Only when no goal tool
126
126
  exists on this surface, open your reply with a `# Goal` block treated
127
127
  as binding. Goals are unlimited; never invent a numeric budget or
128
128
  limit.
129
+ Check `get_goal` first: continue a matching active goal instead of
130
+ duplicating one; surface a conflicting one. Write the objective
131
+ outcome-first: the concrete thing that will be TRUE when done (an
132
+ outcome, never an activity), the named deliverable surfaces, and
133
+ explicit scope bounds — a vague objective produces vague criteria,
134
+ and vague criteria cannot be proven.
129
135
  The criteria MUST list, upfront:
130
136
  - The user-visible deliverable in one line, and the tier with its
131
137
  justification.
@@ -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.1) Checking Ultrawork Trigger"
10
+ "statusMessage": "(OmO 5.0.0-beta.10) 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.1",
3
+ "version": "5.0.0-beta.10",
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",
@@ -133,6 +133,12 @@ exactly `objective`; do not include `status`. Only when no goal tool
133
133
  exists on this surface, open your reply with a `# Goal` block treated
134
134
  as binding. Goals are unlimited; never invent a numeric budget or
135
135
  limit.
136
+ Check `get_goal` first: continue a matching active goal instead of
137
+ duplicating one; surface a conflicting one. Write the objective
138
+ outcome-first: the concrete thing that will be TRUE when done (an
139
+ outcome, never an activity), the named deliverable surfaces, and
140
+ explicit scope bounds — a vague objective produces vague criteria,
141
+ and vague criteria cannot be proven.
136
142
  The criteria MUST list, upfront:
137
143
  - The user-visible deliverable in one line, and the tier with its
138
144
  justification.
@@ -34,7 +34,7 @@ Example opening (adapt the wording, keep every commitment):
34
34
 
35
35
  ## INTENT ROUTING - pick ONE intent reference
36
36
 
37
- **Review modifiers are a gate trigger, not a style cue.** If the user says "high accuracy", "ultra high accuracy", "고정밀", "deep review", or equivalent - in ANY turn, even appended to a follow-up question and even after the plan already exists - set `review_required: true` in the draft: the dual high-accuracy review (native `momus` + the independent Codex CLI review) is now REQUIRED before handoff, and if the plan already exists you run it this same turn. Answering the current question more carefully does NOT satisfy it. This does NOT choose CLEAR/UNCLEAR and does NOT suppress interview.
37
+ **Review modifiers are a gate trigger, not a style cue.** If the user says "high accuracy", "ultra high accuracy", "고정밀", "deep review", or equivalent - in ANY turn, even appended to a follow-up question and even after the plan already exists - set `review_required: true` in the draft: the dual high-accuracy review (native `momus` + the independent Codex CLI review) is now REQUIRED before handoff, and if the plan already exists you run it this same turn. The review runs under the bounded convergence contract in `full-workflow.md`: a 5-round cap (unlimited only on explicit user request), evidence-backed blocker eligibility, and approval-with-notes counting as approval. Answering the current question more carefully does NOT satisfy it. This does NOT choose CLEAR/UNCLEAR and does NOT suppress interview.
38
38
 
39
39
  After grounding, make ONE judgment, record `intent: clear|unclear` plus `review_required`, **ANNOUNCE both to the user in one line**, then load ONE intent reference (you ALSO read `references/full-workflow.md` for the shared mechanics - see below). The test keys on whether the desired **OUTCOME** is clear, NOT on request length. This verdict line and the opening announcement above are the two mandatory user-visible signals of a planning session - it tells the user whether they will be interviewed and whether high-accuracy review is already requested; never skip either.
40
40
 
@@ -72,7 +72,7 @@ When producing the plan, encode every executable item as a column-zero Markdown
72
72
  - **Full scope is the default.** Plan the ENTIRE request; "MVP", "v1", "phase 1", or any reduced subset is never an option you invent or ask about - it exists only if the user introduces it. Scope OUT / Must-NOT-Have entries are guardrails against unrequested additions, never reductions of the request.
73
73
  - **Explore before asking.** Discoverable facts (repo/system/docs truth) -> research and cite, never ask. Preferences/tradeoffs -> the only things you bring to the user. When unsure which, treat it as a user-decision.
74
74
  - **CodeGraph first when present.** Use `codegraph_explore` for repo how/where/what/flow questions before wider reads; if codegraph_* tools are absent, inactive/uninitialized, or cold-start unavailable, continue with Read/Grep/Glob/LSP and the ast-grep skill.
75
- - **Two filters** on every candidate question, in order: (1) Could collected evidence answer it? -> explore instead. (2) Could the user's stated intent plus a defensible default answer it? -> adopt the default, record it, do not ask - UNLESS it is an owner-decision, which always survives as a question even when a default exists: anything irreversible / destructive / safety-critical, or a cross-cutting product choice the user lives with (public config surface, distribution / packaging, external dependency or pinned SHA, data / schema shape). Default the reversible internals; surface the owner-decisions.
75
+ - **Two filters** on every candidate question, in order: (1) Could collected evidence answer it? -> explore instead. (2) Could the user's stated intent plus a defensible default answer it? -> adopt the default, record it, do not ask - UNLESS it is an owner-decision, which always survives as a question even when a default exists: anything irreversible / destructive / safety-critical, or a cross-cutting product choice the user lives with (public config surface, distribution / packaging, external dependency or pinned SHA, data / schema shape, real budget / paid-service spend, expected scale or capacity target, target-audience / compliance limits). Extrinsic constraints (budget, mandated stack, scale, audience) leave no repo evidence, so exploration can never surface them - sweep those axes explicitly once per plan and classify each as explored, defaulted (ledger), or asked. Default the reversible internals; surface the owner-decisions.
76
76
  - **Explore to sufficiency, then STOP.** One research wave per open question; stop when the clearance check is answerable; never re-explore to double-check.
77
77
  - **Parallel-dispatch** independent research in ONE turn and keep working while it runs. Subagent outputs are CLAIMS until you independently verify them.
78
78
  - **Approval is not execution.** Approval authorizes writing the plan ONLY, never implementation. ONE request -> ONE plan, however large.