minimal-agent 0.8.2 → 0.10.0

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 (484) hide show
  1. package/README.md +14 -12
  2. package/package.json +34 -1
  3. package/plugins/cron-runner/.claude-plugin/plugin.json +5 -0
  4. package/plugins/cron-runner/commands/cron.md +26 -0
  5. package/plugins/cron-runner/commands/crons.md +7 -0
  6. package/plugins/cron-runner/plugin.js +34 -0
  7. package/plugins/cron-runner/src/commands.js +348 -0
  8. package/plugins/cron-runner/src/cronTime.js +148 -0
  9. package/plugins/cron-runner/src/lock.js +68 -0
  10. package/plugins/cron-runner/src/runs.js +89 -0
  11. package/plugins/cron-runner/src/scheduleEngine.js +72 -0
  12. package/plugins/cron-runner/src/scheduler.js +355 -0
  13. package/plugins/cron-runner/src/schema.js +140 -0
  14. package/plugins/cron-runner/src/service.js +167 -0
  15. package/plugins/cron-runner/src/store.js +298 -0
  16. package/plugins/cron-runner/src/types.js +1 -0
  17. package/plugins/workflow-runner/commands/workflow.md +4 -4
  18. package/plugins/workflow-runner/commands/workflows.md +1 -1
  19. package/plugins/workflow-runner/plugin.js +3 -1
  20. package/plugins/workflow-runner/src/agentCommon.js +249 -51
  21. package/plugins/workflow-runner/src/dslManifest.js +72 -0
  22. package/plugins/workflow-runner/src/expressions.js +198 -15
  23. package/plugins/workflow-runner/src/index.js +40 -8
  24. package/plugins/workflow-runner/src/jsonPayload.js +1 -1
  25. package/plugins/workflow-runner/src/loader.js +286 -72
  26. package/plugins/workflow-runner/src/multimodal.js +37 -0
  27. package/plugins/workflow-runner/src/recovery.js +49 -39
  28. package/plugins/workflow-runner/src/runner.js +802 -287
  29. package/plugins/workflow-runner/src/stepExecutors/agent.js +157 -39
  30. package/plugins/workflow-runner/src/stepExecutors/assert.js +16 -3
  31. package/plugins/workflow-runner/src/stepExecutors/llm.js +60 -111
  32. package/plugins/workflow-runner/src/stepExecutors/skill.js +47 -47
  33. package/plugins/workflow-runner/src/stepExecutors/tool.js +76 -10
  34. package/plugins/workflow-runner/src/stepExecutors/verify.js +27 -10
  35. package/plugins/workflow-runner/src/taskIdentity.js +296 -0
  36. package/plugins/workflow-runner/src/types.js +19 -9
  37. package/plugins/workflow-runner/src/workflowState.js +516 -33
  38. package/skills/adversarial-review/SKILL.md +0 -1
  39. package/skills/ai-image/SKILL.md +89 -0
  40. package/skills/ai-image/scripts/generate.mjs +497 -0
  41. package/skills/ai-image/scripts/generate_from_plan.mjs +469 -0
  42. package/skills/ai-image/scripts/generate_from_plan_test.mjs +223 -0
  43. package/skills/ai-image/scripts/generate_test.mjs +74 -0
  44. package/skills/browser-automation/SKILL.md +47 -0
  45. package/skills/docx/SKILL.md +25 -3
  46. package/skills/docx/scripts/office/helpers/__pycache__/__init__.cpython-314.pyc +0 -0
  47. package/skills/docx/scripts/office/helpers/__pycache__/merge_runs.cpython-314.pyc +0 -0
  48. package/skills/docx/scripts/office/helpers/__pycache__/simplify_redlines.cpython-314.pyc +0 -0
  49. package/skills/docx/scripts/office/validators/__pycache__/__init__.cpython-314.pyc +0 -0
  50. package/skills/docx/scripts/office/validators/__pycache__/base.cpython-314.pyc +0 -0
  51. package/skills/docx/scripts/office/validators/__pycache__/docx.cpython-314.pyc +0 -0
  52. package/skills/docx/scripts/office/validators/__pycache__/pptx.cpython-314.pyc +0 -0
  53. package/skills/docx/scripts/office/validators/__pycache__/redlining.cpython-314.pyc +0 -0
  54. package/skills/docx/scripts/opc_check.py +253 -0
  55. package/skills/image-gen-openrouter/SKILL.md +10 -2
  56. package/skills/image-stats/SKILL.md +65 -0
  57. package/skills/image-stats/scripts/__pycache__/image_stats.cpython-314.pyc +0 -0
  58. package/skills/image-stats/scripts/__pycache__/image_stats_test.cpython-314.pyc +0 -0
  59. package/skills/image-stats/scripts/image_stats.py +368 -0
  60. package/skills/image-stats/scripts/image_stats_test.py +181 -0
  61. package/skills/pptx/SKILL.md +123 -95
  62. package/skills/pptx/design.md +82 -0
  63. package/skills/pptx/examples/README.md +29 -0
  64. package/skills/pptx/examples/hybrid_example.mjs +107 -0
  65. package/skills/pptx/examples/hybrid_example.pptx +0 -0
  66. package/skills/pptx/pptxgenjs.md +41 -0
  67. package/skills/pptx/scripts/deck_helpers.mjs +224 -0
  68. package/skills/pptx/scripts/layout_lint.py +293 -0
  69. package/skills/pptx/scripts/layout_lint_test.py +160 -0
  70. package/skills/pptx/scripts/opc_check.py +339 -0
  71. package/skills/pptx/scripts/svg_fallback.mjs +145 -0
  72. package/skills/pptx/svg.md +67 -0
  73. package/skills/tts-zh/SKILL.md +19 -2
  74. package/skills/ui-design/SKILL.md +158 -0
  75. package/skills/ui-design/claude_design.md +309 -0
  76. package/skills/ui-design/evals/evals.json +254 -0
  77. package/skills/ui-design/references/aesthetic-direction.md +83 -0
  78. package/skills/ui-design/references/claude-design-protocol.md +36 -0
  79. package/skills/ui-design/references/design-context.md +53 -0
  80. package/skills/ui-design/references/design-execution-playbook.md +82 -0
  81. package/skills/ui-design/references/export-pptx.md +124 -0
  82. package/skills/ui-design/references/layout-composition.md +654 -0
  83. package/skills/ui-design/references/preview-feedback.md +37 -0
  84. package/skills/ui-design/references/source-image-layout.md +189 -0
  85. package/skills/ui-design/references/starter-components.md +78 -0
  86. package/skills/ui-design/references/vi-aegis-vector.md +144 -0
  87. package/skills/ui-design/references/vi-amber-prism.md +133 -0
  88. package/skills/ui-design/references/vi-aqua-glass.md +200 -0
  89. package/skills/ui-design/references/vi-comfort-vision.md +147 -0
  90. package/skills/ui-design/references/vi-ember-prism.md +140 -0
  91. package/skills/ui-design/references/vi-nebula-console.md +151 -0
  92. package/skills/ui-design/references/vi-obsidian-optics.md +139 -0
  93. package/skills/ui-design/references/vi-obsidian-xui.md +143 -0
  94. package/skills/ui-design/references/vi-precision-horizon-dark.md +117 -0
  95. package/skills/ui-design/references/vi-precision-horizon.md +215 -0
  96. package/skills/ui-design/references/vi-solar-relay.md +130 -0
  97. package/skills/ui-design/references/vi-template-workflow.md +48 -0
  98. package/skills/ui-design/references/vi-verdant-grid.md +141 -0
  99. package/skills/ui-design/references/vi-violet-meridian.md +172 -0
  100. package/skills/ui-design/scripts/__pycache__/assemble_material.cpython-314.pyc +0 -0
  101. package/skills/ui-design/scripts/__pycache__/assemble_material_test.cpython-314.pyc +0 -0
  102. package/skills/ui-design/scripts/__pycache__/chart_sanity_check.cpython-314.pyc +0 -0
  103. package/skills/ui-design/scripts/__pycache__/check_language_policy.cpython-314.pyc +0 -0
  104. package/skills/ui-design/scripts/__pycache__/check_ui_artifact.cpython-314.pyc +0 -0
  105. package/skills/ui-design/scripts/__pycache__/check_ui_artifact_pptx_test.cpython-314.pyc +0 -0
  106. package/skills/ui-design/scripts/__pycache__/deck_pages_check.cpython-314.pyc +0 -0
  107. package/skills/ui-design/scripts/__pycache__/deck_pages_check_test.cpython-314.pyc +0 -0
  108. package/skills/ui-design/scripts/__pycache__/deck_visual_style_check.cpython-314.pyc +0 -0
  109. package/skills/ui-design/scripts/__pycache__/deck_visual_style_check_test.cpython-314.pyc +0 -0
  110. package/skills/ui-design/scripts/__pycache__/design_budget_check.cpython-314.pyc +0 -0
  111. package/skills/ui-design/scripts/__pycache__/design_budget_check_test.cpython-314.pyc +0 -0
  112. package/skills/ui-design/scripts/__pycache__/design_repair_hints.cpython-314.pyc +0 -0
  113. package/skills/ui-design/scripts/__pycache__/design_repair_hints_test.cpython-314.pyc +0 -0
  114. package/skills/ui-design/scripts/__pycache__/design_style_check.cpython-314.pyc +0 -0
  115. package/skills/ui-design/scripts/__pycache__/design_style_check_test.cpython-314.pyc +0 -0
  116. package/skills/ui-design/scripts/__pycache__/draft_coverage_check.cpython-314.pyc +0 -0
  117. package/skills/ui-design/scripts/__pycache__/extract_source_assets.cpython-314.pyc +0 -0
  118. package/skills/ui-design/scripts/__pycache__/extract_source_assets_test.cpython-314.pyc +0 -0
  119. package/skills/ui-design/scripts/__pycache__/generated_image_review_collect.cpython-314.pyc +0 -0
  120. package/skills/ui-design/scripts/__pycache__/generated_image_review_collect_test.cpython-314.pyc +0 -0
  121. package/skills/ui-design/scripts/__pycache__/image_plan_lint.cpython-314.pyc +0 -0
  122. package/skills/ui-design/scripts/__pycache__/image_plan_lint_test.cpython-314.pyc +0 -0
  123. package/skills/ui-design/scripts/__pycache__/image_prompt_rewrite.cpython-314.pyc +0 -0
  124. package/skills/ui-design/scripts/__pycache__/image_prompt_rewrite_test.cpython-314.pyc +0 -0
  125. package/skills/ui-design/scripts/__pycache__/layout_balance.cpython-314.pyc +0 -0
  126. package/skills/ui-design/scripts/__pycache__/layout_balance_test.cpython-314.pyc +0 -0
  127. package/skills/ui-design/scripts/__pycache__/normalize_design_json.cpython-314.pyc +0 -0
  128. package/skills/ui-design/scripts/__pycache__/normalize_design_json_test.cpython-314.pyc +0 -0
  129. package/skills/ui-design/scripts/__pycache__/plan_source_layout.cpython-314.pyc +0 -0
  130. package/skills/ui-design/scripts/__pycache__/plan_source_layout_test.cpython-314.pyc +0 -0
  131. package/skills/ui-design/scripts/__pycache__/resolve_source_hint.cpython-314.pyc +0 -0
  132. package/skills/ui-design/scripts/__pycache__/resolve_source_hint_test.cpython-314.pyc +0 -0
  133. package/skills/ui-design/scripts/__pycache__/resolve_source_input.cpython-314.pyc +0 -0
  134. package/skills/ui-design/scripts/__pycache__/resolve_source_input_test.cpython-314.pyc +0 -0
  135. package/skills/ui-design/scripts/__pycache__/scaffold_ui_artifact.cpython-314.pyc +0 -0
  136. package/skills/ui-design/scripts/__pycache__/source_usage_check.cpython-314.pyc +0 -0
  137. package/skills/ui-design/scripts/__pycache__/source_usage_check_test.cpython-314.pyc +0 -0
  138. package/skills/ui-design/scripts/__pycache__/text_readability_pixel.cpython-314.pyc +0 -0
  139. package/skills/ui-design/scripts/__pycache__/visual_quality_gate.cpython-314.pyc +0 -0
  140. package/skills/ui-design/scripts/__pycache__/visual_quality_gate_test.cpython-314.pyc +0 -0
  141. package/skills/ui-design/scripts/assemble_material.py +217 -0
  142. package/skills/ui-design/scripts/assemble_material_test.py +149 -0
  143. package/skills/ui-design/scripts/browser_check_ui_artifact.mjs +221 -0
  144. package/skills/ui-design/scripts/chart_sanity_check.py +261 -0
  145. package/skills/ui-design/scripts/chart_sanity_check_test.py +165 -0
  146. package/skills/ui-design/scripts/check_language_policy.py +351 -0
  147. package/skills/ui-design/scripts/check_ui_artifact.py +435 -0
  148. package/skills/ui-design/scripts/check_ui_artifact_pptx_test.py +251 -0
  149. package/skills/ui-design/scripts/deck_pages_check.py +158 -0
  150. package/skills/ui-design/scripts/deck_pages_check_test.py +134 -0
  151. package/skills/ui-design/scripts/deck_visual_style_check.py +767 -0
  152. package/skills/ui-design/scripts/deck_visual_style_check_test.py +713 -0
  153. package/skills/ui-design/scripts/design_budget_check.py +271 -0
  154. package/skills/ui-design/scripts/design_budget_check_test.py +183 -0
  155. package/skills/ui-design/scripts/design_repair_hints.py +162 -0
  156. package/skills/ui-design/scripts/design_repair_hints_test.py +54 -0
  157. package/skills/ui-design/scripts/design_style_check.py +397 -0
  158. package/skills/ui-design/scripts/design_style_check_test.py +233 -0
  159. package/skills/ui-design/scripts/draft_coverage_check.py +184 -0
  160. package/skills/ui-design/scripts/draft_coverage_check_test.py +131 -0
  161. package/skills/ui-design/scripts/export_pptx_from_html.mjs +2367 -0
  162. package/skills/ui-design/scripts/extract_source_assets.py +607 -0
  163. package/skills/ui-design/scripts/extract_source_assets_test.py +256 -0
  164. package/skills/ui-design/scripts/generated_image_review_collect.py +206 -0
  165. package/skills/ui-design/scripts/generated_image_review_collect_test.py +91 -0
  166. package/skills/ui-design/scripts/image_plan_lint.py +571 -0
  167. package/skills/ui-design/scripts/image_plan_lint_test.py +515 -0
  168. package/skills/ui-design/scripts/image_prompt_rewrite.py +713 -0
  169. package/skills/ui-design/scripts/image_prompt_rewrite_test.py +966 -0
  170. package/skills/ui-design/scripts/layout_balance.py +881 -0
  171. package/skills/ui-design/scripts/layout_balance_test.py +927 -0
  172. package/skills/ui-design/scripts/normalize_design_json.py +272 -0
  173. package/skills/ui-design/scripts/normalize_design_json_test.py +119 -0
  174. package/skills/ui-design/scripts/plan_source_layout.py +1450 -0
  175. package/skills/ui-design/scripts/plan_source_layout_test.py +1136 -0
  176. package/skills/ui-design/scripts/resolve_source_input.py +270 -0
  177. package/skills/ui-design/scripts/resolve_source_input_test.py +98 -0
  178. package/skills/ui-design/scripts/scaffold_ui_artifact.py +377 -0
  179. package/skills/ui-design/scripts/source_usage_check.py +581 -0
  180. package/skills/ui-design/scripts/source_usage_check_test.py +427 -0
  181. package/skills/ui-design/scripts/text_readability_pixel.py +340 -0
  182. package/skills/ui-design/scripts/text_readability_pixel_test.py +219 -0
  183. package/skills/ui-design/scripts/visual_quality_gate.py +301 -0
  184. package/skills/ui-design/scripts/visual_quality_gate_test.py +233 -0
  185. package/skills/ui-design/tests/e2e/prompts/deck.md +19 -0
  186. package/skills/ui-design/tests/e2e/prompts/webpage.md +17 -0
  187. package/skills/ui-design/tests/e2e/render_check.mjs +101 -0
  188. package/skills/ui-design/tests/e2e/rubric.json +54 -0
  189. package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/checks/browser-check.json +49 -0
  190. package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/checks/language-check.txt +12 -0
  191. package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/checks/static-check.txt +15 -0
  192. package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/outputs/index.html +837 -0
  193. package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/prompt.md +12 -0
  194. package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/review.md +21 -0
  195. package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/screenshots/desktop.png +0 -0
  196. package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/screenshots/mobile.png +0 -0
  197. package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/outputs/homepage.html +373 -0
  198. package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/outputs/platform.html +378 -0
  199. package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/prompt.md +13 -0
  200. package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/review.md +26 -0
  201. package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/homepage/browser-check.json +49 -0
  202. package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/homepage/desktop.png +0 -0
  203. package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/homepage/mobile.png +0 -0
  204. package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/platform/browser-check.json +49 -0
  205. package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/platform/desktop.png +0 -0
  206. package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/platform/mobile.png +0 -0
  207. package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-1/checks/static-check.txt +2 -0
  208. package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-1/outputs/index.html +656 -0
  209. package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-1/prompt.md +12 -0
  210. package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-1/render_check.mjs +67 -0
  211. package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-2/checks/static-check.txt +2 -0
  212. package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-2/outputs/index.html +587 -0
  213. package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-2/prompt.md +12 -0
  214. package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-2/review.md +36 -0
  215. package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/checks/browser-check.json +49 -0
  216. package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/checks/language-check.txt +8 -0
  217. package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/checks/static-check.txt +16 -0
  218. package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/outputs/index.html +739 -0
  219. package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/prompt.md +11 -0
  220. package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/review.md +22 -0
  221. package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/screenshots/desktop.png +0 -0
  222. package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/screenshots/mobile.png +0 -0
  223. package/skills/ui-design/tests/e2e/runs/comfort-vision-preview-1/checks/browser-check.json +52 -0
  224. package/skills/ui-design/tests/e2e/runs/comfort-vision-preview-1/outputs/index.html +641 -0
  225. package/skills/ui-design/tests/e2e/runs/comfort-vision-preview-1/screenshots/desktop.png +0 -0
  226. package/skills/ui-design/tests/e2e/runs/comfort-vision-preview-1/screenshots/mobile.png +0 -0
  227. package/skills/ui-design/tests/e2e/runs/ember-prism-red-preview-1/outputs/index.html +467 -0
  228. package/skills/ui-design/tests/e2e/runs/ember-prism-red-preview-1/screenshots/browser-check.json +49 -0
  229. package/skills/ui-design/tests/e2e/runs/ember-prism-red-preview-1/screenshots/desktop.png +0 -0
  230. package/skills/ui-design/tests/e2e/runs/ember-prism-red-preview-1/screenshots/mobile.png +0 -0
  231. package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/outputs/homepage.html +373 -0
  232. package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/outputs/platform.html +378 -0
  233. package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/prompt.md +13 -0
  234. package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/review.md +26 -0
  235. package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/homepage/browser-check.json +49 -0
  236. package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/homepage/desktop.png +0 -0
  237. package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/homepage/mobile.png +0 -0
  238. package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/platform/browser-check.json +49 -0
  239. package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/platform/desktop.png +0 -0
  240. package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/platform/mobile.png +0 -0
  241. package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/checks/browser-check.json +49 -0
  242. package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/checks/language-check.txt +4 -0
  243. package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/checks/static-check.txt +2 -0
  244. package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/execution_notes.md +10 -0
  245. package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/outputs/index.html +587 -0
  246. package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/prompt.md +14 -0
  247. package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/review.md +13 -0
  248. package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/screenshots/desktop.png +0 -0
  249. package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/screenshots/mobile.png +0 -0
  250. package/skills/ui-design/tests/e2e/runs/iteration-1/deck/checks/browser-check.json +24 -0
  251. package/skills/ui-design/tests/e2e/runs/iteration-1/deck/checks/static-check.txt +2 -0
  252. package/skills/ui-design/tests/e2e/runs/iteration-1/deck/execution_notes.md +21 -0
  253. package/skills/ui-design/tests/e2e/runs/iteration-1/deck/outputs/deck.html +451 -0
  254. package/skills/ui-design/tests/e2e/runs/iteration-1/deck/screenshots/slide-01.png +0 -0
  255. package/skills/ui-design/tests/e2e/runs/iteration-1/deck/screenshots/slide-02.png +0 -0
  256. package/skills/ui-design/tests/e2e/runs/iteration-1/review.md +79 -0
  257. package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/checks/browser-check.json +26 -0
  258. package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/checks/static-check.txt +2 -0
  259. package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/execution_notes.md +20 -0
  260. package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/outputs/index.html +534 -0
  261. package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/screenshots/desktop.png +0 -0
  262. package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/screenshots/mobile.png +0 -0
  263. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/checks/browser-check.json +64 -0
  264. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/checks/language-check.txt +7 -0
  265. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/checks/quick-validate.txt +1 -0
  266. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/checks/static-console.txt +2 -0
  267. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/checks/static-homepage.txt +2 -0
  268. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/outputs/console.html +600 -0
  269. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/outputs/homepage.html +556 -0
  270. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/prompt.md +29 -0
  271. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/review.md +57 -0
  272. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/screenshots/console-desktop.png +0 -0
  273. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/screenshots/console-mobile.png +0 -0
  274. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/screenshots/homepage-desktop.png +0 -0
  275. package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/screenshots/homepage-mobile.png +0 -0
  276. package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/checks/browser-check.json +33 -0
  277. package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/checks/language-check.txt +6 -0
  278. package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/checks/quick-validate.txt +1 -0
  279. package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/checks/static-check.txt +2 -0
  280. package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/outputs/index.html +682 -0
  281. package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/prompt.md +13 -0
  282. package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/review.md +59 -0
  283. package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/screenshots/desktop.png +0 -0
  284. package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/screenshots/mobile.png +0 -0
  285. package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/outputs/page-01.html +466 -0
  286. package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/outputs/page-02.html +433 -0
  287. package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/prompt.md +13 -0
  288. package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-01/browser-check.json +49 -0
  289. package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-01/desktop.png +0 -0
  290. package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-01/mobile.png +0 -0
  291. package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-02/browser-check.json +49 -0
  292. package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-02/desktop.png +0 -0
  293. package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-02/mobile.png +0 -0
  294. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/checks/browser-check.json +49 -0
  295. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/checks/language-check.txt +3 -0
  296. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/checks/static-check.txt +2 -0
  297. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/execution_notes.md +24 -0
  298. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/outputs/index.html +723 -0
  299. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/prompt.md +15 -0
  300. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/review.md +26 -0
  301. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/screenshots/desktop.png +0 -0
  302. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/screenshots/mobile.png +0 -0
  303. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/checks/browser-dark.json +49 -0
  304. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/checks/browser-light.json +49 -0
  305. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/checks/language-check.txt +11 -0
  306. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/checks/static-dark.txt +2 -0
  307. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/checks/static-light.txt +3 -0
  308. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/execution_notes.md +23 -0
  309. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/outputs/dark.html +392 -0
  310. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/outputs/light.html +476 -0
  311. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/prompt.md +23 -0
  312. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/review.md +41 -0
  313. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/screenshots/dark/desktop.png +0 -0
  314. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/screenshots/dark/mobile.png +0 -0
  315. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/screenshots/light/desktop.png +0 -0
  316. package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/screenshots/light/mobile.png +0 -0
  317. package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/checks/browser-check.json +54 -0
  318. package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/checks/language-check.txt +5 -0
  319. package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/checks/quick-validate.txt +1 -0
  320. package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/checks/static-check.txt +2 -0
  321. package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/outputs/index.html +765 -0
  322. package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/prompt.md +15 -0
  323. package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/review.md +59 -0
  324. package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/screenshots/desktop.png +0 -0
  325. package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/screenshots/mobile.png +0 -0
  326. package/skills/ui-design/tests/e2e/runs/verdant-grid-preview-1/outputs/index.html +508 -0
  327. package/skills/ui-design/tests/e2e/runs/verdant-grid-preview-1/screenshots/browser-check.json +49 -0
  328. package/skills/ui-design/tests/e2e/runs/verdant-grid-preview-1/screenshots/desktop.png +0 -0
  329. package/skills/ui-design/tests/e2e/runs/verdant-grid-preview-1/screenshots/mobile.png +0 -0
  330. package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/checks/browser-check.json +54 -0
  331. package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/checks/language-check.txt +6 -0
  332. package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/checks/quick-validate.txt +1 -0
  333. package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/checks/static-check.txt +2 -0
  334. package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/outputs/index.html +788 -0
  335. package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/prompt.md +14 -0
  336. package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/review.md +60 -0
  337. package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/screenshots/desktop.png +0 -0
  338. package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/screenshots/mobile.png +0 -0
  339. package/skills/video-compose/SKILL.md +8 -1
  340. package/skills/web-crawler/SKILL.md +70 -0
  341. package/skills/web-crawler/scripts/crawl.mjs +538 -0
  342. package/skills/web-crawler/scripts/crawl.test.mjs +204 -0
  343. package/skills/xlsx/SKILL.md +12 -0
  344. package/skills/xlsx/scripts/opc_check.py +253 -0
  345. package/src/advisorState.js +22 -0
  346. package/src/askBridge.js +97 -3
  347. package/src/bootstrap/workingDir.js +12 -1
  348. package/src/cli/args.js +17 -1
  349. package/src/cli/configMenu.js +236 -0
  350. package/src/cli/configWizard.js +7 -5
  351. package/src/cli/print.js +37 -4
  352. package/src/cli/streamJson.js +77 -24
  353. package/src/cli/wizards/advisorWizard.js +147 -0
  354. package/src/cli/wizards/fieldForm.js +149 -0
  355. package/src/cli/wizards/imageWizard.js +60 -0
  356. package/src/cli/wizards/openRouterWizard.js +23 -0
  357. package/src/cli/wizards/providerPresets.js +95 -0
  358. package/src/cli/wizards/providerWizard.js +219 -0
  359. package/src/cli/wizards/searchWizard.js +23 -0
  360. package/src/cli/wizards/ttsWizard.js +34 -0
  361. package/src/config/configFile.js +441 -83
  362. package/src/config/configService.js +446 -0
  363. package/src/config.js +24 -64
  364. package/src/context/agentHome.js +9 -0
  365. package/src/context/archive.js +7 -2
  366. package/src/context/compact.js +8 -5
  367. package/src/context/contextLock.js +81 -0
  368. package/src/context/persistContext.js +30 -11
  369. package/src/context/reactiveCompact.js +4 -2
  370. package/src/context/recentDirs.js +21 -61
  371. package/src/context/sessionPath.js +97 -23
  372. package/src/context/sessionRegistry.js +303 -24
  373. package/src/context/tokenCounter.js +18 -0
  374. package/src/context/workspaceIndex.js +731 -0
  375. package/src/infra/verification.js +28 -15
  376. package/src/llm/client.js +394 -159
  377. package/src/llm/providers/anthropicFormat.js +241 -0
  378. package/src/llm/providers/openaiFormat.js +190 -0
  379. package/src/loop.js +219 -32
  380. package/src/main.js +61 -11
  381. package/src/messageQueue.js +97 -0
  382. package/src/multimodal.js +203 -0
  383. package/src/plugin-sdk.js +15 -0
  384. package/src/plugins/commandRouter.js +3 -0
  385. package/src/plugins/hookEngine.js +5 -1
  386. package/src/plugins/pluginLifecycle.js +28 -0
  387. package/src/plugins/pluginLoader.js +2 -1
  388. package/src/plugins/pluginRunner.js +49 -21
  389. package/src/plugins/transcript.js +4 -3
  390. package/src/prompts/pluginList.js +5 -5
  391. package/src/prompts/projectInstructions.js +3 -3
  392. package/src/prompts/promptAssembly.js +133 -144
  393. package/src/prompts/skillList.js +12 -22
  394. package/src/prompts/system.js +0 -1
  395. package/src/session/runAgentTurn.js +70 -0
  396. package/src/session/runTurn.js +41 -6
  397. package/src/toolGate.js +17 -0
  398. package/src/tools/advisor/advisor.js +379 -0
  399. package/src/tools/agent/agent.js +555 -0
  400. package/src/tools/agent/agentTypes.js +59 -0
  401. package/src/tools/agent/coordinator.js +93 -0
  402. package/src/tools/agent/worktree.js +270 -0
  403. package/src/tools/ask/ask.js +7 -2
  404. package/src/tools/bash/bash.js +112 -18
  405. package/src/tools/download/download.js +144 -0
  406. package/src/tools/edit/edit.js +1 -0
  407. package/src/tools/edit/multi-edit.js +1 -0
  408. package/src/tools/genimage/genimage.js +242 -0
  409. package/src/tools/genspeech/genspeech.js +67 -0
  410. package/src/tools/glob/glob.js +1 -0
  411. package/src/tools/grep/grep.js +3 -0
  412. package/src/tools/grep/rgPath.js +2 -0
  413. package/src/tools/index.js +25 -2
  414. package/src/tools/read/read.js +1 -0
  415. package/src/tools/shared/killTree.js +52 -0
  416. package/src/tools/toolProgressBridge.js +48 -0
  417. package/src/tools/webbrowser/agentBrowserPath.js +258 -0
  418. package/src/tools/webbrowser/browser.js +59 -42
  419. package/src/tools/webbrowser/browserControl.js +118 -0
  420. package/src/tools/webbrowser/browserDaemon.js +97 -0
  421. package/src/tools/webbrowser/browserService.js +27 -0
  422. package/src/tools/webbrowser/browserStream.js +119 -0
  423. package/src/tools/webbrowser/webbrowser.js +699 -130
  424. package/src/tools/webfetch/webfetch.js +1 -0
  425. package/src/tools/websearch/websearch.js +134 -51
  426. package/src/tools/write/write.js +1 -0
  427. package/src/ui/App.js +249 -22
  428. package/src/ui/AskQuestion.js +29 -10
  429. package/src/ui/InputBox.js +104 -12
  430. package/src/ui/LiveArea.js +112 -19
  431. package/src/ui/MessageList.js +100 -14
  432. package/src/ui/ModelPicker.js +56 -0
  433. package/src/ui/QueuedMessagesBanner.js +14 -0
  434. package/src/ui/Root.js +18 -10
  435. package/src/ui/SessionPicker.js +102 -0
  436. package/src/ui/StatusLine.js +13 -4
  437. package/src/ui/WorkspacePicker.js +55 -0
  438. package/src/ui/figures.js +44 -0
  439. package/src/ui/hooks/askSlot.js +82 -0
  440. package/src/ui/hooks/useChat.js +358 -64
  441. package/src/ui/hooks/usePasteHandler.js +11 -1
  442. package/src/ui/hooks/useTextBuffer.js +1 -3
  443. package/src/ui/liveViewport.js +5 -1
  444. package/src/ui/markdown.js +206 -0
  445. package/src/ui/textBuffer.js +0 -7
  446. package/src/ui/theme.js +32 -0
  447. package/src/utils/debugLog.js +0 -4
  448. package/src/utils/resourcePaths.js +2 -2
  449. package/src/utils/stripThink.js +50 -0
  450. package/src/web/browserBridge.js +447 -0
  451. package/src/web/protocol.js +19 -0
  452. package/workflows/adaptive-research.yaml +13 -5
  453. package/workflows/book-review-short.yaml +36 -10
  454. package/workflows/e2e-write-greet.yaml +6 -2
  455. package/workflows/illustrate.yaml +227 -0
  456. package/workflows/plan.yaml +460 -179
  457. package/workflows/ppt.yaml +1659 -0
  458. package/workflows/ralph-loop.yaml +199 -0
  459. package/workflows/schema.json +81 -23
  460. package/workflows/webppt.yaml +496 -0
  461. package/workflows/word.yaml +710 -0
  462. package/workflows/youtube-shorts.yaml +46 -15
  463. package/MINIMAL-TRACE.md +0 -77
  464. package/plugins/HOW-TO-WRITE-A-PLUGIN.md +0 -186
  465. package/plugins/ralph-wiggum/.claude-plugin/plugin.json +0 -9
  466. package/plugins/ralph-wiggum/README.md +0 -197
  467. package/plugins/ralph-wiggum/commands/cancel-ralph.md +0 -18
  468. package/plugins/ralph-wiggum/commands/help.md +0 -137
  469. package/plugins/ralph-wiggum/commands/ralph-loop.md +0 -85
  470. package/plugins/ralph-wiggum/hooks/hooks.json +0 -15
  471. package/plugins/ralph-wiggum/hooks/stop-hook.sh +0 -191
  472. package/plugins/ralph-wiggum/plugin.js +0 -280
  473. package/plugins/ralph-wiggum/src/goalState.js +0 -258
  474. package/plugins/ralph-wiggum/src/sentinels.js +0 -76
  475. package/plugins/ralph-wiggum/src/stopHookRunner.js +0 -104
  476. package/plugins/ralph-wiggum/src/verificationGate.js +0 -202
  477. package/plugins/workflow-runner/src/miniReAct.js +0 -223
  478. package/plugins/workflow-runner/src/voteHelpers.js +0 -110
  479. package/skills/config/SKILL.md +0 -123
  480. package/skills/frontend-design/LICENSE.txt +0 -177
  481. package/skills/frontend-design/SKILL.md +0 -42
  482. package/src/ui/ProgressPanel.js +0 -54
  483. package/src/ui/StreamingBlock.js +0 -11
  484. package/src/ui/ToolStatus.js +0 -11
