oh-my-opencode 5.0.0-beta.47 → 5.0.0-beta.49

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 (129) hide show
  1. package/README.ja.md +35 -27
  2. package/README.ko.md +35 -27
  3. package/README.md +19 -34
  4. package/README.ru.md +33 -28
  5. package/README.zh-cn.md +31 -27
  6. package/dist/cli/index.js +19 -15
  7. package/dist/cli-node/index.js +19 -15
  8. package/dist/features/team-mode/tools/messaging-fallback-wake.d.ts +2 -0
  9. package/dist/features/team-mode/tools/messaging-live-delivery-recipient.d.ts +2 -0
  10. package/dist/features/team-mode/tools/messaging-runtime.d.ts +6 -0
  11. package/dist/index.js +30 -18
  12. package/dist/tui.js +4 -0
  13. package/package.json +14 -14
  14. package/packages/lsp-daemon/dist/cli.js +6 -3
  15. package/packages/lsp-daemon/dist/client.js +6 -3
  16. package/packages/lsp-daemon/dist/ensure-daemon.d.ts +6 -1
  17. package/packages/lsp-daemon/dist/ensure-daemon.js +9 -2
  18. package/packages/lsp-daemon/dist/index.js +6 -3
  19. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +2 -2
  20. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  21. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  22. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  23. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  24. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  25. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  26. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  27. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  28. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
  29. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +6 -3
  30. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  31. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  32. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  33. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  34. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  35. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  36. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  37. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  38. package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +11 -10
  39. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  40. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  41. package/packages/omo-codex/plugin/components/ultrawork/src/directive-content.ts +1 -1
  42. package/packages/omo-codex/plugin/components/ulw-execute-continuation/AGENTS.md +3 -3
  43. package/packages/omo-codex/plugin/components/ulw-execute-continuation/README.md +3 -3
  44. package/packages/omo-codex/plugin/components/ulw-execute-continuation/directive.md +4 -4
  45. package/packages/omo-codex/plugin/components/ulw-execute-continuation/dist/cli.js +1 -1
  46. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +1 -13
  47. package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
  48. package/packages/omo-codex/plugin/components/ulw-execute-continuation/src/codex-hook.ts +1 -1
  49. package/packages/omo-codex/plugin/components/ulw-execute-continuation/src/types.ts +1 -1
  50. package/packages/omo-codex/plugin/components/ulw-execute-continuation/test/cli.test.ts +3 -7
  51. package/packages/omo-codex/plugin/components/ulw-execute-continuation/test/codex-hook.test.ts +16 -0
  52. package/packages/omo-codex/plugin/components/ulw-loop/README.md +2 -2
  53. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +11 -10
  54. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-template.js +8 -15
  55. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +2 -2
  56. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +1 -1
  57. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +1 -1
  58. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +88 -67
  59. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +3 -4
  60. package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +1 -1
  61. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-fields.js +1 -1
  62. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.js +13 -16
  63. package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.d.ts +2 -0
  64. package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.js +47 -26
  65. package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.js +2 -2
  66. package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.d.ts +1 -0
  67. package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.js +14 -4
  68. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +17 -4
  69. package/packages/omo-codex/plugin/components/ulw-loop/package.json +2 -2
  70. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +1 -1
  71. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-template.ts +8 -14
  72. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +2 -2
  73. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +1 -1
  74. package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +5 -1
  75. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +3 -4
  76. package/packages/omo-codex/plugin/components/ulw-loop/src/domain-types.ts +1 -1
  77. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-fields.ts +4 -1
  78. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate.ts +21 -16
  79. package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-guard.ts +52 -25
  80. package/packages/omo-codex/plugin/components/ulw-loop/src/status-next-actions.ts +2 -2
  81. package/packages/omo-codex/plugin/components/ulw-loop/src/surface.ts +16 -4
  82. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-final.test.ts +11 -12
  83. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-fields-messages.test.ts +98 -0
  84. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-lazycodex-surface.test.ts +93 -0
  85. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-roles.test.ts +9 -4
  86. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate.test.ts +10 -0
  87. package/packages/omo-codex/plugin/components/ulw-loop/test/spawn-guard.test.ts +70 -7
  88. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  89. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  90. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  91. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  92. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  93. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  94. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  95. package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +18 -0
  96. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  97. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  98. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  99. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  100. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  101. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  102. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  103. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
  104. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  105. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  106. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  107. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  108. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  109. package/packages/omo-codex/plugin/package-lock.json +12 -12
  110. package/packages/omo-codex/plugin/package.json +1 -1
  111. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +61 -33
  112. package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +4 -2
  113. package/packages/omo-codex/plugin/skills/refactor/SKILL.md +4 -2
  114. package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +4 -2
  115. package/packages/omo-codex/plugin/skills/review-work/SKILL.md +13 -3
  116. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +11 -10
  117. package/packages/omo-codex/plugin/skills/ulw-execute/SKILL.md +11 -6
  118. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +24 -0
  119. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +1 -1
  120. package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +4 -2
  121. package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +4 -2
  122. package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +8 -4
  123. package/packages/omo-codex/plugin/test/component-hook-contract-cases.mjs +62 -0
  124. package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +3 -3
  125. package/packages/omo-codex/plugin/test/sync-skills-codex-compatibility.test.mjs +23 -1
  126. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +36 -16
  127. package/packages/omo-codex/scripts/install-dist/install-local.mjs +2 -2
  128. package/packages/prompts-core/prompts/ultrawork/codex.md +11 -10
  129. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-ulw-execute-continuation.json +0 -17
