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

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 (268) hide show
  1. package/README.ja.md +1 -1
  2. package/README.ko.md +1 -1
  3. package/README.md +6 -5
  4. package/README.ru.md +1 -1
  5. package/README.zh-cn.md +1 -1
  6. package/bin/oh-my-opencode.js +14 -1
  7. package/bin/oh-my-opencode.test.ts +21 -0
  8. package/dist/cli/index.js +1452 -703
  9. package/dist/cli-node/index.js +1452 -703
  10. package/dist/config/schema/agent-overrides.d.ts +528 -0
  11. package/dist/config/schema/oh-my-opencode-config.d.ts +495 -0
  12. package/dist/features/monitor/batcher.d.ts +3 -1
  13. package/dist/features/monitor/manager-internals.d.ts +1 -0
  14. package/dist/features/monitor/output-injector-types.d.ts +2 -0
  15. package/dist/features/monitor/output-injector.d.ts +6 -0
  16. package/dist/hooks/todo-continuation-enforcer/types.d.ts +1 -0
  17. package/dist/hooks/todo-continuation-enforcer/unrecoverable-request-error.d.ts +9 -0
  18. package/dist/hooks/tool-pair-validator/hook.test-support.d.ts +29 -0
  19. package/dist/hooks/tool-pair-validator/tool-part-ids.d.ts +14 -5
  20. package/dist/hooks/tool-pair-validator/tool-result-repair.d.ts +4 -3
  21. package/dist/hooks/tool-pair-validator/types.d.ts +5 -22
  22. package/dist/index.js +2776 -2240
  23. package/dist/mcp/lsp.d.ts +1 -0
  24. package/dist/oh-my-opencode.schema.json +1466 -131
  25. package/dist/shared/tmux/constants.d.ts +1 -1
  26. package/dist/skills/ast-grep/SOURCE +1 -1
  27. package/dist/skills/ast-grep/install.ps1 +2 -2
  28. package/dist/skills/ast-grep/install.sh +1 -1
  29. package/dist/skills/ast-grep/references/install.md +2 -2
  30. package/dist/skills/ast-grep/tests/smoke.sh +1 -1
  31. package/dist/skills/start-work/SKILL.md +54 -9
  32. package/dist/skills/ultimate-browsing/SKILL.md +2 -2
  33. package/dist/skills/ultimate-browsing/engine/__main__.py +8 -1
  34. package/dist/skills/ultimate-browsing/engine/bias_check.py +11 -0
  35. package/dist/skills/ultimate-browsing/engine/fetch_chain.py +90 -52
  36. package/dist/skills/ultimate-browsing/engine/result_schema.py +10 -1
  37. package/dist/skills/ultimate-browsing/engine/surrogate.py +214 -0
  38. package/dist/skills/ultimate-browsing/engine/surrogates.yaml +60 -0
  39. package/dist/skills/ultimate-browsing/engine/tests/fixtures/amp_redirect_stub.html +7 -0
  40. package/dist/skills/ultimate-browsing/engine/tests/fixtures/search_interstitial.html +19 -0
  41. package/dist/skills/ultimate-browsing/engine/tests/fixtures/wayback_available.json +1 -0
  42. package/dist/skills/ultimate-browsing/engine/tests/fixtures/wayback_snapshot.html +1128 -0
  43. package/dist/skills/ultimate-browsing/engine/tests/test_surrogate.py +252 -0
  44. package/dist/skills/ultimate-browsing/engine/tests/test_surrogate_validators.py +78 -0
  45. package/dist/skills/ultimate-browsing/engine/validators.py +46 -0
  46. package/dist/skills/ultimate-browsing/engine/waf_detector.py +1 -1
  47. package/dist/skills/ultimate-browsing/engine/waf_profiles.yaml +10 -5
  48. package/dist/skills/ultimate-browsing/references/agent-reach/social.md +1 -1
  49. package/dist/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
  50. package/dist/skills/ultimate-browsing/references/insane-search/README.md +4 -4
  51. package/dist/skills/ultimate-browsing/references/insane-search/cache-archive.md +51 -50
  52. package/dist/skills/ultimate-browsing/references/insane-search/fallback.md +1 -1
  53. package/dist/skills/ultimate-browsing/references/insane-search/jina.md +8 -2
  54. package/dist/skills/ultimate-browsing/references/insane-search/naver.md +1 -1
  55. package/dist/skills/ultimate-browsing/references/insane-search/twitter.md +3 -3
  56. package/dist/skills/ulw-plan/SKILL.md +1 -1
  57. package/dist/skills/ulw-plan/references/full-workflow.md +3 -3
  58. package/dist/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
  59. package/dist/skills/ulw-research/SKILL.md +15 -10
  60. package/dist/tui.js +307 -28
  61. package/docs/reference/web-terminal-visual-qa.md +1 -1
  62. package/package.json +27 -19
  63. package/packages/lsp-core/src/lsp/connection.ts +1 -1
  64. package/packages/lsp-daemon/dist/cli.js +27 -13
  65. package/packages/lsp-daemon/dist/client.js +49 -35
  66. package/packages/lsp-daemon/dist/ensure-daemon.d.ts +1 -0
  67. package/packages/lsp-daemon/dist/ensure-daemon.js +18 -5
  68. package/packages/lsp-daemon/dist/index.js +34 -20
  69. package/packages/lsp-tools-mcp/dist/cli.js +1 -1
  70. package/packages/lsp-tools-mcp/dist/lsp/manager.js +1 -1
  71. package/packages/lsp-tools-mcp/dist/mcp.js +1 -1
  72. package/packages/lsp-tools-mcp/dist/tools.js +1 -1
  73. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  74. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +268 -92
  75. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  76. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  77. package/packages/omo-codex/plugin/components/bootstrap/src/setup.ts +7 -7
  78. package/packages/omo-codex/plugin/components/bootstrap/src/worker.ts +3 -0
  79. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +106 -6
  80. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +106 -6
  81. package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
  82. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  83. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  84. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  85. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  86. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  87. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  88. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
  89. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +56 -42
  90. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  91. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  92. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  93. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  94. package/packages/omo-codex/plugin/components/start-work-continuation/AGENTS.md +1 -0
  95. package/packages/omo-codex/plugin/components/start-work-continuation/README.md +5 -1
  96. package/packages/omo-codex/plugin/components/start-work-continuation/directive.md +2 -1
  97. package/packages/omo-codex/plugin/components/start-work-continuation/dist/cli.js +18 -0
  98. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  99. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  100. package/packages/omo-codex/plugin/components/start-work-continuation/src/codex-hook.ts +21 -0
  101. package/packages/omo-codex/plugin/components/start-work-continuation/test/codex-hook.test.ts +105 -0
  102. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  103. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  104. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  105. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  106. package/packages/omo-codex/plugin/components/ultrawork/CHANGELOG.md +2 -0
  107. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-code-reviewer.toml +1 -1
  108. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-gate-reviewer.toml +1 -1
  109. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-qa-executor.toml +1 -1
  110. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-high.toml +1 -1
  111. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-low.toml +1 -1
  112. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-medium.toml +1 -1
  113. package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +2 -2
  114. package/packages/omo-codex/plugin/components/ultrawork/directive.md +3 -2
  115. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  116. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  117. package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +3 -2
  118. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +1 -1
  119. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +3 -3
  120. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
  121. package/packages/omo-codex/plugin/components/ulw-loop/AGENTS.md +1 -1
  122. package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +2 -0
  123. package/packages/omo-codex/plugin/components/ulw-loop/README.md +11 -11
  124. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +3 -2
  125. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.js +1 -1
  126. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +1 -1
  127. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +9 -9
  128. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.js +1 -1
  129. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +66 -66
  130. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +4 -4
  131. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-hook.js +1 -1
  132. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.js +1 -1
  133. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +1 -1
  134. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering.js +1 -1
  135. package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +2 -2
  136. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  137. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  138. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +3 -3
  139. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +22 -25
  140. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-reconciliation.ts +1 -1
  141. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +9 -9
  142. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-steering.ts +1 -1
  143. package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +1 -1
  144. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +4 -4
  145. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-hook.ts +1 -1
  146. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-crud.ts +1 -1
  147. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +1 -1
  148. package/packages/omo-codex/plugin/components/ulw-loop/src/steering.ts +1 -1
  149. package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +2 -2
  150. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-commands.test.ts +2 -2
  151. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-entrypoint.test.ts +1 -1
  152. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-helpers.test.ts +2 -2
  153. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-steering-kind-guidance.test.ts +1 -1
  154. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-hook.test.ts +2 -2
  155. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/quality-gate-builder.ts +1 -1
  156. package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +5 -5
  157. package/packages/omo-codex/plugin/components/ulw-loop/test/plan-io.test.ts +1 -1
  158. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-roles.test.ts +1 -1
  159. package/packages/omo-codex/plugin/components/ulw-loop/test/steering.test.ts +1 -1
  160. package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +1 -1
  161. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  162. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  163. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  164. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  165. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  166. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  167. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  168. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  169. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  170. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  171. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  172. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  173. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  174. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  175. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  176. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  177. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
  178. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  179. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
  180. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  181. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  182. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  183. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  184. package/packages/omo-codex/plugin/package-lock.json +13 -13
  185. package/packages/omo-codex/plugin/package.json +1 -1
  186. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +4 -4
  187. package/packages/omo-codex/plugin/skills/ast-grep/SOURCE +1 -1
  188. package/packages/omo-codex/plugin/skills/ast-grep/install.ps1 +2 -2
  189. package/packages/omo-codex/plugin/skills/ast-grep/install.sh +1 -1
  190. package/packages/omo-codex/plugin/skills/ast-grep/references/install.md +2 -2
  191. package/packages/omo-codex/plugin/skills/ast-grep/tests/smoke.sh +1 -1
  192. package/packages/omo-codex/plugin/skills/start-work/SKILL.md +54 -9
  193. package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +2 -2
  194. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/__main__.py +8 -1
  195. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/bias_check.py +11 -0
  196. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/fetch_chain.py +90 -52
  197. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/result_schema.py +10 -1
  198. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/surrogate.py +214 -0
  199. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/surrogates.yaml +60 -0
  200. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/amp_redirect_stub.html +7 -0
  201. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/search_interstitial.html +19 -0
  202. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/wayback_available.json +1 -0
  203. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/wayback_snapshot.html +1128 -0
  204. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_surrogate.py +252 -0
  205. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_surrogate_validators.py +78 -0
  206. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/validators.py +46 -0
  207. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/waf_detector.py +1 -1
  208. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/waf_profiles.yaml +10 -5
  209. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/agent-reach/social.md +1 -1
  210. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
  211. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +4 -4
  212. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/cache-archive.md +51 -50
  213. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/fallback.md +1 -1
  214. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/jina.md +8 -2
  215. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/naver.md +1 -1
  216. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/twitter.md +3 -3
  217. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +3 -2
  218. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +3 -3
  219. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +22 -25
  220. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +1 -1
  221. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +3 -3
  222. package/packages/omo-codex/plugin/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
  223. package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +15 -10
  224. package/packages/omo-codex/plugin/test/bootstrap-binlinks.test.mjs +12 -12
  225. package/packages/omo-codex/plugin/test/bootstrap-orchestration.test.mjs +36 -4
  226. package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +1 -1
  227. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +4 -4
  228. package/packages/omo-codex/scripts/install-bin-links.test.mjs +56 -2
  229. package/packages/omo-codex/scripts/install-delegated-command.test.mjs +6 -6
  230. package/packages/omo-codex/scripts/install-dist/install-local.mjs +115 -61
  231. package/packages/omo-codex/scripts/install-local-entrypoint.test.mjs +4 -4
  232. package/packages/omo-codex/scripts/install-local.test.mjs +5 -2
  233. package/packages/shared-skills/index.mjs +19 -1
  234. package/packages/shared-skills/skills/ast-grep/SOURCE +1 -1
  235. package/packages/shared-skills/skills/ast-grep/install.ps1 +2 -2
  236. package/packages/shared-skills/skills/ast-grep/install.sh +1 -1
  237. package/packages/shared-skills/skills/ast-grep/references/install.md +2 -2
  238. package/packages/shared-skills/skills/ast-grep/tests/smoke.sh +1 -1
  239. package/packages/shared-skills/skills/start-work/SKILL.md +54 -9
  240. package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +2 -2
  241. package/packages/shared-skills/skills/ultimate-browsing/engine/__main__.py +8 -1
  242. package/packages/shared-skills/skills/ultimate-browsing/engine/bias_check.py +11 -0
  243. package/packages/shared-skills/skills/ultimate-browsing/engine/fetch_chain.py +90 -52
  244. package/packages/shared-skills/skills/ultimate-browsing/engine/result_schema.py +10 -1
  245. package/packages/shared-skills/skills/ultimate-browsing/engine/surrogate.py +214 -0
  246. package/packages/shared-skills/skills/ultimate-browsing/engine/surrogates.yaml +60 -0
  247. package/packages/shared-skills/skills/ultimate-browsing/engine/tests/fixtures/amp_redirect_stub.html +7 -0
  248. package/packages/shared-skills/skills/ultimate-browsing/engine/tests/fixtures/search_interstitial.html +19 -0
  249. package/packages/shared-skills/skills/ultimate-browsing/engine/tests/fixtures/wayback_available.json +1 -0
  250. package/packages/shared-skills/skills/ultimate-browsing/engine/tests/fixtures/wayback_snapshot.html +1128 -0
  251. package/packages/shared-skills/skills/ultimate-browsing/engine/tests/test_surrogate.py +252 -0
  252. package/packages/shared-skills/skills/ultimate-browsing/engine/tests/test_surrogate_validators.py +78 -0
  253. package/packages/shared-skills/skills/ultimate-browsing/engine/validators.py +46 -0
  254. package/packages/shared-skills/skills/ultimate-browsing/engine/waf_detector.py +1 -1
  255. package/packages/shared-skills/skills/ultimate-browsing/engine/waf_profiles.yaml +10 -5
  256. package/packages/shared-skills/skills/ultimate-browsing/references/agent-reach/social.md +1 -1
  257. package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
  258. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +4 -4
  259. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/cache-archive.md +51 -50
  260. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/fallback.md +1 -1
  261. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/jina.md +8 -2
  262. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/naver.md +1 -1
  263. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/twitter.md +3 -3
  264. package/packages/shared-skills/skills/ulw-plan/SKILL.md +1 -1
  265. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +3 -3
  266. package/packages/shared-skills/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
  267. package/packages/shared-skills/skills/ulw-research/SKILL.md +15 -10
  268. package/postinstall.mjs +6 -0
