oh-my-opencode 4.16.0 → 4.16.2

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 (160) hide show
  1. package/.agents/skills/codex-qa/SKILL.md +9 -7
  2. package/.agents/skills/codex-qa/references/logging-debug.md +6 -4
  3. package/.agents/skills/opencode-qa/SKILL.md +9 -9
  4. package/.agents/skills/opencode-qa/references/tui-tmux.md +10 -8
  5. package/dist/cli/codex-ulw-loop.d.ts +8 -0
  6. package/dist/cli/get-local-version/types.d.ts +1 -1
  7. package/dist/cli/index.js +260 -207
  8. package/dist/cli-node/index.js +260 -207
  9. package/dist/features/background-agent/parent-wake-dedupe.d.ts +1 -0
  10. package/dist/features/background-agent/parent-wake-flush-runner.d.ts +2 -0
  11. package/dist/features/background-agent/parent-wake-prompt-dispatch.d.ts +1 -0
  12. package/dist/features/builtin-commands/templates/refactor-sections/intro-and-analysis.d.ts +1 -1
  13. package/dist/features/builtin-commands/templates/remove-ai-slops.d.ts +1 -1
  14. package/dist/features/builtin-commands/templates/start-work.d.ts +1 -1
  15. package/dist/features/monitor/process.d.ts +17 -1
  16. package/dist/index.js +1098 -1020
  17. package/dist/skills/frontend/SKILL.md +9 -9
  18. package/dist/skills/frontend/references/design/README.md +7 -3
  19. package/dist/skills/frontend/references/design/_INDEX.md +1 -1
  20. package/dist/skills/frontend/references/design/design-system-architecture.md +24 -2
  21. package/dist/skills/frontend/references/designpowers/README.md +2 -2
  22. package/dist/skills/frontend/references/designpowers/lane-b-execution.md +1 -1
  23. package/dist/skills/review-work/SKILL.md +3 -1
  24. package/dist/skills/start-work/SKILL.md +4 -2
  25. package/dist/skills/ulw-research/SKILL.md +3 -1
  26. package/dist/skills/visual-qa/SKILL.md +13 -17
  27. package/docs/reference/web-terminal-visual-qa.md +39 -45
  28. package/package.json +31 -25
  29. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  30. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  31. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  32. package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
  33. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  34. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  35. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  36. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  37. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  38. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  39. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  40. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  41. package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus.md +1 -1
  42. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  43. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  44. package/packages/omo-codex/plugin/components/start-work-continuation/directive.md +3 -3
  45. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  46. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  47. package/packages/omo-codex/plugin/components/start-work-continuation/test/codex-hook.test.ts +1 -1
  48. package/packages/omo-codex/plugin/components/teammode/AGENTS.md +1 -1
  49. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  50. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  51. package/packages/omo-codex/plugin/components/teammode/skills/teammode/SKILL.md +3 -3
  52. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  53. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  54. package/packages/omo-codex/plugin/components/ultrawork/directive.md +19 -10
  55. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  56. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  57. package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +19 -10
  58. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +13 -0
  59. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +2 -0
  60. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +22 -1
  61. package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +4 -0
  62. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +19 -10
  63. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +15 -2
  64. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.js +2 -1
  65. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +89 -27
  66. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.d.ts +6 -0
  67. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +55 -9
  68. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-snapshot.d.ts +15 -0
  69. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-snapshot.js +33 -0
  70. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-types.d.ts +10 -3
  71. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering.js +15 -11
  72. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +2 -2
  73. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  74. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +3 -1
  75. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +7 -7
  76. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +17 -2
  77. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-steering.ts +2 -1
  78. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +59 -11
  79. package/packages/omo-codex/plugin/components/ulw-loop/src/steering-snapshot.ts +38 -0
  80. package/packages/omo-codex/plugin/components/ulw-loop/src/steering-types.ts +11 -3
  81. package/packages/omo-codex/plugin/components/ulw-loop/src/steering.ts +15 -7
  82. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-create-goals.test.ts +16 -0
  83. package/packages/omo-codex/plugin/components/ulw-loop/test/plan-io.test.ts +260 -2
  84. package/packages/omo-codex/plugin/components/ulw-loop/test/skill-contract.test.ts +1 -1
  85. package/packages/omo-codex/plugin/components/ulw-loop/test/steering-snapshot.test.ts +124 -0
  86. package/packages/omo-codex/plugin/components/ulw-loop/test/steering.test.ts +101 -2
  87. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  88. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  89. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  90. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.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/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  96. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  97. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  98. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  99. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  100. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  101. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  102. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
  103. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
  104. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  105. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  106. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  107. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  108. package/packages/omo-codex/plugin/package-lock.json +13 -13
  109. package/packages/omo-codex/plugin/package.json +1 -1
  110. package/packages/omo-codex/plugin/scripts/auto-update.mjs +64 -17
  111. package/packages/omo-codex/plugin/scripts/hook-status-message.mjs +10 -6
  112. package/packages/omo-codex/plugin/scripts/migrate-codex-config/multi-agent-v2-guard.mjs +186 -20
  113. package/packages/omo-codex/plugin/scripts/migrate-codex-config/subagent-limit-guard.mjs +51 -3
  114. package/packages/omo-codex/plugin/scripts/migrate-codex-config.mjs +33 -5
  115. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +1 -1
  116. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +9 -9
  117. package/packages/omo-codex/plugin/skills/frontend/references/design/README.md +7 -3
  118. package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +1 -1
  119. package/packages/omo-codex/plugin/skills/frontend/references/design/design-system-architecture.md +24 -2
  120. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/README.md +2 -2
  121. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-b-execution.md +1 -1
  122. package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +1 -1
  123. package/packages/omo-codex/plugin/skills/refactor/SKILL.md +1 -1
  124. package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +1 -1
  125. package/packages/omo-codex/plugin/skills/review-work/SKILL.md +1 -1
  126. package/packages/omo-codex/plugin/skills/start-work/SKILL.md +3 -3
  127. package/packages/omo-codex/plugin/skills/teammode/SKILL.md +3 -3
  128. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +19 -10
  129. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +3 -1
  130. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +7 -7
  131. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +13 -0
  132. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +2 -0
  133. package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +1 -1
  134. package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +14 -18
  135. package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +4 -4
  136. package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +1 -1
  137. package/packages/omo-codex/plugin/test/auto-update.test.mjs +35 -1
  138. package/packages/omo-codex/plugin/test/bootstrap-hooks.test.mjs +1 -1
  139. package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +22 -9
  140. package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +275 -19
  141. package/packages/omo-codex/plugin/test/subagent-limit-migration.test.mjs +33 -0
  142. package/packages/omo-codex/plugin/test/sync-hook-status-messages.test.mjs +6 -6
  143. package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +4 -2
  144. package/packages/omo-codex/plugin/test/ulw-plan-skill-contract.test.mjs +52 -0
  145. package/packages/omo-codex/scripts/install-dist/install-local.mjs +65 -39
  146. package/packages/omo-codex/scripts/install-lazycodex-version-stamp.test.mjs +2 -2
  147. package/packages/shared-skills/skills/frontend/SKILL.md +9 -9
  148. package/packages/shared-skills/skills/frontend/references/design/README.md +7 -3
  149. package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +1 -1
  150. package/packages/shared-skills/skills/frontend/references/design/design-system-architecture.md +24 -2
  151. package/packages/shared-skills/skills/frontend/references/designpowers/README.md +2 -2
  152. package/packages/shared-skills/skills/frontend/references/designpowers/lane-b-execution.md +1 -1
  153. package/packages/shared-skills/skills/review-work/SKILL.md +3 -1
  154. package/packages/shared-skills/skills/start-work/SKILL.md +4 -2
  155. package/packages/shared-skills/skills/ulw-research/SKILL.md +3 -1
  156. package/packages/shared-skills/skills/visual-qa/SKILL.md +13 -17
  157. package/script/qa/strip-ansi.mjs +10 -0
  158. package/script/qa/web-terminal-visual-qa.mjs +112 -195
  159. package/script/qa/xterm-live-terminal.mjs +180 -0
  160. package/script/qa/web-terminal-renderer.mjs +0 -218