@@ -0,0 +1,93 @@
1
+ import { expect, it } from "vitest";
2
+ import { validateQualityGate } from "../src/quality-gate.js";
3
+
4
+ const base = {
5
+ manualQa: {
6
+ by: "main-session",
7
+ status: "passed",
8
+ evidence: "qa",
9
+ surfaceEvidence: [
10
+ { id: "s", criterionRef: "C1", surface: "cli", invocation: "true", verdict: "passed", artifactRefs: ["a"] },
11
+ ],
12
+ adversarialCases: [
13
+ {
14
+ id: "x",
15
+ criterionRef: "C1",
16
+ scenario: "x",
17
+ expectedBehavior: "x",
18
+ verdict: "not_applicable",
19
+ reason: "x",
20
+ artifactRefs: ["a"],
21
+ },
22
+ ],
23
+ artifactRefs: [{ id: "a", kind: "cli-transcript", description: "a", path: "qa.txt" }],
24
+ },
25
+ gateReview: {
26
+ by: "category:unspecified-high",
27
+ recommendation: "APPROVE",
28
+ reportPath: "gate.md",
29
+ evidence: "gate",
30
+ blockers: [],
31
+ },
32
+ iteration: { fullRerun: true, status: "passed", rerunCommands: ["true"], evidence: "rerun" },
33
+ criteriaCoverage: {
34
+ totalCriteria: 1,
35
+ passCount: 1,
36
+ originalIntent: "i",
37
+ desiredOutcome: "d",
38
+ userOutcomeReview: "u",
39
+ adversarialClassesCovered: ["x"],
40
+ },
41
+ };
42
+ it("accepts lazycodex self-review gate without codeReview", () =>
43
+ expect(() => validateQualityGate(base)).not.toThrow());
44
+ it("accepts wrapped and optional codeReview forms", () => {
45
+ expect(() => validateQualityGate({ qualityGate: base })).not.toThrow();
46
+ expect(() =>
47
+ validateQualityGate({
48
+ ...base,
49
+ codeReview: {
50
+ by: "lazycodex-code-reviewer",
51
+ recommendation: "APPROVE",
52
+ codeQualityStatus: "CLEAR",
53
+ reportPath: "code.md",
54
+ evidence: "review",
55
+ blockers: [],
56
+ },
57
+ }),
58
+ ).not.toThrow();
59
+ });
60
+ it("#given main-session codeReview #when validated #then preserves the accepted author", () => {
61
+ const gate = validateQualityGate({
62
+ ...base,
63
+ codeReview: {
64
+ by: "main-session",
65
+ recommendation: "APPROVE",
66
+ codeQualityStatus: "CLEAR",
67
+ reportPath: "code.md",
68
+ evidence: "review",
69
+ blockers: [],
70
+ },
71
+ });
72
+ expect(gate.surface).toBe("lazycodex");
73
+ if (gate.surface === "lazycodex") expect(gate.codeReview?.by).toBe("main-session");
74
+ });
75
+ it("#given random codeReview author #when validated #then rejects the lane", () => {
76
+ expect(() =>
77
+ validateQualityGate({
78
+ ...base,
79
+ codeReview: {
80
+ by: "random",
81
+ recommendation: "APPROVE",
82
+ codeQualityStatus: "CLEAR",
83
+ reportPath: "code.md",
84
+ evidence: "review",
85
+ blockers: [],
86
+ },
87
+ }),
88
+ ).toThrow(/codeReview\.by/);
89
+ });
90
+ it("rejects an unknown gate acceptor", () =>
91
+ expect(() => validateQualityGate({ ...base, gateReview: { ...base.gateReview, by: "random-agent" } })).toThrow(
92
+ /gateReview\.by/,
93
+ ));
@@ -132,10 +132,15 @@ describe("validateQualityGate reviewer roles", () => {
132
132
  expect(error.message).toContain("no codeReview lane");
133
133
  });