@@ -1,46 +1,50 @@
1
- # 캐시 & 아카이브
1
+ # 캐시 & 아카이브 (surrogate 경로)
2
2
 
3
- > 원본 사이트가 차단되었을 때 캐시된/아카이브된 버전으로 접근.
4
- > Google Cache는 2024년 7월 종료됨 AMP 캐시와 archive.today가 대체.
3
+ > 원본 사이트가 차단되었을 때 캐시/아카이브된 **사본**으로 접근.
4
+ > 2026-08-09 실측 probe 기준으로 정렬. 경로는 생명 주기가 짧다 — 이 파일도
5
+ > 90일마다 재검증 대상. (당일 probe: 기존 기대 경로 6개 중 4개 사망 또는 스텁 반환.)
5
6
 
6
7
  ## 의존성
7
8
 
8
- 없음 (curl만 사용).
9
+ 없음 (curl만 사용). 수동 경로이며, 자동화는 엔진 Phase 2.5(`engine/surrogates.yaml`)가 담당한다.
9
10
 
10
- ## 1. Google AMP 캐시
11
+ ## 엔진 자동 폴백 (Phase 2.5)
11
12
 
12
- AMP 지원 사이트의 캐시 버전. 뉴스/미디어 사이트에 효과적.
13
+ `waf_profiles.yaml`의 `fallback_when_challenge`가 `surrogate_wayback`을 앞에 두므로,
14
+ 그리드 실패 후 브라우저 실행 전에 아카이브 경로를 먼저 시도한다.
15
+ 성공 시 `FetchResult.provenance = "snapshot"`, `snapshot_timestamp` = 아카이브의 자체 타임스탬프,
16
+ `trust = "archive"`가 채워진다. **사본이므로 반드시 날짜와 함께 인용할 것.**
17
+ `--allow-proxy` 없이는 `kind: proxy` 엔트리는 절대 실행되지 않으며, 프록시에는
18
+ Cookie/Authorization 헤더를 보내지 않는다 (중계자 = 구조적 MITM).
19
+
20
+ ## 1. Wayback Machine (Internet Archive) — 1순위
21
+
22
+ **2026-08-09 probe: 정상 동작.** `available` API가 200 JSON으로 스냅샷 URL과
23
+ 타임스탬프를 돌려준다 — 출처(provenance) 확보에 가장 좋은 primitive.
13
24
 
14
25
  ```bash
15
- # URL 변환: domain의 .을 -로 cdn.ampproject.org
16
- # 예: www.bbc.com → www-bbc-com.cdn.ampproject.org
17
-
18
- python3 -c "
19
- from urllib.parse import urlparse
20
- url = '{URL}'
21
- p = urlparse(url)
22
- domain_sub = p.netloc.replace('.', '-')
23
- print(f'https://{domain_sub}.cdn.ampproject.org/c/s/{p.netloc}{p.path}')
24
- "
25
-
26
- # 변환된 URL로 접근
27
- curl -sL "https://{domain-with-dashes}.cdn.ampproject.org/c/s/{netloc}{path}"
26
+ # 스냅샷 존재 여부 + 최신 스냅샷 URL/타임스탬프 (진입점으로 이것을 쓸 것)
27
+ curl -sL "https://archive.org/wayback/available?url={URL}"
28
+
29
+ # 반환 JSON의 archived_snapshots.closest.url 로 접근
30
+ curl -sL "https://web.archive.org/web/{timestamp}/{URL}"
28
31
  ```
29
32
 