@@ -8,7 +8,7 @@
8
8
  "type": "command",
9
9
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook pre-tool-use",
10
10
  "timeout": 5,
11
- "statusMessage": "(OmO) Recommending Git Bash MCP"
11
+ "statusMessage": "(OmO 4.16.2) Recommending Git Bash MCP"
12
12
  }
13
13
  ]
14
14
  }
@@ -20,7 +20,7 @@
20
20
  "type": "command",
21
21
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-compact",
22
22
  "timeout": 5,
23
- "statusMessage": "(OmO) Resetting Git Bash MCP Reminder"
23
+ "statusMessage": "(OmO 4.16.2) Resetting Git Bash MCP Reminder"
24
24
  }
25
25
  ]
26
26
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sisyphuslabs/codex-git-bash-hook",
3
- "version": "4.16.0",
3
+ "version": "4.16.2",
4
4
  "description": "Codex hook component that reminds Windows sessions to prefer the OMO git_bash MCP.",
5
5
  "type": "module",
6
6
  "private": true,
@@ -8,7 +8,7 @@
8
8
  "type": "command",
9
9
  "command": "node \"${PLUGIN_ROOT}/components/lazycodex-executor-verify/dist/cli.js\" hook subagent-stop",
10
10
  "timeout": 10,
11
- "statusMessage": "(OmO) Verifying LazyCodex Executor Evidence"
11
+ "statusMessage": "(OmO 4.16.2) Verifying LazyCodex Executor Evidence"
12
12
  }
13
13
  ]
14
14
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-yeongyu/codex-lazycodex-executor-verify",
3
- "version": "4.16.0",
3
+ "version": "4.16.2",
4
4
  "description": "Codex SubagentStop evidence verifier for LazyCodex executor completions.",
5
5
  "type": "module",
6
6
  "packageManager": "npm@11.12.1",
@@ -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) Checking LSP Diagnostics"
11
+ "statusMessage": "(OmO 4.16.2) 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) Resetting LSP Diagnostics Cache"
24
+ "statusMessage": "(OmO 4.16.2) 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": "4.16.0",
3
+ "version": "4.16.2",
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",
@@ -41,7 +41,7 @@ omo-codex auto-runs LSP diagnostics after every edit and injects the result: any
41
41
 
42
42
  # Subagents
43
43
 
44
- Read-only Codex subagent roles live in `CODEX_HOME/agents/`. Spawn: `multi_agent_v1.spawn_agent({"message":"TASK: act as a <role>. ...","fork_context":false})`
44
+ Read-only Codex subagent roles live in `CODEX_HOME/agents/`. Spawn: `multi_agent_v1.spawn_agent({"message":"TASK: act as a <role>. ...","fork_context":false})`. If your tool list instead has a flat `spawn_agent` with a required `task_name` (`multi_agent_v2`): `spawn_agent({"task_name":"<lowercase_digits_underscores>","message":"TASK: act as a <role>. ...","fork_turns":"none"})` — finished agents end on their own; `wait_agent` takes only `timeout_ms`.
45
45
 
46
46
  - `explorer` - codebase search
47
47
  - `librarian` - external docs, OSS code, API contracts
@@ -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) Loading Project Rules"
10
+ "statusMessage": "(OmO 4.16.2) 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) Loading Project Rules"
22
+ "statusMessage": "(OmO 4.16.2) 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) Matching Project Rules"
35
+ "statusMessage": "(OmO 4.16.2) 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) Resetting Project Rule Cache"
48
+ "statusMessage": "(OmO 4.16.2) 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": "4.16.0",
3
+ "version": "4.16.2",
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",
@@ -19,8 +19,8 @@ You are mid-flight on a Prometheus work plan; this turn is an automatic continua
19
19
  2. Pick the FIRST unchecked top-level checkbox in `## TODOs` or `## Final Verification Wave`. Ignore nested checkboxes under Acceptance Criteria / Evidence / Definition of Done.