134
134
 
135
- it("#given a four-section senpi gate #when validated on the default lazycodex surface #then codeReview is required", () => {
136
- const error = qualityGateError(senpiGate());
137
- expect(error.code).toBe("ULW_LOOP_QUALITY_GATE_INVALID");
138
- expect(error.message).toContain("codeReview");
135
+ it("#given a four-section gate #when validated on the default lazycodex surface #then codeReview is optional", () => {
136
+ expect(() =>
137
+ validateQualityGate(
138
+ senpiGate({
139
+ manualQa: { ...BASE_GATE.manualQa, by: "main-session" },
140
+ gateReview: { ...BASE_GATE.gateReview, by: "category:deep" },
141
+ }),
142
+ ),
143
+ ).not.toThrow();
139
144
  });
140
145
 
141
146
  it("#given swapped omo-senpi reviewer roles #when validated on the omo-senpi surface #then section-specific roles are enforced", () => {
@@ -136,6 +136,16 @@ describe("validateQualityGate", () => {
136
136
  expect(gate.manualQa.artifactRefs).toHaveLength(5);
137
137
  });
138
138
 
139
+ it("#given missing manualQa section #when validated #then it explains accepted input forms", () => {
140
+ const input = makeGate();
141
+ delete input["manualQa"];
142
+
143
+ const error = getQualityGateError(input);
144
+
145
+ expect(error.message).toContain("accepted input");
146
+ expect(error.message).toContain('top-level "qualityGate" key');
147
+ });
148
+
139
149
  it("#given missing manualQa surface evidence #when validated #then it fails closed", () => {
140
150
  // given
141
151
  const input = makeGate({
@@ -2,18 +2,22 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
2
  import { mkdtemp, rm } from "node:fs/promises";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
+ import { Readable, Writable } from "node:stream";
5
6
  import { afterEach, beforeEach, describe, expect, it } from "vitest";
6
7
 
7
8
  import type { PreToolUsePayload } from "../src/codex-hook.ts";
8
- import { applySpawnGuards } from "../src/spawn-guard.ts";
9
+ import { applySpawnGuards, DEFAULT_FANOUT_LIMIT, runSpawnAdmissionRecorderCli } from "../src/spawn-guard.ts";
9
10
 
10
11
  let workDir: string;
11
12
  let originalLimit: string | undefined;
12
13
  let originalReviewLimit: string | undefined;
13
14
  let originalToolkitSurface: string | undefined;
15
+ let originalPluginData: string | undefined;
14
16
 
15
17
  beforeEach(async () => {
16
18
  workDir = await mkdtemp(join(tmpdir(), "ulw-spawn-guard-"));
19
+ originalPluginData = process.env["PLUGIN_DATA"];
20
+ process.env["PLUGIN_DATA"] = join(workDir, "plugin-data");
17
21
  originalLimit = process.env["OMO_SPAWN_FANOUT_LIMIT"];
18
22
  originalReviewLimit = process.env["OMO_ULW_LOOP_REVIEW_SPAWN_LIMIT"];
19
23
  originalToolkitSurface = process.env["OMO_AGENT_TOOLKIT_SURFACE"];
@@ -30,6 +34,8 @@ afterEach(async () => {
30
34
  else process.env["OMO_ULW_LOOP_REVIEW_SPAWN_LIMIT"] = originalReviewLimit;
31
35
  if (originalToolkitSurface === undefined) delete process.env["OMO_AGENT_TOOLKIT_SURFACE"];
32
36
  else process.env["OMO_AGENT_TOOLKIT_SURFACE"] = originalToolkitSurface;
37
+ if (originalPluginData === undefined) delete process.env["PLUGIN_DATA"];
38
+ else process.env["PLUGIN_DATA"] = originalPluginData;
33
39
  await rm(workDir, { recursive: true, force: true });
34
40
  });
35
41
 
@@ -98,7 +104,66 @@ function deny(output: string): { permissionDecision: string; permissionDecisionR
98
104
  return JSON.parse(output).hookSpecificOutput;
99
105
  }
100
106
 
107
+ describe("spawn admission breaker", () => {
108
+ async function record(response: unknown): Promise<string> {
109
+ let output = "";
110
+ const stdout = new Writable({
111
+ write(chunk, _encoding, callback) {
112
+ output += chunk.toString();
113
+ callback();
114
+ },
115
+ });
116
+ await runSpawnAdmissionRecorderCli(
117
+ Readable.from([
118
+ JSON.stringify({
119
+ ...payload("spawn_agent", { message: "scan" }),
120
+ hook_event_name: "PostToolUse",
121
+ tool_response: response,
122
+ }),
123
+ ]),
124
+ stdout,
125
+ );
126
+ return output;
127
+ }
128
+
129
+ it.each(["too many active cells", "AgentLimitReached", "max_threads", "max_concurrent_threads_per_session"])(
130
+ "records %s silently and denies without a plan while isolating other sessions",
131
+ async (reason) => {
132
+ expect(await record(reason)).toBe("");
133
+ const marker = JSON.parse(readFileSync(join(workDir, "plugin-data", "spawn-breaker", "s1.json"), "utf8"));
134
+ expect(Object.keys(marker).sort()).toEqual(["at", "reason"]);
135
+ expect(marker.reason).toBe(reason);
136
+ expect(Number.isFinite(Date.parse(marker.at))).toBe(true);
137
+ expect(deny(applySpawnGuards(payload("spawn_agent", {}))).permissionDecision).toBe("deny");
138
+ expect(applySpawnGuards({ ...payload("spawn_agent", {}), session_id: "clean" })).toBe("");
139
+ },
140
+ );
141
+
142
+ it("does not record a successful admission", async () => {
143
+ expect(await record({ agent_id: "worker-1" })).toBe("");
144
+ expect(existsSync(join(workDir, "plugin-data", "spawn-breaker", "s1.json"))).toBe(false);
145
+ });
146
+
147
+ it("denies before artifact, quota, and state lock guards", async () => {
148
+ writeGoals();
149
+ writeFileSync(
150
+ join(sessionDir(), ".state.lock"),
151
+ JSON.stringify({ pid: process.pid, createdAt: new Date().toISOString(), token: "live" }),
152
+ );
153
+ await record("AgentLimitReached");
154
+ const output = deny(
155
+ applySpawnGuards(payload("spawn_agent", { agent_type: "lazycodex-gate-reviewer" }), { lockTimeoutMs: 0 }),
156
+ );
157
+ expect(output.permissionDecisionReason).toContain("AgentLimitReached");
158
+ expect(existsSync(join(sessionDir(), "spawn-count.json"))).toBe(false);
159
+ expect(existsSync(join(sessionDir(), "review-spawn-counts.json"))).toBe(false);
160
+ });
161
+ });
162
+
101
163
  describe("applySpawnGuards fan-out cap", () => {
164
+ it("defaults to 24 spawns", () => {
165
+ expect(DEFAULT_FANOUT_LIMIT).toBe(24);
166
+ });
102
167
  it("#given spawns under the limit #when guarded #then allows and counts", () => {
103
168
  writeGoals();
104
169
 
@@ -251,7 +316,7 @@ describe("applySpawnGuards gate-artifact guard", () => {
251
316
  );
252
317
 
253
318
  expect(output).not.toBe("");
254
- expect(deny(output).permissionDecisionReason).toContain("g1-code-review.md");
319
+ expect(deny(output).permissionDecisionReason).toContain("g1-manual-qa.md");
255
320
  expect(existsSync(join(sessionDir(), "review-spawn-counts.json"))).toBe(false);
256
321
  });
257
322
 
@@ -265,7 +330,7 @@ describe("applySpawnGuards gate-artifact guard", () => {
265
330
  const parsed = deny(output);
266
331
  expect(parsed.permissionDecision).toBe("deny");
267
332
  expect(parsed.permissionDecisionReason).toContain("missing");
268
- expect(parsed.permissionDecisionReason).toContain("g1-code-review.md");
333
+ expect(parsed.permissionDecisionReason).toContain("g1-manual-qa.md");
269
334
  });
270
335
 
271
336
  it("#given senpi main-session QA is present but code review is absent #when the gate reviewer spawns #then the self-check allows it", () => {
@@ -366,10 +431,9 @@ describe("applySpawnGuards gate-artifact guard", () => {
366
431
  expect(counters["lazycodex-code-reviewer:g1:a1"]).toBeUndefined();
367
432
  });
368
433
 
369
- it("#given v1 artifacts on disk #when the gate spawns #then allows", () => {
434
+ it("#given only v1 manual QA on disk #when the gate spawns #then allows", () => {
370
435
  writeGoals();
371
436
  mkdirSync(join(workDir, ".omo", "evidence"), { recursive: true });
372
- writeFileSync(join(workDir, ".omo", "evidence", "g1-code-review.md"), "report\n");
373
437
  writeFileSync(join(workDir, ".omo", "evidence", "g1-manual-qa.md"), "matrix\n");
374
438
 
375
439
  const output = applySpawnGuards(
@@ -388,14 +452,13 @@ describe("applySpawnGuards gate-artifact guard", () => {
388
452
  payload("spawn_agent", { agent_type: "lazycodex-gate-reviewer", message: "final gate review" }),
389
453
  );
390
454
 
391
- expect(deny(output).permissionDecisionReason).toContain(".omo/evidence/ulw/s1/g1/a1/g1-code-review.md");
455
+ expect(deny(output).permissionDecisionReason).toContain(".omo/evidence/ulw/s1/g1/a1/g1-manual-qa.md");
392
456
  });
393
457
 
394
458
  it("#given a v2 plan with attempt-dir artifacts #when the gate spawns #then allows", () => {
395
459
  writeGoals({ evidenceLayoutVersion: 2 });
396
460
  const attemptDir = join(workDir, ".omo", "evidence", "ulw", "s1", "g1", "a1");
397
461
  mkdirSync(attemptDir, { recursive: true });
398
- writeFileSync(join(attemptDir, "g1-code-review.md"), "report\n");
399
462
  writeFileSync(join(attemptDir, "g1-manual-qa.md"), "matrix\n");
400
463
 
401
464
  const output = applySpawnGuards(
@@ -7,7 +7,7 @@
7
7
  "type": "command",
8
8
  "command": "node \"${PLUGIN_ROOT}/components/git-bash/dist/cli.js\" hook post-compact",
9
9
  "timeout": 5,
10
- "statusMessage": "(OmO 5.0.0-beta.47) Resetting Git Bash MCP Reminder",
10
+ "statusMessage": "(OmO 5.0.0-beta.49) Resetting Git Bash MCP Reminder",
11
11
  "commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\git-bash\\dist\\cli.js\" hook post-compact"
12
12
  }
13
13
  ],
@@ -7,7 +7,7 @@
7
7
  "type": "command",
8
8
  "command": "node \"${PLUGIN_ROOT}/components/lsp/dist/cli.js\" hook post-compact",
9
9
  "timeout": 5,
10
- "statusMessage": "(OmO 5.0.0-beta.47) Resetting LSP Diagnostics Cache",
10
+ "statusMessage": "(OmO 5.0.0-beta.49) Resetting LSP Diagnostics Cache",
11
11
  "commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\lsp\\dist\\cli.js\" hook post-compact"
12
12
  }
13
13
  ],
@@ -7,7 +7,7 @@
7
7
  "type": "command",
8
8
  "command": "node \"${PLUGIN_ROOT}/components/rules/dist/cli.js\" hook post-compact",
9
9
  "timeout": 10,
10
- "statusMessage": "(OmO 5.0.0-beta.47) Resetting Project Rule Cache",
10
+ "statusMessage": "(OmO 5.0.0-beta.49) Resetting Project Rule Cache",
11
11
  "commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\rules\\dist\\cli.js\" hook post-compact"
12
12
  }
13
13
  ],
@@ -7,7 +7,7 @@
7
7
  "type": "command",
8
8
  "command": "node \"${PLUGIN_ROOT}/components/comment-checker/dist/cli.js\" hook post-tool-use",
9
9
  "timeout": 30,
10
- "statusMessage": "(OmO 5.0.0-beta.47) Checking Comments",
10
+ "statusMessage": "(OmO 5.0.0-beta.49) Checking Comments",
11
11
  "commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\comment-checker\\dist\\cli.js\" hook post-tool-use"
12
12
  }
13
13
  ],
@@ -7,7 +7,7 @@
7
7
  "type": "command",
8
8
  "command": "node \"${PLUGIN_ROOT}/components/lsp/dist/cli.js\" hook post-tool-use",
9
9
  "timeout": 60,
10
- "statusMessage": "(OmO 5.0.0-beta.47) Checking LSP Diagnostics",
10
+ "statusMessage": "(OmO 5.0.0-beta.49) Checking LSP Diagnostics",
11
11
  "commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\lsp\\dist\\cli.js\" hook post-tool-use"
12
12
  }
13
13
  ],
@@ -8,7 +8,7 @@
8
8
  "type": "command",
9
9
  "command": "node \"${PLUGIN_ROOT}/components/teammode/dist/cli.js\" hook post-tool-use",
10
10
  "timeout": 10,
11
- "statusMessage": "(OmO 5.0.0-beta.47) Checking Thread Title Hygiene",
11
+ "statusMessage": "(OmO 5.0.0-beta.49) Checking Thread Title Hygiene",
12
12
  "commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\teammode\\dist\\cli.js\" hook post-tool-use"
13
13
  }
14
14
  ]
@@ -7,7 +7,7 @@
7
7
  "type": "command",
8
8
  "command": "node \"${PLUGIN_ROOT}/components/rules/dist/cli.js\" hook post-tool-use",
9
9
  "timeout": 10,
10
- "statusMessage": "(OmO 5.0.0-beta.47) Matching Project Rules",
10
+ "statusMessage": "(OmO 5.0.0-beta.49) Matching Project Rules",
11
11
  "commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\rules\\dist\\cli.js\" hook post-tool-use"
12
12
  }
13
13
  ],
@@ -0,0 +1,18 @@
1
+ {
2
+ "hooks": {
3
+ "PostToolUse": [
4
+ {
5
+ "matcher": "^(spawn_agent|collaborationspawn_agent|collaboration\\.spawn_agent)$",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "node \"${PLUGIN_ROOT}/components/ulw-loop/dist/cli.js\" hook post-tool-use-spawn",
10
+ "timeout": 5,
11
+ "statusMessage": "(OmO 5.0.0-beta.49) Recording Spawn Admission",
12
+ "commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\ulw-loop\\dist\\cli.js\" hook post-tool-use-spawn"
13
+ }
14
+ ]
15
+ }
16
+ ]
17
+ }
18
+ }
@@ -7,7 +7,7 @@
7
7
  "type": "command",
8
8
  "command": "node \"${PLUGIN_ROOT}/components/ulw-loop/dist/cli.js\" hook pre-tool-use",
9
9
  "timeout": 5,
10
- "statusMessage": "(OmO 5.0.0-beta.47) Enforcing Unlimited Goal Budget",
10
+ "statusMessage": "(OmO 5.0.0-beta.49) Enforcing Unlimited Goal Budget",
11
11
  "commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\ulw-loop\\dist\\cli.js\" hook pre-tool-use"
12
12
  }
13
13
  ],
@@ -8,7 +8,7 @@
8
8
  "type": "command",
9
9
  "command": "node \"${PLUGIN_ROOT}/components/ulw-loop/dist/cli.js\" hook pre-tool-use-spawn",
10
10
  "timeout": 5,
11
- "statusMessage": "(OmO 5.0.0-beta.47) Guarding Ulw-Loop Spawns",
11
+ "statusMessage": "(OmO 5.0.0-beta.49) Guarding Ulw-Loop Spawns",
12
12
  "commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\ulw-loop\\dist\\cli.js\" hook pre-tool-use-spawn"
13
13
  }
14
14
  ]
@@ -7,7 +7,7 @@
7
7
  "type": "command",
8
8
  "command": "node \"${PLUGIN_ROOT}/components/git-bash/dist/cli.js\" hook pre-tool-use",
9
9
  "timeout": 5,
10
- "statusMessage": "(OmO 5.0.0-beta.47) Recommending Git Bash MCP",
10
+ "statusMessage": "(OmO 5.0.0-beta.49) Recommending Git Bash MCP",
11
11
  "commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\git-bash\\dist\\cli.js\" hook pre-tool-use"
12
12
  }
13
13
  ],