30
- **성공 조건**: 사이트가 AMP 페이지를 제공하는 경우 (대부분의 뉴스/미디어)
31
- **실패 조건**: AMP 미지원 사이트, 매우 최신 콘텐츠 (캐시 지연 ~15초)
33
+ > **CDX API 주의**: 이전 버전이 권장하던 `web.archive.org/cdx/search/cdx`는
34
+ > 2026-08 probe에서 503 반환. 스냅샷 열거가 필요 없으면 `available` API만 사용.
32
35
 
33
- ## 2. archive.today
36
+ **성공 조건**: 크롤링 대상이었던 공개 URL
37
+ **실패 조건**: robots.txt로 차단된 사이트, 스냅샷이 없는 URL, SPA 스냅샷 (렌더링 안 됨)
38
+
39
+ ## 2. archive.today — 2순위
34
40
 
35
41
  사용자 제출 아카이브. 페이월 기사, 삭제된 콘텐츠에 특히 유용.
36
- 도메인이 여러 하나가 차단되면 다른 사용.
42
+ **2026-08 probe: 429 rate-limit이 잦고 도메인이 수시로 회전** (archive.ph → archive.md 관찰).
43
+ 하나가 차단되면 다른 도메인을 순회한다 (엔진 `host_rotation`과 동일 패턴).
37
44
 
38
45
  ```bash
39
- # 최신 스냅샷 조회
40
- curl -sL "https://archive.ph/newest/{URL}"
41
-
42
- # 도메인 로테이션 (하나가 차단되면 다른 것)
43
- for domain in archive.ph archive.is archive.md archive.vn archive.li; do
46
+ # 최신 스냅샷 조회 — 도메인 회전은 필수 경로, 예외 처리 아님
47
+ for domain in archive.ph archive.md archive.li archive.is; do
44
48
  resp=$(curl -sL -o /dev/null -w "%{http_code}" "https://$domain/newest/{URL}")
45
49
  if [ "$resp" = "200" ] || [ "$resp" = "302" ]; then
46
50
  echo "성공: https://$domain/newest/{URL}"
@@ -50,34 +54,31 @@ for domain in archive.ph archive.is archive.md archive.vn archive.li; do
50
54
  done
51
55
  ```
52
56
 
53
- **성공 조건**: 누군가 이전에 해당 URL을 아카이브한 경우
54
- **실패 조건**: 아카이브된 적 없는 URL
57
+ **주의**: 429 응답에도 KB 본문이 딸려 오므로 상태코드 대신 본문 검증이 필요하다.
55
58
 
56
- ## 3. Wayback Machine (Internet Archive)
59
+ ## 3. AMP 캐시 — 강등 (사실상 무용)
57
60
 
58
- ```bash
59
- # 스냅샷 존재 여부 확인
60
- curl -sL "https://archive.org/wayback/available?url={URL}"
61
-
62
- # 최신 스냅샷으로 접근
63
- curl -sL "https://web.archive.org/web/{URL}"
61
+ 과거 1순위였으나 **2026-08 probe에서 사실상 무력화**:
62
+ `{host}.cdn.ampproject.org/c/s/...`가 HTTP 200을 돌려주지만, 실제 본문은
63
+ **322바이트짜리 `<TITLE>Redirecting</TITLE>` meta-refresh** — 대상은 다시 **원본(차단된) 페이지**다.
64
+ 이걸 성공으로 착각하면 에이전트가 차단 페이지로 되돌아가는 루프가 생긴다.
64
65
 
65
- # CDX API 스냅샷 목록 조회
66
- curl -sL "https://web.archive.org/cdx/search/cdx?url={URL}&output=json&fl=timestamp,statuscode&limit=5"
67
- ```
68
-
69
- **성공 조건**: 크롤링 대상이었던 공개 URL
70
- **실패 조건**: robots.txt로 차단된 사이트, SPA (렌더링 안 됨), iframe 기반 사이트
66
+ 엔진은 `engine/validators.py:is_redirect_stub`으로 패턴을 CHALLENGE 판정한다
67
+ (3KB 미만 + meta-refresh/JS redirect + 대상 호스트 재등장 조합).
68
+ 수동 사용도 권장하지 않는다.
71
69
 
72
- ## 4. Google Cache (종료됨)
70
+ ## 4. Google Cache — 사망 확정
73
71
 
74
- > **2024년 7월 종료.** `webcache.googleusercontent.com`은 이상 동작하지 않음.
75
- > 대신 AMP 캐시 또는 archive.today를 사용.
72
+ **2024년 7월 종료** 후로도 `webcache.googleusercontent.com`이 HTTP 200 + 수십 KB의
73
+ 본문을 반환하지만, 실제로는 `<title>Google Search</title>` 인터스티셜 + JS 리다이렉트다
74
+ (2026-08 probe 재확인). **캐시가 아니라 검색 홈이다.**
75
+ 엔진은 `INTERSTITIAL_TITLE_MARKERS`로 판정해 성공 집계에서 배제한다.
76
76
 
77
- ## 시도 순서
77
+ ## 시도 순서 (probe 근거)
78
78
 
79
79
  ```
80
- 1. AMP 캐시 (뉴스/미디어 사이트 높은 성공률)
81
- 2. archive.today (페이월/삭제 콘텐츠 아카이브 있으면 확실)
82
- 3. Wayback Machine (오래된 콘텐츠스냅샷 있으면 확실)
80
+ 1. Wayback available API스냅샷 URL + 타임스탬프 (provenance까지 확보)
81
+ 2. archive.today 도메인 회전 (429 대비, 본문 검증 필수)
82
+ 3. AMP 캐시: 시도하지 않음 (redirect stub원본으로 회귀)
83
+ 4. Google Cache: 시도하지 않음 (사망, 검색 인터스티셜 반환)
83
84
  ```
@@ -141,7 +141,7 @@ browser_evaluate → () => document.body.innerText (Light Mode — 먼저)
141
141
 
142
142
  | 패턴 | 감지 방법 | 처리 |
143
143
  |------|----------|------|
144
- | X SPA 셸 (247KB) | 200 OK + `Sign in to X` 또는 `hasResults: false` | 실패 — WebSearch+oEmbed 폴백 |
144
+ | X SPA 셸 (247KB) | 200 OK + `Sign in to X` 또는 `hasResults: false` | 실패 — 웹 검색 도구+oEmbed 폴백 |
145
145
  | CAPTCHA 페이지 | 200 OK + `captcha\|recaptcha\|hcaptcha\|cf-turnstile` | 실패 — 다음 Phase |
146
146
  | 소프트 페이월 | 200 OK + `member-only\|subscribe to read\|구독하세요` | 부분 성공 — 메타만 채택 |
147
147
  | DDG 소프트 리밋 | 202 Accepted + body 15KB 미만 | 실패 — 다른 엔진 폴백 |
@@ -2,12 +2,18 @@
2
2
 
3
3
  > `r.jina.ai/URL` 한 줄로 거의 모든 공개 URL을 마크다운으로 변환.
4
4
  > Puppeteer 기반 실제 브라우저 렌더링 — JS SPA까지 처리.
5
- > **API 키 불필요. 무료: 분당 500 RPM.**
5
+ >
6
+ > **2026-08-09 probe 기준 무료 무키 경로는 종료됨.** 익명 호출은 401이며,
7
+ > 리다이렉트를 따라가면 Cloudflare Turnstile(`Just a moment...`)에 막힌다.
8
+ > **이제 `JINA_API_KEY` 환경 변수가 필요**하다 — `Authorization: Bearer <key>` 헤더.
9
+ > 엔진에서는 `engine/surrogates.yaml`의 `jina_reader` 엔트리가 키가 있을 때만 활성화된다
10
+ > (kind=reader, provenance=live — 서버 측 재렌더링).
11
+ > 예전 "무료 500 RPM" 안내는 모두 폐기되었으므로 따르지 않는다.
6
12
 
7
13
  ## 기본 사용
8
14
 
9
15
  ```bash
10
- curl -s "https://r.jina.ai/{URL}"
16
+ curl -s -H "Authorization: Bearer ${JINA_API_KEY}" "https://r.jina.ai/{URL}"
11
17
  ```
12
18
 
13
19
  ## 고급 기능