@@ -1,56 +1,491 @@
1
1
  /**
2
2
  * ============================================================
3
- * src/workflows/workflowState.ts —— workflow 运行状态持久化
3
+ * plugins/workflow-runner/src/workflowState.ts —— 工作流状态持久化
4
4
  * ------------------------------------------------------------
5
- * 与 GoalState 类似的轻量目录模型,但只用于 debug / 中断恢复(P0 不实现
6
- * 恢复,只写出现场)。目录结构:
5
+ * Phase 1 升级:支持断点续执行、任务身份判定、capture 回放、产物管理。
7
6
  *
8
- * <cwd>/.minimal-agent-workflow/
9
- * ├── current.json # { name, startedAt }
10
- * ├── inputs.json # 用户传入的 inputs 快照
11
- * ├── vars.json # 最后一次成功 step 后的 VarStack.snapshot()
12
- * └── progress.md # 时间戳追加的 step 完成日志
7
+ * 核心变更:
8
+ * - init() 不再无条件清空,而是先读旧状态 → 判定任务身份 → 分发 4 种模式
9
+ * - 新增 checkpoints/ 目录记录每步完成状态和 capture 变量
10
+ * - 产物生命周期:current.json.artifacts 记录工作流【声明】的产物路径(相对 cwd,
11
+ * 来自 yaml 的 def.artifacts / step.artifacts);new-task 时据此清旧产物(如旧 PLAN.md),
12
+ * completed 时据此报实际存在的产物。不再用从不写入的 artifacts/ 子目录。
13
+ * - resume 模式时回放已完成步骤的 capture 到 vars 中
14
+ * - completed 检测:成功后 archive() 把目录改名 .done,故 init() 在活动目录缺失时
15
+ * 回退读 .done/current.json(status=done + taskId 匹配 → completed),修活「completed 死代码」。
13
16
  *
14
- * init() 进 workflow 前 reset 一次;cleanup() 在 finally 把文件删掉
15
- * + rmdir(保持 /new 扫描 .minimal-agent-* 子目录的语义一致)。
16
- *
17
- * 与 GoalState 的核心区别:workflow 不需要 PHASE / completion / learnings 文件,
18
- * 因为执行流程是确定性的,没有 LLM 自规划过程。
17
+ * 目录结构(E6:按 workflow 名隔离,跨工作流互不可见/互不干扰):
18
+ * <cwd>/.minimal-agent-workflow/<name>/ (成功后改名为 <name>.done/)
19
+ * ├── current.json # { name, taskId, status, startedAt, artifacts?, lastFailedStep?, lastError? }
20
+ * ├── inputs.json # 用户传入的 inputs 快照
21
+ * ├── vars.json # 最后一次成功 step 后的 VarStack.snapshot()
22
+ * ├── progress.md # 时间戳追加的 step 完成日志
23
+ * ├── supplements.json # 贯穿补充要求(pause 反馈/澄清结论,resume 恢复进锚定)
24
+ * └── checkpoints/ # 每步一个 JSON:{ stepId, completedAt, output, captures, varsSnapshot }
25
+ * # 顶层步用原名;顶层 loop 内步用复合名 loopId@@迭代号@@stepId
26
+ * # (resume 可恢复到迭代中间,见 scanLoopResume)
27
+ * /new 按 .minimal-agent 前缀清理父目录,行为不变。
19
28
  * ============================================================
20
29
  */