@@ -7,7 +7,7 @@
7
7
  "type": "command",
8
8
  "command": "node \"${PLUGIN_ROOT}/scripts/auto-update.mjs\" hook session-start",
9
9
  "timeout": 15,
10
- "statusMessage": "(OmO 5.0.0-beta.47) Checking Auto Update",
10
+ "statusMessage": "(OmO 5.0.0-beta.49) Checking Auto Update",
11
11
  "commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\scripts\\auto-update.mjs\" hook session-start"
12
12
  }
13
13
  ],
@@ -8,7 +8,7 @@
8
8
  "command": "node \"${PLUGIN_ROOT}/components/bootstrap/dist/cli.js\" hook session-start",
9
9
  "commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\bootstrap.ps1\"",
10
10
  "timeout": 30,
11
- "statusMessage": "(OmO 5.0.0-beta.47) Checking Bootstrap Provisioning"
11
+ "statusMessage": "(OmO 5.0.0-beta.49) Checking Bootstrap Provisioning"
12
12
  }
13
13
  ]
14
14
  }
@@ -7,7 +7,7 @@
7
7
  "type": "command",
8
8
  "command": "node \"${PLUGIN_ROOT}/components/rules/dist/cli.js\" hook session-start",
9
9
  "timeout": 10,