20
20
  3. Follow the `start-work` skill in full. The skill is already loaded from your earlier turn — re-read its file at `packages/omo-codex/plugin/skills/start-work/SKILL.md` if you have lost context.
21
21
  4. Apply the checkbox's tier from its ledger entry, or classify it now per the start-work skill: LIGHT (default — a narrow change inside existing layers) needs one real-surface proof of the deliverable, with auxiliary surfaces first-class for CLI- or data-shaped work, and only trigger-mapped adversarial classes; HEAVY (new module/abstraction, auth/security, external integration, schema/migration, concurrency, cross-domain refactor, care signals) takes the full per-criterion regime. When unsure, take HEAVY; never downgrade.
22
- 5. Decompose the checkbox into atomic sub-tasks. Dispatch them in PARALLEL via `multi_agent_v1.spawn_agent` calls in this same response unless a sub-task has a NAMED blocking dependency (input from another sub-task or shared file). Use `fork_context: false` unless full history is truly required. Put role and specialty instructions inside `message`.
23
- 6. Every sub-task message MUST be self-contained, executable, not a context handoff: start with `TASK: <imperative assignment>`, then name `DELIVERABLE`, `SCOPE`, and `VERIFY`. It must include all 7 sections and a Manual-QA channel with exact invocation (`curl`, `send-keys`, `browser:control-in-app-browser` action, `page.click`) and PASS/FAIL observable, plus ultraqa classes, artifact, and cleanup receipt. Channels: HTTP (`curl -i`); tmux (`send-keys` + `capture-pane`); browser (Codex: `browser:control-in-app-browser` first unless auth/persistent profile needed; else Chrome/agent-browser); computer use.
22
+ 5. Decompose the checkbox into atomic sub-tasks. Dispatch them in PARALLEL via `multi_agent_v1.spawn_agent` calls in this same response unless a sub-task has a NAMED blocking dependency (input from another sub-task or shared file). Use `fork_context: false` unless full history is truly required. Put role and specialty instructions inside `message`. Flat `spawn_agent` requiring `task_name` instead (`multi_agent_v2`)? Add `"task_name"`, use `fork_turns: "none"`, `wait_agent` takes only `timeout_ms`, finished agents end on their own.
23
+ 6. Every sub-task message MUST be self-contained, executable, not a context handoff: start with `TASK: <imperative assignment>`, then name `DELIVERABLE`, `SCOPE`, and `VERIFY`. It must include all 7 sections and a Manual-QA channel with exact invocation (`curl`, `send-keys`, `browser:control-in-app-browser` action, `page.click`) and PASS/FAIL observable, plus ultraqa classes, artifact, and cleanup receipt. Channels: HTTP (`curl -i`); terminal/TUI (`send-keys` for boot smoke; xterm.js web terminal for color/visual evidence, never `tmux capture-pane`); browser (Codex: `browser:control-in-app-browser` first unless auth/persistent profile needed; else Chrome/agent-browser); computer use.
24
24
  7. Treat every worker DoneClaim as untrusted input. Run independent AdversarialVerify before any checkbox can become FullyDone; `confirmed` is the only pass verdict, while `false-positive`, `needs-fix`, and `needs-human-review` loop back to the executor with exact feedback.
25
25
  8. Use `multi_agent_v1.wait_agent` for mailbox signals, not proof of completion — a timeout only means no new mailbox update arrived; a running child is alive. For sub-tasks likely to exceed one wait cycle, require `WORKING: <task> - <current phase>` before long passes and `BLOCKED: <reason>` only when progress stops. Send `TASK STILL ACTIVE: return <deliverable> or BLOCKED: <reason>` only when the child is completed without the deliverable, ack-only, or no longer running. If that followup is still silent or ack-only, record inconclusive, do not count it as pass/review approval, close if safe, and respawn a smaller `fork_context: false` task with the missing deliverable.
26
26
  9. After verification of ALL sub-tasks under this checkbox: `apply_patch` the plan to change `- [ ]` → `- [x]`, re-read the plan to confirm the count decreased, append a `task-completed` line to the ledger, then continue.
@@ -30,7 +30,7 @@ You are mid-flight on a Prometheus work plan; this turn is an automatic continua
30
30
 
31
31
  - No production code before a failing-first proof exists: a unit test at a seam, otherwise the sub-task's Manual-QA scenario captured failing. A test that mirrors its implementation (mock-call assertions, pinned constants) is not evidence. When the change touches existing behavior, PIN it first: a baseline characterization test that passes on the unchanged code, with exact inputs, exact observable, and exact assertion. PIN → RED → GREEN → SURFACE.
32
32
  - No `--dry-run` as evidence. No "should work". No "tests pass" as completion proof.
33
- - TUI visual evidence MUST use the web terminal pattern when a task drives an OpenCode/Codex/terminal UI: capture the pane or run `node script/qa/web-terminal-visual-qa.mjs --title "<surface>" --from-file <capture.txt> --evidence-dir <dir>` (or `--command` when tmux is available), then cite `terminal.png`, `terminal.txt`, and `metadata.json`.
33
+ - TUI visual evidence MUST render through the real xterm.js web terminal, never `tmux capture-pane`: run `node script/qa/web-terminal-visual-qa.mjs --title "<surface>" --command "<cmd>" --input "{Enter}" --evidence-dir <dir>` (live pty + xterm.js in Chrome; `--from-file <capture>` replays a raw stream), then cite `terminal.png`, `terminal.txt`, and `metadata.json`.
34
34
  - No `as any` / `@ts-ignore` / `@ts-expect-error`. No deleting failing tests.
