@bonesofspring/ai-rules 0.2.18 → 0.2.19

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 (653) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +5 -3
  3. package/bin/cli.js +111 -4
  4. package/package.json +6 -3
  5. package/presets/_shared/README.md +1 -1
  6. package/presets/_shared/assets/docs-specs/schemas/frontmatter-v1.schema.json +1 -1
  7. package/presets/_shared/core/agent-team/agent-artifact-contracts.md +38 -0
  8. package/presets/_shared/core/agent-team/agent-team-orchestrator.md +1 -0
  9. package/presets/_shared/core/architecture/feature-delivery-workflow.md +2 -1
  10. package/presets/_shared/core/architecture/product-specs-authoring.md +6 -3
  11. package/presets/_shared/core/architecture/product-specs.md +8 -3
  12. package/presets/_shared/core/meta/preset-no-cross-stack-leakage.md +1 -0
  13. package/presets/_shared/core/quality/anti-sycophancy-discipline.md +1 -1
  14. package/presets/_shared/core/quality/code-quality-and-refactoring.md +1 -1
  15. package/presets/_shared/core/quality/mcp-usage.md +84 -0
  16. package/presets/claude/android-kotlin/MCP.md +20 -1
  17. package/presets/claude/android-kotlin/agents/accessibility-reviewer.md +6 -0
  18. package/presets/claude/android-kotlin/agents/ci-investigator.md +8 -0
  19. package/presets/claude/android-kotlin/agents/debugger.md +8 -0
  20. package/presets/claude/android-kotlin/agents/feature-developer.md +23 -0
  21. package/presets/claude/android-kotlin/agents/migration-specialist.md +6 -0
  22. package/presets/claude/android-kotlin/agents/performance-auditor.md +6 -0
  23. package/presets/claude/android-kotlin/agents/solution-architect.md +6 -0
  24. package/presets/claude/android-kotlin/agents/task-analyst.md +17 -0
  25. package/presets/claude/android-kotlin/agents/task-router.md +6 -0
  26. package/presets/claude/android-kotlin/commands/spec-start.md +1 -1
  27. package/presets/claude/android-kotlin/mcp.json +1 -1
  28. package/presets/claude/android-kotlin/rules/README.md +1 -0
  29. package/presets/claude/android-kotlin/rules/architecture/feature-delivery.md +3 -1
  30. package/presets/claude/android-kotlin/rules/architecture/product-specs-authoring.md +6 -4
  31. package/presets/claude/android-kotlin/rules/architecture/product-specs.md +8 -4
  32. package/presets/claude/android-kotlin/rules/tooling-and-review/agent-team-orchestrator.md +2 -1
  33. package/presets/claude/android-kotlin/rules/tooling-and-review/anti-sycophancy-discipline.md +1 -1
  34. package/presets/claude/android-kotlin/rules/tooling-and-review/code-quality.md +1 -1
  35. package/presets/claude/android-kotlin/rules/tooling-and-review/mcp-usage.md +100 -0
  36. package/presets/claude/android-kotlin/rules/tooling-and-review/preset-no-cross-stack-leakage.md +2 -0
  37. package/presets/claude/android-kotlin/skills/README.md +2 -0
  38. package/presets/claude/android-kotlin/skills/ci-investigation/SKILL.md +8 -0
  39. package/presets/claude/android-kotlin/skills/debug-investigation/SKILL.md +8 -0
  40. package/presets/claude/android-kotlin/skills/feature-delivery/SKILL.md +6 -0
  41. package/presets/claude/android-kotlin/skills/spec-discovery/SKILL.md +58 -0
  42. package/presets/claude/android-kotlin/team/README.md +8 -0
  43. package/presets/claude/android-kotlin/team/fixtures/feature-full.json +1 -0
  44. package/presets/claude/android-kotlin/team/fixtures/memlog.example.md +9 -0
  45. package/presets/claude/go/MCP.md +22 -1
  46. package/presets/claude/go/agents/ci-investigator.md +8 -0
  47. package/presets/claude/go/agents/debugger.md +8 -0
  48. package/presets/claude/go/agents/feature-developer.md +23 -0
  49. package/presets/claude/go/agents/migration-specialist.md +6 -0
  50. package/presets/claude/go/agents/performance-auditor.md +6 -0
  51. package/presets/claude/go/agents/solution-architect.md +6 -0
  52. package/presets/claude/go/agents/task-analyst.md +17 -0
  53. package/presets/claude/go/agents/task-router.md +6 -0
  54. package/presets/claude/go/commands/feature-continue.md +11 -40
  55. package/presets/claude/go/commands/spec-start.md +1 -1
  56. package/presets/claude/go/mcp.json +1 -1
  57. package/presets/claude/go/rules/README.md +2 -1
  58. package/presets/claude/go/rules/architecture/feature-delivery.md +2 -1
  59. package/presets/claude/go/rules/architecture/product-specs-authoring.md +6 -4
  60. package/presets/claude/go/rules/architecture/product-specs.md +8 -4
  61. package/presets/claude/go/rules/tooling-and-review/agent-team-orchestrator.md +1 -0
  62. package/presets/claude/go/rules/tooling-and-review/anti-sycophancy-discipline.md +1 -1
  63. package/presets/claude/go/rules/tooling-and-review/code-quality.md +1 -1
  64. package/presets/claude/go/rules/tooling-and-review/mcp-usage.md +99 -0
  65. package/presets/claude/go/rules/tooling-and-review/preset-no-cross-stack-leakage.md +1 -0
  66. package/presets/claude/go/skills/README.md +1 -1
  67. package/presets/claude/go/skills/ci-investigation/SKILL.md +7 -0
  68. package/presets/claude/go/skills/code-review/SKILL.md +1 -0
  69. package/presets/claude/go/skills/debug-investigation/SKILL.md +8 -0
  70. package/presets/claude/go/skills/feature-delivery/SKILL.md +7 -1
  71. package/presets/claude/go/skills/spec-discovery/SKILL.md +58 -0
  72. package/presets/claude/go/team/README.md +8 -0
  73. package/presets/claude/go/team/fixtures/feature-full.json +46 -10
  74. package/presets/claude/go/team/fixtures/memlog.example.md +9 -0
  75. package/presets/claude/ios-swift/MCP.md +20 -1
  76. package/presets/claude/ios-swift/agents/accessibility-reviewer.md +7 -10
  77. package/presets/claude/ios-swift/agents/api-contract-reviewer.md +2 -11
  78. package/presets/claude/ios-swift/agents/ci-investigator.md +10 -11
  79. package/presets/claude/ios-swift/agents/debugger.md +10 -11
  80. package/presets/claude/ios-swift/agents/feature-developer.md +23 -0
  81. package/presets/claude/ios-swift/agents/migration-specialist.md +8 -11
  82. package/presets/claude/ios-swift/agents/performance-auditor.md +8 -11
  83. package/presets/claude/ios-swift/agents/qa-tester.md +2 -11
  84. package/presets/claude/ios-swift/agents/security-reviewer.md +2 -11
  85. package/presets/claude/ios-swift/agents/solution-architect.md +6 -0
  86. package/presets/claude/ios-swift/agents/task-analyst.md +17 -0
  87. package/presets/claude/ios-swift/agents/task-router.md +6 -0
  88. package/presets/claude/ios-swift/agents/unit-test-generator.md +2 -11
  89. package/presets/claude/ios-swift/agents/unit-test-healer.md +2 -11
  90. package/presets/claude/ios-swift/agents/unit-test-planner.md +2 -11
  91. package/presets/claude/ios-swift/agents/xcuitest-test-generator.md +1 -11
  92. package/presets/claude/ios-swift/agents/xcuitest-test-healer.md +1 -11
  93. package/presets/claude/ios-swift/agents/xcuitest-test-planner.md +1 -13
  94. package/presets/claude/ios-swift/commands/spec-start.md +1 -1
  95. package/presets/claude/ios-swift/mcp.json +1 -1
  96. package/presets/claude/ios-swift/rules/README.md +3 -1
  97. package/presets/claude/ios-swift/rules/architecture/feature-delivery.md +2 -1
  98. package/presets/claude/ios-swift/rules/architecture/product-specs-authoring.md +6 -4
  99. package/presets/claude/ios-swift/rules/architecture/product-specs.md +8 -4
  100. package/presets/claude/ios-swift/rules/tooling-and-review/agent-team-orchestrator.md +2 -1
  101. package/presets/claude/ios-swift/rules/tooling-and-review/anti-sycophancy-discipline.md +1 -1
  102. package/presets/claude/ios-swift/rules/tooling-and-review/code-quality.md +1 -1
  103. package/presets/claude/ios-swift/rules/tooling-and-review/mcp-usage.md +100 -0
  104. package/presets/claude/ios-swift/rules/tooling-and-review/preset-no-cross-stack-leakage.md +1 -0
  105. package/presets/claude/ios-swift/skills/README.md +2 -0
  106. package/presets/claude/ios-swift/skills/ci-investigation/SKILL.md +8 -0
  107. package/presets/claude/ios-swift/skills/code-review/SKILL.md +1 -1
  108. package/presets/claude/ios-swift/skills/debug-investigation/SKILL.md +9 -1
  109. package/presets/claude/ios-swift/skills/feature-delivery/SKILL.md +7 -1
  110. package/presets/claude/ios-swift/skills/spec-discovery/SKILL.md +58 -0
  111. package/presets/claude/ios-swift/team/README.md +8 -0
  112. package/presets/claude/ios-swift/team/fixtures/feature-full.json +39 -9
  113. package/presets/claude/ios-swift/team/fixtures/memlog.example.md +9 -0
  114. package/presets/claude/java/CLAUDE.md +1 -1
  115. package/presets/claude/java/MCP.md +21 -0
  116. package/presets/claude/java/agents/ci-investigator.md +8 -0
  117. package/presets/claude/java/agents/debugger.md +8 -0
  118. package/presets/claude/java/agents/feature-developer.md +23 -0
  119. package/presets/claude/java/agents/migration-specialist.md +6 -0
  120. package/presets/claude/java/agents/performance-auditor.md +6 -0
  121. package/presets/claude/java/agents/solution-architect.md +6 -0
  122. package/presets/claude/java/agents/task-analyst.md +17 -0
  123. package/presets/claude/java/agents/task-router.md +6 -0
  124. package/presets/claude/java/commands/feature-continue.md +11 -40
  125. package/presets/claude/java/commands/spec-start.md +1 -1
  126. package/presets/claude/java/mcp.json +1 -1
  127. package/presets/claude/java/rules/README.md +1 -0
  128. package/presets/claude/java/rules/architecture/feature-delivery.md +2 -1
  129. package/presets/claude/java/rules/architecture/product-specs-authoring.md +6 -4
  130. package/presets/claude/java/rules/architecture/product-specs.md +8 -4
  131. package/presets/claude/java/rules/tooling-and-review/agent-team-orchestrator.md +1 -0
  132. package/presets/claude/java/rules/tooling-and-review/anti-sycophancy-discipline.md +1 -1
  133. package/presets/claude/java/rules/tooling-and-review/code-quality.md +1 -1
  134. package/presets/claude/java/rules/tooling-and-review/mcp-usage.md +98 -0
  135. package/presets/claude/java/rules/tooling-and-review/preset-no-cross-stack-leakage.md +1 -0
  136. package/presets/claude/java/skills/README.md +1 -1
  137. package/presets/claude/java/skills/ci-investigation/SKILL.md +7 -0
  138. package/presets/claude/java/skills/code-review/SKILL.md +1 -0
  139. package/presets/claude/java/skills/debug-investigation/SKILL.md +8 -0
  140. package/presets/claude/java/skills/feature-delivery/SKILL.md +7 -1
  141. package/presets/claude/java/skills/spec-discovery/SKILL.md +58 -0
  142. package/presets/claude/java/team/README.md +8 -0
  143. package/presets/claude/java/team/fixtures/feature-full.json +46 -10
  144. package/presets/claude/java/team/fixtures/memlog.example.md +9 -0
  145. package/presets/claude/mcp-ts/MCP.md +20 -1
  146. package/presets/claude/mcp-ts/agents/feature-developer.md +23 -0
  147. package/presets/claude/mcp-ts/agents/solution-architect.md +5 -0
  148. package/presets/claude/mcp-ts/agents/task-analyst.md +17 -0
  149. package/presets/claude/mcp-ts/agents/task-router.md +6 -0
  150. package/presets/claude/mcp-ts/commands/spec-start.md +1 -1
  151. package/presets/claude/mcp-ts/mcp.json +1 -1
  152. package/presets/claude/mcp-ts/rules/README.md +1 -0
  153. package/presets/claude/mcp-ts/rules/architecture/feature-delivery.md +3 -1
  154. package/presets/claude/mcp-ts/rules/architecture/product-specs-authoring.md +6 -4
  155. package/presets/claude/mcp-ts/rules/architecture/product-specs.md +8 -4
  156. package/presets/claude/mcp-ts/rules/tooling-and-review/agent-team-orchestrator.md +1 -0
  157. package/presets/claude/mcp-ts/rules/tooling-and-review/anti-sycophancy-discipline.md +1 -1
  158. package/presets/claude/mcp-ts/rules/tooling-and-review/code-quality.md +1 -1
  159. package/presets/claude/mcp-ts/rules/tooling-and-review/mcp-usage.md +99 -0
  160. package/presets/claude/mcp-ts/rules/tooling-and-review/preset-no-cross-stack-leakage.md +1 -0
  161. package/presets/claude/mcp-ts/skills/README.md +2 -0
  162. package/presets/claude/mcp-ts/skills/code-review/SKILL.md +1 -0
  163. package/presets/claude/mcp-ts/skills/debug-investigation/SKILL.md +7 -0
  164. package/presets/claude/mcp-ts/skills/feature-delivery/SKILL.md +7 -1
  165. package/presets/claude/mcp-ts/skills/spec-discovery/SKILL.md +58 -0
  166. package/presets/claude/mcp-ts/team/README.md +7 -0
  167. package/presets/claude/mcp-ts/team/fixtures/feature-full.json +5 -2
  168. package/presets/claude/mcp-ts/team/fixtures/memlog.example.md +9 -0
  169. package/presets/claude/next/MCP.md +22 -0
  170. package/presets/claude/next/agents/accessibility-reviewer.md +8 -0
  171. package/presets/claude/next/agents/ci-investigator.md +8 -0
  172. package/presets/claude/next/agents/debugger.md +12 -0
  173. package/presets/claude/next/agents/feature-developer.md +25 -0
  174. package/presets/claude/next/agents/migration-specialist.md +6 -0
  175. package/presets/claude/next/agents/performance-auditor.md +8 -0
  176. package/presets/claude/next/agents/playwright-test-generator.md +11 -1
  177. package/presets/claude/next/agents/playwright-test-healer.md +8 -1
  178. package/presets/claude/next/agents/solution-architect.md +6 -0
  179. package/presets/claude/next/agents/task-analyst.md +17 -0
  180. package/presets/claude/next/agents/task-router.md +6 -0
  181. package/presets/claude/next/commands/feature-continue.md +11 -40
  182. package/presets/claude/next/commands/spec-start.md +1 -1
  183. package/presets/claude/next/mcp.json +3 -3
  184. package/presets/claude/next/rules/README.md +5 -3
  185. package/presets/claude/next/rules/architecture/feature-delivery-workflow.md +2 -1
  186. package/presets/claude/next/rules/architecture/product-specs-authoring.md +6 -4
  187. package/presets/claude/next/rules/architecture/product-specs.md +8 -4
  188. package/presets/claude/next/rules/testing/tests-unit.md +5 -0
  189. package/presets/claude/next/rules/tooling-and-review/agent-team-orchestrator.md +2 -1
  190. package/presets/claude/next/rules/tooling-and-review/anti-sycophancy-discipline.md +1 -1
  191. package/presets/claude/next/rules/tooling-and-review/code-quality.md +1 -1
  192. package/presets/claude/next/rules/tooling-and-review/mcp-usage.md +101 -0
  193. package/presets/claude/next/rules/tooling-and-review/preset-no-cross-stack-leakage.md +1 -0
  194. package/presets/claude/next/skills/README.md +2 -0
  195. package/presets/claude/next/skills/ci-investigation/SKILL.md +8 -0
  196. package/presets/claude/next/skills/code-review/SKILL.md +1 -1
  197. package/presets/claude/next/skills/debug-investigation/SKILL.md +13 -1
  198. package/presets/claude/next/skills/feature-delivery/SKILL.md +9 -1
  199. package/presets/claude/next/skills/spec-discovery/SKILL.md +58 -0
  200. package/presets/claude/next/team/README.md +11 -0
  201. package/presets/claude/next/team/fixtures/feature-full.json +43 -9
  202. package/presets/claude/next/team/fixtures/memlog.example.md +9 -0
  203. package/presets/claude/nuxt/MCP.md +22 -0
  204. package/presets/claude/nuxt/agents/accessibility-reviewer.md +8 -0
  205. package/presets/claude/nuxt/agents/ci-investigator.md +8 -0
  206. package/presets/claude/nuxt/agents/debugger.md +12 -0
  207. package/presets/claude/nuxt/agents/feature-developer.md +25 -0
  208. package/presets/claude/nuxt/agents/migration-specialist.md +6 -0
  209. package/presets/claude/nuxt/agents/performance-auditor.md +8 -0
  210. package/presets/claude/nuxt/agents/playwright-test-generator.md +11 -1
  211. package/presets/claude/nuxt/agents/playwright-test-healer.md +8 -1
  212. package/presets/claude/nuxt/agents/solution-architect.md +6 -0
  213. package/presets/claude/nuxt/agents/task-analyst.md +17 -0
  214. package/presets/claude/nuxt/agents/task-router.md +10 -4
  215. package/presets/claude/nuxt/commands/spec-start.md +1 -1
  216. package/presets/claude/nuxt/mcp.json +3 -3
  217. package/presets/claude/nuxt/rules/README.md +2 -0
  218. package/presets/claude/nuxt/rules/architecture/feature-delivery-workflow.md +2 -1
  219. package/presets/claude/nuxt/rules/architecture/product-specs-authoring.md +6 -4
  220. package/presets/claude/nuxt/rules/architecture/product-specs.md +8 -4
  221. package/presets/claude/nuxt/rules/tooling-and-review/agent-team-orchestrator.md +2 -1
  222. package/presets/claude/nuxt/rules/tooling-and-review/anti-sycophancy-discipline.md +1 -1
  223. package/presets/claude/nuxt/rules/tooling-and-review/code-quality.md +1 -1
  224. package/presets/claude/nuxt/rules/tooling-and-review/mcp-usage.md +106 -0
  225. package/presets/claude/nuxt/rules/tooling-and-review/preset-no-cross-stack-leakage.md +1 -0
  226. package/presets/claude/nuxt/skills/README.md +2 -0
  227. package/presets/claude/nuxt/skills/ci-investigation/SKILL.md +8 -0
  228. package/presets/claude/nuxt/skills/code-review/SKILL.md +1 -1
  229. package/presets/claude/nuxt/skills/debug-investigation/SKILL.md +13 -1
  230. package/presets/claude/nuxt/skills/feature-delivery/SKILL.md +9 -1
  231. package/presets/claude/nuxt/skills/spec-discovery/SKILL.md +58 -0
  232. package/presets/claude/nuxt/team/README.md +11 -0
  233. package/presets/claude/nuxt/team/fixtures/feature-full.json +43 -9
  234. package/presets/claude/nuxt/team/fixtures/memlog.example.md +9 -0
  235. package/presets/claude/php-hexagonal/CLAUDE.md +1 -1
  236. package/presets/claude/php-hexagonal/MCP.md +20 -1
  237. package/presets/claude/php-hexagonal/agents/ci-investigator.md +8 -0
  238. package/presets/claude/php-hexagonal/agents/debugger.md +8 -0
  239. package/presets/claude/php-hexagonal/agents/feature-developer.md +23 -0
  240. package/presets/claude/php-hexagonal/agents/migration-specialist.md +6 -0
  241. package/presets/claude/php-hexagonal/agents/performance-auditor.md +6 -0
  242. package/presets/claude/php-hexagonal/agents/solution-architect.md +6 -0
  243. package/presets/claude/php-hexagonal/agents/task-analyst.md +17 -0
  244. package/presets/claude/php-hexagonal/agents/task-router.md +6 -0
  245. package/presets/claude/php-hexagonal/commands/feature-continue.md +11 -40
  246. package/presets/claude/php-hexagonal/commands/spec-start.md +1 -1
  247. package/presets/claude/php-hexagonal/mcp.json +1 -1
  248. package/presets/claude/php-hexagonal/rules/README.md +1 -0
  249. package/presets/claude/php-hexagonal/rules/architecture/feature-delivery.md +2 -1
  250. package/presets/claude/php-hexagonal/rules/architecture/product-specs-authoring.md +6 -4
  251. package/presets/claude/php-hexagonal/rules/architecture/product-specs.md +8 -4
  252. package/presets/claude/php-hexagonal/rules/tooling-and-review/agent-team-orchestrator.md +1 -0
  253. package/presets/claude/php-hexagonal/rules/tooling-and-review/anti-sycophancy-discipline.md +1 -1
  254. package/presets/claude/php-hexagonal/rules/tooling-and-review/code-quality.md +1 -1
  255. package/presets/claude/php-hexagonal/rules/tooling-and-review/mcp-usage.md +98 -0
  256. package/presets/claude/php-hexagonal/rules/tooling-and-review/preset-no-cross-stack-leakage.md +1 -0
  257. package/presets/claude/php-hexagonal/skills/README.md +1 -1
  258. package/presets/claude/php-hexagonal/skills/ci-investigation/SKILL.md +7 -0
  259. package/presets/claude/php-hexagonal/skills/code-review/SKILL.md +1 -0
  260. package/presets/claude/php-hexagonal/skills/debug-investigation/SKILL.md +8 -0
  261. package/presets/claude/php-hexagonal/skills/feature-delivery/SKILL.md +7 -1
  262. package/presets/claude/php-hexagonal/skills/spec-discovery/SKILL.md +58 -0
  263. package/presets/claude/php-hexagonal/team/README.md +8 -0
  264. package/presets/claude/php-hexagonal/team/fixtures/feature-full.json +46 -10
  265. package/presets/claude/php-hexagonal/team/fixtures/memlog.example.md +9 -0
  266. package/presets/claude/php-laravel/MCP.md +21 -0
  267. package/presets/claude/php-laravel/agents/ci-investigator.md +8 -0
  268. package/presets/claude/php-laravel/agents/debugger.md +8 -0
  269. package/presets/claude/php-laravel/agents/feature-developer.md +23 -0
  270. package/presets/claude/php-laravel/agents/migration-specialist.md +6 -0
  271. package/presets/claude/php-laravel/agents/performance-auditor.md +6 -0
  272. package/presets/claude/php-laravel/agents/solution-architect.md +6 -0
  273. package/presets/claude/php-laravel/agents/task-analyst.md +17 -0
  274. package/presets/claude/php-laravel/agents/task-router.md +6 -0
  275. package/presets/claude/php-laravel/commands/feature-continue.md +11 -40
  276. package/presets/claude/php-laravel/commands/spec-start.md +1 -1
  277. package/presets/claude/php-laravel/mcp.json +1 -1
  278. package/presets/claude/php-laravel/rules/README.md +1 -0
  279. package/presets/claude/php-laravel/rules/architecture/feature-delivery.md +3 -1
  280. package/presets/claude/php-laravel/rules/architecture/product-specs-authoring.md +6 -4
  281. package/presets/claude/php-laravel/rules/architecture/product-specs.md +8 -4
  282. package/presets/claude/php-laravel/rules/tooling-and-review/agent-team-orchestrator.md +1 -0
  283. package/presets/claude/php-laravel/rules/tooling-and-review/anti-sycophancy-discipline.md +1 -1
  284. package/presets/claude/php-laravel/rules/tooling-and-review/code-quality.md +1 -1
  285. package/presets/claude/php-laravel/rules/tooling-and-review/mcp-usage.md +98 -0
  286. package/presets/claude/php-laravel/rules/tooling-and-review/preset-no-cross-stack-leakage.md +1 -0
  287. package/presets/claude/php-laravel/skills/README.md +1 -1
  288. package/presets/claude/php-laravel/skills/ci-investigation/SKILL.md +7 -0
  289. package/presets/claude/php-laravel/skills/code-review/SKILL.md +1 -0
  290. package/presets/claude/php-laravel/skills/debug-investigation/SKILL.md +8 -0
  291. package/presets/claude/php-laravel/skills/feature-delivery/SKILL.md +7 -1
  292. package/presets/claude/php-laravel/skills/spec-discovery/SKILL.md +58 -0
  293. package/presets/claude/php-laravel/team/README.md +7 -0
  294. package/presets/claude/php-laravel/team/fixtures/feature-full.json +38 -9
  295. package/presets/claude/php-laravel/team/fixtures/memlog.example.md +9 -0
  296. package/presets/claude/svelte/MCP.md +22 -0
  297. package/presets/claude/svelte/agents/accessibility-reviewer.md +8 -0
  298. package/presets/claude/svelte/agents/ci-investigator.md +8 -0
  299. package/presets/claude/svelte/agents/debugger.md +12 -0
  300. package/presets/claude/svelte/agents/feature-developer.md +25 -0
  301. package/presets/claude/svelte/agents/migration-specialist.md +6 -0
  302. package/presets/claude/svelte/agents/performance-auditor.md +8 -0
  303. package/presets/claude/svelte/agents/playwright-test-generator.md +11 -1
  304. package/presets/claude/svelte/agents/playwright-test-healer.md +8 -1
  305. package/presets/claude/svelte/agents/solution-architect.md +6 -0
  306. package/presets/claude/svelte/agents/task-analyst.md +17 -0
  307. package/presets/claude/svelte/agents/task-router.md +6 -0
  308. package/presets/claude/svelte/commands/spec-start.md +1 -1
  309. package/presets/claude/svelte/mcp.json +3 -3
  310. package/presets/claude/svelte/rules/README.md +2 -0
  311. package/presets/claude/svelte/rules/architecture/feature-delivery-workflow.md +2 -1
  312. package/presets/claude/svelte/rules/architecture/product-specs-authoring.md +6 -4
  313. package/presets/claude/svelte/rules/architecture/product-specs.md +8 -4
  314. package/presets/claude/svelte/rules/tooling-and-review/agent-team-orchestrator.md +2 -1
  315. package/presets/claude/svelte/rules/tooling-and-review/anti-sycophancy-discipline.md +1 -1
  316. package/presets/claude/svelte/rules/tooling-and-review/code-quality.md +1 -1
  317. package/presets/claude/svelte/rules/tooling-and-review/mcp-usage.md +101 -0
  318. package/presets/claude/svelte/rules/tooling-and-review/preset-no-cross-stack-leakage.md +1 -0
  319. package/presets/claude/svelte/skills/README.md +2 -0
  320. package/presets/claude/svelte/skills/ci-investigation/SKILL.md +8 -0
  321. package/presets/claude/svelte/skills/code-review/SKILL.md +1 -1
  322. package/presets/claude/svelte/skills/debug-investigation/SKILL.md +13 -1
  323. package/presets/claude/svelte/skills/feature-delivery/SKILL.md +9 -1
  324. package/presets/claude/svelte/skills/spec-discovery/SKILL.md +58 -0
  325. package/presets/claude/svelte/team/README.md +11 -0
  326. package/presets/claude/svelte/team/fixtures/feature-full.json +43 -9
  327. package/presets/claude/svelte/team/fixtures/memlog.example.md +9 -0
  328. package/presets/cursor/android-kotlin/MCP.md +20 -1
  329. package/presets/cursor/android-kotlin/agents/accessibility-reviewer.md +6 -0
  330. package/presets/cursor/android-kotlin/agents/ci-investigator.md +8 -0
  331. package/presets/cursor/android-kotlin/agents/debugger.md +8 -0
  332. package/presets/cursor/android-kotlin/agents/feature-developer.md +23 -0
  333. package/presets/cursor/android-kotlin/agents/migration-specialist.md +6 -0
  334. package/presets/cursor/android-kotlin/agents/performance-auditor.md +6 -0
  335. package/presets/cursor/android-kotlin/agents/solution-architect.md +6 -0
  336. package/presets/cursor/android-kotlin/agents/task-analyst.md +17 -0
  337. package/presets/cursor/android-kotlin/agents/task-router.md +6 -0
  338. package/presets/cursor/android-kotlin/commands/spec-start.md +1 -1
  339. package/presets/cursor/android-kotlin/mcp.json +1 -1
  340. package/presets/cursor/android-kotlin/rules/README.md +2 -0
  341. package/presets/cursor/android-kotlin/rules/agent-team-orchestrator.mdc +2 -1
  342. package/presets/cursor/android-kotlin/rules/anti-sycophancy-discipline.mdc +1 -1
  343. package/presets/cursor/android-kotlin/rules/code-quality-and-refactoring.mdc +1 -1
  344. package/presets/cursor/android-kotlin/rules/feature-delivery-workflow.mdc +3 -1
  345. package/presets/cursor/android-kotlin/rules/mcp-usage.mdc +99 -0
  346. package/presets/cursor/android-kotlin/rules/preset-no-cross-stack-leakage.mdc +3 -1
  347. package/presets/cursor/android-kotlin/rules/product-specs-authoring.mdc +6 -4
  348. package/presets/cursor/android-kotlin/rules/product-specs.mdc +8 -4
  349. package/presets/cursor/android-kotlin/skills/README.md +2 -0
  350. package/presets/cursor/android-kotlin/skills/ci-investigation/SKILL.md +8 -0
  351. package/presets/cursor/android-kotlin/skills/debug-investigation/SKILL.md +8 -0
  352. package/presets/cursor/android-kotlin/skills/feature-delivery/SKILL.md +6 -0
  353. package/presets/cursor/android-kotlin/skills/spec-discovery/SKILL.md +58 -0
  354. package/presets/cursor/android-kotlin/team/README.md +8 -0
  355. package/presets/cursor/android-kotlin/team/fixtures/feature-full.json +1 -0
  356. package/presets/cursor/android-kotlin/team/fixtures/memlog.example.md +9 -0
  357. package/presets/cursor/go/MCP.md +22 -1
  358. package/presets/cursor/go/agents/ci-investigator.md +8 -0
  359. package/presets/cursor/go/agents/debugger.md +8 -0
  360. package/presets/cursor/go/agents/feature-developer.md +23 -0
  361. package/presets/cursor/go/agents/migration-specialist.md +6 -0
  362. package/presets/cursor/go/agents/performance-auditor.md +6 -0
  363. package/presets/cursor/go/agents/solution-architect.md +6 -0
  364. package/presets/cursor/go/agents/task-analyst.md +17 -0
  365. package/presets/cursor/go/agents/task-router.md +6 -0
  366. package/presets/cursor/go/commands/spec-start.md +1 -1
  367. package/presets/cursor/go/mcp.json +1 -1
  368. package/presets/cursor/go/rules/README.md +2 -1
  369. package/presets/cursor/go/rules/agent-team-orchestrator.mdc +1 -0
  370. package/presets/cursor/go/rules/anti-sycophancy-discipline.mdc +1 -1
  371. package/presets/cursor/go/rules/code-quality-and-refactoring.mdc +1 -1
  372. package/presets/cursor/go/rules/feature-delivery-workflow.mdc +2 -1
  373. package/presets/cursor/go/rules/mcp-usage.mdc +98 -0
  374. package/presets/cursor/go/rules/preset-no-cross-stack-leakage.mdc +1 -0
  375. package/presets/cursor/go/rules/product-specs-authoring.mdc +6 -4
  376. package/presets/cursor/go/rules/product-specs.mdc +8 -4
  377. package/presets/cursor/go/skills/README.md +1 -1
  378. package/presets/cursor/go/skills/ci-investigation/SKILL.md +7 -0
  379. package/presets/cursor/go/skills/code-review/SKILL.md +1 -0
  380. package/presets/cursor/go/skills/debug-investigation/SKILL.md +8 -0
  381. package/presets/cursor/go/skills/feature-delivery/SKILL.md +7 -1
  382. package/presets/cursor/go/skills/spec-discovery/SKILL.md +58 -0
  383. package/presets/cursor/go/team/README.md +8 -0
  384. package/presets/cursor/go/team/fixtures/feature-full.json +46 -10
  385. package/presets/cursor/go/team/fixtures/memlog.example.md +9 -0
  386. package/presets/cursor/ios-swift/MCP.md +20 -1
  387. package/presets/cursor/ios-swift/agents/accessibility-reviewer.md +7 -10
  388. package/presets/cursor/ios-swift/agents/api-contract-reviewer.md +2 -11
  389. package/presets/cursor/ios-swift/agents/ci-investigator.md +10 -11
  390. package/presets/cursor/ios-swift/agents/debugger.md +10 -11
  391. package/presets/cursor/ios-swift/agents/feature-developer.md +23 -0
  392. package/presets/cursor/ios-swift/agents/migration-specialist.md +8 -11
  393. package/presets/cursor/ios-swift/agents/performance-auditor.md +8 -11
  394. package/presets/cursor/ios-swift/agents/qa-tester.md +2 -11
  395. package/presets/cursor/ios-swift/agents/security-reviewer.md +2 -11
  396. package/presets/cursor/ios-swift/agents/solution-architect.md +6 -0
  397. package/presets/cursor/ios-swift/agents/task-analyst.md +17 -0
  398. package/presets/cursor/ios-swift/agents/task-router.md +6 -0
  399. package/presets/cursor/ios-swift/agents/unit-test-generator.md +2 -11
  400. package/presets/cursor/ios-swift/agents/unit-test-healer.md +2 -11
  401. package/presets/cursor/ios-swift/agents/unit-test-planner.md +2 -11
  402. package/presets/cursor/ios-swift/agents/xcuitest-test-generator.md +1 -11
  403. package/presets/cursor/ios-swift/agents/xcuitest-test-healer.md +1 -11
  404. package/presets/cursor/ios-swift/agents/xcuitest-test-planner.md +1 -13
  405. package/presets/cursor/ios-swift/commands/spec-start.md +1 -1
  406. package/presets/cursor/ios-swift/mcp.json +1 -1
  407. package/presets/cursor/ios-swift/rules/README.md +2 -0
  408. package/presets/cursor/ios-swift/rules/agent-team-orchestrator.mdc +2 -1
  409. package/presets/cursor/ios-swift/rules/anti-sycophancy-discipline.mdc +1 -1
  410. package/presets/cursor/ios-swift/rules/code-quality-and-refactoring.mdc +1 -1
  411. package/presets/cursor/ios-swift/rules/feature-delivery-workflow.mdc +2 -1
  412. package/presets/cursor/ios-swift/rules/mcp-usage.mdc +99 -0
  413. package/presets/cursor/ios-swift/rules/preset-no-cross-stack-leakage.mdc +1 -0
  414. package/presets/cursor/ios-swift/rules/product-specs-authoring.mdc +6 -4
  415. package/presets/cursor/ios-swift/rules/product-specs.mdc +8 -4
  416. package/presets/cursor/ios-swift/skills/README.md +2 -0
  417. package/presets/cursor/ios-swift/skills/ci-investigation/SKILL.md +8 -0
  418. package/presets/cursor/ios-swift/skills/code-review/SKILL.md +1 -1
  419. package/presets/cursor/ios-swift/skills/debug-investigation/SKILL.md +9 -1
  420. package/presets/cursor/ios-swift/skills/feature-delivery/SKILL.md +7 -1
  421. package/presets/cursor/ios-swift/skills/spec-discovery/SKILL.md +58 -0
  422. package/presets/cursor/ios-swift/team/README.md +8 -0
  423. package/presets/cursor/ios-swift/team/fixtures/feature-full.json +39 -9
  424. package/presets/cursor/ios-swift/team/fixtures/memlog.example.md +9 -0
  425. package/presets/cursor/java/AGENTS.md +1 -1
  426. package/presets/cursor/java/MCP.md +20 -1
  427. package/presets/cursor/java/agents/ci-investigator.md +8 -0
  428. package/presets/cursor/java/agents/debugger.md +8 -0
  429. package/presets/cursor/java/agents/feature-developer.md +23 -0
  430. package/presets/cursor/java/agents/migration-specialist.md +6 -0
  431. package/presets/cursor/java/agents/performance-auditor.md +6 -0
  432. package/presets/cursor/java/agents/solution-architect.md +6 -0
  433. package/presets/cursor/java/agents/task-analyst.md +17 -0
  434. package/presets/cursor/java/agents/task-router.md +6 -0
  435. package/presets/cursor/java/commands/spec-start.md +1 -1
  436. package/presets/cursor/java/mcp.json +1 -1
  437. package/presets/cursor/java/rules/README.md +2 -1
  438. package/presets/cursor/java/rules/agent-team-orchestrator.mdc +1 -0
  439. package/presets/cursor/java/rules/anti-sycophancy-discipline.mdc +1 -1
  440. package/presets/cursor/java/rules/code-quality-and-refactoring.mdc +1 -1
  441. package/presets/cursor/java/rules/feature-delivery-workflow.mdc +2 -1
  442. package/presets/cursor/java/rules/mcp-usage.mdc +97 -0
  443. package/presets/cursor/java/rules/preset-no-cross-stack-leakage.mdc +1 -0
  444. package/presets/cursor/java/rules/product-specs-authoring.mdc +6 -4
  445. package/presets/cursor/java/rules/product-specs.mdc +8 -4
  446. package/presets/cursor/java/skills/README.md +1 -1
  447. package/presets/cursor/java/skills/ci-investigation/SKILL.md +7 -0
  448. package/presets/cursor/java/skills/code-review/SKILL.md +1 -0
  449. package/presets/cursor/java/skills/debug-investigation/SKILL.md +8 -0
  450. package/presets/cursor/java/skills/feature-delivery/SKILL.md +7 -1
  451. package/presets/cursor/java/skills/spec-discovery/SKILL.md +58 -0
  452. package/presets/cursor/java/team/README.md +8 -0
  453. package/presets/cursor/java/team/fixtures/feature-full.json +46 -10
  454. package/presets/cursor/java/team/fixtures/memlog.example.md +9 -0
  455. package/presets/cursor/mcp-ts/MCP.md +20 -1
  456. package/presets/cursor/mcp-ts/agents/feature-developer.md +23 -0
  457. package/presets/cursor/mcp-ts/agents/solution-architect.md +5 -0
  458. package/presets/cursor/mcp-ts/agents/task-analyst.md +17 -0
  459. package/presets/cursor/mcp-ts/agents/task-router.md +6 -0
  460. package/presets/cursor/mcp-ts/commands/spec-start.md +1 -1
  461. package/presets/cursor/mcp-ts/mcp.json +1 -1
  462. package/presets/cursor/mcp-ts/rules/README.md +3 -2
  463. package/presets/cursor/mcp-ts/rules/agent-team-orchestrator.mdc +1 -0
  464. package/presets/cursor/mcp-ts/rules/anti-sycophancy-discipline.mdc +1 -1
  465. package/presets/cursor/mcp-ts/rules/code-quality-and-refactoring.mdc +1 -1
  466. package/presets/cursor/mcp-ts/rules/feature-delivery-workflow.mdc +2 -1
  467. package/presets/cursor/mcp-ts/rules/mcp-usage.mdc +98 -0
  468. package/presets/cursor/mcp-ts/rules/preset-no-cross-stack-leakage.mdc +1 -0
  469. package/presets/cursor/mcp-ts/rules/product-specs-authoring.mdc +6 -4
  470. package/presets/cursor/mcp-ts/rules/product-specs.mdc +8 -4
  471. package/presets/cursor/mcp-ts/skills/README.md +2 -0
  472. package/presets/cursor/mcp-ts/skills/code-review/SKILL.md +1 -0
  473. package/presets/cursor/mcp-ts/skills/debug-investigation/SKILL.md +7 -0
  474. package/presets/cursor/mcp-ts/skills/feature-delivery/SKILL.md +7 -1
  475. package/presets/cursor/mcp-ts/skills/spec-discovery/SKILL.md +58 -0
  476. package/presets/cursor/mcp-ts/team/README.md +7 -0
  477. package/presets/cursor/mcp-ts/team/fixtures/feature-full.json +5 -2
  478. package/presets/cursor/mcp-ts/team/fixtures/memlog.example.md +9 -0
  479. package/presets/cursor/next/MCP.md +21 -1
  480. package/presets/cursor/next/agents/accessibility-reviewer.md +8 -0
  481. package/presets/cursor/next/agents/ci-investigator.md +8 -0
  482. package/presets/cursor/next/agents/debugger.md +12 -0
  483. package/presets/cursor/next/agents/feature-developer.md +25 -0
  484. package/presets/cursor/next/agents/migration-specialist.md +6 -0
  485. package/presets/cursor/next/agents/performance-auditor.md +8 -0
  486. package/presets/cursor/next/agents/playwright-test-generator.md +9 -1
  487. package/presets/cursor/next/agents/playwright-test-healer.md +9 -1
  488. package/presets/cursor/next/agents/playwright-test-planner.md +1 -1
  489. package/presets/cursor/next/agents/solution-architect.md +6 -0
  490. package/presets/cursor/next/agents/task-analyst.md +17 -0
  491. package/presets/cursor/next/agents/task-router.md +6 -0
  492. package/presets/cursor/next/commands/spec-start.md +1 -1
  493. package/presets/cursor/next/mcp.json +3 -3
  494. package/presets/cursor/next/rules/README.md +3 -2
  495. package/presets/cursor/next/rules/agent-team-orchestrator.mdc +2 -1
  496. package/presets/cursor/next/rules/anti-sycophancy-discipline.mdc +1 -1
  497. package/presets/cursor/next/rules/code-quality-and-refactoring.mdc +1 -1
  498. package/presets/cursor/next/rules/feature-delivery-workflow.mdc +2 -1
  499. package/presets/cursor/next/rules/mcp-usage.mdc +100 -0
  500. package/presets/cursor/next/rules/preset-no-cross-stack-leakage.mdc +1 -0
  501. package/presets/cursor/next/rules/product-specs-authoring.mdc +6 -4
  502. package/presets/cursor/next/rules/product-specs.mdc +8 -4
  503. package/presets/cursor/next/rules/tests-unit.mdc +5 -0
  504. package/presets/cursor/next/skills/README.md +2 -0
  505. package/presets/cursor/next/skills/ci-investigation/SKILL.md +8 -0
  506. package/presets/cursor/next/skills/code-review/SKILL.md +1 -1
  507. package/presets/cursor/next/skills/debug-investigation/SKILL.md +13 -1
  508. package/presets/cursor/next/skills/feature-delivery/SKILL.md +9 -1
  509. package/presets/cursor/next/skills/spec-discovery/SKILL.md +58 -0
  510. package/presets/cursor/next/team/README.md +11 -0
  511. package/presets/cursor/next/team/fixtures/feature-full.json +1 -0
  512. package/presets/cursor/next/team/fixtures/memlog.example.md +9 -0
  513. package/presets/cursor/nuxt/MCP.md +21 -1
  514. package/presets/cursor/nuxt/agents/accessibility-reviewer.md +8 -0
  515. package/presets/cursor/nuxt/agents/ci-investigator.md +8 -0
  516. package/presets/cursor/nuxt/agents/debugger.md +12 -0
  517. package/presets/cursor/nuxt/agents/feature-developer.md +25 -0
  518. package/presets/cursor/nuxt/agents/migration-specialist.md +6 -0
  519. package/presets/cursor/nuxt/agents/performance-auditor.md +8 -0
  520. package/presets/cursor/nuxt/agents/playwright-test-generator.md +9 -1
  521. package/presets/cursor/nuxt/agents/playwright-test-healer.md +9 -1
  522. package/presets/cursor/nuxt/agents/playwright-test-planner.md +1 -1
  523. package/presets/cursor/nuxt/agents/solution-architect.md +6 -0
  524. package/presets/cursor/nuxt/agents/task-analyst.md +17 -0
  525. package/presets/cursor/nuxt/agents/task-router.md +6 -0
  526. package/presets/cursor/nuxt/commands/spec-start.md +1 -1
  527. package/presets/cursor/nuxt/mcp.json +3 -3
  528. package/presets/cursor/nuxt/rules/README.md +2 -1
  529. package/presets/cursor/nuxt/rules/agent-team-orchestrator.mdc +2 -1
  530. package/presets/cursor/nuxt/rules/anti-sycophancy-discipline.mdc +1 -1
  531. package/presets/cursor/nuxt/rules/code-quality-and-refactoring.mdc +1 -1
  532. package/presets/cursor/nuxt/rules/feature-delivery-workflow.mdc +2 -1
  533. package/presets/cursor/nuxt/rules/mcp-usage.mdc +100 -0
  534. package/presets/cursor/nuxt/rules/preset-no-cross-stack-leakage.mdc +1 -0
  535. package/presets/cursor/nuxt/rules/product-specs-authoring.mdc +6 -4
  536. package/presets/cursor/nuxt/rules/product-specs.mdc +8 -4
  537. package/presets/cursor/nuxt/skills/README.md +2 -0
  538. package/presets/cursor/nuxt/skills/ci-investigation/SKILL.md +8 -0
  539. package/presets/cursor/nuxt/skills/code-review/SKILL.md +1 -1
  540. package/presets/cursor/nuxt/skills/debug-investigation/SKILL.md +13 -1
  541. package/presets/cursor/nuxt/skills/feature-delivery/SKILL.md +9 -1
  542. package/presets/cursor/nuxt/skills/spec-discovery/SKILL.md +58 -0
  543. package/presets/cursor/nuxt/team/README.md +11 -0
  544. package/presets/cursor/nuxt/team/fixtures/feature-full.json +43 -9
  545. package/presets/cursor/nuxt/team/fixtures/memlog.example.md +9 -0
  546. package/presets/cursor/php-hexagonal/AGENTS.md +1 -1
  547. package/presets/cursor/php-hexagonal/MCP.md +20 -1
  548. package/presets/cursor/php-hexagonal/agents/ci-investigator.md +8 -0
  549. package/presets/cursor/php-hexagonal/agents/debugger.md +8 -0
  550. package/presets/cursor/php-hexagonal/agents/feature-developer.md +23 -0
  551. package/presets/cursor/php-hexagonal/agents/migration-specialist.md +6 -0
  552. package/presets/cursor/php-hexagonal/agents/performance-auditor.md +6 -0
  553. package/presets/cursor/php-hexagonal/agents/solution-architect.md +6 -0
  554. package/presets/cursor/php-hexagonal/agents/task-analyst.md +17 -0
  555. package/presets/cursor/php-hexagonal/agents/task-router.md +6 -0
  556. package/presets/cursor/php-hexagonal/commands/spec-start.md +1 -1
  557. package/presets/cursor/php-hexagonal/mcp.json +1 -1
  558. package/presets/cursor/php-hexagonal/rules/README.md +2 -1
  559. package/presets/cursor/php-hexagonal/rules/agent-team-orchestrator.mdc +1 -0
  560. package/presets/cursor/php-hexagonal/rules/anti-sycophancy-discipline.mdc +1 -1
  561. package/presets/cursor/php-hexagonal/rules/code-quality-and-refactoring.mdc +1 -1
  562. package/presets/cursor/php-hexagonal/rules/feature-delivery-workflow.mdc +2 -1
  563. package/presets/cursor/php-hexagonal/rules/mcp-usage.mdc +97 -0
  564. package/presets/cursor/php-hexagonal/rules/preset-no-cross-stack-leakage.mdc +1 -0
  565. package/presets/cursor/php-hexagonal/rules/product-specs-authoring.mdc +6 -4
  566. package/presets/cursor/php-hexagonal/rules/product-specs.mdc +8 -4
  567. package/presets/cursor/php-hexagonal/skills/README.md +1 -1
  568. package/presets/cursor/php-hexagonal/skills/ci-investigation/SKILL.md +7 -0
  569. package/presets/cursor/php-hexagonal/skills/code-review/SKILL.md +1 -0
  570. package/presets/cursor/php-hexagonal/skills/debug-investigation/SKILL.md +8 -0
  571. package/presets/cursor/php-hexagonal/skills/feature-delivery/SKILL.md +7 -1
  572. package/presets/cursor/php-hexagonal/skills/spec-discovery/SKILL.md +58 -0
  573. package/presets/cursor/php-hexagonal/team/README.md +8 -0
  574. package/presets/cursor/php-hexagonal/team/fixtures/feature-full.json +46 -10
  575. package/presets/cursor/php-hexagonal/team/fixtures/memlog.example.md +9 -0
  576. package/presets/cursor/php-laravel/AGENTS.md +1 -1
  577. package/presets/cursor/php-laravel/MCP.md +21 -0
  578. package/presets/cursor/php-laravel/agents/ci-investigator.md +8 -0
  579. package/presets/cursor/php-laravel/agents/debugger.md +8 -0
  580. package/presets/cursor/php-laravel/agents/feature-developer.md +23 -0
  581. package/presets/cursor/php-laravel/agents/migration-specialist.md +6 -0
  582. package/presets/cursor/php-laravel/agents/performance-auditor.md +6 -0
  583. package/presets/cursor/php-laravel/agents/solution-architect.md +6 -0
  584. package/presets/cursor/php-laravel/agents/task-analyst.md +17 -0
  585. package/presets/cursor/php-laravel/agents/task-router.md +6 -0
  586. package/presets/cursor/php-laravel/commands/spec-start.md +1 -1
  587. package/presets/cursor/php-laravel/mcp.json +1 -1
  588. package/presets/cursor/php-laravel/rules/README.md +2 -1
  589. package/presets/cursor/php-laravel/rules/agent-team-orchestrator.mdc +1 -0
  590. package/presets/cursor/php-laravel/rules/anti-sycophancy-discipline.mdc +1 -1
  591. package/presets/cursor/php-laravel/rules/code-quality-and-refactoring.mdc +1 -1
  592. package/presets/cursor/php-laravel/rules/feature-delivery-workflow.mdc +2 -1
  593. package/presets/cursor/php-laravel/rules/mcp-usage.mdc +97 -0
  594. package/presets/cursor/php-laravel/rules/preset-no-cross-stack-leakage.mdc +1 -0
  595. package/presets/cursor/php-laravel/rules/product-specs-authoring.mdc +6 -4
  596. package/presets/cursor/php-laravel/rules/product-specs.mdc +8 -4
  597. package/presets/cursor/php-laravel/skills/README.md +1 -1
  598. package/presets/cursor/php-laravel/skills/ci-investigation/SKILL.md +7 -0
  599. package/presets/cursor/php-laravel/skills/code-review/SKILL.md +1 -0
  600. package/presets/cursor/php-laravel/skills/debug-investigation/SKILL.md +8 -0
  601. package/presets/cursor/php-laravel/skills/feature-delivery/SKILL.md +7 -1
  602. package/presets/cursor/php-laravel/skills/spec-discovery/SKILL.md +58 -0
  603. package/presets/cursor/php-laravel/team/README.md +7 -0
  604. package/presets/cursor/php-laravel/team/fixtures/feature-full.json +38 -9
  605. package/presets/cursor/php-laravel/team/fixtures/memlog.example.md +9 -0
  606. package/presets/cursor/svelte/MCP.md +21 -1
  607. package/presets/cursor/svelte/agents/accessibility-reviewer.md +8 -0
  608. package/presets/cursor/svelte/agents/ci-investigator.md +8 -0
  609. package/presets/cursor/svelte/agents/debugger.md +12 -0
  610. package/presets/cursor/svelte/agents/feature-developer.md +25 -0
  611. package/presets/cursor/svelte/agents/migration-specialist.md +6 -0
  612. package/presets/cursor/svelte/agents/performance-auditor.md +8 -0
  613. package/presets/cursor/svelte/agents/playwright-test-generator.md +9 -1
  614. package/presets/cursor/svelte/agents/playwright-test-healer.md +9 -1
  615. package/presets/cursor/svelte/agents/playwright-test-planner.md +1 -1
  616. package/presets/cursor/svelte/agents/solution-architect.md +6 -0
  617. package/presets/cursor/svelte/agents/task-analyst.md +17 -0
  618. package/presets/cursor/svelte/agents/task-router.md +6 -0
  619. package/presets/cursor/svelte/commands/spec-start.md +1 -1
  620. package/presets/cursor/svelte/mcp.json +3 -3
  621. package/presets/cursor/svelte/rules/README.md +2 -1
  622. package/presets/cursor/svelte/rules/agent-team-orchestrator.mdc +2 -1
  623. package/presets/cursor/svelte/rules/anti-sycophancy-discipline.mdc +1 -1
  624. package/presets/cursor/svelte/rules/code-quality-and-refactoring.mdc +1 -1
  625. package/presets/cursor/svelte/rules/feature-delivery-workflow.mdc +2 -1
  626. package/presets/cursor/svelte/rules/mcp-usage.mdc +100 -0
  627. package/presets/cursor/svelte/rules/preset-no-cross-stack-leakage.mdc +1 -0
  628. package/presets/cursor/svelte/rules/product-specs-authoring.mdc +6 -4
  629. package/presets/cursor/svelte/rules/product-specs.mdc +8 -4
  630. package/presets/cursor/svelte/skills/README.md +2 -0
  631. package/presets/cursor/svelte/skills/ci-investigation/SKILL.md +8 -0
  632. package/presets/cursor/svelte/skills/code-review/SKILL.md +1 -1
  633. package/presets/cursor/svelte/skills/debug-investigation/SKILL.md +13 -1
  634. package/presets/cursor/svelte/skills/feature-delivery/SKILL.md +9 -1
  635. package/presets/cursor/svelte/skills/spec-discovery/SKILL.md +58 -0
  636. package/presets/cursor/svelte/team/README.md +11 -0
  637. package/presets/cursor/svelte/team/fixtures/feature-full.json +43 -9
  638. package/presets/cursor/svelte/team/fixtures/memlog.example.md +9 -0
  639. package/scripts/aggregate-agent-task-metrics.mjs +212 -0
  640. package/scripts/check-hook-only-lifecycle.sh +46 -0
  641. package/scripts/check-preset-i18n.sh +61 -0
  642. package/scripts/check-preset-leakage.sh +450 -0
  643. package/scripts/check-preset-structure.sh +70 -0
  644. package/scripts/check-preset-token-budget.sh +139 -0
  645. package/scripts/check-preset-twin-map.sh +122 -0
  646. package/scripts/check-product-specs.sh +90 -0
  647. package/scripts/check-rule-eval.mjs +149 -0
  648. package/scripts/check-shared-core-drift.sh +148 -0
  649. package/scripts/close-agent-task-human-gate.mjs +61 -0
  650. package/scripts/sync-dogfood-cursor.sh +70 -0
  651. package/scripts/sync-shared-core-embeds.sh +114 -0
  652. package/scripts/test-agent-task-metrics-hooks.mjs +895 -0
  653. package/scripts/test-cli-mcp-merge.mjs +137 -0