10
- "statusMessage": "(OmO 5.0.0-beta.47) Loading Project Rules",
10
+ "statusMessage": "(OmO 5.0.0-beta.49) Loading Project Rules",
11
11
  "commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\rules\\dist\\cli.js\" hook session-start"
12
12
  }
13
13
  ]
@@ -7,7 +7,7 @@
7
7
  "type": "command",
8
8
  "command": "node \"${PLUGIN_ROOT}/components/telemetry/dist/cli.js\" hook session-start",
9
9
  "timeout": 15,
10
- "statusMessage": "(OmO 5.0.0-beta.47) Recording Session Telemetry",
10
+ "statusMessage": "(OmO 5.0.0-beta.49) Recording Session Telemetry",
11
11
  "commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\telemetry\\dist\\cli.js\" hook session-start"
12
12
  }
13
13
  ]
@@ -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.47) Checking Ulw-Execute Continuation",
10
+ "statusMessage": "(OmO 5.0.0-beta.49) Checking Ulw-Execute Continuation",
11
11
  "commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\ulw-execute-continuation\\dist\\cli.js\" hook stop"
12
12
  }
13
13
  ]
@@ -7,7 +7,7 @@
7
7
  "type": "command",
8
8
  "command": "node \"${PLUGIN_ROOT}/components/ulw-loop/dist/cli.js\" hook stop",