35
35
  - Probe every ultraqa adversarial class whose trigger fact holds (malformed input, prompt injection, cancel/resume, stale state, dirty worktree, hung or long commands, flaky tests, misleading success output, repeated interruptions — trigger map in the start-work skill) and capture the observable for each. A clean happy-path artifact alone is NOT a PASS when an applicable class went unprobed; record skipped classes with a one-line not-applicable reason.
36
36
  - Cleanup receipt is mandatory. Register each QA teardown (scripts, tmux, browser contexts, PIDs, ports, containers, temp dirs) as a todo when it spawns, then execute it. Leftover QA state = BLOCKED, not PASS.
@@ -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) Checking Start-Work Continuation"
10
+ "statusMessage": "(OmO 4.16.2) 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) Checking Start-Work Continuation"
22
+ "statusMessage": "(OmO 4.16.2) 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": "4.16.0",
3
+ "version": "4.16.2",
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",
@@ -135,7 +135,7 @@ describe("start-work Stop hook", () => {
135
135
  expect(parsed.reason).toMatch(/When unsure[^.]{0,30}HEAVY/);
136
136
  expect(parsed.reason).toMatch(/mirrors its implementation/);
137
137
  expect((parsed.reason.match(/malformed input, prompt injection/g) ?? []).length).toBe(1);
138
- expect(parsed.reason.split(/\s+/).filter(Boolean).length).toBeLessThanOrEqual(1100);
138
+ expect(parsed.reason.split(/\s+/).filter(Boolean).length).toBeLessThanOrEqual(1135);
139
139
  });
140
140
 
141
141
  it("#given active codex work #when continuation directive is emitted #then PR lifecycle stays worktree-bound", () => {
@@ -41,6 +41,6 @@ Codex team-mode component. Two deliverables in one dir:
41
41
  - Archive ambiguity: "Ambiguous Codex thread id" from `codex_app.set_thread_archived` is an app-thread archival blocker, not a team-state blocker. Record it via `archive --note`, never claim the thread was archived, never delete team state before evidence is copied or the user accepts the loss.
42
42
  - `integrate` lands member branches with merge commits only (`--no-ff`); never squash or rebase.
43
43
  - `bind-thread` refuses while the team has fewer than 2 members; a single-member team is a subagent, not a team. Member focus, name, and threadTitle must each be unique (case/whitespace-insensitive).
44
- - Every member is a real `codex_app.create_thread` thread bound via `bind-thread`; `multi_agent_v1.spawn_agent` is never a substitute.
44
+ - Every member is a real `codex_app.create_thread` thread bound via `bind-thread`; a spawned in-process subagent (`multi_agent_v1.spawn_agent` or flat `spawn_agent`) is never a substitute.
45
45
  - The hook must stay silent (empty stdout) on unrelated tools and malformed payloads; it never blocks a Codex turn.
46
46
  - `init` with an explicit `--session <leader thread id>` makes `leader.sessionId` messageable; without it members cannot report and the leader is stuck polling. Re-running `init` is a safe no-op.
@@ -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) Checking Thread Title Hygiene"
11
+ "statusMessage": "(OmO 4.16.2) Checking Thread Title Hygiene"
12
12
  }
13
13
  ]
14
14
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sisyphuslabs/codex-teammode",
3
- "version": "4.16.0",
3
+ "version": "4.16.2",
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,
@@ -19,7 +19,7 @@ Use a TEAM when EITHER holds:
19
19
  - one task still needs exploration, yet its GOAL is already clear - parallel investigation under
20
20
  a fixed objective.
21
21
 
22
- Use plain subagents (`$ulw` / `multi_agent_v1.spawn_agent`) - NOT a team - when EITHER holds:
22
+ Use plain subagents (`$ulw` / `multi_agent_v1.spawn_agent` / flat `spawn_agent` on `multi_agent_v2`) - NOT a team - when EITHER holds:
23
23
  - the work IS perfectly isolated, so there is no coordination cost worth paying; or
24
24
  - the GOAL is still ambiguous, where one mind should resolve direction before any fan-out.
25
25
 
@@ -39,7 +39,7 @@ merge), not the keystrokes.
39
39
  ## Compose by part, ownership, or perspective - not by job title
40
40
 
41
41
  A team is ALWAYS two or more members - never a single-member team. One worker on an isolated
42
- job is a subagent (`multi_agent_v1.spawn_agent`), not a team; if you end up with a single member,
42
+ job is a spawned subagent, not a team; if you end up with a single member,
43
43
  either split off a second distinct slice or drop the team and use a subagent.
44
44
 
45
45
  Compose the team from what you actually KNOW about the work. Ground the split in real knowledge
@@ -110,7 +110,7 @@ do not treat the intended mutation as complete; retry after the named command fi
110
110
  lose in the sidebar without this link.
111
111
 
112
112
  Every team member is a real Codex thread created with `codex_app.create_thread` - this is strict,
113
- not a preference. NEVER substitute `multi_agent_v1.spawn_agent`, or any other in-process subagent,
113
+ not a preference. NEVER substitute a spawned in-process subagent (`multi_agent_v1.spawn_agent` or flat `spawn_agent`)
114
114
  for a team member: a spawned agent is an ephemeral helper that does not show up as a team thread,
115
115
  cannot carry the `[team name] <member name>` title, and cannot be inspected, titled, archived, or
116
116
  re-opened with the `codex_app.*` thread tools - which defeats the entire point of a durable team.
@@ -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) Recording Session Telemetry"
10
+ "statusMessage": "(OmO 4.16.2) Recording Session Telemetry"
11
11
  }
12
12
  ]
13
13
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-yeongyu/codex-telemetry",
3
- "version": "4.16.0",
3
+ "version": "4.16.2",
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",
@@ -49,9 +49,10 @@ exercises the surface; capture the artifact.
49
49
  1. HTTP call — hit the live endpoint with `curl -i` (or a
50
50
  Playwright APIRequestContext); capture status line + headers +
51
51
  body.