@@ -0,0 +1,895 @@
1
+ #!/usr/bin/env node
2
+
3
+ import assert from 'node:assert/strict';
4
+ import { execFileSync, spawn } from 'node:child_process';
5
+ import fs from 'node:fs';
6
+ import path from 'node:path';
7
+ import { fileURLToPath } from 'node:url';
8
+
9
+ const scriptDirectory = path.dirname(fileURLToPath(import.meta.url));
10
+ const packageDirectory = path.resolve(scriptDirectory, '..');
11
+ const presetsDirectory = path.join(packageDirectory, 'presets');
12
+ const hooks = [
13
+ ...fs.readdirSync(path.join(presetsDirectory, 'cursor')).map((stack) => path.join(presetsDirectory, 'cursor', stack, 'hooks', 'chain-team-phases.sh')),
14
+ ...fs.readdirSync(path.join(presetsDirectory, 'claude')).map((stack) => path.join(presetsDirectory, 'claude', stack, 'hooks', 'chain-team-phases.sh')),
15
+ ];
16
+
17
+ assert.equal(hooks.length, 14, 'expected every packaged Cursor and Claude hook');
18
+
19
+ function readJson(filePath) {
20
+ return JSON.parse(fs.readFileSync(filePath, 'utf8'));
21
+ }
22
+
23
+ function writeJson(filePath, value) {
24
+ fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`);
25
+ }
26
+
27
+ function invokeHook(hook, workingDirectory, attemptId) {
28
+ return execFileSync('bash', [hook], {
29
+ cwd: workingDirectory,
30
+ encoding: 'utf8',
31
+ input: JSON.stringify({ status: 'completed', attemptId }),
32
+ });
33
+ }
34
+
35
+ function invokeHookAsync(hook, workingDirectory, attemptId) {
36
+ return new Promise((resolve, reject) => {
37
+ const child = spawn('bash', [hook], { cwd: workingDirectory, stdio: ['pipe', 'pipe', 'pipe'] });
38
+ let stdout = '';
39
+ let stderr = '';
40
+ child.stdout.setEncoding('utf8');
41
+ child.stderr.setEncoding('utf8');
42
+ child.stdout.on('data', (chunk) => {
43
+ stdout += chunk;
44
+ });
45
+ child.stderr.on('data', (chunk) => {
46
+ stderr += chunk;
47
+ });
48
+ child.on('error', reject);
49
+ child.on('close', (code) => {
50
+ if (code === 0) resolve(stdout);
51
+ else reject(new Error(`${hook} exited ${code}: ${stderr}`));
52
+ });
53
+ child.stdin.end(JSON.stringify({ status: 'completed', attemptId }));
54
+ });
55
+ }
56
+
57
+ function writeTask(root, hook, slug, pipeline, status, metrics, artifacts = {}) {
58
+ const platform = hook.includes(`${path.sep}cursor${path.sep}`) ? 'cursor' : 'claude';
59
+ const teamRoot = path.join(root, `.${platform}`, 'team');
60
+ const taskDirectory = path.join(teamRoot, 'tasks', slug);
61
+ fs.mkdirSync(taskDirectory, { recursive: true });
62
+ writeJson(path.join(teamRoot, 'active-task.json'), { slug });
63
+ writeJson(path.join(taskDirectory, 'pipeline.json'), pipeline);
64
+ writeJson(path.join(taskDirectory, 'status.json'), status);
65
+ writeJson(path.join(taskDirectory, 'metrics.json'), metrics);
66
+ for (const [name, content] of Object.entries(artifacts)) {
67
+ fs.writeFileSync(path.join(taskDirectory, name), content);
68
+ }
69
+ return taskDirectory;
70
+ }
71
+
72
+ function prepareTask(root, hook) {
73
+ const platform = hook.includes(`${path.sep}cursor${path.sep}`) ? 'cursor' : 'claude';
74
+ const teamRoot = path.join(root, `.${platform}`, 'team');
75
+ const taskDirectory = path.join(teamRoot, 'tasks', 'reverse-parallel');
76
+ fs.mkdirSync(taskDirectory, { recursive: true });
77
+ writeJson(path.join(teamRoot, 'active-task.json'), { slug: 'reverse-parallel' });
78
+ writeJson(path.join(taskDirectory, 'pipeline.json'), {
79
+ autoChain: true,
80
+ steps: [
81
+ { agent: 'starter' },
82
+ { agent: ['alpha', 'beta'], parallel: true },
83
+ { agent: 'gamma' },
84
+ ],
85
+ });
86
+
87
+ const runId = 'reverse-parallel-run';
88
+ const starterAttemptId = `${runId}:step-0:starter:attempt-1`;
89
+ writeJson(path.join(taskDirectory, 'status.json'), {
90
+ slug: 'reverse-parallel',
91
+ intent: 'feature',
92
+ pipelineIndex: 0,
93
+ currentAgent: 'starter',
94
+ phase: 'executing',
95
+ state: 'completed',
96
+ activeAttempts: {
97
+ [starterAttemptId]: {
98
+ agent: 'starter',
99
+ stepIndex: 0,
100
+ attempt: 1,
101
+ startedAt: '2026-01-01T00:00:00.000Z',
102
+ parallelGroupId: null,
103
+ },
104
+ },
105
+ metricsRunId: runId,
106
+ });
107
+ writeJson(path.join(taskDirectory, 'metrics.json'), {
108
+ schemaVersion: 1,
109
+ task: { runId, slug: 'reverse-parallel', preset: 'ai-rules', stack: 'test', platform, intent: 'feature', profile: 'test' },
110
+ events: [
111
+ { eventId: `${runId}:task_started`, type: 'task_started', at: '2026-01-01T00:00:00.000Z' },
112
+ { eventId: `${runId}:starter`, type: 'attempt_started', attemptId: starterAttemptId, agent: 'starter', stepIndex: 0, attempt: 1, at: '2026-01-01T00:00:00.000Z' },
113
+ ],
114
+ });
115
+ return { taskDirectory, starterAttemptId };
116
+ }
117
+
118
+ function setCompleted(taskDirectory) {
119
+ const statusPath = path.join(taskDirectory, 'status.json');
120
+ const status = readJson(statusPath);
121
+ writeJson(statusPath, { ...status, state: 'completed' });
122
+ }
123
+
124
+ for (const hook of hooks) {
125
+ const root = fs.mkdtempSync(path.join(packageDirectory, '.agent-task-metrics-'));
126
+ try {
127
+ const { taskDirectory, starterAttemptId } = prepareTask(root, hook);
128
+ const parallelHandoff = JSON.parse(invokeHook(hook, root, starterAttemptId)).followup_message;
129
+ const statusAfterScheduling = readJson(path.join(taskDirectory, 'status.json'));
130
+ const activeAttempts = statusAfterScheduling.activeAttempts;
131
+ const alphaAttemptId = Object.keys(activeAttempts).find((attemptId) => activeAttempts[attemptId].agent === 'alpha');
132
+ const betaAttemptId = Object.keys(activeAttempts).find((attemptId) => activeAttempts[attemptId].agent === 'beta');
133
+
134
+ assert.ok(alphaAttemptId && betaAttemptId, `${hook}: parallel attempts were not activated`);
135
+ assert.match(parallelHandoff, new RegExp(`alpha=${alphaAttemptId}`), `${hook}: alpha attempt ID missing from handoff`);
136
+ assert.match(parallelHandoff, new RegExp(`beta=${betaAttemptId}`), `${hook}: beta attempt ID missing from handoff`);
137
+
138
+ setCompleted(taskDirectory);
139
+ const results = await Promise.all([
140
+ invokeHookAsync(hook, root, betaAttemptId),
141
+ invokeHookAsync(hook, root, alphaAttemptId),
142
+ ]);
143
+ const finalStatus = readJson(path.join(taskDirectory, 'status.json'));
144
+ assert.equal(finalStatus.pipelineIndex, 2, `${hook}: parallel step did not advance`);
145
+ assert.equal(finalStatus.currentAgent, 'gamma', `${hook}: next agent was not scheduled`);
146
+ assert.deepEqual(finalStatus.parallelCompleted, [], `${hook}: parallel completion state was not reset`);
147
+ assert.ok(
148
+ results.some((result) => /gamma/.test(JSON.parse(result).followup_message || '')),
149
+ `${hook}: expected one next-agent handoff`,
150
+ );
151
+
152
+ const finishedAgents = readJson(path.join(taskDirectory, 'metrics.json')).events
153
+ .filter((event) => event.type === 'attempt_finished')
154
+ .map((event) => event.attemptId);
155
+ assert.ok(finishedAgents.includes(alphaAttemptId) && finishedAgents.includes(betaAttemptId), `${hook}: both reverse-order attempts must finish`);
156
+ assert.equal(new Set(finishedAgents).size, finishedAgents.length, `${hook}: parallel completion emitted duplicate terminal events`);
157
+ } finally {
158
+ fs.rmSync(root, { recursive: true, force: true });
159
+ }
160
+ }
161
+
162
+ for (const hook of hooks) {
163
+ const root = fs.mkdtempSync(path.join(packageDirectory, '.agent-task-metrics-retry-'));
164
+ try {
165
+ const platform = hook.includes(`${path.sep}cursor${path.sep}`) ? 'cursor' : 'claude';
166
+ const runId = 'serial-retry-run';
167
+ const reviewerAttemptId = `${runId}:step-5:security-reviewer:attempt-1`;
168
+ const taskDirectory = writeTask(
169
+ root,
170
+ hook,
171
+ 'serial-retry',
172
+ {
173
+ autoChain: true,
174
+ steps: [
175
+ { agent: 'feature-developer', scope: 'wp-1' },
176
+ { agent: 'build-verifier', scope: 'wp-1' },
177
+ { agent: 'security-reviewer', scope: 'wp-1' },
178
+ { agent: 'feature-developer', scope: 'wp-2' },
179
+ { agent: 'build-verifier', scope: 'wp-2' },
180
+ { agent: 'security-reviewer', scope: 'wp-2' },
181
+ ],
182
+ },
183
+ {
184
+ slug: 'serial-retry',
185
+ intent: 'feature',
186
+ pipelineIndex: 5,
187
+ currentAgent: 'security-reviewer',
188
+ phase: 'executing',
189
+ state: 'changes_requested',
190
+ activeAttempts: {
191
+ [reviewerAttemptId]: {
192
+ agent: 'security-reviewer',
193
+ stepIndex: 5,
194
+ attempt: 1,
195
+ startedAt: '2026-01-01T00:00:00.000Z',
196
+ parallelGroupId: null,
197
+ },
198
+ },
199
+ metricsRunId: runId,
200
+ },
201
+ {
202
+ schemaVersion: 1,
203
+ task: { runId, slug: 'serial-retry', preset: 'ai-rules', stack: 'test', platform, intent: 'feature', profile: 'test' },
204
+ events: [
205
+ { eventId: `${runId}:task_started`, type: 'task_started', at: '2026-01-01T00:00:00.000Z' },
206
+ { eventId: `${runId}:reviewer-start`, type: 'attempt_started', attemptId: reviewerAttemptId, agent: 'security-reviewer', stepIndex: 5, attempt: 1, at: '2026-01-01T00:00:00.000Z' },
207
+ ],
208
+ },
209
+ );
210
+
211
+ const fixHandoff = JSON.parse(invokeHook(hook, root, reviewerAttemptId)).followup_message;
212
+ const fixStatus = readJson(path.join(taskDirectory, 'status.json'));
213
+ const developerAttempts = Object.entries(fixStatus.activeAttempts).filter(([, entry]) => entry.agent === 'feature-developer');
214
+ assert.equal(fixStatus.pipelineIndex, 3, `${hook}: retry must target the nearest preceding developer step`);
215
+ assert.equal(developerAttempts.length, 1, `${hook}: retry must activate exactly one developer attempt`);
216
+ const developerAttemptId = developerAttempts[0][0];
217
+ assert.match(fixHandoff, new RegExp(developerAttemptId), `${hook}: developer retry attempt ID missing from handoff`);
218
+ assert.notEqual(developerAttemptId, reviewerAttemptId, `${hook}: retry attempt ID collided with predecessor`);
219
+
220
+ setCompleted(taskDirectory);
221
+ const reviewHandoff = JSON.parse(invokeHook(hook, root, developerAttemptId)).followup_message;
222
+ const reviewStatus = readJson(path.join(taskDirectory, 'status.json'));
223
+ const reviewerAttempts = Object.entries(reviewStatus.activeAttempts).filter(([, entry]) => entry.agent === 'security-reviewer');
224
+ assert.equal(reviewStatus.pipelineIndex, 5, `${hook}: completed fix must return to the requesting reviewer step`);
225
+ assert.equal(reviewerAttempts.length, 1, `${hook}: reviewer retry must activate exactly one attempt`);
226
+ const retriedReviewerAttemptId = reviewerAttempts[0][0];
227
+ assert.match(reviewHandoff, new RegExp(retriedReviewerAttemptId), `${hook}: reviewer retry attempt ID missing from handoff`);
228
+ assert.match(retriedReviewerAttemptId, /attempt-2$/, `${hook}: reviewer retry ordinal must increment`);
229
+
230
+ const beforeDuplicate = readJson(path.join(taskDirectory, 'status.json'));
231
+ assert.deepEqual(JSON.parse(invokeHook(hook, root, developerAttemptId)), {}, `${hook}: stale duplicate stop must be ignored`);
232
+ assert.deepEqual(readJson(path.join(taskDirectory, 'status.json')), beforeDuplicate, `${hook}: stale duplicate stop mutated status`);
233
+ const developerFinishes = readJson(path.join(taskDirectory, 'metrics.json')).events.filter(
234
+ (event) => event.type === 'attempt_finished' && event.attemptId === developerAttemptId,
235
+ );
236
+ assert.equal(developerFinishes.length, 1, `${hook}: stale duplicate stop emitted a second terminal event`);
237
+ } finally {
238
+ fs.rmSync(root, { recursive: true, force: true });
239
+ }
240
+ }
241
+
242
+ for (const hook of hooks) {
243
+ const root = fs.mkdtempSync(path.join(packageDirectory, '.agent-task-metrics-no-chain-'));
244
+ try {
245
+ const platform = hook.includes(`${path.sep}cursor${path.sep}`) ? 'cursor' : 'claude';
246
+ const runId = 'no-chain-run';
247
+ const attemptId = `${runId}:step-0:feature-developer:attempt-1`;
248
+ const taskDirectory = writeTask(
249
+ root,
250
+ hook,
251
+ 'no-chain',
252
+ { autoChain: false, steps: [{ agent: 'feature-developer' }] },
253
+ {
254
+ slug: 'no-chain',
255
+ intent: 'feature',
256
+ pipelineIndex: 0,
257
+ currentAgent: 'feature-developer',
258
+ phase: 'executing',
259
+ state: 'completed',
260
+ activeAttempts: {
261
+ [attemptId]: {
262
+ agent: 'feature-developer',
263
+ stepIndex: 0,
264
+ attempt: 1,
265
+ startedAt: '2026-01-01T00:00:00.000Z',
266
+ parallelGroupId: null,
267
+ },
268
+ },
269
+ metricsRunId: runId,
270
+ },
271
+ {
272
+ schemaVersion: 1,
273
+ task: { runId, slug: 'no-chain', preset: 'ai-rules', stack: 'test', platform, intent: 'feature', profile: 'test' },
274
+ events: [
275
+ { eventId: `${runId}:task_started`, type: 'task_started', at: '2026-01-01T00:00:00.000Z' },
276
+ { eventId: `${runId}:start`, type: 'attempt_started', attemptId, agent: 'feature-developer', stepIndex: 0, attempt: 1, at: '2026-01-01T00:00:00.000Z' },
277
+ ],
278
+ },
279
+ );
280
+
281
+ assert.deepEqual(JSON.parse(invokeHook(hook, root, attemptId)), {}, `${hook}: non-chaining stop must not hand off`);
282
+ assert.equal(Object.keys(readJson(path.join(taskDirectory, 'status.json')).activeAttempts).length, 0, `${hook}: finished non-chaining attempt was not persisted`);
283
+ assert.deepEqual(JSON.parse(invokeHook(hook, root, attemptId)), {}, `${hook}: repeated non-chaining stop must be ignored`);
284
+ const terminals = readJson(path.join(taskDirectory, 'metrics.json')).events.filter(
285
+ (event) => event.type === 'attempt_finished' && event.attemptId === attemptId,
286
+ );
287
+ assert.equal(terminals.length, 1, `${hook}: repeated non-chaining stop duplicated terminal metrics`);
288
+ } finally {
289
+ fs.rmSync(root, { recursive: true, force: true });
290
+ }
291
+ }
292
+
293
+ for (const hook of hooks) {
294
+ const root = fs.mkdtempSync(path.join(packageDirectory, '.agent-task-metrics-mixed-parallel-'));
295
+ try {
296
+ const platform = hook.includes(`${path.sep}cursor${path.sep}`) ? 'cursor' : 'claude';
297
+ const runId = 'mixed-parallel-run';
298
+ const alphaAttemptId = `${runId}:step-1:code-reviewer:attempt-1`;
299
+ const betaAttemptId = `${runId}:step-1:security-reviewer:attempt-1`;
300
+ const groupId = `${runId}:step-1`;
301
+ const taskDirectory = writeTask(
302
+ root,
303
+ hook,
304
+ 'mixed-parallel',
305
+ {
306
+ autoChain: true,
307
+ steps: [
308
+ { agent: 'feature-developer' },
309
+ { agent: ['code-reviewer', 'security-reviewer'], parallel: true },
310
+ ],
311
+ },
312
+ {
313
+ slug: 'mixed-parallel',
314
+ intent: 'feature',
315
+ pipelineIndex: 1,
316
+ currentAgent: 'code-reviewer',
317
+ phase: 'executing',
318
+ state: 'changes_requested',
319
+ parallelCompleted: [],
320
+ activeAttempts: {
321
+ [alphaAttemptId]: { agent: 'code-reviewer', stepIndex: 1, attempt: 1, startedAt: '2026-01-01T00:00:00.000Z', parallelGroupId: groupId },
322
+ [betaAttemptId]: { agent: 'security-reviewer', stepIndex: 1, attempt: 1, startedAt: '2026-01-01T00:00:00.000Z', parallelGroupId: groupId },
323
+ },
324
+ metricsRunId: runId,
325
+ },
326
+ {
327
+ schemaVersion: 1,
328
+ task: { runId, slug: 'mixed-parallel', preset: 'ai-rules', stack: 'test', platform, intent: 'feature', profile: 'test' },
329
+ events: [
330
+ { eventId: `${runId}:task_started`, type: 'task_started', at: '2026-01-01T00:00:00.000Z' },
331
+ { eventId: `${runId}:alpha`, type: 'attempt_started', attemptId: alphaAttemptId, agent: 'code-reviewer', stepIndex: 1, attempt: 1, at: '2026-01-01T00:00:00.000Z' },
332
+ { eventId: `${runId}:beta`, type: 'attempt_started', attemptId: betaAttemptId, agent: 'security-reviewer', stepIndex: 1, attempt: 1, at: '2026-01-01T00:00:00.000Z' },
333
+ ],
334
+ },
335
+ );
336
+
337
+ assert.deepEqual(JSON.parse(invokeHook(hook, root, betaAttemptId)), {}, `${hook}: parallel failure must wait for join`);
338
+ let status = readJson(path.join(taskDirectory, 'status.json'));
339
+ assert.equal(status.pipelineIndex, 1, `${hook}: parallel failure advanced before join`);
340
+ assert.ok(status.activeAttempts[alphaAttemptId], `${hook}: parallel sibling was lost before join`);
341
+ assert.equal(
342
+ Object.values(status.activeAttempts).filter((entry) => entry.agent === 'feature-developer').length,
343
+ 0,
344
+ `${hook}: developer retry started before join`,
345
+ );
346
+
347
+ setCompleted(taskDirectory);
348
+ const handoff = JSON.parse(invokeHook(hook, root, alphaAttemptId)).followup_message;
349
+ status = readJson(path.join(taskDirectory, 'status.json'));
350
+ const developerAttempts = Object.values(status.activeAttempts).filter((entry) => entry.agent === 'feature-developer');
351
+ assert.equal(status.pipelineIndex, 0, `${hook}: joined retry must target preceding developer`);
352
+ assert.equal(developerAttempts.length, 1, `${hook}: joined parallel failure must schedule exactly one developer retry`);
353
+ assert.equal(status.retryAfterFix, 'security-reviewer', `${hook}: mixed outcomes lost requesting reviewer`);
354
+ assert.match(handoff, /feature-developer/, `${hook}: joined retry handoff missing developer`);
355
+ } finally {
356
+ fs.rmSync(root, { recursive: true, force: true });
357
+ }
358
+ }
359
+
360
+ for (const hook of hooks) {
361
+ const root = fs.mkdtempSync(path.join(packageDirectory, '.agent-task-metrics-skip-'));
362
+ try {
363
+ const platform = hook.includes(`${path.sep}cursor${path.sep}`) ? 'cursor' : 'claude';
364
+ const runId = 'skip-run';
365
+ const starterAttemptId = `${runId}:step-0:starter:attempt-1`;
366
+ const taskDirectory = writeTask(
367
+ root,
368
+ hook,
369
+ 'skip',
370
+ {
371
+ autoChain: true,
372
+ steps: [
373
+ { agent: 'starter' },
374
+ { agent: 'debugger', skipIf: 'debugger.fixed' },
375
+ { agent: 'gamma' },
376
+ ],
377
+ },
378
+ {
379
+ slug: 'skip',
380
+ intent: 'bugfix',
381
+ pipelineIndex: 0,
382
+ currentAgent: 'starter',
383
+ phase: 'executing',
384
+ state: 'completed',
385
+ activeAttempts: {
386
+ [starterAttemptId]: {
387
+ agent: 'starter',
388
+ stepIndex: 0,
389
+ attempt: 1,
390
+ startedAt: '2026-01-01T00:00:00.000Z',
391
+ parallelGroupId: null,
392
+ },
393
+ },
394
+ metricsRunId: runId,
395
+ },
396
+ {
397
+ schemaVersion: 1,
398
+ task: { runId, slug: 'skip', preset: 'ai-rules', stack: 'test', platform, intent: 'bugfix', profile: 'test' },
399
+ events: [
400
+ { eventId: `${runId}:task_started`, type: 'task_started', at: '2026-01-01T00:00:00.000Z' },
401
+ { eventId: `${runId}:starter`, type: 'attempt_started', attemptId: starterAttemptId, agent: 'starter', stepIndex: 0, attempt: 1, at: '2026-01-01T00:00:00.000Z' },
402
+ ],
403
+ },
404
+ { 'debug-report.md': 'fixApplied: true\n' },
405
+ );
406
+
407
+ invokeHook(hook, root, starterAttemptId);
408
+ const status = readJson(path.join(taskDirectory, 'status.json'));
409
+ assert.equal(status.pipelineIndex, 2, `${hook}: skipIf did not advance to the next executable step`);
410
+ const skipped = readJson(path.join(taskDirectory, 'metrics.json')).events.filter((event) => event.type === 'attempt_skipped');
411
+ assert.equal(skipped.length, 1, `${hook}: skipIf must emit exactly one attempt_skipped event`);
412
+ assert.equal(skipped[0].agent, 'debugger', `${hook}: attempt_skipped attributed to the wrong agent`);
413
+ } finally {
414
+ fs.rmSync(root, { recursive: true, force: true });
415
+ }
416
+ }
417
+
418
+ for (const command of [
419
+ ...fs.readdirSync(path.join(presetsDirectory, 'cursor')).map((stack) => path.join(presetsDirectory, 'cursor', stack, 'commands', 'task-continue.md')),
420
+ ...fs.readdirSync(path.join(presetsDirectory, 'claude')).map((stack) => path.join(presetsDirectory, 'claude', stack, 'commands', 'task-continue.md')),
421
+ ]) {
422
+ const source = fs.readFileSync(command, 'utf8');
423
+ assert.match(source, /action":"end_human_gate"/, `${command}: must invoke installed hook end_human_gate action`);
424
+ assert.match(source, /hooks\/chain-team-phases\.sh/, `${command}: must reference installed chain-team-phases.sh`);
425
+ assert.match(source, /single authority/, `${command}: must declare hook as single authority for gate resume`);
426
+ assert.match(source, /\*\*Do not\*\* manually increment/, `${command}: must forbid manual pipelineIndex advance before hook`);
427
+ assert.doesNotMatch(
428
+ source,
429
+ /Сбрось gate:[\s\S]*pipelineIndex \+ 1[\s\S]*end_human_gate/,
430
+ `${command}: must not document pre-hook status advance`,
431
+ );
432
+ }
433
+
434
+ for (const hook of hooks) {
435
+ // Initialized-consumer regression following task-continue.md:
436
+ // pre-resume status → hook end_human_gate (no manual pipelineIndex++) → invoke from status.currentAgent.
437
+ const root = fs.mkdtempSync(path.join(packageDirectory, '.agent-task-metrics-gate-'));
438
+ try {
439
+ const platform = hook.includes(`${path.sep}cursor${path.sep}`) ? 'cursor' : 'claude';
440
+ const stack = path.basename(path.dirname(path.dirname(hook)));
441
+ const presetCommand = path.join(path.dirname(path.dirname(hook)), 'commands', 'task-continue.md');
442
+ const installedHook = path.join(root, `.${platform}`, 'hooks', 'chain-team-phases.sh');
443
+ const installedCommand = path.join(root, `.${platform}`, 'commands', 'task-continue.md');
444
+ fs.mkdirSync(path.dirname(installedHook), { recursive: true });
445
+ fs.mkdirSync(path.dirname(installedCommand), { recursive: true });
446
+ fs.copyFileSync(hook, installedHook);
447
+ fs.copyFileSync(presetCommand, installedCommand);
448
+ const commandSource = fs.readFileSync(installedCommand, 'utf8');
449
+ assert.match(commandSource, /single authority/);
450
+ assert.match(commandSource, /\*\*Do not\*\* manually increment/);
451
+
452
+ const teamRoot = path.join(root, `.${platform}`, 'team');
453
+ const taskDirectory = path.join(teamRoot, 'tasks', 'gate-resume');
454
+ fs.mkdirSync(taskDirectory, { recursive: true });
455
+ const runId = 'gate-resume-run';
456
+ const gateEventId = `${runId}:gate:1`;
457
+ writeJson(path.join(teamRoot, 'active-task.json'), { slug: 'gate-resume' });
458
+ writeJson(path.join(taskDirectory, 'pipeline.json'), {
459
+ autoChain: true,
460
+ steps: [{ agent: 'task-analyst' }, { agent: 'feature-developer', label: 'Implement' }],
461
+ });
462
+ writeJson(path.join(taskDirectory, 'status.json'), {
463
+ slug: 'gate-resume',
464
+ intent: 'feature',
465
+ pipelineIndex: 0,
466
+ currentAgent: 'task-analyst',
467
+ phase: 'human_gate',
468
+ state: 'awaiting_approval',
469
+ awaitingHumanGate: true,
470
+ activeHumanGateEventId: gateEventId,
471
+ metricsRunId: runId,
472
+ activeAttempts: {},
473
+ });
474
+ writeJson(path.join(taskDirectory, 'metrics.json'), {
475
+ schemaVersion: 1,
476
+ task: { runId, slug: 'gate-resume', preset: 'ai-rules', stack, platform, intent: 'feature', profile: 'standard' },
477
+ events: [
478
+ { eventId: `${runId}:task_started`, type: 'task_started', at: '2026-01-01T00:00:00.000Z' },
479
+ { eventId: `${runId}:analyst`, type: 'attempt_started', attemptId: `${runId}:step-0:task-analyst:attempt-1`, agent: 'task-analyst', stepIndex: 0, attempt: 1, at: '2026-01-01T00:00:00.000Z' },
480
+ { eventId: `${runId}:analyst-done`, type: 'attempt_finished', attemptId: `${runId}:step-0:task-analyst:attempt-1`, outcome: 'completed', durationMs: 1000, at: '2026-01-01T00:00:01.000Z' },
481
+ { eventId: gateEventId, type: 'human_gate_started', at: '2026-01-01T00:00:01.000Z' },
482
+ ],
483
+ });
484
+
485
+ const handoff = JSON.parse(
486
+ execFileSync('bash', [installedHook], {
487
+ cwd: root,
488
+ encoding: 'utf8',
489
+ input: JSON.stringify({ status: 'completed', action: 'end_human_gate', activateNext: true }),
490
+ }),
491
+ );
492
+ assert.match(handoff.followup_message || '', /feature-developer/, `${hook}: consumer hook must hand off next agent`);
493
+
494
+ const status = readJson(path.join(taskDirectory, 'status.json'));
495
+ assert.equal(status.awaitingHumanGate, false, `${hook}: gate remained active`);
496
+ assert.equal(status.activeHumanGateEventId, undefined, `${hook}: gate event ID remained active`);
497
+ assert.equal(status.pipelineIndex, 1, `${hook}: gate resume did not advance`);
498
+ assert.equal(status.currentAgent, 'feature-developer', `${hook}: gate resume targeted wrong agent`);
499
+
500
+ const types = readJson(path.join(taskDirectory, 'metrics.json')).events.map((event) => event.type);
501
+ const gateEndedAt = types.lastIndexOf('human_gate_ended');
502
+ const nextAttemptAt = types.lastIndexOf('attempt_started');
503
+ assert.ok(gateEndedAt >= 0, `${hook}: human_gate_ended missing from ledger`);
504
+ assert.ok(nextAttemptAt > gateEndedAt, `${hook}: attempt_started must come after human_gate_ended`);
505
+ } finally {
506
+ fs.rmSync(root, { recursive: true, force: true });
507
+ }
508
+ }
509
+
510
+ for (const hook of hooks) {
511
+ const root = fs.mkdtempSync(path.join(packageDirectory, '.agent-task-metrics-manifest-reconcile-'));
512
+ try {
513
+ const platform = hook.includes(`${path.sep}cursor${path.sep}`) ? 'cursor' : 'claude';
514
+ const runId = 'manifest-reconcile-run';
515
+ const reviewerAttemptId = `${runId}:step-1:code-reviewer:attempt-1`;
516
+ const nowIso = '2026-01-01T00:00:00.000Z';
517
+ const taskDirectory = writeTask(
518
+ root,
519
+ hook,
520
+ 'manifest-reconcile',
521
+ {
522
+ autoChain: true,
523
+ steps: [
524
+ { agent: 'feature-developer', artifactOutputId: 'implementation' },
525
+ { agent: 'code-reviewer', artifactInputIds: ['implementation'], artifactOutputId: 'review' },
526
+ ],
527
+ },
528
+ {
529
+ slug: 'manifest-reconcile',
530
+ intent: 'review-only',
531
+ pipelineIndex: 1,
532
+ currentAgent: 'code-reviewer',
533
+ phase: 'executing',
534
+ state: 'in_progress',
535
+ activeAttempts: {
536
+ [reviewerAttemptId]: {
537
+ agent: 'code-reviewer',
538
+ stepIndex: 1,
539
+ attempt: 1,
540
+ startedAt: nowIso,
541
+ parallelGroupId: null,
542
+ },
543
+ },
544
+ metricsRunId: runId,
545
+ },
546
+ {
547
+ schemaVersion: 1,
548
+ task: {
549
+ runId,
550
+ slug: 'manifest-reconcile',
551
+ preset: 'ai-rules',
552
+ stack: 'test',
553
+ platform,
554
+ intent: 'review-only',
555
+ profile: 'test',
556
+ },
557
+ events: [
558
+ { eventId: `${runId}:task_started`, type: 'task_started', at: nowIso },
559
+ {
560
+ eventId: `${runId}:review-start`,
561
+ type: 'attempt_started',
562
+ attemptId: reviewerAttemptId,
563
+ agent: 'code-reviewer',
564
+ stepIndex: 1,
565
+ attempt: 1,
566
+ at: nowIso,
567
+ },
568
+ ],
569
+ },
570
+ {
571
+ 'artifact-manifest.json': `${JSON.stringify(
572
+ {
573
+ schemaVersion: 1,
574
+ slug: 'manifest-reconcile',
575
+ updatedAt: nowIso,
576
+ artifacts: [
577
+ {
578
+ id: 'review',
579
+ producer: 'code-reviewer',
580
+ status: 'blocked',
581
+ authoritativePaths: ['review.md'],
582
+ acceptanceCriteriaIds: [],
583
+ taskIds: [],
584
+ timestamps: { createdAt: nowIso, updatedAt: nowIso, completedAt: nowIso },
585
+ receipt: {
586
+ outcome: 'changes_requested',
587
+ attemptId: reviewerAttemptId,
588
+ summary: 'Review found blockers.',
589
+ evidencePaths: ['review.md'],
590
+ },
591
+ },
592
+ ],
593
+ },
594
+ null,
595
+ 2,
596
+ )}\n`,
597
+ 'review.md': '# review\nREQUEST_CHANGES\n',
598
+ },
599
+ );
600
+
601
+ const handoff = JSON.parse(invokeHook(hook, root, reviewerAttemptId)).followup_message;
602
+ const status = readJson(path.join(taskDirectory, 'status.json'));
603
+ assert.equal(status.currentAgent, 'feature-developer', `${hook}: manifest receipt must drive retry to developer`);
604
+ assert.equal(status.retryAfterFix, 'code-reviewer', `${hook}: retryAfterFix must point at reviewer`);
605
+ assert.match(handoff || '', /feature-developer/, `${hook}: expected developer handoff after receipt reconcile`);
606
+
607
+ const finished = readJson(path.join(taskDirectory, 'metrics.json')).events.find(
608
+ (event) => event.type === 'attempt_finished' && event.attemptId === reviewerAttemptId,
609
+ );
610
+ assert.ok(finished, `${hook}: missing attempt_finished after receipt reconcile`);
611
+ assert.equal(finished.outcome, 'changes_requested', `${hook}: metrics outcome must come from manifest receipt`);
612
+ } finally {
613
+ fs.rmSync(root, { recursive: true, force: true });
614
+ }
615
+ }
616
+
617
+ for (const hook of hooks) {
618
+ const root = fs.mkdtempSync(path.join(packageDirectory, '.agent-task-metrics-blocked-receipt-'));
619
+ try {
620
+ const platform = hook.includes(`${path.sep}cursor${path.sep}`) ? 'cursor' : 'claude';
621
+ const runId = 'blocked-receipt-run';
622
+ const attemptId = `${runId}:step-0:feature-developer:attempt-1`;
623
+ const startedAt = '2026-02-01T00:00:00.000Z';
624
+ const taskDirectory = writeTask(
625
+ root,
626
+ hook,
627
+ 'blocked-receipt',
628
+ {
629
+ autoChain: true,
630
+ steps: [
631
+ { agent: 'feature-developer', artifactInputIds: ['analysis'], artifactOutputId: 'implementation-wp1' },
632
+ { agent: 'build-verifier', artifactInputIds: ['implementation-wp1'], artifactOutputId: 'validation-wp1' },
633
+ ],
634
+ },
635
+ {
636
+ slug: 'blocked-receipt',
637
+ intent: 'feature',
638
+ pipelineIndex: 0,
639
+ currentAgent: 'feature-developer',
640
+ phase: 'executing',
641
+ state: 'in_progress',
642
+ activeAttempts: {
643
+ [attemptId]: {
644
+ agent: 'feature-developer',
645
+ stepIndex: 0,
646
+ attempt: 1,
647
+ startedAt,
648
+ parallelGroupId: null,
649
+ },
650
+ },
651
+ metricsRunId: runId,
652
+ },
653
+ {
654
+ schemaVersion: 1,
655
+ task: { runId, slug: 'blocked-receipt', preset: 'ai-rules', stack: 'test', platform, intent: 'feature', profile: 'test' },
656
+ events: [
657
+ { eventId: `${runId}:task_started`, type: 'task_started', at: startedAt },
658
+ { eventId: `${runId}:developer-start`, type: 'attempt_started', attemptId, agent: 'feature-developer', stepIndex: 0, attempt: 1, at: startedAt },
659
+ ],
660
+ },
661
+ {
662
+ 'artifact-manifest.json': `${JSON.stringify(
663
+ {
664
+ schemaVersion: 1,
665
+ slug: 'blocked-receipt',
666
+ updatedAt: startedAt,
667
+ artifacts: [
668
+ {
669
+ id: 'implementation-wp1',
670
+ producer: 'feature-developer',
671
+ status: 'blocked',
672
+ authoritativePaths: ['implementation.md'],
673
+ acceptanceCriteriaIds: ['AC-1'],
674
+ taskIds: ['T1'],
675
+ timestamps: { createdAt: startedAt, updatedAt: startedAt, completedAt: startedAt },
676
+ receipt: {
677
+ outcome: 'blocked',
678
+ attemptId,
679
+ summary: 'Implementation requires a user decision.',
680
+ evidencePaths: ['implementation.md'],
681
+ },
682
+ },
683
+ ],
684
+ },
685
+ null,
686
+ 2,
687
+ )}\n`,
688
+ },
689
+ );
690
+
691
+ assert.deepEqual(JSON.parse(invokeHook(hook, root, attemptId)), {}, `${hook}: blocked receipt must not hand off`);
692
+ const status = readJson(path.join(taskDirectory, 'status.json'));
693
+ assert.equal(status.pipelineIndex, 0, `${hook}: blocked receipt advanced the pipeline`);
694
+ assert.equal(status.currentAgent, 'feature-developer', `${hook}: blocked receipt changed the active producer`);
695
+ assert.equal(status.state, 'blocked', `${hook}: blocked receipt did not persist blocked state`);
696
+ assert.equal(status.phase, 'blocked', `${hook}: blocked receipt did not persist blocked phase`);
697
+ assert.equal(Object.keys(status.activeAttempts).length, 0, `${hook}: blocked terminal attempt remained active`);
698
+
699
+ const terminal = readJson(path.join(taskDirectory, 'metrics.json')).events.find(
700
+ (event) => event.type === 'attempt_finished' && event.attemptId === attemptId,
701
+ );
702
+ assert.equal(terminal?.outcome, 'blocked', `${hook}: blocked receipt outcome missing from metrics`);
703
+ } finally {
704
+ fs.rmSync(root, { recursive: true, force: true });
705
+ }
706
+ }
707
+
708
+ for (const hook of hooks) {
709
+ const root = fs.mkdtempSync(path.join(packageDirectory, '.agent-task-metrics-stale-receipt-'));
710
+ try {
711
+ const platform = hook.includes(`${path.sep}cursor${path.sep}`) ? 'cursor' : 'claude';
712
+ const runId = 'stale-receipt-run';
713
+ const attemptId = `${runId}:step-2:code-reviewer:attempt-2`;
714
+ const startedAt = '2026-02-01T00:00:00.000Z';
715
+ const staleAt = '2026-01-01T00:00:00.000Z';
716
+ const taskDirectory = writeTask(
717
+ root,
718
+ hook,
719
+ 'stale-receipt',
720
+ {
721
+ autoChain: true,
722
+ steps: [
723
+ { agent: 'code-reviewer', artifactOutputId: 'review-wp1' },
724
+ { agent: 'feature-developer', artifactInputIds: ['review-wp1'], artifactOutputId: 'implementation-wp2' },
725
+ { agent: 'code-reviewer', artifactInputIds: ['implementation-wp2'], artifactOutputId: 'review-wp2' },
726
+ { agent: 'build-verifier', artifactInputIds: ['review-wp2'], artifactOutputId: 'validation-wp2' },
727
+ ],
728
+ },
729
+ {
730
+ slug: 'stale-receipt',
731
+ intent: 'feature',
732
+ pipelineIndex: 2,
733
+ currentAgent: 'code-reviewer',
734
+ phase: 'executing',
735
+ state: 'in_progress',
736
+ activeAttempts: {
737
+ [attemptId]: {
738
+ agent: 'code-reviewer',
739
+ stepIndex: 2,
740
+ attempt: 2,
741
+ startedAt,
742
+ parallelGroupId: null,
743
+ },
744
+ },
745
+ metricsRunId: runId,
746
+ },
747
+ {
748
+ schemaVersion: 1,
749
+ task: { runId, slug: 'stale-receipt', preset: 'ai-rules', stack: 'test', platform, intent: 'feature', profile: 'test' },
750
+ events: [
751
+ { eventId: `${runId}:task_started`, type: 'task_started', at: staleAt },
752
+ { eventId: `${runId}:review-start`, type: 'attempt_started', attemptId, agent: 'code-reviewer', stepIndex: 2, attempt: 2, at: startedAt },
753
+ ],
754
+ },
755
+ {
756
+ 'artifact-manifest.json': `${JSON.stringify(
757
+ {
758
+ schemaVersion: 1,
759
+ slug: 'stale-receipt',
760
+ updatedAt: staleAt,
761
+ artifacts: [
762
+ {
763
+ id: 'review-wp1',
764
+ producer: 'code-reviewer',
765
+ status: 'blocked',
766
+ authoritativePaths: ['review.md'],
767
+ acceptanceCriteriaIds: ['AC-1'],
768
+ taskIds: ['T1'],
769
+ timestamps: { createdAt: staleAt, updatedAt: staleAt, completedAt: staleAt },
770
+ receipt: {
771
+ outcome: 'changes_requested',
772
+ summary: 'Prior work package requested changes.',
773
+ evidencePaths: ['review.md'],
774
+ },
775
+ },
776
+ {
777
+ id: 'review-wp2',
778
+ producer: 'code-reviewer',
779
+ status: 'completed',
780
+ authoritativePaths: ['review.md'],
781
+ acceptanceCriteriaIds: ['AC-2'],
782
+ taskIds: ['T2'],
783
+ timestamps: { createdAt: staleAt, updatedAt: staleAt, completedAt: staleAt },
784
+ receipt: {
785
+ outcome: 'completed',
786
+ summary: 'Stale receipt from before the active attempt.',
787
+ evidencePaths: ['review.md'],
788
+ },
789
+ },
790
+ ],
791
+ },
792
+ null,
793
+ 2,
794
+ )}\n`,
795
+ },
796
+ );
797
+
798
+ assert.deepEqual(JSON.parse(invokeHook(hook, root, attemptId)), {}, `${hook}: stale receipt must not hand off`);
799
+ const status = readJson(path.join(taskDirectory, 'status.json'));
800
+ assert.equal(status.pipelineIndex, 2, `${hook}: stale receipt advanced the pipeline`);
801
+ assert.equal(status.currentAgent, 'code-reviewer', `${hook}: stale receipt changed the active producer`);
802
+ assert.equal(status.state, 'awaiting_artifact_receipt', `${hook}: stale receipt did not enter receipt-wait state`);
803
+ assert.ok(status.activeAttempts[attemptId], `${hook}: stale receipt consumed the active attempt`);
804
+ assert.equal(
805
+ readJson(path.join(taskDirectory, 'metrics.json')).events.filter(
806
+ (event) => event.type === 'attempt_finished' && event.attemptId === attemptId,
807
+ ).length,
808
+ 0,
809
+ `${hook}: stale receipt emitted terminal metrics`,
810
+ );
811
+ } finally {
812
+ fs.rmSync(root, { recursive: true, force: true });
813
+ }
814
+ }
815
+
816
+ {
817
+ const root = fs.mkdtempSync(path.join(packageDirectory, '.agent-task-metrics-aggregate-'));
818
+ try {
819
+ const tasksDirectory = path.join(root, 'tasks');
820
+ const missingDirectory = path.join(tasksDirectory, 'missing-ledger');
821
+ const malformedDirectory = path.join(tasksDirectory, 'malformed-ledger');
822
+ const invalidDirectory = path.join(tasksDirectory, 'invalid-ledger');
823
+ const duplicateDirectory = path.join(tasksDirectory, 'duplicate-attempt-id');
824
+ fs.mkdirSync(missingDirectory, { recursive: true });
825
+ fs.mkdirSync(malformedDirectory, { recursive: true });
826
+ fs.mkdirSync(invalidDirectory, { recursive: true });
827
+ fs.mkdirSync(duplicateDirectory, { recursive: true });
828
+ fs.writeFileSync(path.join(malformedDirectory, 'metrics.json'), '{not-json\n');
829
+ writeJson(path.join(invalidDirectory, 'metrics.json'), {
830
+ schemaVersion: 1,
831
+ task: { runId: 'invalid-ledger-run', slug: 'invalid-ledger' },
832
+ events: [null],
833
+ });
834
+ writeJson(path.join(duplicateDirectory, 'metrics.json'), {
835
+ schemaVersion: 1,
836
+ task: {
837
+ runId: 'duplicate-attempt-id-run',
838
+ slug: 'duplicate-attempt-id',
839
+ preset: 'ai-rules',
840
+ stack: 'next',
841
+ platform: 'cursor',
842
+ intent: 'feature',
843
+ profile: 'test',
844
+ },
845
+ events: [
846
+ {
847
+ eventId: 'duplicate-attempt-id-run:start-1',
848
+ type: 'attempt_started',
849
+ attemptId: 'duplicate-attempt-id-run:step-0:feature-developer:attempt-1',
850
+ agent: 'feature-developer',
851
+ stepIndex: 0,
852
+ attempt: 1,
853
+ at: '2026-01-01T00:00:00.000Z',
854
+ },
855
+ {
856
+ eventId: 'duplicate-attempt-id-run:start-duplicate',
857
+ type: 'attempt_started',
858
+ attemptId: 'duplicate-attempt-id-run:step-0:feature-developer:attempt-1',
859
+ agent: 'feature-developer',
860
+ stepIndex: 0,
861
+ attempt: 1,
862
+ at: '2026-01-01T00:00:01.000Z',
863
+ },
864
+ ],
865
+ });
866
+
867
+ const aggregate = JSON.parse(
868
+ execFileSync(
869
+ process.execPath,
870
+ [path.join(scriptDirectory, 'aggregate-agent-task-metrics.mjs'), '--team-root', root],
871
+ { encoding: 'utf8' },
872
+ ),
873
+ );
874
+ assert.equal(aggregate.completeness.missingLedgerCount, 1, 'aggregator must count missing ledgers separately');
875
+ assert.equal(aggregate.completeness.malformedLedgerCount, 1, 'aggregator must count malformed ledgers separately');
876
+ assert.equal(aggregate.completeness.invalidLedgerCount, 1, 'aggregator must count structurally invalid ledgers separately');
877
+ assert.equal(aggregate.completeness.duplicateAttemptIdCount, 1, 'aggregator must reject duplicate attempt IDs');
878
+ assert.ok(
879
+ aggregate.incomplete.some((entry) => entry.category === 'missing_ledger'),
880
+ 'aggregator missing-ledger category was not reported',
881
+ );
882
+ assert.ok(
883
+ aggregate.incomplete.some((entry) => entry.category === 'malformed_json'),
884
+ 'aggregator malformed-JSON category was not reported',
885
+ );
886
+ assert.ok(
887
+ aggregate.incomplete.some((entry) => entry.category === 'invalid_ledger'),
888
+ 'aggregator invalid-ledger category was not reported',
889
+ );
890
+ } finally {
891
+ fs.rmSync(root, { recursive: true, force: true });
892
+ }
893
+ }
894
+
895
+ console.log(`Verified retry, parallel, skip, gate, manifest-reconcile, and aggregation lifecycle in ${hooks.length} hooks.`);