@@ -90,7 +90,7 @@ r = s.get(f"https://search.naver.com/search.naver?where=news&query={quote('검
90
90
 
91
91
  ### 한국어 키워드 검색의 핵심 경로
92
92
 
93
- WebSearch는 한국어 신규 콘텐츠 인덱싱이 지연되지만, 네이버 검색은 한국어에 최적화되어 있다.
93
+ 검색 도구는 한국어 신규 콘텐츠 인덱싱이 지연되지만, 네이버 검색은 한국어에 최적화되어 있다.
94
94
  **한국 사이트 키워드 검색 → 네이버 검색 직접 접근이 가장 정확하고 빠르다.**
95
95
 
96
96
  ## 네이버 카페
@@ -5,10 +5,10 @@
5
5
  ## 검색 (트윗 발견)
6
6
 
7
7
  ```python
8
- WebSearch(query="site:x.com {검색어}")
8
+ <사용 가능한 web search tool>(query="site:x.com {검색어}") # Claude Code: WebSearch / OpenCode 계열: websearch_web_search_exa 등 — 하네스마다 실제 tool 이름이 다르므로 현재 세션의 tool 목록에서 확인할 것
9
9
  ```
10
10
 
11
- WebSearch는 X 포스트를 검색 결과로 반환한다. 제목, snippet, URL을 획득할 수 있지만 트윗 전문이나 engagement 수치는 없다.
11
+ 검색 도구는 X 포스트를 검색 결과로 반환한다. 제목, snippet, URL을 획득할 수 있지만 트윗 전문이나 engagement 수치는 없다.
12
12
 
13
13
  ## 타임라인 조회 — Syndication API
14
14
 
@@ -89,7 +89,7 @@ curl -sL "https://publish.twitter.com/oembed?url=https://x.com/{user}/status/{tw
89
89
  ## 조합 패턴 (검색 → 상세)
90
90
 
91
91
  ```
92
- 1단계: WebSearch(query="site:x.com {키워드}") → 트윗 URL 획득
92
+ 1단계: 웹 검색 도구(query="site:x.com {키워드}") → 트윗 URL 획득
93
93
  2단계: curl oEmbed API → 트윗 전문 획득
94
94
  ```
95
95
 
@@ -242,8 +242,9 @@ library/API/docs/web — delegate to the `librarian` subagent. Spawn them
242
242
  # Execution loop (PIN → RED → GREEN → SURFACE → CLEAN)
243
243
  Until every success criterion PASSES with its evidence captured:
244
244
  1. Pick next criterion → mark in_progress → update notepad `## Now`.
245
- 2. PIN + RED: when touching existing behavior, first pin it with a
246
- characterization test that passes on the unchanged code. Then
245
+ 2. PIN + RED: when refactoring behavior whose regressions the change
246
+ could hide, first pin it with a characterization test that passes on
247
+ the unchanged code. Then
247
248
  capture the failing-first proof through the cheapest faithful
248
249
  channel — a unit test where a seam exists, an integration/e2e test
249
250
  where the behavior lives in wiring, or the criterion's real-surface
@@ -20,9 +20,9 @@ This skill is intentionally compact. The full workflow lives in `references/full
20
20
  ## Non-Negotiables
21
21
 
22
22
  - Use the ulw-loop CLI state under `.omo/ulw-loop`; do not hand-edit goal state.
23
- - Register goals up front (`omo ulw-loop create-goals`, then `create_goal` from the printed handoff) and mirror every atomic step into the live `update_plan` checklist: one ultra-granular step per action, exactly one in_progress, transitions marked the instant they happen.
24
- - After any compaction or context loss, re-read brief + goals + ledger FIRST plus `omo ulw-loop status --json`, then resume; never re-plan from scratch.
25
- - If `omo ulw-loop create-goals` says the existing aggregate is already complete, start unrelated new work with a fresh `--session-id <new-id>` instead of steering or forcing the completed default state. Use `--force` only to intentionally overwrite completed evidence.
23
+ - Register goals up front (`omo-agent-toolkit ulw-loop create-goals`, then `create_goal` from the printed handoff) and mirror every atomic step into the live `update_plan` checklist: one ultra-granular step per action, exactly one in_progress, transitions marked the instant they happen.
24
+ - After any compaction or context loss, re-read brief + goals + ledger FIRST plus `omo-agent-toolkit ulw-loop status --json`, then resume; never re-plan from scratch.
25
+ - If `omo-agent-toolkit ulw-loop create-goals` says the existing aggregate is already complete, start unrelated new work with a fresh `--session-id <new-id>` instead of steering or forcing the completed default state. Use `--force` only to intentionally overwrite completed evidence.
26
26
  - Every success criterion needs observable evidence from a real surface: a channel (terminal/TUI via the xterm.js web terminal, HTTP, browser, computer-use) or, for CLI- or data-shaped criteria, an auxiliary surface (CLI stdout, DB diff, parsed config dump).
27
27
  - Evidence is bound to the tree it was captured at (`git rev-parse --short "HEAD^{tree}"`); it goes stale only when tracked content changes — a rebase or amend that keeps the tree identical keeps it valid. When the tree differs, re-run at the current HEAD and re-record, never relabel or regenerate. Record only after cleanup receipts exist.
28
28
  - Delegate code edits, test writes, fixes, and QA execution to right-sized Codex subagents when the workflow requires it.
@@ -66,8 +66,8 @@ Codex subagent reliability:
66
66
  - `.omo/ulw-loop/goals.json`: goals with embedded `successCriteria` per goal.
67
67
  - `.omo/ulw-loop/ledger.jsonl`: append-only audit trail.
68
68
  - Read artifacts before resuming, steering, or checkpointing.
69
- - After compaction or context loss, re-read brief + goals + ledger FIRST, then `omo ulw-loop status --json`. Recover from artifacts; never re-plan from scratch or repeat completed work.
70
- - Never invent state outside `.omo/ulw-loop` artifacts or `omo ulw-loop status --json`.
69
+ - After compaction or context loss, re-read brief + goals + ledger FIRST, then `omo-agent-toolkit ulw-loop status --json`. Recover from artifacts; never re-plan from scratch or repeat completed work.
70
+ - Never invent state outside `.omo/ulw-loop` artifacts or `omo-agent-toolkit ulw-loop status --json`.
71
71
 
72
72
  ## Bootstrap
73
73
  Do all three steps before execution. No edits, goal tools, or checkpointing before bootstrap completes.
@@ -86,10 +86,10 @@ if [ -z "$ULW_LOOP_NODE" ]; then
86
86
  fi
87
87
 
88
88
  ULW_LOOP_CLI=
89
- if command -v omo >/dev/null 2>&1 && omo ulw-loop help >/dev/null 2>&1; then
90
- ULW_LOOP_CLI=omo
89
+ if command -v omo-agent-toolkit >/dev/null 2>&1 && omo-agent-toolkit ulw-loop help >/dev/null 2>&1; then
90
+ ULW_LOOP_CLI=omo-agent-toolkit
91
91
  elif [ -n "$ULW_LOOP_NODE" ]; then
92
- for candidate in "$HOME/.local/bin/omo" "$CODEX_HOME/bin/omo" "$CODEX_HOME"/plugins/cache/sisyphuslabs/omo/*/components/ulw-loop/dist/cli.js; do
92
+ for candidate in "$HOME/.local/bin/omo-agent-toolkit" "$CODEX_HOME/bin/omo-agent-toolkit" "$CODEX_HOME"/plugins/cache/sisyphuslabs/omo/*/components/ulw-loop/dist/cli.js; do
93
93
  [ -f "$candidate" ] || [ -x "$candidate" ] || continue
94
94
  if "$ULW_LOOP_NODE" "$candidate" ulw-loop help >/dev/null 2>&1; then
95
95
  ULW_LOOP_CLI="$candidate"
@@ -97,15 +97,12 @@ elif [ -n "$ULW_LOOP_NODE" ]; then
97
97
  fi
98
98
  done
99
99
 
100
- if [ -n "$ULW_LOOP_CLI" ] && [ -n "$ULW_LOOP_NODE" ]; then
101
- omo() { "$ULW_LOOP_NODE" "$ULW_LOOP_CLI" "$@"; }
102
- fi
103
100
  fi
104
101
 
105
102
  if [ -z "${ULW_LOOP_CLI:-}" ]; then
106
103
  /bin/mkdir -p .omo/ulw-loop 2>/dev/null || mkdir -p .omo/ulw-loop 2>/dev/null || true
107
104
  NOTE="${NOTE:-.omo/ulw-loop/bootstrap-notepad.md}"
108
- printf '%s\n' "No ulw-loop-capable omo executable found; PATH omo may be the OpenCode CLI without the Codex ulw-loop subcommand, and cached ulw-loop CLI was not found under ${CODEX_HOME:-$HOME/.codex}." >> "$NOTE" 2>/dev/null || true
105
+ printf '%s\n' "No ulw-loop-capable omo-agent-toolkit executable found; PATH omo-agent-toolkit may lack the Codex ulw-loop subcommand, and cached ulw-loop CLI was not found under ${CODEX_HOME:-$HOME/.codex}." >> "$NOTE" 2>/dev/null || true
109
106
  printf '%s\n' "Install with npx lazycodex-ai install or set CODEX_LOCAL_BIN_DIR to a PATH directory." >&2
110
107
  fi
111
108
  ```
@@ -113,13 +110,13 @@ If `ULW_LOOP_CLI` is empty, open the durable notepad first, record the missing C
113
110
 
114
111
  Run one form:
115
112
  ```sh
116
- omo ulw-loop create-goals --brief "<brief>" [--validation-batch-json <json-or-path>] --json
117
- omo ulw-loop create-goals --brief-file <path> [--validation-batch-json <json-or-path>] --json
118
- cat <brief> | omo ulw-loop create-goals --from-stdin [--validation-batch-json <json-or-path>] --json
113
+ omo-agent-toolkit ulw-loop create-goals --brief "<brief>" [--validation-batch-json <json-or-path>] --json
114
+ omo-agent-toolkit ulw-loop create-goals --brief-file <path> [--validation-batch-json <json-or-path>] --json
115
+ cat <brief> | omo-agent-toolkit ulw-loop create-goals --from-stdin [--validation-batch-json <json-or-path>] --json
119
116
  ```
120
117
  If the existing aggregate is already complete, do not steer or force the
121
118
  completed default state for unrelated new work. Start a fresh run with
122
- `omo ulw-loop create-goals --session-id <new-id> ...`; use `--force`
119
+ `omo-agent-toolkit ulw-loop create-goals --session-id <new-id> ...`; use `--force`
123
120
  only when deliberately overwriting completed evidence.
124
121
  Write state through the CLI path. Do not hand-edit state files.
125
122
 
@@ -138,14 +135,14 @@ Use channel-table evidence verbs — not vibes.
138
135
  Revise any criterion that lacks observable `expectedEvidence` or a named channel before execution.
139
136
 
140
137
  ### 3. Inspect state
141
- Run `omo ulw-loop status --json`.
138
+ Run `omo-agent-toolkit ulw-loop status --json`.
142
139
  Read pending goals, criteria IDs, current ledger head, blockers, and aggregate Codex objective.
143
140
 
144
141
  ## Execution Loop
145
142
  Loop per goal. Cap at 5 cycles per goal. Cap identical same-criterion failures at 3.
146
143
 
147
144
  ### Acquire Next Goal
148
- 1. Run `omo ulw-loop complete-goals --json` and read the handoff, including criteria. After the first goal starts, a successful complete checkpoint normally prints the next goal instruction directly; use `complete-goals` as the manual fallback/resume path.
145
+ 1. Run `omo-agent-toolkit ulw-loop complete-goals --json` and read the handoff, including criteria. After the first goal starts, a successful complete checkpoint normally prints the next goal instruction directly; use `complete-goals` as the manual fallback/resume path.
149
146
  2. Call `get_goal` and inspect active Codex state.
150
147
  3. Apply this table exactly:
151
148
 
@@ -154,7 +151,7 @@ Loop per goal. Cap at 5 cycles per goal. Cap identical same-criterion failures a
154
151
  | no active goal | You MUST call `create_goal` — goal registration goes through the tool, never prose — with objective only from `instruction.json.objective`; do not copy lifecycle fields such as `status`. |
155
152
  | same aggregate objective active | Continue the current ulw-loop story. |
156
153
  | different goal active | STOP. Checkpoint blocked and surface the conflict. |
157
- 4. If retrying failed work, run `omo ulw-loop complete-goals --retry-failed --json`.
154
+ 4. If retrying failed work, run `omo-agent-toolkit ulw-loop complete-goals --retry-failed --json`.
158
155
  5. Never create a second Codex goal for the same aggregate objective.
159
156
 
160
157
  ### Per-Criterion Cycle
@@ -166,9 +163,9 @@ Loop per goal. Cap at 5 cycles per goal. Cap identical same-criterion failures a
166
163
  6. CAPTURE: collect the observable artifact path: transcript, stdout, screenshot, assertion, status+body, diff, or parsed dump. No artifact written at the evidence path — not done; record BLOCKED and respawn QA.
167
164
  7. CLEAN (PAIRED, NEVER SKIP): tear down every runtime artifact step 5 spawned BEFORE recording — server PIDs (`kill`, verify `kill -0` fails), `tmux` sessions (`tmux kill-session -t ulw-qa-<criterion>`; confirm `tmux ls`), browser / Playwright contexts (`.close()`), containers (`docker rm -f`), bound ports (`lsof -i :<port>` empty), temp sockets / files / dirs (`rm -rf` the `mktemp` paths), QA-only env vars, AND close every finished worker (v1 `close_agent`; on V2 finished workers end on their own — `interrupt_agent` any still running). Register each teardown as its own todo the moment the QA spawns the resource (scripts, tmux assets, browsers / agent-browser sessions, PIDs, ports) so none is forgotten. Embed a one-line cleanup receipt in the evidence string, e.g. `cleanup: killed 12345; tmux kill-session ulw-qa-foo; rm -rf /tmp/ulw.aB12cD; interrupt_agent w-3`. Missing receipt → record BLOCKED, not PASS.
168
165
  8. RECORD one result immediately from the artifact you just wrote — never from memory or a later turn — stamping the capture tree `$(git rev-parse --short "HEAD^{tree}")` into the evidence:
169
- - PASS: `omo ulw-loop record-evidence --goal-id <id> --criterion-id <id> --status pass --evidence "<observable> @tree:<short-tree> | <cleanup receipt>" --json`
170
- - FAIL: `omo ulw-loop record-evidence --goal-id <id> --criterion-id <id> --status fail --evidence "<observable> @tree:<short-tree> | <cleanup receipt>" --notes "<diagnosis>" --json`
171
- - BLOCKED: `omo ulw-loop record-evidence --goal-id <id> --criterion-id <id> --status blocked --evidence "<observable>" --notes "<safety/blocker/leftover-state>" --json`
166
+ - PASS: `omo-agent-toolkit ulw-loop record-evidence --goal-id <id> --criterion-id <id> --status pass --evidence "<observable> @tree:<short-tree> | <cleanup receipt>" --json`
167
+ - FAIL: `omo-agent-toolkit ulw-loop record-evidence --goal-id <id> --criterion-id <id> --status fail --evidence "<observable> @tree:<short-tree> | <cleanup receipt>" --notes "<diagnosis>" --json`
168
+ - BLOCKED: `omo-agent-toolkit ulw-loop record-evidence --goal-id <id> --criterion-id <id> --status blocked --evidence "<observable>" --notes "<safety/blocker/leftover-state>" --json`
172
169
  9. If actual does not match expected, diagnose, respawn the right-sized worker with the failure context to fix minimally, and rerun the SAME criterion (including a fresh cleanup).
173
170
  10. After 3 same-criterion failures, exit the goal with diagnosis.
174
171
  11. After 5 cycles on one goal without required criteria passing, checkpoint failed.
@@ -177,7 +174,7 @@ Loop per goal. Cap at 5 cycles per goal. Cap identical same-criterion failures a
177
174
  ### Goal Completion
178
175
  1. Non-final aggregate goal: confirm every `essential` criterion is `pass`; non-essential criteria may remain pending. Final aggregate goal: confirm every criterion across the whole plan is `pass`.
179
176
  2. Call `get_goal` for a fresh snapshot.
180
- 3. Run `omo ulw-loop checkpoint --goal-id <id> --status complete --evidence "<criteria evidence summary>" --codex-goal-json <snapshot> --json`; on success it auto-starts and prints the next eligible goal unless `--no-advance` is passed.
177
+ 3. Run `omo-agent-toolkit ulw-loop checkpoint --goal-id <id> --status complete --evidence "<criteria evidence summary>" --codex-goal-json <snapshot> --json`; on success it auto-starts and prints the next eligible goal unless `--no-advance` is passed.
181
178
  4. If blocked or failed, checkpoint with `--status blocked` or `--status failed` and include diagnosis evidence.
182
179
  5. If this is the final goal, run the final quality gate first and pass `--quality-gate-json`.
183
180
 
@@ -189,16 +186,16 @@ Trigger only for the final aggregate goal after every criterion in every goal is
189
186
  3b. Only then spawn lazycodex-gate-reviewer with those artifact paths.
190
187
  3c. The gate's approval binds to the frozen tree and full commit SHA and covers its three lanes — code quality, hands-on QA, and goal verification. Immediately append one durable `.omo/ulw-loop/ledger.jsonl` record per passing lane with the lane name, full SHA, verdict, and report artifact/source. Before reuse after continuation or compaction, re-read the ledger and require the exact lane/SHA pair; memory or an unstamped report is not coverage. A later rebase or amend that keeps the tree identical still has a new SHA and needs fresh lane stamps; changed content needs fresh review of the delta.
191
188
  4. Treat timeout, missing deliverable, ack-only, `BLOCKED:`, or inconclusive review as a blocker. Any fix restarts the freeze at the new HEAD: re-run ONLY the proofs it invalidated and stamp the fresh output — never regenerate all evidence or relabel stale output to HEAD — re-review the delta at most TWICE; then record-review-blockers (step 5) and surface to the user.
192
- 5. If review remains blocked, run `omo ulw-loop record-review-blockers --goal-id <id> --title "<...>" --objective "<...>" --evidence "<review findings>" --codex-goal-json <snapshot> --json`.
189
+ 5. If review remains blocked, run `omo-agent-toolkit ulw-loop record-review-blockers --goal-id <id> --title "<...>" --objective "<...>" --evidence "<review findings>" --codex-goal-json <snapshot> --json`.
193
190
  6. If clean, checkpoint final completion:
194
191
  ```sh
195
- omo ulw-loop checkpoint --goal-id <id> --status complete --evidence "<e2e evidence + manual QA notes>" --codex-goal-json <snapshot> --quality-gate-json <json-or-path> --json
192
+ omo-agent-toolkit ulw-loop checkpoint --goal-id <id> --status complete --evidence "<e2e evidence + manual QA notes>" --codex-goal-json <snapshot> --quality-gate-json <json-or-path> --json
196
193
  ```
197
194
  `--quality-gate-json` shape:
198
195
  ```json
199
196
  {
200
197
  "codeReview":{"by":"lazycodex-code-reviewer","recommendation":"APPROVE","codeQualityStatus":"CLEAR","reportPath":"test/fixtures/artifacts/code-review.md","evidence":"Diff review passed.","blockers":[]},
201
- "manualQa":{"by":"lazycodex-qa-executor","status":"passed","evidence":"CLI and data surfaces passed.","surfaceEvidence":[{"id":"surface-cli-pass","criterionRef":"C1","surface":"cli","invocation":"omo ulw-loop checkpoint --quality-gate-json sample-quality-gate.json --json","verdict":"passed","artifactRefs":["artifact-cli-pass"]},{"id":"surface-data-pass","criterionRef":"C2","surface":"data","invocation":"diff -u before-ledger.json after-ledger.json","verdict":"passed","artifactRefs":["artifact-data-diff"]}],"adversarialCases":[{"id":"adv-malformed-input","criterionRef":"C3","scenario":"malformed gate input omits manual QA evidence","expectedBehavior":"validator rejects ULW_LOOP_QUALITY_GATE_INVALID","verdict":"passed","artifactRefs":["artifact-cli-reject"]}],"artifactRefs":[{"id":"artifact-cli-pass","kind":"cli-transcript","description":"CLI pass artifact.","path":"test/fixtures/artifacts/cli-pass.txt"},{"id":"artifact-cli-reject","kind":"log","description":"Reject log artifact.","path":"test/fixtures/artifacts/rejection.txt"},{"id":"artifact-data-diff","kind":"data-diff","description":"Data diff artifact.","path":"test/fixtures/artifacts/data-diff.txt"}]},
198
+ "manualQa":{"by":"lazycodex-qa-executor","status":"passed","evidence":"CLI and data surfaces passed.","surfaceEvidence":[{"id":"surface-cli-pass","criterionRef":"C1","surface":"cli","invocation":"omo-agent-toolkit ulw-loop checkpoint --quality-gate-json sample-quality-gate.json --json","verdict":"passed","artifactRefs":["artifact-cli-pass"]},{"id":"surface-data-pass","criterionRef":"C2","surface":"data","invocation":"diff -u before-ledger.json after-ledger.json","verdict":"passed","artifactRefs":["artifact-data-diff"]}],"adversarialCases":[{"id":"adv-malformed-input","criterionRef":"C3","scenario":"malformed gate input omits manual QA evidence","expectedBehavior":"validator rejects ULW_LOOP_QUALITY_GATE_INVALID","verdict":"passed","artifactRefs":["artifact-cli-reject"]}],"artifactRefs":[{"id":"artifact-cli-pass","kind":"cli-transcript","description":"CLI pass artifact.","path":"test/fixtures/artifacts/cli-pass.txt"},{"id":"artifact-cli-reject","kind":"log","description":"Reject log artifact.","path":"test/fixtures/artifacts/rejection.txt"},{"id":"artifact-data-diff","kind":"data-diff","description":"Data diff artifact.","path":"test/fixtures/artifacts/data-diff.txt"}]},
202
199
  "gateReview":{"by":"lazycodex-gate-reviewer","recommendation":"APPROVE","reportPath":"test/fixtures/artifacts/gate-review.md","evidence":"Gate review passed.","blockers":[]},
203
200
  "iteration":{"fullRerun":true,"status":"passed","rerunCommands":["bunx vitest run packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-doc.test.ts"],"evidence":"Focused rerun passed."},
204
201
  "criteriaCoverage":{"totalCriteria":3,"passCount":3,"originalIntent":"User wanted artifact-backed completion.","desiredOutcome":"Behavior ships with review and QA evidence.","userOutcomeReview":"Result matches brief and goals.","adversarialClassesCovered":["malformed_input","stale_state"]}
@@ -219,10 +216,10 @@ Use steering only for structured evidence-backed mutation. Reject natural-langua
219
216
  | annotate_ledger | Audit-only note | `--evidence`, `--rationale` |
220
217
  | mark_blocked_superseded | Old story replaced by new evidence | `--goal-id`, `--replacements?`, `--evidence`, `--rationale` |
221
218
 
222
- Command form: `omo ulw-loop steer --kind <kind> [<kind-specific-fields>] --evidence "<...>" --rationale "<...>" --json`. For multiple evidence-backed plan-shape changes discovered together, pass `--proposals-json <json-or-path>` with an array of proposals; the batch applies atomically or rejects without partial plan mutation.
219
+ Command form: `omo-agent-toolkit ulw-loop steer --kind <kind> [<kind-specific-fields>] --evidence "<...>" --rationale "<...>" --json`. For multiple evidence-backed plan-shape changes discovered together, pass `--proposals-json <json-or-path>` with an array of proposals; the batch applies atomically or rejects without partial plan mutation.
223
220
 
224
221
  Validation batches are optional aggregate-mode review boundaries declared at create time with `--validation-batch-json`. A batch-final member requires all other members resolved, all member criteria pass, and a member-spanning quality gate; split/supersede steering keeps batch membership updated.
225
- Structured prompt directives accepted: `OMO_ULW_LOOP_STEER: { ... }`, `omo.ulw-loop.steer: {...}`, `omo ulw-loop steer: {...}`.
222
+ Structured prompt directives accepted: `OMO_ULW_LOOP_STEER: { ... }`, `omo.ulw-loop.steer: {...}`, `omo ulw-loop steer: {...}`, `omo-agent-toolkit ulw-loop steer: {...}`.
226
223
 
227
224
  ## Constraints
228
225
  1. NEVER call `update_goal` mid-aggregate; only on final story after the quality gate passes.
@@ -64,7 +64,7 @@ Both invocations are resume-safe no-ops for artifacts already present. Do NOT ha
64
64
 
65
65
  ## Plan artifact producer contract
66
66
 
67
- When producing the plan, encode every executable item as a column-zero Markdown task row: implementation rows MUST match `- [ ] N. <title>` (where `N` is a positive decimal integer), and final-verifier rows MUST match `- [ ] F<number>. <title>`. Prose headings, numbered paragraphs, and ordinary bullets are not task substitutes and MUST NOT be counted as implementation or final-verifier tasks. Before handoff, run a structural self-check over the plan: verify that every implementation row and final-verifier row is column-zero, matches its required grammar, and appears in the intended `## Todos` or `## Final verification wave` section; verify that no prose heading or bullet is being used as a task; and repair the plan before handoff if any check fails.
67
+ When producing the plan, encode every executable item as a column-zero Markdown task row: implementation rows MUST match `- [ ] N. <title>` (where `N` is a positive decimal integer), and final-verifier rows MUST match `- [ ] F<number>. <title>`. Prose headings, numbered paragraphs, and ordinary bullets are not task substitutes and MUST NOT be counted as implementation or final-verifier tasks. Before handoff, run a structural self-check over the plan: verify that every implementation row and final-verifier row is column-zero, matches its required grammar, and appears in the intended `## Todos` or `## Final verification wave` section; verify that no prose heading or bullet is being used as a task; verify that every implementation row carries a nested `Recommended task executor category:` line (final-verifier rows default to `unspecified-high` when unannotated); and repair the plan before handoff if any check fails.
68
68
 
69
69
  ## Universal invariants (hold on every path)
70
70
 
@@ -154,11 +154,11 @@ No Metis, no plan file, no execution until the user approves. The UNCLEAR path a
154
154
  ## Commit strategy
155
155
  ## Success criteria
156
156
  ```
157
- > Target 5-8 todos per wave; fewer than 3 (except the final) means under-splitting. Implementation + Test = ONE todo. Each todo carries: exhaustive References (the executor has no interview context), agent-executable Acceptance criteria, happy + failure QA scenarios each with an evidence path, and a Commit line.
157
+ > Target 5-8 todos per wave; fewer than 3 (except the final) means under-splitting. Implementation + Test = ONE todo. Each todo carries: exhaustive References (the executor has no interview context), agent-executable Acceptance criteria, happy + failure QA scenarios each with an evidence path, a Commit line, and a `Recommended task executor category:` line - the routing verdict the executor follows, with a one-line reason, in the omo category vocabulary: `quick` (mechanical / single-file - the default for every splittable piece), `unspecified-low` (small misc), `unspecified-high` (standard multi-file feature), `visual-engineering` (frontend/UI), `writing` (docs), `git` (git ops), `deep` (hairy debugging or cross-module reasoning), `ultrabrain` (ONE genuinely hard cohesive problem, delegated whole). Prefer many small `quick`-routable todos spread across parallel waves; when splitting would sever shared reasoning, keep ONE todo routed to `deep`/`ultrabrain` - never force-split work whose parts share one insight. Harnesses without categories map by difficulty: quick/unspecified-low/writing/git = low, unspecified-high/visual-engineering = medium, deep/ultrabrain = high.
158
158
 
159
159
  ## Plan artifact producer contract
160
160
 
161
- When producing the plan, encode every executable item as a column-zero Markdown task row: implementation rows MUST match `- [ ] N. <title>` (where `N` is a positive decimal integer), and final-verifier rows MUST match `- [ ] F<number>. <title>`. Prose headings, numbered paragraphs, and ordinary bullets are not task substitutes and MUST NOT be counted as implementation or final-verifier tasks. Before handoff, run a structural self-check over the plan: verify that every implementation row and final-verifier row is column-zero, matches its required grammar, and appears in the intended `## Todos` or `## Final verification wave` section; verify that no prose heading or bullet is being used as a task; and repair the plan before handoff if any check fails.
161
+ When producing the plan, encode every executable item as a column-zero Markdown task row: implementation rows MUST match `- [ ] N. <title>` (where `N` is a positive decimal integer), and final-verifier rows MUST match `- [ ] F<number>. <title>`. Prose headings, numbered paragraphs, and ordinary bullets are not task substitutes and MUST NOT be counted as implementation or final-verifier tasks. Before handoff, run a structural self-check over the plan: verify that every implementation row and final-verifier row is column-zero, matches its required grammar, and appears in the intended `## Todos` or `## Final verification wave` section; verify that no prose heading or bullet is being used as a task; verify that every implementation row carries a nested `Recommended task executor category:` line (final-verifier rows default to `unspecified-high` when unannotated); and repair the plan before handoff if any check fails.
162
162
 
163
163
  ### Final verification wave (after ALL todos)
164
164
  Runs in parallel; ALL must APPROVE; surface results and wait for the user's explicit okay before declaring complete: F1 plan compliance audit, F2 code quality review, F3 real manual QA, F4 scope fidelity.
@@ -174,7 +174,7 @@ Every "present the plan summary/brief" above delivers THIS structure, in the use
174
174
 
175
175
  1. **What this plan drives** - the work it performs, in 1-2 sentences.
176
176
  2. **End state** - the concrete things that will exist or behave differently once execution finishes.
177
- 3. **Shape** - how many phases/waves and how many tasks: N implementation todos (`- [ ] N.` rows) + F final-verification tasks (`- [ ] F<n>.` rows).
177
+ 3. **Shape** - how many phases/waves and how many tasks: N implementation todos (`- [ ] N.` rows) + F final-verification tasks (`- [ ] F<n>.` rows), plus the executor-category mix (e.g. 6x `quick`, 2x `unspecified-high`, 1x `ultrabrain`).
178
178
  4. **Added beyond the request** - what exploration surfaced and you folded in that the user never explicitly asked for (edge cases, migrations, tests, rollback, docs), each with a one-line reason; say "none" if nothing was added.
179
179
  5. **Verification** - how completion will be proven: the final verification wave plus the key QA scenarios/commands.
180
180
  6. **Execution handoff** - the plan runs in a worker session via `$start-work <plan-name>`; introduce the options: `--worktree <absolute-path>` (task-owned worktree; required for PR/branch work), `--make-pr` (deliver as a PR; auto-creates a task-owned worktree), `--ship` (implies `--make-pr`, keeps working until the PR is reviewed and MERGED).
@@ -254,7 +254,7 @@ Your next move: <fill - e.g. approve, or run a high-accuracy review>. Full execu
254
254
  ## Verification strategy
255
255
  > Zero human intervention - all verification is agent-executed.
256
256
  - Test decision: <TDD | tests-after | none> + framework
257
- - Evidence: <attemptDir>/task-<N>-${slug}.<ext> (attemptDir = currentAttemptDir from 'omo ulw-loop status --json', .omo/evidence/ulw/<session>/<goalId>/a<attempt>; outside ulw-loop use .omo/evidence/)
257
+ - Evidence: <attemptDir>/task-<N>-${slug}.<ext> (attemptDir = currentAttemptDir from 'omo-agent-toolkit ulw-loop status --json', .omo/evidence/ulw/<session>/<goalId>/a<attempt>; outside ulw-loop use .omo/evidence/)
258
258
 
259
259
  ## Execution strategy
260
260
  ### Parallel execution waves
@@ -157,7 +157,7 @@ Never guess the shape of the deliverable. After the decomposition and before spa
157
157
  - Propose the TEMPLATE too, chosen from the domain and the user's own context: section skeleton, citation style, length target, language, and any house style they have used before. A prior document the user points at is the strongest template signal — read it and mirror its structure and tagging.
158
158
  - Ask once, compactly: proposed format + proposed template + what each option costs. Then stop and wait. Guessing here wastes the entire assembly pass.
159
159
 
160
- Record the answer in the journal; it is the binding contract for Phase 5.
160
+ Record the answer in the journal; Phase 5 opens by turning it into `design-spec.md`.
161
161
 
162
162
  ## Phase 1 — Saturation wave
163
163
 
@@ -179,7 +179,7 @@ Role protocols — embed the relevant one in each spawn message; every worker ge
179
179
 
180
180
  - **Codebase (explore), 2-4 workers.** Grep with 3+ keyword variations; structural/AST search; LSP definitions and references; file-name globs; `git log --all -S '<keyword>'` and `--grep` for history including deleted code. Cross-validate hits across tools. Report absolute file paths, patterns with `file:line`, and how findings connect.
181
181
  - **Web (librarian), 3-6 workers.** At least 10 distinct websearch queries per worker, each with a different operator or angle (see Search craft); fetch the full page for every result that matters — snippets lie. Context7 with 3+ queries per known library. grep.app and `gh search code|repos|issues` for real-world usage. Official docs via sitemap discovery (`<base>/sitemap.xml`), then targeted pages.
182
- - **Browsing, 0-3 workers.** Pages plain fetch cannot read (WAF, 403, Cloudflare, dynamic rendering, login): the worker loads the `ultimate-browsing` skill and escalates through its tiers — Tier-1 insane-search engine first, then Tier-2 Chrome stealth — rather than abandoning the source. Capture screenshots when visual context matters. When one blocked territory hides many leads, fan out more browsing subagents in parallel for breadth instead of serializing one worker through them.
182
+ - **Browsing, 0-3 workers.** Pages plain fetch cannot read (WAF, 403, Cloudflare, dynamic rendering, login): the worker loads the `ultimate-browsing` skill and escalates through its tiers — Tier-1 insane-search engine first (including its Phase-2.5 archive surrogates), then Tier-2 Chrome stealth — rather than abandoning the source. Capture screenshots when visual context matters. **Provenance is part of the claim**: when a source came back with `provenance` of `snapshot` (an archive copy), cite it with its `snapshot_timestamp` and never state it as the current live page; content from a `proxy` route is `untrusted` and needs a second independent route before any claim rests on it. When one blocked territory hides many leads, fan out more browsing subagents in parallel for breadth instead of serializing one worker through them.
183
183
  - **Repo deep-dive (librarian), 0-2 workers.** Shallow-clone the most relevant repos to `${TMPDIR:-/tmp}`, pin the HEAD SHA, read core modules, follow call chains, return SHA-pinned permalinks.
184
184
 
185
185
  Example spawn (codebase axis; librarian, browsing, and repo-dive follow the same contract with their own protocol):
@@ -220,7 +220,7 @@ The Phase 0 core question is the fixed goal of the run and never drifts. An excu
220
220
 
221
221
  Interest alone is not a trigger. Anything without one stays a queued lead in `expansion-log.md`, and the wave plan continues.
222
222
 
223
- **Budget the dive before you take it.** State the worker count and the probe count for this level in the ENTER row. An excursion may spawn at most ONE nested sub-excursion; a third level means the thing has become its own research question — surface immediately and either promote it to a real axis with its own worker or record it as an out-of-scope gap in `SYNTHESIS.md`. When the `ulw-loop` skill is driving the run, a promotion is `omo ulw-loop steer --kind add_subgoal --title "<axis>" --objective "<what it must answer>" --evidence "<what surfaced it>" --rationale "<why the plan changes>"`.
223
+ **Budget the dive before you take it.** State the worker count and the probe count for this level in the ENTER row. An excursion may spawn at most ONE nested sub-excursion; a third level means the thing has become its own research question — surface immediately and either promote it to a real axis with its own worker or record it as an out-of-scope gap in `SYNTHESIS.md`. When the `ulw-loop` skill is driving the run, a promotion is `omo-agent-toolkit ulw-loop steer --kind add_subgoal --title "<axis>" --objective "<what it must answer>" --evidence "<what surfaced it>" --rationale "<why the plan changes>"`.
224
224
 
225
225
  **EXIT (surface) the moment any of these holds** — you do not need all of them:
226
226
 
@@ -229,7 +229,7 @@ Interest alone is not a trigger. Anything without one stays a queued lead in `ex
229
229
  - The finding stops moving any claim's status — diminishing return is an exit, not a reason to push harder.
230
230
  - The level's stated budget is spent.
231
231
 
232
- **Fold back on the way out.** Every EXIT writes one line saying what the excursion changed in the top-level answer, and `none — <reason>` is a legitimate, required outcome; an excursion whose result is silently dropped is a lost run. Update the parent claim node or axis digest with the result, then mirror the whole excursion into the loop ledger — `omo ulw-loop steer --kind annotate_ledger --evidence "<what the excursion observed>" --rationale "<what it changed, or none>"`, and `omo ulw-loop record-evidence --goal-id <id> --criterion-id <id> --status pass|fail|blocked --evidence "<artifact>"` when it settled a criterion. After a compaction, `omo ulw-loop status --json` plus `excursion-log.md` tell you which excursions are still open.
232
+ **Fold back on the way out.** Every EXIT writes one line saying what the excursion changed in the top-level answer, and `none — <reason>` is a legitimate, required outcome; an excursion whose result is silently dropped is a lost run. Update the parent claim node or axis digest with the result, then mirror the whole excursion into the loop ledger — `omo-agent-toolkit ulw-loop steer --kind annotate_ledger --evidence "<what the excursion observed>" --rationale "<what it changed, or none>"`, and `omo-agent-toolkit ulw-loop record-evidence --goal-id <id> --criterion-id <id> --status pass|fail|blocked --evidence "<artifact>"` when it settled a criterion. After a compaction, `omo-agent-toolkit ulw-loop status --json` plus `excursion-log.md` tell you which excursions are still open.
233
233
 
234
234
  **Anti-drift.** After every EXIT, re-read the core question in the journal and confirm the run still answers it. Three consecutive excursions that changed nothing end excursions for the run: converge on what you have.
235
235
 
@@ -311,27 +311,31 @@ The format answered at the Phase 0 gate is binding. Absent an explicit user over
311
311
 
312
312
  | Target | How |
313
313
  |---|---|
314
- | PDF (default) | Author the report as one self-contained HTML file, then print it headless: `chrome --headless --disable-gpu --no-pdf-header-footer --print-to-pdf=<out.pdf> file://<report.html>`. For CJK, embed a real webfont (Pretendard, Noto Sans KR) instead of trusting system fallbacks. `uv run --with weasyprint python` is the fallback renderer. |
314
+ | PDF (default) | Author the report as one self-contained HTML file, then print it headless: `chrome --headless --disable-gpu --no-pdf-header-footer --print-to-pdf=<out.pdf> file://<report.html>`. Embed the `design-spec.md` fonts as real webfonts (CJK included) instead of trusting system fallbacks. `uv run --with weasyprint python` is the fallback renderer. |
315
315
  | DOCX (default) | `pandoc <report.md> -o <out.docx>`, adding `--reference-doc=<template.docx>` when the user has a house style; `uv run --with python-docx python` when pandoc is unavailable. Charts and Mermaid renders go in as images. |
316
316
  | Slides / deck | `uv run --with python-pptx python` — one claim per slide, a chart or diagram per claim. |
317
317
  | Standalone HTML / Markdown | The authored source itself. |
318
318
 
319
- Asset workers (background, parallel) — a research report without visuals is a wall of text nobody reads:
319
+ **Write `design-spec.md` the moment the format gate is answered — before any asset worker spawns.** It is the one design contract every asset and assembly worker receives: template family (a document the user pointed at is the strongest signal — mirror its structure and register; absent one, default to the clean analyst-report register restrained accent palette, generous margins, styled section headings, no emoji, no clipart), accent palette, body/heading fonts (a real CJK webfont — Pretendard, Noto Sans KR — when the report language needs one), and the figure standard below. One font family and one palette govern prose, charts, Mermaid, and generated images alike; a diagram rendering in a random default font inside a styled report is a defect, not a style choice.
320
+
321
+ **The figure standard — binding for every image, chart, and diagram.** Each figure sits in a fixed-size container styled from the spec (border, background, caption); the image scales to fit entirely inside it with its original aspect ratio preserved — object-fit: contain semantics — never stretched, never cropped, never spilling out. Every chart carries a title, axis labels, units, and value labels in the report's language; a bare number the reader cannot name is a defect.
322
+
323
+ Asset workers (background, parallel, each fed `design-spec.md`) — visuals are the DEFAULT deliverable of this phase, not garnish the user must ask for; a delivered report without figures is an incomplete run:
320
324
 
321
325
  - **Charts for every quantitative finding, computed from real data.** Pull the numbers into an actual table first (CSV/JSON under `$SESSION_DIR`), then plot from that table, never from prose. Follow the data-scientist tool doctrine — numpy always, Polars for filtering/sorting/transforms, DuckDB for joins/aggregations/window functions, never pandas — and load the `data-scientist` skill when this session has it: `uv run --with numpy --with polars --with duckdb --with pyarrow --with matplotlib python`. Keep `pyarrow` in that set — the DuckDB-to-Polars handoff (`.pl()`) fails without it, and `.df()` fails without pandas, so hand data across through `.pl()`, never `.df()`. Save to `$SESSION_DIR/assets/`.
322
- - **Mermaid graphs** for process, architecture, argument, timeline, and evidence-flow structure. Render each to SVG and confirm the file exists before the document references it.
323
- - **Generated visuals** through the imagegen skill when a diagram, cover, or narrative visual earns its place.
326
+ - **Mermaid graphs** for process, architecture, argument, timeline, and evidence-flow structure, themed to the spec's fonts and palette. Render each to SVG and confirm the file exists before the document references it.
327
+ - **Generated visuals through the imagegen skill whenever the session has it:** a cover plus a concept illustration per major theme, prompted from the spec's style, palette, and mood document-styled illustration, never generic stock art dropped into a designed page.
324
328
  - **Full-page screenshots** of the top 5-10 sources (browsing worker) as provenance you can show.
325
329
 
326
330
  **Verify the asset manifest before rendering.** List every asset the document references, assert each file exists and is non-empty on disk, and re-render whatever is missing. A document that renders with three broken diagrams is a document you will publish twice.
327
331
 
328
- Assembly worker — `task(category="deep", load_skills=["frontend", "visual-qa", "open-design", "data-scientist", "imagegen", "ulw-loop"], run_in_background=true, ...)`: before writing, read every available design and visualization skill and apply it — the report is a designed artifact, not a text dump. Use the template the user approved; absent a stronger house style the default skeleton is executive summary → key findings by theme → detailed analysis (quotes under 20 words with attribution, charts, Mermaid graphs, generated visuals, SHA-pinned permalinks, verification results) → comparative analysis when options compete → numbered sources with access dates → methodology appendix (workers, waves, searches, verifications, debate rounds) → correction log naming what verification overturned. Write it long and specific: every claim cites `[Source N]`, and the sources section lists every source the run actually used rather than a curated few.
332
+ Assembly worker — `task(category="deep", load_skills=["frontend", "visual-qa", "open-design", "data-scientist", "imagegen", "ulw-loop"], run_in_background=true, ...)`: before writing, read every available design and visualization skill and apply it — the report is a designed artifact, not a text dump; the worker's prompt carries `design-spec.md`. Use the template the user approved; absent a stronger house style the default skeleton is executive summary → key findings by theme → detailed analysis (quotes under 20 words with attribution, charts, Mermaid graphs, generated visuals, SHA-pinned permalinks, verification results) → comparative analysis when options compete → numbered sources with access dates → methodology appendix (workers, waves, searches, verifications, debate rounds) → correction log naming what verification overturned. Write it long and specific: every claim cites `[Source N]`, and the sources section lists every source the run actually used rather than a curated few.
329
333
 
330
334
  ### The delivery gate — visual QA must PASS
331
335
 
332
336
  Nothing reaches the user until the gate passes:
333
337
 
334
- **Visual QA (always).** Render the produced artifact back to images — PDF pages to PNG, the HTML in a real browser — and look at them: missing or broken figures, clipped tables, overflowing CJK text, blank pages, unreadable chart labels, wrong page breaks. Fix and re-render until the pages are clean. Reading the source markup is not visual QA; inspect the pixels.
338
+ **Visual QA (always).** Render the produced artifact back to images — PDF pages to PNG, the HTML in a real browser — and look at them: missing or broken figures, images stretched or spilling their containers, diagram or chart text rendered off the spec's font or palette, clipped tables, overflowing CJK text, blank pages, unlabeled chart values, wrong page breaks. Fix and re-render until the pages are clean. Reading the source markup is not visual QA; inspect the pixels.
335
339
 
336
340
  Then deliver: the artifact plus a compact chat-readable summary of what it says — the answer in a few sentences, the numbers that matter, and what to look at first. The document is the deliverable; the summary is what gets it read.
337
341
 
@@ -387,6 +391,7 @@ High-yield combinations: official docs (`site:<docs domain>`), GitHub implementa
387
391
  | A derived estimate presented as a measured number | MEASURED / ASSUMED / DERIVED lineage on every quantitative claim, plus a sensitivity line |
388
392
  | Delivering before the delivery gates pass | Visual QA on rendered pages always, plus the harness's proofread gate — a typo the user finds means a gate did not run |
389
393
  | Referencing an asset that is not on disk | Verify the asset manifest before rendering; re-render whatever is missing |
394
+ | A figure stretched, cropped, or styled off the report's design language | `design-spec.md` binds every asset: fixed containers, contain-fit with aspect preserved, spec fonts and palette in charts and Mermaid |
390
395
  | Chasing an interesting find with no ENTER trigger | Excursions need a named trigger; everything else stays a queued lead |
391
396
  | An excursion that never came back, or drifted into a new mission | EXIT rules are unconditional; depth 3 means promote it to an axis or record it as a gap |
392
397
  | An excursion whose result was never folded back | Every EXIT writes what it changed in the top-level answer, `none` included, and mirrors into the loop ledger |