9
9
  "timeout": 10,
10
- "statusMessage": "(OmO 5.0.0-beta.47) Checking Ulw-Loop Resume",
10
+ "statusMessage": "(OmO 5.0.0-beta.49) Checking Ulw-Loop Resume",
11
11
  "commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\ulw-loop\\dist\\cli.js\" hook stop"
12
12
  }
13
13
  ]
@@ -7,7 +7,7 @@
7
7
  "type": "command",
8
8
  "command": "node \"${PLUGIN_ROOT}/components/lazycodex-executor-verify/dist/cli.js\" hook subagent-stop",
9
9
  "timeout": 10,
10
- "statusMessage": "(OmO 5.0.0-beta.47) Verifying LazyCodex Executor Evidence",
10
+ "statusMessage": "(OmO 5.0.0-beta.49) Verifying LazyCodex Executor Evidence",
11
11
  "commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\lazycodex-executor-verify\\dist\\cli.js\" hook subagent-stop"
12
12
  }
13
13
  ],
@@ -7,7 +7,7 @@
7
7
  "type": "command",
8
8
  "command": "node \"${PLUGIN_ROOT}/components/ultrawork/dist/cli.js\" hook user-prompt-submit",
9
9
  "timeout": 5,
10
- "statusMessage": "(OmO 5.0.0-beta.47) Checking Ultrawork Trigger",
10
+ "statusMessage": "(OmO 5.0.0-beta.49) Checking Ultrawork Trigger",
11
11
  "commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\ultrawork\\dist\\cli.js\" hook user-prompt-submit"