52
- 2. tmux `tmux new-session -d -s ulw-qa-<criterion>`, drive with
53
- `send-keys`, dump via `tmux capture-pane -pS -E -`; transcript
54
- is the artifact.
52
+ 2. Terminal / TUI - drive a real pty and prove it through the
53
+ xterm.js web terminal (see the TUI visual QA note below). tmux
54
+ `send-keys` is fine for a boot smoke; NEVER `tmux capture-pane`
55
+ for color / layout / CJK evidence, which degrades truecolor.
55
56
  3. Browser use — in Codex, use `browser:control-in-app-browser`
56
57
  first when available and no authenticated/persistent user browser
57
58
  profile is required. Otherwise use Chrome to drive the REAL page;
@@ -79,13 +80,13 @@ channel scenario when the behavior is user-facing. `--dry-run`,
79
80
  printing the command, "should respond", and "looks correct" never
80
81
  count.
81
82
 
82
- For TUI visual QA, terminal transcripts alone are not enough when a
83
- visual surface is being evaluated. In this repo, prefer
84
- `node script/qa/web-terminal-visual-qa.mjs --title "<surface>" --from-file <capture.txt> --evidence-dir <dir>`
85
- or the helper's `--command` tmux-backed PTY connector when available.
86
- Outside this repo, capture equivalent browser/computer-use rendered
87
- terminal evidence: screenshot, plain transcript, rendered HTML or action
88
- log, and cleanup receipt.
83
+ For TUI visual QA, render the terminal through the real xterm.js web
84
+ terminal and screenshot it - never a `tmux capture-pane` dump, which
85
+ degrades color and wide-glyph width. In this repo:
86
+ `node script/qa/web-terminal-visual-qa.mjs --title "<surface>" --command "<cmd>" --input "{Enter}" --evidence-dir <dir>`
87
+ (live pty + xterm.js in Chrome; `--from-file <capture>` replays a raw
88
+ stream). Outside this repo, capture equivalent browser-rendered terminal
89
+ evidence: screenshot + plain transcript + cleanup receipt.
89
90
 
90
91
  # Bootstrap (DO ALL FOUR BEFORE ANY OTHER WORK — NO SKIPPING)
91
92
 
@@ -258,6 +259,7 @@ Every `multi_agent_v1.spawn_agent` message is self-contained and starts with
258
259
  handoff. Use `fork_context: false` unless full history is truly
259
260
  required; paste only the context the child needs. Full-history forks can
260
261
  make the child continue old parent context instead of the delegated task.
262
+ If your tool list has a flat `spawn_agent` with a required `task_name` instead of `multi_agent_v1.*` (`multi_agent_v2`), rewrite: `fork_context: false` becomes `fork_turns: "none"`, `send_input` becomes `send_message`, finished agents end on their own (no `close_agent`; `followup_task` re-tasks, `interrupt_agent` stops), and `wait_agent` takes only `timeout_ms`, returning on any child mailbox activity.
261
263
 
262
264
  # TOML-backed subagent routing compatibility
263
265
  Treat TOML-backed role routing as **routing-unverified**. The
@@ -287,6 +289,13 @@ evidence for that step. Do not start dependent implementation until the
287
289
  audit, research, or review result is integrated or explicitly recorded
288
290
  as inconclusive. Do not generate a plan before spawned research lanes
289
291
  that feed the plan have returned or been closed as inconclusive.
292
+ Spawn every independent child for the current wave first. After the wave
293
+ is launched, run `multi_agent_v1.wait_agent` for each spawned child until
294
+ each reaches terminal status (`completed`, `failed`, `blocked`, or
295
+ explicitly recorded inconclusive) before any dependent `update_plan`
296
+ transition, `create_goal` continuation, implementation tool call, plan
297
+ drafting, approval-gate work, PR handoff, or final response. A timeout is
298
+ not terminal status.
290
299
  Do not write the final answer, PR handoff, or completion summary while
291
300
  active child agents remain open. Use short `multi_agent_v1.wait_agent` cycles.