21
- import { mkdir, writeFile, appendFile, rm, rename } from 'node:fs/promises';
30
+ import { createHash } from 'node:crypto';
31
+ import { mkdir, writeFile, appendFile, rm, rename, readFile, readdir } from 'node:fs/promises';
32
+ import { existsSync } from 'node:fs';
22
33
  import { join } from 'node:path';
23
- const STATE_DIR = '.minimal-agent-workflow';
34
+ import { computeTaskId, extractGoal, workflowStateDir, } from './taskIdentity.js';
24
35
  const DONE_SUFFIX = '.done';
36
+ const CHECKPOINTS_DIR = 'checkpoints';
37
+ const SUPPLEMENTS_FILE = 'supplements.json';
38
+ /**
39
+ * 顶层 loop 内步的复合 checkpoint 文件名分隔符。
40
+ * 选 '@@':yaml step id 习惯用 [a-z0-9_],不会撞;且对文件系统安全。
41
+ */
42
+ export const LOOP_CP_SEP = '@@';
43
+ /** 复合 checkpoint 名:<loopId>@@<迭代号>@@<stepId>(runner 的 CpScope 与本模块扫描共用)。 */
44
+ export function loopCheckpointName(loopId, iteration, stepId) {
45
+ return `${loopId}${LOOP_CP_SEP}${iteration}${LOOP_CP_SEP}${stepId}`;
46
+ }
47
+ /** 解析复合 checkpoint 文件名;非复合名(普通顶层步)返回 null。 */
48
+ function parseLoopCheckpointName(name) {
49
+ const parts = name.split(LOOP_CP_SEP);
50
+ if (parts.length !== 3)
51
+ return null;
52
+ const iteration = Number(parts[1]);
53
+ if (!Number.isInteger(iteration) || iteration < 0)
54
+ return null;
55
+ return { loopId: parts[0], iteration, stepId: parts[2] };
56
+ }
57
+ /**
58
+ * 工作流定义的**结构指纹**:步骤 id + 执行形态 + 嵌套块(then/else/do)骨架的 hash。
59
+ * prompt 文案、args、condition 等内容字段不参与——改提示词/参数不应作废断点;
60
+ * 改结构(增删步/换 id/换类型/调嵌套)才作废:resume 的恢复点是**索引**、循环断点是
61
+ * 复合名(loopId@@迭代@@stepId),结构一变旧 checkpoint 就对不上,按旧断点续跑会错跳步
62
+ * (曾真实发生:plan.yaml v3→v4 重构后同 goal 重跑提示「从第 2 步续跑」,跳过的步与
63
+ * 新结构毫无对应关系)。current.json 记录运行时的指纹,init 同任务重跑时比对。
64
+ */
65
+ export function computeDefFingerprint(steps) {
66
+ const skeleton = (list) => (list ?? []).map((s) => ({
67
+ id: s.id,
68
+ kind: s.type ??
69
+ (s.tool ? 'tool' : s.skill ? 'skill' : s.agent ? 'agent' : s.llm ? 'llm' : '?'),
70
+ then: s.then ? skeleton(s.then) : undefined,
71
+ else: s.else ? skeleton(s.else) : undefined,
72
+ do: s.do ? skeleton(s.do) : undefined,
73
+ }));
74
+ return createHash('sha1')
75
+ .update(JSON.stringify(skeleton(steps)))
76
+ .digest('hex')
77
+ .slice(0, 16);
78
+ }
25
79
  export class WorkflowState {
26
80
  dir;
27
- constructor(workingDir) {
28
- this.dir = join(workingDir, STATE_DIR);
81
+ workingDir;
82
+ constructor(workingDir, workflowName) {
83
+ this.workingDir = workingDir;
84
+ // 按 workflow 名隔离(与 taskIdentity.computeTaskId 读的是同一权威路径)
85
+ this.dir = workflowStateDir(workingDir, workflowName);
29
86
  }
30
- async init(name, inputs) {
31
- // 启动新 workflow 时清理旧状态(含之前的归档)
32
- await rm(this.dir, { recursive: true, force: true }).catch(() => { });
33
- await rm(this.dir + DONE_SUFFIX, { recursive: true, force: true }).catch(() => { });
34
- await mkdir(this.dir, { recursive: true });
35
- await writeFile(join(this.dir, 'current.json'), JSON.stringify({ name, startedAt: new Date().toISOString() }, null, 2), 'utf8');
36
- await writeFile(join(this.dir, 'inputs.json'), JSON.stringify(inputs, null, 2), 'utf8');
37
- await writeFile(join(this.dir, 'progress.md'), `# ${name}\n\n`, 'utf8');
87
+ /**
88
+ * 初始化工作流状态 —— 核心入口,返回恢复信息。
89
+ *
90
+ * 4 种模式:
91
+ * 1. fresh — 首次运行此工作流(无旧状态)
92
+ * 2. new-task — 不同任务 → 清理旧产物后全新开始
93
+ * 3. completed — 同一任务已完成 → 返回产物列表
94
+ * 4. resume — 同一任务未完成 → 扫描 checkpoint 决定恢复点
95
+ *
96
+ * hash 相等 = 同任务(权威信号,与时间无关)。hash 不等且旧任务【未完成】时
97
+ * 不再一票否决 new-task:若提供了 arbitrate(语义仲裁器,见 taskIdentity.ts),
98
+ * 由它判定新输入是「旧任务的延续指令(如"继续")→ resume」还是「全新任务 → new-task」。
99
+ */
100
+ async init(name, inputs, steps,
101
+ // 跨次重跑回退步数(= WorkflowDef.self_heal.backoff),runWorkflow 注入;缺省 1。
102
+ selfHealBackoff = 1,
103
+ // 工作流【声明】的产物路径(相对 cwd,= def.artifacts + step.artifacts),runWorkflow 注入。
104
+ declaredArtifacts = [],
105
+ // 语义仲裁器(hash 不等 + 旧任务未完成时的二审),runWorkflow 注入;缺省直接 new-task。
106
+ arbitrate) {
107
+ // 1. 计算当前任务的 identity(goal 内容 hash 是唯一权威信号)
108
+ // 与本次定义的结构指纹(resume 兼容性信号:yaml 结构变了旧断点即作废)
109
+ const identity = computeTaskId(name, inputs, this.workingDir);
110
+ const fp = computeDefFingerprint(steps);
111
+ // 2. 尝试读取活动目录的 current.json
112
+ const oldState = await this.readCurrentState();
113
+ if (!oldState) {
114
+ // 活动目录无状态 —— 可能是「上次成功已归档到 .done」。读归档判定 completed / 不同 goal 新任务。
115
+ const archived = await this.readArchivedState();
116
+ if (archived && archived.name === name) {
117
+ if (archived.taskId === identity.hash) {
118
+ // 模式 3: completed —— 同任务此前已成功(报实际存在的声明产物)
119
+ return {
120
+ mode: 'completed',
121
+ artifacts: this.existingArtifacts(archived.artifacts ?? declaredArtifacts),
122
+ };
123
+ }
124
+ // 同名 workflow 但 goal 不同 → 全新任务:清旧归档声明产物后 fresh
125
+ // (legacy 归档无 artifacts 字段时用本次声明清单兜底——同名 workflow 的声明产物
126
+ // 语义稳定,旧任务的产物路径与本次一致的概率极高,残留比误删危害大)
127
+ const cleaned = await this.cleanupDeclaredArtifacts(archived.artifacts ?? declaredArtifacts);
128
+ await this.cleanSlate(name, inputs, identity.hash, declaredArtifacts, fp);
129
+ return {
130
+ mode: 'new-task',
131
+ startFrom: 0,
132
+ cleanedArtifacts: [
133
+ ...cleaned,
134
+ ...(await this.cleanupStaleDeclared(declaredArtifacts)),
135
+ ],
136
+ };
137
+ }
138
+ // 模式 1: fresh —— 活动 + 归档都没有,首次运行。
139
+ // 声明产物若已存在于磁盘 = 残留孤儿(如 /new 删状态目录后的旧 PLAN.md,
140
+ // artifacts 清单随 current.json 一起被删,引擎无从知道它属于谁)。
141
+ // 用户约定:全新任务开始时清理残留与中间文件——删除范围**仅限本工作流
142
+ // 声明的产物**(与运行自身对它们的覆盖写权限一致,不碰用户其他文件)。
143
+ await this.cleanSlate(name, inputs, identity.hash, declaredArtifacts, fp);
144
+ return {
145
+ mode: 'fresh',
146
+ startFrom: 0,
147
+ cleanedArtifacts: await this.cleanupStaleDeclared(declaredArtifacts),
148
+ };
149
+ }
150
+ // 3. 有活动状态(上次中断 / 失败 / 进行中,未归档)—— 用 hash 判同/异任务
151
+ if (!identity.isSameTask) {
152
+ // hash 不等 + 同名 workflow + 旧任务未完成 → 语义仲裁二审:
153
+ // 新输入可能是「继续」这类延续指令(goal 文本必然与旧任务不同,按旧规则
154
+ // 会被误判 new-task 把没做完的产物清掉重开)。不同名 workflow / 旧任务已
155
+ // 完成 / 未提供仲裁器 → 维持 new-task。仲裁器自身抛错也兜底 new-task。
156
+ if (arbitrate &&
157
+ identity.reason === 'hash_diff' &&
158
+ oldState.name === name &&
159
+ oldState.status !== 'done' &&
160
+ // 定义结构已变(或 legacy 无指纹)→ 旧断点不可续,仲裁 resume 无意义,
161
+ // 跳过仲裁直接走 new-task
162
+ oldState.defFingerprint === fp) {
163
+ const prevGoal = extractGoal((await this.readInputs()) ?? {});
164
+ const newGoal = extractGoal(inputs);
165
+ let verdict = 'new';
166
+ try {
167
+ verdict = await arbitrate({
168
+ workflowName: name,
169
+ prevGoal,
170
+ newGoal,
171
+ completedStepIds: await this.scanCheckpoints(steps),
172
+ totalSteps: steps.length,
173
+ artifacts: oldState.artifacts ?? [],
174
+ });
175
+ }
176
+ catch {
177
+ verdict = 'new';
178
+ }
179
+ if (verdict === 'resume') {
180
+ // 延续旧任务:状态目录原样保留(taskId 仍是旧 goal 的 hash——
181
+ // 下次再输「继续」依然 hash 不等 → 再次仲裁快路径命中,语义自洽)。
182
+ const info = await this.buildResumeInfo(oldState, steps, selfHealBackoff);
183
+ info.prevGoal = prevGoal;
184
+ info.supplementaryGoal = newGoal;
185
+ return info;
186
+ }
187
+ }
188
+ // 模式 2: new-task —— 不同任务,清旧声明产物 + 旧状态后全新开始。
189
+ // legacy 状态文件无 artifacts 字段时:仅当同名 workflow 用本次声明清单兜底
190
+ //(不同名 workflow 的产物不是我们的,不能殃及)。
191
+ const cleaned = await this.cleanupDeclaredArtifacts(oldState.artifacts ?? (oldState.name === name ? declaredArtifacts : []));
192
+ await this.cleanSlate(name, inputs, identity.hash, declaredArtifacts, fp);
193
+ return {
194
+ mode: 'new-task',
195
+ startFrom: 0,
196
+ cleanedArtifacts: [
197
+ ...cleaned,
198
+ ...(await this.cleanupStaleDeclared(declaredArtifacts)),
199
+ ],
200
+ };
201
+ }
202
+ // 4. 同一任务 —— 检查完成状态(兜底:正常成功会 archive,故活动目录 done 少见)
203
+ if (oldState.status === 'done') {
204
+ return {
205
+ mode: 'completed',
206
+ artifacts: this.existingArtifacts(oldState.artifacts ?? declaredArtifacts),
207
+ };
208
+ }
209
+ // 4.5 定义结构变更守卫:同任务但 yaml 结构改过(增删步/换 id/调嵌套)——
210
+ // resume 恢复点是索引、循环断点是复合名,结构一变旧 checkpoint 全对不上,
211
+ // 按旧断点续跑会错跳步(曾真实发生:plan v3→v4 重构后同 goal 重跑
212
+ // 「从第 2 步续跑」,用户困惑是 bug 还是残留)。旧现场作废、全新开始,
213
+ // runner 经 defChanged 旗标向用户明示。legacy 状态(无 defFingerprint
214
+ // 字段)无从验证兼容性,同样按变更处理(一次性升级成本,安全优先)。
215
+ if (oldState.defFingerprint !== fp) {
216
+ const cleaned = await this.cleanupDeclaredArtifacts(oldState.artifacts ?? declaredArtifacts);
217
+ await this.cleanSlate(name, inputs, identity.hash, declaredArtifacts, fp);
218
+ return {
219
+ mode: 'new-task',
220
+ startFrom: 0,
221
+ defChanged: true,
222
+ cleanedArtifacts: [
223
+ ...cleaned,
224
+ ...(await this.cleanupStaleDeclared(declaredArtifacts)),
225
+ ],
226
+ };
227
+ }
228
+ // 5. 模式 4: resume —— 同一任务未完成,扫描 checkpoint 决定恢复点。
229
+ return this.buildResumeInfo(oldState, steps, selfHealBackoff);
230
+ }
231
+ /**
232
+ * 构建 resume 信息:扫描 checkpoint 决定恢复点 + 加载 capture 回放数据。
233
+ * 回退步数由 WorkflowDef.self_heal.backoff 经 runWorkflow 传入(缺省 1)。
234
+ * 同 goal resume(hash 相等)与仲裁延续 resume(hash 不等但判定延续)共用。
235
+ */
236
+ async buildResumeInfo(oldState, steps, selfHealBackoff) {
237
+ const completedSteps = await this.scanCheckpoints(steps);
238
+ // 恢复点 = 最后一个已完成步在 steps[] 中的【索引】+1 - backoff。
239
+ // 不能用 checkpoint【计数】当索引:when=false 跳过步 / pause 步不记 checkpoint,
240
+ // 计数会低估位置 → resume 重复执行已跑过的步(对非幂等 tool 步有实害)。
241
+ // 已完成步是连续前缀时索引法与计数法等价(向后兼容)。
242
+ const lastCompletedId = completedSteps[completedSteps.length - 1];
243
+ const lastIdx = lastCompletedId !== undefined
244
+ ? steps.findIndex((s) => s.id === lastCompletedId)
245
+ : -1;
246
+ const recoveryStart = Math.max(0, lastIdx + 1 - selfHealBackoff);
247
+ // 加载 capturedVars 用于回放
248
+ const capturedVars = await this.loadAllCaptures(completedSteps);
249
+ // 循环级恢复:中断发生在某顶层 loop 的迭代中间(该 loop 自身无完成 checkpoint、
250
+ // 但有复合迭代 checkpoint)→ 顶层直接定位到该 loop、迭代内续跑,
251
+ // 不再整条循环从头重来(plan.yaml 95% 的工作都在一个 loop 里,此前粒度形同虚设)。
252
+ const loopResume = await this.scanLoopResume(steps, completedSteps, selfHealBackoff);
253
+ if (loopResume) {
254
+ return {
255
+ mode: 'resume',
256
+ startFrom: loopResume.loopIndex,
257
+ completedStepIds: completedSteps,
258
+ failedStep: oldState.lastFailedStep,
259
+ recoveryStart: loopResume.loopIndex,
260
+ lastError: oldState.lastError,
261
+ capturedVars,
262
+ loopResume,
263
+ };
264
+ }
265
+ return {
266
+ mode: 'resume',
267
+ startFrom: recoveryStart,
268
+ completedStepIds: completedSteps,
269
+ failedStep: oldState.lastFailedStep,
270
+ recoveryStart,
271
+ lastError: oldState.lastError,
272
+ capturedVars,
273
+ };
274
+ }
275
+ /**
276
+ * 扫描复合迭代 checkpoint(loopId@@iter@@stepId),产出进行中循环的恢复信息。
277
+ * 候选条件:顶层 type=loop 步 + 自身无完成 checkpoint(completedTopIds 不含它)。
278
+ * 多个候选(罕见,前一循环中断后又跑到后一循环)取顶层索引最大者(最远进度)。
279
+ */
280
+ async scanLoopResume(steps, completedTopIds, selfHealBackoff) {
281
+ const cpDir = join(this.dir, CHECKPOINTS_DIR);
282
+ let files;
283
+ try {
284
+ files = await readdir(cpDir);
285
+ }
286
+ catch {
287
+ return null;
288
+ }
289
+ const completedTop = new Set(completedTopIds);
290
+ // loopId → iteration → stepId 集合
291
+ const byLoop = new Map();
292
+ for (const f of files) {
293
+ if (!f.endsWith('.json'))
294
+ continue;
295
+ const parsed = parseLoopCheckpointName(f.replace(/\.json$/, ''));
296
+ if (!parsed)
297
+ continue;
298
+ let iters = byLoop.get(parsed.loopId);
299
+ if (!iters)
300
+ byLoop.set(parsed.loopId, (iters = new Map()));
301
+ let ids = iters.get(parsed.iteration);
302
+ if (!ids)
303
+ iters.set(parsed.iteration, (ids = new Set()));
304
+ ids.add(parsed.stepId);
305
+ }
306
+ if (byLoop.size === 0)
307
+ return null;
308
+ let best = null;
309
+ for (const [loopId, iters] of byLoop) {
310
+ const loopIndex = steps.findIndex((s) => s.id === loopId && s.type === 'loop');
311
+ if (loopIndex === -1)
312
+ continue; // yaml 改动后的孤儿 checkpoint,忽略
313
+ if (completedTop.has(loopId))
314
+ continue; // 该循环已整体完成
315
+ const loopDef = steps[loopIndex];
316
+ const doSteps = loopDef.do ?? [];
317
+ const validInner = new Set(doSteps.map((s) => s.id));
318
+ const iteration = Math.max(...iters.keys());
319
+ const innerIds = [...(iters.get(iteration) ?? [])]
320
+ .filter((id) => validInner.has(id))
321
+ .sort((a, b) => doSteps.findIndex((s) => s.id === a) - doSteps.findIndex((s) => s.id === b));
322
+ if (innerIds.length === 0)
323
+ continue;
324
+ const lastInnerIdx = doSteps.findIndex((s) => s.id === innerIds[innerIds.length - 1]);
325
+ const innerStartFrom = Math.max(0, lastInnerIdx + 1 - selfHealBackoff);
326
+ // 中断时刻最近的 vars 快照(迭代内最后一个完成步的 checkpoint)
327
+ let lastVarsSnapshot;
328
+ try {
329
+ const raw = await readFile(join(cpDir, `${loopCheckpointName(loopId, iteration, innerIds[innerIds.length - 1])}.json`), 'utf-8');
330
+ lastVarsSnapshot = JSON.parse(raw).varsSnapshot;
331
+ }
332
+ catch {
333
+ // 快照读失败不阻断:仍可定位迭代,变量靠顶层 capture 回放兜底
334
+ }
335
+ const candidate = {
336
+ loopId,
337
+ loopIndex,
338
+ iteration,
339
+ innerStartFrom,
340
+ completedInnerIds: innerIds,
341
+ lastVarsSnapshot,
342
+ };
343
+ if (!best || candidate.loopIndex > best.loopIndex)
344
+ best = candidate;
345
+ }
346
+ return best;
38
347
  }
348
+ // ---- 公共方法:贯穿补充要求持久化(goalSupplements,runner 写/读) ----
349
+ /** 追加一条用户补充要求到 supplements.json(resume 跨进程不丢)。 */
350
+ async appendSupplement(text) {
351
+ const list = await this.readSupplements();
352
+ list.push(text);
353
+ await writeFile(join(this.dir, SUPPLEMENTS_FILE), JSON.stringify(list, null, 2), 'utf-8').catch(() => { });
354
+ }
355
+ /** 读取已累积的补充要求列表(无文件 / 解析失败返回 [])。 */
356
+ async readSupplements() {
357
+ try {
358
+ const raw = await readFile(join(this.dir, SUPPLEMENTS_FILE), 'utf-8');
359
+ const parsed = JSON.parse(raw);
360
+ return Array.isArray(parsed) ? parsed.filter((x) => typeof x === 'string') : [];
361
+ }
362
+ catch {
363
+ return [];
364
+ }
365
+ }
366
+ // ---- 公共方法:checkpoint / 失败 / 完成 ----
367
+ /** 记录单个步骤成功完成(含 capture 变量和 vars 快照) */
368
+ async recordCheckpoint(stepId, output, captures, varsSnapshot) {
369
+ const cpDir = join(this.dir, CHECKPOINTS_DIR);
370
+ await mkdir(cpDir, { recursive: true }).catch(() => { });
371
+ const data = {
372
+ stepId,
373
+ completedAt: new Date().toISOString(),
374
+ output,
375
+ captures,
376
+ varsSnapshot,
377
+ };
378
+ await writeFile(join(cpDir, `${stepId}.json`), JSON.stringify(data, null, 2), 'utf-8');
379
+ }
380
+ /** 记录步骤失败:更新 current.json 的 lastFailedStep 和 lastError */
381
+ async recordFailure(stepId, error) {
382
+ const current = await this.readCurrentState();
383
+ if (current) {
384
+ current.lastFailedStep = stepId;
385
+ current.lastError = error;
386
+ current.status = 'failed';
387
+ await this.writeCurrent(current);
388
+ }
389
+ }
390
+ /** 标记整个工作流完成 */
391
+ async markDone() {
392
+ const current = await this.readCurrentState();
393
+ if (current) {
394
+ current.status = 'done';
395
+ await this.writeCurrent(current);
396
+ }
397
+ }
398
+ // ---- 公共方法:进度与变量(保持原有签名兼容) ----
399
+ /** 追加进度日志 */
39
400
  async appendProgress(line) {
40
401
  const ts = new Date().toISOString().replace('T', ' ').slice(0, 19);
41
- await appendFile(join(this.dir, 'progress.md'), `- ${ts} ${line}\n`, 'utf8').catch(() => { });
402
+ await appendFile(join(this.dir, 'progress.md'), `- ${ts} ${line}\n`, 'utf-8').catch(() => { });
42
403
  }
404
+ /** 写入 vars 快照 */
43
405
  async writeVars(snapshot) {
44
- await writeFile(join(this.dir, 'vars.json'), JSON.stringify(snapshot, null, 2), 'utf8').catch(() => { });
406
+ await writeFile(join(this.dir, 'vars.json'), JSON.stringify(snapshot, null, 2), 'utf-8').catch(() => { });
407
+ }
408
+ /**
409
+ * 扫描 checkpoints/ 目录,返回按 steps 数组顺序排列的已完成 step id 列表。
410
+ * 只返回在 steps[] 中存在的 id(防止 YAML 改动后 orphaned checkpoint 干扰恢复)。
411
+ */
412
+ async scanCheckpoints(steps) {
413
+ const cpDir = join(this.dir, CHECKPOINTS_DIR);
414
+ const validIds = new Set(steps.map((s) => s.id));
415
+ try {
416
+ const files = await readdir(cpDir);
417
+ const ids = [];
418
+ for (const f of files) {
419
+ if (!f.endsWith('.json'))
420
+ continue;
421
+ const stepId = f.replace(/\.json$/, '');
422
+ if (validIds.has(stepId))
423
+ ids.push(stepId);
424
+ }
425
+ // 按 steps 数组中的原始顺序排列(非文件系统顺序)
426
+ return ids.sort((a, b) => {
427
+ const ai = steps.findIndex((s) => s.id === a);
428
+ const bi = steps.findIndex((s) => s.id === b);
429
+ return ai - bi;
430
+ });
431
+ }
432
+ catch {
433
+ return [];
434
+ }
435
+ }
436
+ /** 加载最近一次成功的 vars 快照 */
437
+ async loadLastGoodVars() {
438
+ try {
439
+ const raw = await readFile(join(this.dir, 'vars.json'), 'utf-8');
440
+ return JSON.parse(raw);
441
+ }
442
+ catch {
443
+ return null;
444
+ }
445
+ }
446
+ /** 加载所有已完成步骤的 capture 变量(用于 resume 时回放到 VarStack) */
447
+ async loadAllCaptures(stepIds) {
448
+ const result = {};
449
+ const cpDir = join(this.dir, CHECKPOINTS_DIR);
450
+ for (const sid of stepIds) {
451
+ try {
452
+ const raw = await readFile(join(cpDir, `${sid}.json`), 'utf-8');
453
+ const cp = JSON.parse(raw);
454
+ if (cp.captures && Object.keys(cp.captures).length > 0) {
455
+ result[sid] = cp.captures;
456
+ }
457
+ }
458
+ catch {
459
+ // 单个 checkpoint 读失败不阻断整体
460
+ }
461
+ }
462
+ return result;
45
463
  }
464
+ // ---- 私有方法:声明式产物生命周期 ----
465
+ /** 删除工作流【声明】的产物文件(相对 cwd),用于 new-task 清理旧任务残留(如旧 PLAN.md)。
466
+ * 仅删工作流自己声明的产物、仅 force-rm 文件,scoped 安全。返回清理过的路径列表。 */
467
+ async cleanupDeclaredArtifacts(paths) {
468
+ for (const p of paths) {
469
+ await rm(join(this.workingDir, p), { force: true }).catch(() => { });
470
+ }
471
+ return paths;
472
+ }
473
+ /** 从声明产物路径里过滤出 cwd 下【实际存在】的文件(completed 报真实产物用)。 */
474
+ existingArtifacts(paths) {
475
+ return paths.filter((p) => existsSync(join(this.workingDir, p)));
476
+ }
477
+ /** 清理【实际存在】的本次声明产物(fresh/new-task 启动时清残留孤儿),返回真正删掉的路径。 */
478
+ async cleanupStaleDeclared(declaredArtifacts) {
479
+ return this.cleanupDeclaredArtifacts(this.existingArtifacts(declaredArtifacts));
480
+ }
481
+ // ---- 公共方法:归档与清理(保持原有签名兼容) ----
46
482
  /**
47
483
  * 归档(成功完成时调用):重命名状态目录为 .done 后缀,保留所有中间产物。
48
- * vars.json / progress.md / inputs.json 全部保留——供后续对话 Read 回溯。
484
+ * vars.json / progress.md / inputs.json / checkpoints/ 全部保留——供后续对话 Read 回溯。
49
485
  */
50
486
  async archive() {
51
487
  const doneDir = this.dir + DONE_SUFFIX;
52
488
  try {
53
- // 先清理旧的归档(如果存在)
54
489
  await rm(doneDir, { recursive: true, force: true });
55
490
  }
56
491
  catch {
@@ -63,12 +498,60 @@ export class WorkflowState {
63
498
  // rename 失败时静默(某些文件系统/权限问题),保留原目录
64
499
  }
65
500
  }
66
- /**
67
- * 强制清理(/new 或新 workflow init 时调用):删除状态目录(含 .done 归档)。
68
- */
501
+ /** 强制清理(/new 或新任务 init 时调用):删除状态目录(含 .done 归档) */
69
502
  async cleanup() {
70
503
  await rm(this.dir, { recursive: true, force: true }).catch(() => { });
71
- // 同时清理可能的归档目录
72
504
  await rm(this.dir + DONE_SUFFIX, { recursive: true, force: true }).catch(() => { });
73
505
  }
506
+ // ---- 私有方法 ----
507
+ /** 创建全新的空白状态目录(含 checkpoints/ 子目录),并记录声明产物清单。 */
508
+ async cleanSlate(name, inputs, taskId, declaredArtifacts = [], defFingerprint) {
509
+ await this.cleanup();
510
+ await mkdir(this.dir, { recursive: true });
511
+ await mkdir(join(this.dir, CHECKPOINTS_DIR), { recursive: true });
512
+ await this.writeCurrent({
513
+ name,
514
+ taskId,
515
+ status: 'running',
516
+ startedAt: new Date().toISOString(),
517
+ artifacts: declaredArtifacts,
518
+ defFingerprint,
519
+ });
520
+ await writeFile(join(this.dir, 'inputs.json'), JSON.stringify(inputs, null, 2), 'utf-8');
521
+ await writeFile(join(this.dir, 'progress.md'), `# ${name}\n\n`, 'utf-8');
522
+ }
523
+ /** 读取旧任务的 inputs.json(仲裁时取旧 goal 用),失败返回 null */
524
+ async readInputs() {
525
+ try {
526
+ const raw = await readFile(join(this.dir, 'inputs.json'), 'utf-8');
527
+ return JSON.parse(raw);
528
+ }
529
+ catch {
530
+ return null;
531
+ }
532
+ }
533
+ /** 读取 current.json,解析失败或文件不存在返回 null */
534
+ async readCurrentState() {
535
+ try {
536
+ const raw = await readFile(join(this.dir, 'current.json'), 'utf-8');
537
+ return JSON.parse(raw);
538
+ }
539
+ catch {
540
+ return null;
541
+ }
542
+ }
543
+ /** 读取归档目录(.done)的 current.json,用于 completed 检测(成功后 dir 被 archive 改名)。 */
544
+ async readArchivedState() {
545
+ try {
546
+ const raw = await readFile(join(this.dir + DONE_SUFFIX, 'current.json'), 'utf-8');
547
+ return JSON.parse(raw);
548
+ }
549
+ catch {
550
+ return null;
551
+ }
552
+ }
553
+ /** 写入 current.json */
554
+ async writeCurrent(data) {
555
+ await writeFile(join(this.dir, 'current.json'), JSON.stringify(data, null, 2), 'utf-8');
556
+ }
74
557
  }
@@ -1,7 +1,6 @@
1
1
  ---
2
2
  name: adversarial-review
3
3
  description: 质疑一个结论 / 计划 / 既有评审 / 设计方案是否站得住脚——默认怀疑、逼出证据,把发现分成「真问题 / 误报 / 待澄清」。注意:若用户只是想给代码找冗余 / 反模式 / 做常规质量改进,用 /simplify 而非本 skill。
4
- triggers: 对抗审查、反向提问、红队、挑战这个结论、验证某结论或方案是否站得住脚、哪些是误报哪些是真问题、审稿、复核这个判断
5
4
  ---
6
5
 
7
6
  # /adversarial-review —— 对抗式审查(反向提问,默认怀疑)