12
12
  }
13
13
  ]
@@ -7,7 +7,7 @@
7
7
  "type": "command",
8
8
  "command": "node \"${PLUGIN_ROOT}/components/ulw-loop/dist/cli.js\" hook user-prompt-submit",
9
9
  "timeout": 10,
10
- "statusMessage": "(OmO 5.0.0-beta.47) Checking Ulw-Loop Steering",
10
+ "statusMessage": "(OmO 5.0.0-beta.49) Checking Ulw-Loop Steering",
11
11
  "commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\ulw-loop\\dist\\cli.js\" hook user-prompt-submit"
12
12
  }
13
13
  ]
@@ -7,7 +7,7 @@
7
7
  "type": "command",
8
8
  "command": "node \"${PLUGIN_ROOT}/components/rules/dist/cli.js\" hook user-prompt-submit",
9
9
  "timeout": 10,
10
- "statusMessage": "(OmO 5.0.0-beta.47) Loading Project Rules",
10
+ "statusMessage": "(OmO 5.0.0-beta.49) Loading Project Rules",
11
11
  "commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\rules\\dist\\cli.js\" hook user-prompt-submit"
12
12
  }
13
13
  ]
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@sisyphuslabs/omo-codex-plugin",
3
- "version": "5.0.0-beta.47",
3
+ "version": "5.0.0-beta.49",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@sisyphuslabs/omo-codex-plugin",
9
- "version": "5.0.0-beta.47",
9
+ "version": "5.0.0-beta.49",
10
10
  "workspaces": [
11
11
  "components/comment-checker",
12
12
  "components/git-bash",
@@ -90,7 +90,7 @@
90
90
  },