292
301
  After two silent waits send `TASK STILL ACTIVE: return <deliverable> or
@@ -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) Checking Ultrawork Trigger"
10
+ "statusMessage": "(OmO 4.16.2) Checking Ultrawork Trigger"
11
11
  }
12
12
  ]
13
13
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-yeongyu/codex-ultrawork",
3
- "version": "4.16.0",
3
+ "version": "4.16.2",
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",
@@ -56,9 +56,10 @@ exercises the surface; capture the artifact.
56
56
  1. HTTP call — hit the live endpoint with `curl -i` (or a
57
57
  Playwright APIRequestContext); capture status line + headers +
58
58
  body.
59
- 2. tmux `tmux new-session -d -s ulw-qa-<criterion>`, drive with
60
- `send-keys`, dump via `tmux capture-pane -pS -E -`; transcript
61
- is the artifact.
59
+ 2. Terminal / TUI - drive a real pty and prove it through the
60
+ xterm.js web terminal (see the TUI visual QA note below). tmux
61
+ `send-keys` is fine for a boot smoke; NEVER `tmux capture-pane`
62
+ for color / layout / CJK evidence, which degrades truecolor.
62
63
  3. Browser use — in Codex, use `browser:control-in-app-browser`
63
64
  first when available and no authenticated/persistent user browser
64
65
  profile is required. Otherwise use Chrome to drive the REAL page;
@@ -86,13 +87,13 @@ channel scenario when the behavior is user-facing. `--dry-run`,
86
87
  printing the command, "should respond", and "looks correct" never
87
88
  count.
88
89
 
89
- For TUI visual QA, terminal transcripts alone are not enough when a
90
- visual surface is being evaluated. In this repo, prefer
91
- `node script/qa/web-terminal-visual-qa.mjs --title "<surface>" --from-file <capture.txt> --evidence-dir <dir>`
92
- or the helper's `--command` tmux-backed PTY connector when available.
93
- Outside this repo, capture equivalent browser/computer-use rendered
94
- terminal evidence: screenshot, plain transcript, rendered HTML or action
95
- log, and cleanup receipt.
90
+ For TUI visual QA, render the terminal through the real xterm.js web
91
+ terminal and screenshot it - never a `tmux capture-pane` dump, which
92
+ degrades color and wide-glyph width. In this repo:
93
+ `node script/qa/web-terminal-visual-qa.mjs --title "<surface>" --command "<cmd>" --input "{Enter}" --evidence-dir <dir>`
94
+ (live pty + xterm.js in Chrome; `--from-file <capture>` replays a raw
95
+ stream). Outside this repo, capture equivalent browser-rendered terminal
96
+ evidence: screenshot + plain transcript + cleanup receipt.
96
97
 
97
98
  # Bootstrap (DO ALL FOUR BEFORE ANY OTHER WORK — NO SKIPPING)
98
99
 
@@ -265,6 +266,7 @@ Every `multi_agent_v1.spawn_agent` message is self-contained and starts with
265
266
  handoff. Use `fork_context: false` unless full history is truly
266
267
  required; paste only the context the child needs. Full-history forks can
267
268
  make the child continue old parent context instead of the delegated task.
269
+ If your tool list has a flat `spawn_agent` with a required `task_name` instead of `multi_agent_v1.*` (`multi_agent_v2`), rewrite: `fork_context: false` becomes `fork_turns: "none"`, `send_input` becomes `send_message`, finished agents end on their own (no `close_agent`; `followup_task` re-tasks, `interrupt_agent` stops), and `wait_agent` takes only `timeout_ms`, returning on any child mailbox activity.
268
270
 
269
271
  # TOML-backed subagent routing compatibility
270
272
  Treat TOML-backed role routing as **routing-unverified**. The
@@ -294,6 +296,13 @@ evidence for that step. Do not start dependent implementation until the
294
296
  audit, research, or review result is integrated or explicitly recorded
295
297
  as inconclusive. Do not generate a plan before spawned research lanes
296
298
  that feed the plan have returned or been closed as inconclusive.
299
+ Spawn every independent child for the current wave first. After the wave
300
+ is launched, run `multi_agent_v1.wait_agent` for each spawned child until
301
+ each reaches terminal status (`completed`, `failed`, `blocked`, or
302
+ explicitly recorded inconclusive) before any dependent `update_plan`
303
+ transition, `create_goal` continuation, implementation tool call, plan
304
+ drafting, approval-gate work, PR handoff, or final response. A timeout is
305
+ not terminal status.
297
306
  Do not write the final answer, PR handoff, or completion summary while
298
307
  active child agents remain open. Use short `multi_agent_v1.wait_agent` cycles.
299
308
  After two silent waits send `TASK STILL ACTIVE: return <deliverable> or
@@ -67,6 +67,19 @@ Fan out read-only research before deciding. Every spawn names DELIVERABLE / SCOP
67
67
  multi_agent_v1.spawn_agent({"message":"TASK: act as an explorer. DELIVERABLE: ... SCOPE: ... VERIFY: ...","agent_type":"explorer","fork_context":false})
68
68
  ```
69
69
 
70
+ If your tool list has a flat `spawn_agent` with a required `task_name` instead of `multi_agent_v1.*` (`multi_agent_v2`), rewrite: add `"task_name":"<lowercase_digits_underscores>"`, replace `"fork_context":false` with `"fork_turns":"none"`, and `wait_agent` takes only `timeout_ms`, returning on any child mailbox activity (finished agents end on their own).
71
+
72
+ Spawn every independent child for the current wave first. After the wave
73
+ is launched, use `multi_agent_v1.wait_agent` for each child until each
74
+ reaches terminal status. A timeout is not terminal status. Do not start dependent planning, drafting, approval-gate work, or final handoff until each child result is integrated or recorded as inconclusive.
75
+
76
+ For work likely to exceed one wait cycle, require the child to send
77
+ `WORKING: <task> - <current phase>` before long passes and
78
+ `BLOCKED: <reason>` only when progress stops. A `multi_agent_v1.wait_agent`
79
+ timeout only means no new mailbox update arrived. Treat a running child as
80
+ alive. Fallback only when the child is completed without the deliverable,
81
+ ack-only after followup, explicitly `BLOCKED:`, or no longer running.
82
+
70
83
  Roles: `explorer` (internal patterns/conventions/tests), `librarian` (external docs/contracts), `metis` (gap analysis), `momus` (high-accuracy plan review). Full spawn/wait/fallback discipline is in `references/full-workflow.md`.
71
84
 
72
85
  ## Stop rules
@@ -96,6 +96,8 @@ Every spawn starts with `TASK:`, then DELIVERABLE / SCOPE / VERIFY inside `messa
96
96
  multi_agent_v1.spawn_agent({"message":"TASK: act as an explorer. DELIVERABLE: ... SCOPE: ... VERIFY: ...","agent_type":"explorer","fork_context":false})
97
97
  ```
98
98
 
99
+ If your tool list has a flat `spawn_agent` with a required `task_name` instead of `multi_agent_v1.*` (`multi_agent_v2`), rewrite: add `"task_name":"<lowercase_digits_underscores>"`, replace `"fork_context":false` with `"fork_turns":"none"`, and `wait_agent` takes only `timeout_ms`, returning on any child mailbox activity (finished agents end on their own — skip the close step).
100
+
99
101
  Roles: `explorer`, `librarian`, `metis`, `momus`. Spawn long plan/reviewer agents in the background and poll with short waits; require the child to send `WORKING: <task> - <phase>` before long passes and `BLOCKED: <reason>` only when progress stops. A wait timeout only means no new mailbox update arrived; treat a running child as alive. Fall back only when the child completed without the deliverable, is ack-only after followup, explicitly `BLOCKED:`, or no longer running; then respawn a smaller `fork_context: false` job. Close each agent after integrating its result.
100
102
 
101
103
  ## Stop rules
@@ -190,7 +190,7 @@ describe("codex ultrawork hook", () => {
190
190
  expect(parsed.hookSpecificOutput.additionalContext).toMatch(/# Manual-QA channels/);
191
191
  expect(parsed.hookSpecificOutput.additionalContext).toMatch(/TESTS ALONE NEVER PROVE DONE/);
192
192
  expect(parsed.hookSpecificOutput.additionalContext).toMatch(/1\. HTTP call/);
193
- expect(parsed.hookSpecificOutput.additionalContext).toMatch(/2\. tmux/);
193
+ expect(parsed.hookSpecificOutput.additionalContext).toMatch(/2\. Terminal \/ TUI/);
194
194
  expect(parsed.hookSpecificOutput.additionalContext).toMatch(/3\. Browser use/);
195
195
  expect(parsed.hookSpecificOutput.additionalContext).toMatch(/4\. Computer use/);
196
196
  expect(parsed.hookSpecificOutput.additionalContext).toMatch(/CLEANUP \(PAIRED/);
@@ -244,6 +244,27 @@ describe("codex ultrawork hook", () => {
244
244
  expect(directive).toMatch(/WORKING:/);
245
245
  });
246
246
 
247
+ it("#given directive #when inspected #then blocks dependent work until spawned planners finish", () => {
248
+ // given
249
+ const payload = {
250
+ hook_event_name: "UserPromptSubmit",
251
+ prompt: "ulw",
252
+ };
253
+
254
+ // when
255
+ const output = runUserPromptSubmitHook(payload, { skillFilePath: null });
256
+ const parsed = parseHookOutput(output);
257
+
258
+ // then
259
+ const directive = parsed.hookSpecificOutput.additionalContext;
260
+ expect(directive).toMatch(/Subagent-dependent transition barrier/);
261
+ expect(directive).toMatch(/Spawn every independent child for the current wave first/);
262
+ expect(directive).toMatch(/After the wave\s+is launched[\s\S]{0,240}wait_agent[\s\S]{0,240}terminal status/);
263
+ expect(directive).not.toMatch(/Immediately after any `multi_agent_v1\.spawn_agent`/);
264
+ expect(directive).toMatch(/Do not start dependent implementation/);
265
+ expect(directive).toMatch(/Do not mark an `update_plan` step `completed`/);
266
+ });
267
+
247
268
  it("#given directive #when inspected #then keeps impact-proportional sizing invariants", () => {
248
269
  // given
249
270
  const payload = {
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## [0.1.0] - unreleased
4
4
 
5
+ - **Memory:** steering ledger entries no longer embed the full plan four times (`before`/`after` at both the audit and entry level). Accepted steers now record a compact `UlwLoopSteeringPlanSnapshot` (plan counters + only the goals the mutation touched), shrinking a measured real-world entry from 189KB to 7.8KB (~24x) and ending quadratic `ledger.jsonl` growth over long runs.
6
+ - **Memory:** steering dedup (`--idempotency-key` / `promptSignature`) streams the ledger line-by-line with a substring pre-filter instead of `JSON.parse`-ing every entry into memory; dedup returns strip legacy full-plan `before`/`after` payloads from re-surfaced audits. `readSteeringLedgerEntries` streams too.
7
+ - **Memory:** `withUlwLoopMutationLock` no longer retains the mutation result (full plan/audit) per `(repo, scope)` in its module-level lock map; settled gates self-evict, so long-lived embedders stop accumulating entries.
8
+ - **Fix:** `omo ulw-loop steer --idempotency-key` was parsed but never forwarded into the proposal, so CLI steers never deduped. It is now wired through.
5
9
  - Standalone ultrawork injection (`--with-ultrawork`) now emits the same compact bootstrap pointer as the ultrawork component (opener mandate, `create_goal` with `objective` only, read the bundled `ultrawork` skill at a runtime-resolved absolute path), falling back to the full bundled directive when the plugin skills tree is absent. Keeps the injected payload below Codex App's hook-output truncation budget (code-yeongyu/oh-my-openagent#5828).
6
10
  - Initial scaffold of codex-ulw-loop plugin.
7
11
  - Per-Criterion Cycle: `EXECUTE` is now **EXECUTE-AS-SCENARIO** — the agent must run the Manual-QA channel scenario the criterion named (HTTP call / tmux / browser use / computer use; see new `## Manual-QA channels` section). Inserted a new **CLEAN (PAIRED, NEVER SKIP)** step that tears down every QA-spawned process / `tmux` session / browser context / container / port / temp dir before recording evidence; the cleanup receipt is embedded in the `--evidence` string. Missing receipt → record BLOCKED, not PASS. Added Constraint #13 and a Stop Rule for leftover state.
@@ -49,9 +49,10 @@ exercises the surface; capture the artifact.
49
49
  1. HTTP call — hit the live endpoint with `curl -i` (or a
50
50
  Playwright APIRequestContext); capture status line + headers +
51
51
  body.
52
- 2. tmux `tmux new-session -d -s ulw-qa-<criterion>`, drive with
53
- `send-keys`, dump via `tmux capture-pane -pS -E -`; transcript
54
- is the artifact.
52
+ 2. Terminal / TUI - drive a real pty and prove it through the
53
+ xterm.js web terminal (see the TUI visual QA note below). tmux
54
+ `send-keys` is fine for a boot smoke; NEVER `tmux capture-pane`
55
+ for color / layout / CJK evidence, which degrades truecolor.
55
56
  3. Browser use — in Codex, use `browser:control-in-app-browser`
56
57
  first when available and no authenticated/persistent user browser
57
58
  profile is required. Otherwise use Chrome to drive the REAL page;
@@ -79,13 +80,13 @@ channel scenario when the behavior is user-facing. `--dry-run`,
79
80
  printing the command, "should respond", and "looks correct" never
80
81
  count.
81
82
 