91
91
  "components/comment-checker": {
92
92
  "name": "@code-yeongyu/codex-comment-checker",
93
- "version": "5.0.0-beta.47",
93
+ "version": "5.0.0-beta.49",
94
94
  "license": "MIT",
95
95
  "bin": {
96
96
  "omo-comment-checker": "dist/cli.js"
@@ -111,7 +111,7 @@
111
111
  },
112
112
  "components/git-bash": {
113
113
  "name": "@sisyphuslabs/codex-git-bash-hook",
114
- "version": "5.0.0-beta.47",
114
+ "version": "5.0.0-beta.49",
115
115
  "bin": {
116
116
  "omo-git-bash-hook": "dist/cli.js"
117
117
  },
@@ -125,7 +125,7 @@
125
125
  },
126
126
  "components/lazycodex-executor-verify": {
127
127
  "name": "@code-yeongyu/codex-lazycodex-executor-verify",
128
- "version": "5.0.0-beta.47",
128
+ "version": "5.0.0-beta.49",
129
129
  "license": "MIT",
130
130
  "bin": {
131
131
  "lazycodex-executor-verify": "dist/cli.js"
@@ -142,7 +142,7 @@
142
142
  },
143
143
  "components/lsp": {
144
144
  "name": "@code-yeongyu/codex-lsp",
145
- "version": "5.0.0-beta.47",
145
+ "version": "5.0.0-beta.49",
146
146
  "license": "MIT",
147
147
  "dependencies": {
148
148
  "@code-yeongyu/lsp-daemon": "file:../../../../lsp-daemon",
@@ -163,7 +163,7 @@
163
163
  },
164
164
  "components/rules": {
165
165
  "name": "@code-yeongyu/codex-rules",
166
- "version": "5.0.0-beta.47",
166
+ "version": "5.0.0-beta.49",
167
167
  "license": "MIT",
168
168
  "dependencies": {
169
169
  "picomatch": "^4.0.7"
@@ -185,7 +185,7 @@
185
185
  },
186
186
  "components/teammode": {
187
187
  "name": "@sisyphuslabs/codex-teammode",
188
- "version": "5.0.0-beta.47",
188
+ "version": "5.0.0-beta.49",
189
189
  "devDependencies": {
190
190
  "@types/node": "^26.2.0",
191
191
  "bun-types": "^1.4.0",
@@ -198,7 +198,7 @@
198
198
  },
199
199
  "components/telemetry": {
200
200
  "name": "@code-yeongyu/codex-telemetry",
201
- "version": "5.0.0-beta.47",
201
+ "version": "5.0.0-beta.49",
202
202
  "license": "MIT",
203
203
  "bin": {
204
204
  "omo-telemetry": "dist/cli.js"
@@ -216,7 +216,7 @@
216
216
  },
217
217
  "components/ultrawork": {
218
218
  "name": "@code-yeongyu/codex-ultrawork",
219
- "version": "5.0.0-beta.47",
219
+ "version": "5.0.0-beta.49",
220
220
  "license": "MIT",
221
221
  "bin": {
222
222
  "omo-ultrawork": "dist/cli.js"
@@ -234,7 +234,7 @@
234
234
  },
235
235
  "components/ulw-execute-continuation": {
236
236
  "name": "@code-yeongyu/codex-ulw-execute-continuation",
237
- "version": "5.0.0-beta.47",
237
+ "version": "5.0.0-beta.49",
238
238
  "license": "MIT",
239
239
  "bin": {
240
240
  "omo-ulw-execute-continuation": "dist/cli.js"
@@ -251,7 +251,7 @@
251
251
  },
252
252
  "components/ulw-loop": {
253
253
  "name": "@code-yeongyu/codex-ulw-loop",
254
- "version": "5.0.0-beta.47",
254
+ "version": "5.0.0-beta.49",
255
255
  "license": "MIT",
256
256
  "bin": {
257
257
  "omo-ulw-loop": "dist/cli.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sisyphuslabs/omo-codex-plugin",
3
- "version": "5.0.0-beta.47",
3
+ "version": "5.0.0-beta.49",
4
4
  "description": "Aggregate Codex plugin root for OMO components.",
5
5
  "type": "module",
6
6
  "packageManager": "npm@11.12.1",