82
- For TUI visual QA, terminal transcripts alone are not enough when a
83
- visual surface is being evaluated. In this repo, prefer
84
- `node script/qa/web-terminal-visual-qa.mjs --title "<surface>" --from-file <capture.txt> --evidence-dir <dir>`
85
- or the helper's `--command` tmux-backed PTY connector when available.
86
- Outside this repo, capture equivalent browser/computer-use rendered
87
- terminal evidence: screenshot, plain transcript, rendered HTML or action
88
- log, and cleanup receipt.
83
+ For TUI visual QA, render the terminal through the real xterm.js web
84
+ terminal and screenshot it - never a `tmux capture-pane` dump, which
85
+ degrades color and wide-glyph width. In this repo:
86
+ `node script/qa/web-terminal-visual-qa.mjs --title "<surface>" --command "<cmd>" --input "{Enter}" --evidence-dir <dir>`
87
+ (live pty + xterm.js in Chrome; `--from-file <capture>` replays a raw
88
+ stream). Outside this repo, capture equivalent browser-rendered terminal
89
+ evidence: screenshot + plain transcript + cleanup receipt.
89
90
 
90
91
  # Bootstrap (DO ALL FOUR BEFORE ANY OTHER WORK — NO SKIPPING)
91
92
 
@@ -258,6 +259,7 @@ Every `multi_agent_v1.spawn_agent` message is self-contained and starts with
258
259
  handoff. Use `fork_context: false` unless full history is truly
259
260
  required; paste only the context the child needs. Full-history forks can
260
261
  make the child continue old parent context instead of the delegated task.
262
+ If your tool list has a flat `spawn_agent` with a required `task_name` instead of `multi_agent_v1.*` (`multi_agent_v2`), rewrite: `fork_context: false` becomes `fork_turns: "none"`, `send_input` becomes `send_message`, finished agents end on their own (no `close_agent`; `followup_task` re-tasks, `interrupt_agent` stops), and `wait_agent` takes only `timeout_ms`, returning on any child mailbox activity.
261
263
 
262
264
  # TOML-backed subagent routing compatibility
263
265
  Treat TOML-backed role routing as **routing-unverified**. The
@@ -287,6 +289,13 @@ evidence for that step. Do not start dependent implementation until the
287
289
  audit, research, or review result is integrated or explicitly recorded
288
290
  as inconclusive. Do not generate a plan before spawned research lanes
289
291
  that feed the plan have returned or been closed as inconclusive.
292
+ Spawn every independent child for the current wave first. After the wave
293
+ is launched, run `multi_agent_v1.wait_agent` for each spawned child until
294
+ each reaches terminal status (`completed`, `failed`, `blocked`, or
295
+ explicitly recorded inconclusive) before any dependent `update_plan`
296
+ transition, `create_goal` continuation, implementation tool call, plan
297
+ drafting, approval-gate work, PR handoff, or final response. A timeout is
298
+ not terminal status.
290
299
  Do not write the final answer, PR handoff, or completion summary while
291
300
  active child agents remain open. Use short `multi_agent_v1.wait_agent` cycles.
292
301
  After two silent waits send `TASK STILL ACTIVE: return <deliverable> or
@@ -24,8 +24,8 @@ export async function ulwLoopCommand(argv) {
24
24
  const rest = argv.slice(1);
25
25
  const repoRoot = process.cwd();
26
26
  const json = hasFlag(rest, "--json");
27
- const scope = commandScope(rest);
28
27
  try {
28
+ const scope = commandScope(rest);
29
29
  if (!isUlwLoopSubcommand(command)) {
30
30
  if (json) {
31
31
  printJsonError(new UlwLoopError(`Unknown ulw-loop subcommand: ${command}.`, "ULW_LOOP_SUBCOMMAND_UNKNOWN", {
@@ -79,7 +79,20 @@ export async function ulwLoopCommand(argv) {
79
79
  function unhandledSubcommand(command) {
80
80
  throw new UlwLoopError(`Unhandled ulw-loop subcommand: ${String(command)}.`, "ULW_LOOP_SUBCOMMAND_UNHANDLED");
81
81
  }
82
+ const SESSION_ID_FLAG = "--session-id";
83
+ function sessionIdFlagPresent(argv) {
84
+ return hasFlag(argv, SESSION_ID_FLAG) || argv.some((arg) => arg.startsWith(`${SESSION_ID_FLAG}=`));
85
+ }
82
86
  function commandScope(argv) {
83
- const sessionId = readValue(argv, "--session-id") ?? resolveUlwLoopSessionIdFromEnv();
87
+ if (sessionIdFlagPresent(argv)) {
88
+ const sessionId = readValue(argv, SESSION_ID_FLAG)?.trim();
89
+ if (!sessionId) {
90
+ throw new UlwLoopError(`${SESSION_ID_FLAG} requires a non-empty value.`, "ULW_LOOP_SESSION_ID_REQUIRED", {
91
+ details: { flag: SESSION_ID_FLAG },
92
+ });
93
+ }
94
+ return { sessionId };
95
+ }
96
+ const sessionId = resolveUlwLoopSessionIdFromEnv();
84
97
  return sessionId === null ? undefined : { sessionId };
85
98
  }
@@ -83,7 +83,8 @@ function neverKind(kind) { return fail(`Unsupported steering kind: ${String(kind
83
83
  export async function parseSteeringProposal(argv) {
84
84
  const kind = parseSteeringKind(argv);
85
85
  const source = parseSteeringSource(argv);
86
- const base = { kind, source, evidence: required(argv, "--evidence"), rationale: required(argv, "--rationale") };
86
+ const idempotencyKey = text(readValue(argv, "--idempotency-key"), "--idempotency-key");
87
+ const base = { kind, source, evidence: required(argv, "--evidence"), rationale: required(argv, "--rationale"), ...(idempotencyKey === undefined ? {} : { idempotencyKey }) };
87
88
  switch (kind) {
88
89
  case "add_subgoal": return normalizeSteeringProposal({ ...base, title: required(argv, "--title"), objective: required(argv, "--objective") });
89
90
  case "split_subgoal": {