@bonesofspring/ai-rules 0.2.20 → 0.2.22

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 (505) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +17 -2
  3. package/bin/cli.js +83 -6
  4. package/package.json +5 -2
  5. package/presets/_shared/README.md +2 -1
  6. package/presets/_shared/assets/docs-specs/INDEX.md +4 -1
  7. package/presets/_shared/core/agent-team/agent-artifact-contracts.md +15 -0
  8. package/presets/_shared/core/agent-team/agent-task-metrics.md +1 -1
  9. package/presets/_shared/core/agent-team/agent-team-orchestrator.md +1 -3
  10. package/presets/_shared/core/meta/preset-pr-checklist.md +5 -1
  11. package/presets/_shared/core/meta/preset-token-budget.md +7 -3
  12. package/presets/_shared/core/meta/preset-twin-sync.md +2 -0
  13. package/presets/_shared/core/testing/testing-principles.md +70 -0
  14. package/presets/claude/android-kotlin/agents/README.md +2 -1
  15. package/presets/claude/android-kotlin/agents/build-verifier.md +2 -0
  16. package/presets/claude/android-kotlin/agents/code-reviewer.md +2 -0
  17. package/presets/claude/android-kotlin/agents/debugger.md +1 -0
  18. package/presets/claude/android-kotlin/agents/feature-developer.md +4 -1
  19. package/presets/claude/android-kotlin/agents/openspec-author.md +163 -0
  20. package/presets/claude/android-kotlin/agents/qa-tester.md +2 -0
  21. package/presets/claude/android-kotlin/agents/task-analyst.md +1 -1
  22. package/presets/claude/android-kotlin/agents/task-router.md +9 -1
  23. package/presets/claude/android-kotlin/agents/tech-writer.md +4 -0
  24. package/presets/claude/android-kotlin/commands/README.md +0 -2
  25. package/presets/claude/android-kotlin/commands/task-continue.md +1 -1
  26. package/presets/claude/android-kotlin/commands/task.md +1 -5
  27. package/presets/claude/android-kotlin/commands/technical-retro.md +2 -2
  28. package/presets/claude/android-kotlin/hooks/chain-team-phases.sh +105 -13
  29. package/presets/claude/android-kotlin/rules/README.md +1 -0
  30. package/presets/claude/android-kotlin/rules/tooling-and-review/agent-team-orchestrator.md +7 -4
  31. package/presets/claude/android-kotlin/rules/tooling-and-review/ai-local-overlay.md +48 -0
  32. package/presets/claude/android-kotlin/rules/tooling-and-review/preset-pr-checklist.md +5 -1
  33. package/presets/claude/android-kotlin/rules/tooling-and-review/preset-token-budget.md +7 -3
  34. package/presets/claude/android-kotlin/rules/tooling-and-review/preset-twin-sync.md +2 -0
  35. package/presets/claude/go/README.md +1 -1
  36. package/presets/claude/go/agents/README.md +3 -2
  37. package/presets/claude/go/agents/build-verifier.md +4 -0
  38. package/presets/claude/go/agents/code-reviewer.md +4 -0
  39. package/presets/claude/go/agents/debugger.md +4 -0
  40. package/presets/claude/go/agents/feature-developer.md +5 -0
  41. package/presets/claude/go/agents/openspec-author.md +163 -0
  42. package/presets/claude/go/agents/qa-tester.md +4 -0
  43. package/presets/claude/go/agents/task-router.md +9 -1
  44. package/presets/claude/go/agents/tech-writer.md +4 -0
  45. package/presets/claude/go/commands/README.md +0 -2
  46. package/presets/claude/go/commands/task-continue.md +1 -1
  47. package/presets/claude/go/commands/task.md +1 -4
  48. package/presets/claude/go/hooks/chain-team-phases.sh +105 -14
  49. package/presets/claude/go/rules/README.md +1 -0
  50. package/presets/claude/go/rules/tooling-and-review/agent-team-orchestrator.md +2 -4
  51. package/presets/claude/go/rules/tooling-and-review/ai-local-overlay.md +48 -0
  52. package/presets/claude/go/rules/tooling-and-review/preset-pr-checklist.md +5 -1
  53. package/presets/claude/go/rules/tooling-and-review/preset-token-budget.md +7 -3
  54. package/presets/claude/go/rules/tooling-and-review/preset-twin-sync.md +2 -0
  55. package/presets/claude/ios-swift/agents/README.md +3 -2
  56. package/presets/claude/ios-swift/agents/build-verifier.md +2 -0
  57. package/presets/claude/ios-swift/agents/code-reviewer.md +2 -0
  58. package/presets/claude/ios-swift/agents/debugger.md +1 -0
  59. package/presets/claude/ios-swift/agents/feature-developer.md +4 -1
  60. package/presets/claude/ios-swift/agents/openspec-author.md +163 -0
  61. package/presets/claude/ios-swift/agents/qa-tester.md +2 -0
  62. package/presets/claude/ios-swift/agents/task-analyst.md +1 -1
  63. package/presets/claude/ios-swift/agents/task-router.md +9 -1
  64. package/presets/claude/ios-swift/agents/tech-writer.md +4 -0
  65. package/presets/claude/ios-swift/commands/README.md +0 -2
  66. package/presets/claude/ios-swift/commands/task-continue.md +1 -1
  67. package/presets/claude/ios-swift/commands/task.md +1 -5
  68. package/presets/claude/ios-swift/commands/technical-retro.md +2 -2
  69. package/presets/claude/ios-swift/hooks/chain-team-phases.sh +105 -13
  70. package/presets/claude/ios-swift/rules/README.md +1 -0
  71. package/presets/claude/ios-swift/rules/tooling-and-review/agent-team-orchestrator.md +7 -4
  72. package/presets/claude/ios-swift/rules/tooling-and-review/ai-local-overlay.md +48 -0
  73. package/presets/claude/ios-swift/rules/tooling-and-review/preset-pr-checklist.md +5 -1
  74. package/presets/claude/ios-swift/rules/tooling-and-review/preset-token-budget.md +7 -3
  75. package/presets/claude/ios-swift/rules/tooling-and-review/preset-twin-sync.md +2 -0
  76. package/presets/claude/java/CLAUDE.md +1 -1
  77. package/presets/claude/java/agents/README.md +3 -2
  78. package/presets/claude/java/agents/build-verifier.md +4 -0
  79. package/presets/claude/java/agents/code-reviewer.md +4 -0
  80. package/presets/claude/java/agents/debugger.md +4 -0
  81. package/presets/claude/java/agents/feature-developer.md +5 -0
  82. package/presets/claude/java/agents/openspec-author.md +163 -0
  83. package/presets/claude/java/agents/qa-tester.md +4 -0
  84. package/presets/claude/java/agents/task-router.md +9 -1
  85. package/presets/claude/java/agents/tech-writer.md +4 -0
  86. package/presets/claude/java/commands/README.md +0 -2
  87. package/presets/claude/java/commands/task-continue.md +1 -1
  88. package/presets/claude/java/commands/task.md +1 -4
  89. package/presets/claude/java/hooks/chain-team-phases.sh +105 -14
  90. package/presets/claude/java/rules/README.md +1 -0
  91. package/presets/claude/java/rules/tooling-and-review/agent-team-orchestrator.md +2 -4
  92. package/presets/claude/java/rules/tooling-and-review/ai-local-overlay.md +48 -0
  93. package/presets/claude/java/rules/tooling-and-review/preset-pr-checklist.md +5 -1
  94. package/presets/claude/java/rules/tooling-and-review/preset-token-budget.md +7 -3
  95. package/presets/claude/java/rules/tooling-and-review/preset-twin-sync.md +2 -0
  96. package/presets/claude/mcp-ts/agents/build-verifier.md +4 -0
  97. package/presets/claude/mcp-ts/agents/feature-developer.md +5 -0
  98. package/presets/claude/mcp-ts/agents/task-analyst.md +1 -1
  99. package/presets/claude/mcp-ts/agents/task-router.md +1 -1
  100. package/presets/claude/mcp-ts/commands/README.md +0 -2
  101. package/presets/claude/mcp-ts/commands/task-continue.md +1 -1
  102. package/presets/claude/mcp-ts/commands/task.md +1 -4
  103. package/presets/claude/mcp-ts/commands/technical-retro.md +2 -2
  104. package/presets/claude/mcp-ts/hooks/chain-team-phases.sh +91 -20
  105. package/presets/claude/mcp-ts/rules/README.md +1 -0
  106. package/presets/claude/mcp-ts/rules/tooling-and-review/agent-team-orchestrator.md +2 -4
  107. package/presets/claude/mcp-ts/rules/tooling-and-review/ai-local-overlay.md +48 -0
  108. package/presets/claude/mcp-ts/rules/tooling-and-review/preset-pr-checklist.md +5 -1
  109. package/presets/claude/mcp-ts/rules/tooling-and-review/preset-token-budget.md +7 -3
  110. package/presets/claude/mcp-ts/rules/tooling-and-review/preset-twin-sync.md +2 -0
  111. package/presets/claude/next/README.md +1 -0
  112. package/presets/claude/next/agents/README.md +2 -2
  113. package/presets/claude/next/agents/build-verifier.md +13 -1
  114. package/presets/claude/next/agents/code-reviewer.md +2 -0
  115. package/presets/claude/next/agents/debugger.md +4 -0
  116. package/presets/claude/next/agents/feature-developer.md +4 -1
  117. package/presets/claude/next/agents/openspec-author.md +163 -0
  118. package/presets/claude/next/agents/qa-tester.md +4 -0
  119. package/presets/claude/next/agents/task-analyst.md +1 -1
  120. package/presets/claude/next/agents/task-router.md +5 -1
  121. package/presets/claude/next/agents/tech-writer.md +4 -0
  122. package/presets/claude/next/agents/unit-test-generator.md +1 -1
  123. package/presets/claude/next/agents/unit-test-planner.md +1 -1
  124. package/presets/claude/next/commands/README.md +0 -2
  125. package/presets/claude/next/commands/task-continue.md +1 -1
  126. package/presets/claude/next/commands/task.md +1 -4
  127. package/presets/claude/next/hooks/chain-team-phases.sh +105 -13
  128. package/presets/claude/next/rules/README.md +1 -0
  129. package/presets/claude/next/rules/api-and-data/http-client.md +1 -1
  130. package/presets/claude/next/rules/architecture/reference-features.md +1 -1
  131. package/presets/claude/next/rules/testing/README.md +7 -1
  132. package/presets/claude/next/rules/testing/tests-e2e-structure.md +86 -48
  133. package/presets/claude/next/rules/testing/tests-unit.md +78 -51
  134. package/presets/claude/next/rules/tooling-and-review/agent-team-orchestrator.md +3 -4
  135. package/presets/claude/next/rules/tooling-and-review/ai-local-overlay.md +48 -0
  136. package/presets/claude/next/rules/tooling-and-review/preset-pr-checklist.md +5 -1
  137. package/presets/claude/next/rules/tooling-and-review/preset-token-budget.md +7 -3
  138. package/presets/claude/next/rules/tooling-and-review/preset-twin-sync.md +2 -0
  139. package/presets/claude/next/rules/ui-and-accessibility/react-ui.md +1 -1
  140. package/presets/claude/next/skills/playwright-e2e/SKILL.md +5 -3
  141. package/presets/claude/next/skills/unit-testing/SKILL.md +6 -4
  142. package/presets/claude/next/team/README.md +0 -3
  143. package/presets/claude/nuxt/agents/README.md +1 -1
  144. package/presets/claude/nuxt/agents/build-verifier.md +2 -0
  145. package/presets/claude/nuxt/agents/code-reviewer.md +2 -0
  146. package/presets/claude/nuxt/agents/debugger.md +4 -0
  147. package/presets/claude/nuxt/agents/feature-developer.md +4 -1
  148. package/presets/claude/nuxt/agents/openspec-author.md +163 -0
  149. package/presets/claude/nuxt/agents/qa-tester.md +4 -0
  150. package/presets/claude/nuxt/agents/task-analyst.md +1 -1
  151. package/presets/claude/nuxt/agents/task-router.md +5 -1
  152. package/presets/claude/nuxt/agents/tech-writer.md +4 -0
  153. package/presets/claude/nuxt/commands/README.md +0 -2
  154. package/presets/claude/nuxt/commands/task-continue.md +1 -1
  155. package/presets/claude/nuxt/commands/task.md +1 -5
  156. package/presets/claude/nuxt/commands/technical-retro.md +2 -2
  157. package/presets/claude/nuxt/hooks/chain-team-phases.sh +105 -13
  158. package/presets/claude/nuxt/rules/README.md +1 -0
  159. package/presets/claude/nuxt/rules/testing/README.md +6 -0
  160. package/presets/claude/nuxt/rules/testing/tests-e2e-structure.md +86 -43
  161. package/presets/claude/nuxt/rules/testing/tests-unit.md +58 -45
  162. package/presets/claude/nuxt/rules/tooling-and-review/agent-team-orchestrator.md +8 -5
  163. package/presets/claude/nuxt/rules/tooling-and-review/ai-local-overlay.md +48 -0
  164. package/presets/claude/nuxt/rules/tooling-and-review/preset-pr-checklist.md +5 -1
  165. package/presets/claude/nuxt/rules/tooling-and-review/preset-token-budget.md +7 -3
  166. package/presets/claude/nuxt/rules/tooling-and-review/preset-twin-sync.md +2 -0
  167. package/presets/claude/nuxt/team/README.md +0 -3
  168. package/presets/claude/php-hexagonal/CLAUDE.md +1 -1
  169. package/presets/claude/php-hexagonal/agents/README.md +3 -2
  170. package/presets/claude/php-hexagonal/agents/build-verifier.md +4 -0
  171. package/presets/claude/php-hexagonal/agents/code-reviewer.md +4 -0
  172. package/presets/claude/php-hexagonal/agents/debugger.md +4 -0
  173. package/presets/claude/php-hexagonal/agents/feature-developer.md +5 -0
  174. package/presets/claude/php-hexagonal/agents/openspec-author.md +163 -0
  175. package/presets/claude/php-hexagonal/agents/qa-tester.md +4 -0
  176. package/presets/claude/php-hexagonal/agents/task-router.md +9 -1
  177. package/presets/claude/php-hexagonal/agents/tech-writer.md +4 -0
  178. package/presets/claude/php-hexagonal/commands/README.md +0 -2
  179. package/presets/claude/php-hexagonal/commands/task-continue.md +1 -1
  180. package/presets/claude/php-hexagonal/commands/task.md +1 -4
  181. package/presets/claude/php-hexagonal/hooks/chain-team-phases.sh +105 -14
  182. package/presets/claude/php-hexagonal/rules/README.md +1 -0
  183. package/presets/claude/php-hexagonal/rules/tooling-and-review/agent-team-orchestrator.md +2 -4
  184. package/presets/claude/php-hexagonal/rules/tooling-and-review/ai-local-overlay.md +48 -0
  185. package/presets/claude/php-hexagonal/rules/tooling-and-review/preset-pr-checklist.md +5 -1
  186. package/presets/claude/php-hexagonal/rules/tooling-and-review/preset-token-budget.md +7 -3
  187. package/presets/claude/php-hexagonal/rules/tooling-and-review/preset-twin-sync.md +2 -0
  188. package/presets/claude/php-laravel/agents/README.md +3 -2
  189. package/presets/claude/php-laravel/agents/build-verifier.md +4 -0
  190. package/presets/claude/php-laravel/agents/code-reviewer.md +4 -0
  191. package/presets/claude/php-laravel/agents/debugger.md +4 -0
  192. package/presets/claude/php-laravel/agents/feature-developer.md +5 -0
  193. package/presets/claude/php-laravel/agents/openspec-author.md +163 -0
  194. package/presets/claude/php-laravel/agents/qa-tester.md +4 -0
  195. package/presets/claude/php-laravel/agents/task-router.md +6 -1
  196. package/presets/claude/php-laravel/agents/tech-writer.md +4 -0
  197. package/presets/claude/php-laravel/commands/README.md +0 -2
  198. package/presets/claude/php-laravel/commands/task-continue.md +1 -1
  199. package/presets/claude/php-laravel/commands/task.md +1 -4
  200. package/presets/claude/php-laravel/hooks/chain-team-phases.sh +105 -14
  201. package/presets/claude/php-laravel/rules/README.md +1 -0
  202. package/presets/claude/php-laravel/rules/tooling-and-review/agent-team-orchestrator.md +2 -4
  203. package/presets/claude/php-laravel/rules/tooling-and-review/ai-local-overlay.md +48 -0
  204. package/presets/claude/php-laravel/rules/tooling-and-review/preset-pr-checklist.md +5 -1
  205. package/presets/claude/php-laravel/rules/tooling-and-review/preset-token-budget.md +7 -3
  206. package/presets/claude/php-laravel/rules/tooling-and-review/preset-twin-sync.md +2 -0
  207. package/presets/claude/svelte/agents/README.md +1 -1
  208. package/presets/claude/svelte/agents/build-verifier.md +2 -0
  209. package/presets/claude/svelte/agents/code-reviewer.md +2 -0
  210. package/presets/claude/svelte/agents/debugger.md +4 -0
  211. package/presets/claude/svelte/agents/feature-developer.md +4 -1
  212. package/presets/claude/svelte/agents/openspec-author.md +163 -0
  213. package/presets/claude/svelte/agents/qa-tester.md +4 -0
  214. package/presets/claude/svelte/agents/task-analyst.md +1 -1
  215. package/presets/claude/svelte/agents/task-router.md +5 -1
  216. package/presets/claude/svelte/agents/tech-writer.md +4 -0
  217. package/presets/claude/svelte/commands/README.md +0 -2
  218. package/presets/claude/svelte/commands/task-continue.md +1 -1
  219. package/presets/claude/svelte/commands/task.md +1 -5
  220. package/presets/claude/svelte/commands/technical-retro.md +2 -2
  221. package/presets/claude/svelte/hooks/chain-team-phases.sh +105 -13
  222. package/presets/claude/svelte/rules/README.md +1 -0
  223. package/presets/claude/svelte/rules/testing/README.md +6 -0
  224. package/presets/claude/svelte/rules/testing/tests-e2e-structure.md +87 -45
  225. package/presets/claude/svelte/rules/testing/tests-unit.md +70 -23
  226. package/presets/claude/svelte/rules/tooling-and-review/agent-team-orchestrator.md +8 -5
  227. package/presets/claude/svelte/rules/tooling-and-review/ai-local-overlay.md +48 -0
  228. package/presets/claude/svelte/rules/tooling-and-review/preset-pr-checklist.md +5 -1
  229. package/presets/claude/svelte/rules/tooling-and-review/preset-token-budget.md +7 -3
  230. package/presets/claude/svelte/rules/tooling-and-review/preset-twin-sync.md +2 -0
  231. package/presets/claude/svelte/team/README.md +0 -3
  232. package/presets/cursor/android-kotlin/agents/README.md +2 -1
  233. package/presets/cursor/android-kotlin/agents/build-verifier.md +2 -0
  234. package/presets/cursor/android-kotlin/agents/code-reviewer.md +2 -0
  235. package/presets/cursor/android-kotlin/agents/debugger.md +1 -0
  236. package/presets/cursor/android-kotlin/agents/feature-developer.md +4 -1
  237. package/presets/cursor/android-kotlin/agents/openspec-author.md +164 -0
  238. package/presets/cursor/android-kotlin/agents/qa-tester.md +2 -0
  239. package/presets/cursor/android-kotlin/agents/task-analyst.md +1 -1
  240. package/presets/cursor/android-kotlin/agents/task-router.md +9 -1
  241. package/presets/cursor/android-kotlin/agents/tech-writer.md +4 -0
  242. package/presets/cursor/android-kotlin/commands/README.md +0 -2
  243. package/presets/cursor/android-kotlin/commands/task-continue.md +1 -1
  244. package/presets/cursor/android-kotlin/commands/task.md +1 -5
  245. package/presets/cursor/android-kotlin/commands/technical-retro.md +2 -2
  246. package/presets/cursor/android-kotlin/hooks/chain-team-phases.sh +105 -13
  247. package/presets/cursor/android-kotlin/rules/agent-team-orchestrator.mdc +7 -4
  248. package/presets/cursor/android-kotlin/rules/ai-local-overlay.mdc +43 -0
  249. package/presets/cursor/android-kotlin/rules/preset-pr-checklist.mdc +5 -1
  250. package/presets/cursor/android-kotlin/rules/preset-token-budget.mdc +7 -3
  251. package/presets/cursor/android-kotlin/rules/preset-twin-sync.mdc +2 -0
  252. package/presets/cursor/go/README.md +6 -6
  253. package/presets/cursor/go/agents/README.md +3 -2
  254. package/presets/cursor/go/agents/build-verifier.md +4 -0
  255. package/presets/cursor/go/agents/code-reviewer.md +4 -0
  256. package/presets/cursor/go/agents/debugger.md +4 -0
  257. package/presets/cursor/go/agents/feature-developer.md +5 -0
  258. package/presets/cursor/go/agents/openspec-author.md +164 -0
  259. package/presets/cursor/go/agents/qa-tester.md +4 -0
  260. package/presets/cursor/go/agents/task-router.md +9 -1
  261. package/presets/cursor/go/agents/tech-writer.md +4 -0
  262. package/presets/cursor/go/commands/README.md +0 -2
  263. package/presets/cursor/go/commands/task-continue.md +1 -1
  264. package/presets/cursor/go/commands/task.md +1 -4
  265. package/presets/cursor/go/commands/technical-retro.md +2 -2
  266. package/presets/cursor/go/hooks/chain-team-phases.sh +105 -14
  267. package/presets/cursor/go/rules/agent-team-orchestrator.mdc +2 -4
  268. package/presets/cursor/go/rules/ai-local-overlay.mdc +43 -0
  269. package/presets/cursor/go/rules/preset-pr-checklist.mdc +5 -1
  270. package/presets/cursor/go/rules/preset-token-budget.mdc +7 -3
  271. package/presets/cursor/go/rules/preset-twin-sync.mdc +2 -0
  272. package/presets/cursor/ios-swift/README.md +6 -6
  273. package/presets/cursor/ios-swift/agents/README.md +3 -2
  274. package/presets/cursor/ios-swift/agents/build-verifier.md +2 -0
  275. package/presets/cursor/ios-swift/agents/code-reviewer.md +2 -0
  276. package/presets/cursor/ios-swift/agents/debugger.md +1 -0
  277. package/presets/cursor/ios-swift/agents/feature-developer.md +4 -1
  278. package/presets/cursor/ios-swift/agents/openspec-author.md +164 -0
  279. package/presets/cursor/ios-swift/agents/qa-tester.md +2 -0
  280. package/presets/cursor/ios-swift/agents/task-analyst.md +1 -1
  281. package/presets/cursor/ios-swift/agents/task-router.md +9 -1
  282. package/presets/cursor/ios-swift/agents/tech-writer.md +4 -0
  283. package/presets/cursor/ios-swift/commands/README.md +1 -3
  284. package/presets/cursor/ios-swift/commands/task-continue.md +1 -1
  285. package/presets/cursor/ios-swift/commands/task.md +1 -5
  286. package/presets/cursor/ios-swift/commands/technical-retro.md +2 -2
  287. package/presets/cursor/ios-swift/hooks/chain-team-phases.sh +105 -13
  288. package/presets/cursor/ios-swift/rules/agent-team-orchestrator.mdc +7 -4
  289. package/presets/cursor/ios-swift/rules/ai-local-overlay.mdc +43 -0
  290. package/presets/cursor/ios-swift/rules/preset-pr-checklist.mdc +5 -1
  291. package/presets/cursor/ios-swift/rules/preset-token-budget.mdc +7 -3
  292. package/presets/cursor/ios-swift/rules/preset-twin-sync.mdc +2 -0
  293. package/presets/cursor/java/AGENTS.md +1 -1
  294. package/presets/cursor/java/agents/README.md +3 -2
  295. package/presets/cursor/java/agents/build-verifier.md +4 -0
  296. package/presets/cursor/java/agents/code-reviewer.md +4 -0
  297. package/presets/cursor/java/agents/debugger.md +4 -0
  298. package/presets/cursor/java/agents/feature-developer.md +5 -0
  299. package/presets/cursor/java/agents/openspec-author.md +164 -0
  300. package/presets/cursor/java/agents/qa-tester.md +4 -0
  301. package/presets/cursor/java/agents/task-router.md +9 -1
  302. package/presets/cursor/java/agents/tech-writer.md +4 -0
  303. package/presets/cursor/java/commands/README.md +0 -2
  304. package/presets/cursor/java/commands/task-continue.md +1 -1
  305. package/presets/cursor/java/commands/task.md +1 -4
  306. package/presets/cursor/java/commands/technical-retro.md +2 -2
  307. package/presets/cursor/java/hooks/chain-team-phases.sh +105 -14
  308. package/presets/cursor/java/rules/agent-team-orchestrator.mdc +2 -4
  309. package/presets/cursor/java/rules/ai-local-overlay.mdc +43 -0
  310. package/presets/cursor/java/rules/preset-pr-checklist.mdc +5 -1
  311. package/presets/cursor/java/rules/preset-token-budget.mdc +7 -3
  312. package/presets/cursor/java/rules/preset-twin-sync.mdc +2 -0
  313. package/presets/cursor/mcp-ts/agents/build-verifier.md +4 -0
  314. package/presets/cursor/mcp-ts/agents/feature-developer.md +5 -0
  315. package/presets/cursor/mcp-ts/agents/task-analyst.md +1 -1
  316. package/presets/cursor/mcp-ts/agents/task-router.md +1 -1
  317. package/presets/cursor/mcp-ts/commands/README.md +0 -2
  318. package/presets/cursor/mcp-ts/commands/task-continue.md +1 -1
  319. package/presets/cursor/mcp-ts/commands/task.md +1 -4
  320. package/presets/cursor/mcp-ts/commands/technical-retro.md +2 -2
  321. package/presets/cursor/mcp-ts/hooks/chain-team-phases.sh +91 -20
  322. package/presets/cursor/mcp-ts/rules/agent-team-orchestrator.mdc +2 -4
  323. package/presets/cursor/mcp-ts/rules/ai-local-overlay.mdc +43 -0
  324. package/presets/cursor/mcp-ts/rules/preset-pr-checklist.mdc +5 -1
  325. package/presets/cursor/mcp-ts/rules/preset-token-budget.mdc +7 -3
  326. package/presets/cursor/mcp-ts/rules/preset-twin-sync.mdc +2 -0
  327. package/presets/cursor/next/README.md +8 -6
  328. package/presets/cursor/next/REPO_AGENTS.md +8 -0
  329. package/presets/cursor/next/agents/README.md +2 -2
  330. package/presets/cursor/next/agents/build-verifier.md +13 -1
  331. package/presets/cursor/next/agents/code-reviewer.md +2 -0
  332. package/presets/cursor/next/agents/debugger.md +4 -0
  333. package/presets/cursor/next/agents/feature-developer.md +4 -1
  334. package/presets/cursor/next/agents/openspec-author.md +164 -0
  335. package/presets/cursor/next/agents/qa-tester.md +4 -0
  336. package/presets/cursor/next/agents/task-analyst.md +1 -1
  337. package/presets/cursor/next/agents/task-router.md +5 -1
  338. package/presets/cursor/next/agents/tech-writer.md +4 -0
  339. package/presets/cursor/next/agents/unit-test-generator.md +1 -1
  340. package/presets/cursor/next/agents/unit-test-planner.md +1 -1
  341. package/presets/cursor/next/commands/README.md +0 -2
  342. package/presets/cursor/next/commands/task-continue.md +1 -1
  343. package/presets/cursor/next/commands/task.md +1 -4
  344. package/presets/cursor/next/commands/technical-retro.md +2 -2
  345. package/presets/cursor/next/hooks/chain-team-phases.sh +105 -13
  346. package/presets/cursor/next/rules/README.md +6 -3
  347. package/presets/cursor/next/rules/agent-team-orchestrator.mdc +7 -5
  348. package/presets/cursor/next/rules/ai-local-overlay.mdc +43 -0
  349. package/presets/cursor/next/rules/http-client.mdc +1 -1
  350. package/presets/cursor/next/rules/preset-pr-checklist.mdc +5 -1
  351. package/presets/cursor/next/rules/preset-token-budget.mdc +7 -3
  352. package/presets/cursor/next/rules/preset-twin-sync.mdc +2 -0
  353. package/presets/cursor/next/rules/react-ui.mdc +1 -1
  354. package/presets/cursor/next/rules/reference-features.mdc +1 -1
  355. package/presets/cursor/next/rules/tests-e2e-structure.mdc +85 -43
  356. package/presets/cursor/next/rules/tests-unit.mdc +79 -48
  357. package/presets/cursor/next/skills/playwright-e2e/SKILL.md +5 -3
  358. package/presets/cursor/next/skills/unit-testing/SKILL.md +6 -4
  359. package/presets/cursor/next/team/README.md +0 -3
  360. package/presets/cursor/nuxt/README.md +6 -6
  361. package/presets/cursor/nuxt/agents/README.md +1 -1
  362. package/presets/cursor/nuxt/agents/build-verifier.md +2 -0
  363. package/presets/cursor/nuxt/agents/code-reviewer.md +2 -0
  364. package/presets/cursor/nuxt/agents/debugger.md +4 -0
  365. package/presets/cursor/nuxt/agents/feature-developer.md +4 -1
  366. package/presets/cursor/nuxt/agents/openspec-author.md +164 -0
  367. package/presets/cursor/nuxt/agents/qa-tester.md +4 -0
  368. package/presets/cursor/nuxt/agents/task-analyst.md +1 -1
  369. package/presets/cursor/nuxt/agents/task-router.md +5 -1
  370. package/presets/cursor/nuxt/agents/tech-writer.md +4 -0
  371. package/presets/cursor/nuxt/commands/README.md +0 -2
  372. package/presets/cursor/nuxt/commands/task-continue.md +1 -1
  373. package/presets/cursor/nuxt/commands/task.md +1 -5
  374. package/presets/cursor/nuxt/commands/technical-retro.md +2 -2
  375. package/presets/cursor/nuxt/hooks/chain-team-phases.sh +105 -13
  376. package/presets/cursor/nuxt/rules/README.md +3 -1
  377. package/presets/cursor/nuxt/rules/agent-team-orchestrator.mdc +8 -5
  378. package/presets/cursor/nuxt/rules/ai-local-overlay.mdc +43 -0
  379. package/presets/cursor/nuxt/rules/preset-pr-checklist.mdc +5 -1
  380. package/presets/cursor/nuxt/rules/preset-token-budget.mdc +7 -3
  381. package/presets/cursor/nuxt/rules/preset-twin-sync.mdc +2 -0
  382. package/presets/cursor/nuxt/rules/tests-e2e-structure.mdc +87 -43
  383. package/presets/cursor/nuxt/rules/tests-unit.mdc +62 -47
  384. package/presets/cursor/nuxt/team/README.md +0 -3
  385. package/presets/cursor/php-hexagonal/AGENTS.md +1 -1
  386. package/presets/cursor/php-hexagonal/agents/README.md +3 -2
  387. package/presets/cursor/php-hexagonal/agents/build-verifier.md +4 -0
  388. package/presets/cursor/php-hexagonal/agents/code-reviewer.md +4 -0
  389. package/presets/cursor/php-hexagonal/agents/debugger.md +4 -0
  390. package/presets/cursor/php-hexagonal/agents/feature-developer.md +5 -0
  391. package/presets/cursor/php-hexagonal/agents/openspec-author.md +164 -0
  392. package/presets/cursor/php-hexagonal/agents/qa-tester.md +4 -0
  393. package/presets/cursor/php-hexagonal/agents/task-router.md +9 -1
  394. package/presets/cursor/php-hexagonal/agents/tech-writer.md +4 -0
  395. package/presets/cursor/php-hexagonal/commands/README.md +0 -2
  396. package/presets/cursor/php-hexagonal/commands/task-continue.md +1 -1
  397. package/presets/cursor/php-hexagonal/commands/task.md +1 -4
  398. package/presets/cursor/php-hexagonal/commands/technical-retro.md +2 -2
  399. package/presets/cursor/php-hexagonal/hooks/chain-team-phases.sh +105 -14
  400. package/presets/cursor/php-hexagonal/rules/agent-team-orchestrator.mdc +2 -4
  401. package/presets/cursor/php-hexagonal/rules/ai-local-overlay.mdc +43 -0
  402. package/presets/cursor/php-hexagonal/rules/preset-pr-checklist.mdc +5 -1
  403. package/presets/cursor/php-hexagonal/rules/preset-token-budget.mdc +7 -3
  404. package/presets/cursor/php-hexagonal/rules/preset-twin-sync.mdc +2 -0
  405. package/presets/cursor/php-laravel/AGENTS.md +1 -1
  406. package/presets/cursor/php-laravel/agents/README.md +3 -2
  407. package/presets/cursor/php-laravel/agents/build-verifier.md +4 -0
  408. package/presets/cursor/php-laravel/agents/code-reviewer.md +4 -0
  409. package/presets/cursor/php-laravel/agents/debugger.md +4 -0
  410. package/presets/cursor/php-laravel/agents/feature-developer.md +5 -0
  411. package/presets/cursor/php-laravel/agents/openspec-author.md +164 -0
  412. package/presets/cursor/php-laravel/agents/qa-tester.md +4 -0
  413. package/presets/cursor/php-laravel/agents/task-router.md +6 -1
  414. package/presets/cursor/php-laravel/agents/tech-writer.md +4 -0
  415. package/presets/cursor/php-laravel/commands/README.md +0 -2
  416. package/presets/cursor/php-laravel/commands/task-continue.md +1 -1
  417. package/presets/cursor/php-laravel/commands/task.md +1 -4
  418. package/presets/cursor/php-laravel/commands/technical-retro.md +2 -2
  419. package/presets/cursor/php-laravel/hooks/chain-team-phases.sh +105 -14
  420. package/presets/cursor/php-laravel/rules/agent-team-orchestrator.mdc +2 -4
  421. package/presets/cursor/php-laravel/rules/ai-local-overlay.mdc +43 -0
  422. package/presets/cursor/php-laravel/rules/preset-pr-checklist.mdc +5 -1
  423. package/presets/cursor/php-laravel/rules/preset-token-budget.mdc +7 -3
  424. package/presets/cursor/php-laravel/rules/preset-twin-sync.mdc +2 -0
  425. package/presets/cursor/svelte/README.md +6 -6
  426. package/presets/cursor/svelte/agents/README.md +1 -1
  427. package/presets/cursor/svelte/agents/build-verifier.md +2 -0
  428. package/presets/cursor/svelte/agents/code-reviewer.md +2 -0
  429. package/presets/cursor/svelte/agents/debugger.md +4 -0
  430. package/presets/cursor/svelte/agents/feature-developer.md +4 -1
  431. package/presets/cursor/svelte/agents/openspec-author.md +164 -0
  432. package/presets/cursor/svelte/agents/qa-tester.md +4 -0
  433. package/presets/cursor/svelte/agents/task-analyst.md +1 -1
  434. package/presets/cursor/svelte/agents/task-router.md +5 -1
  435. package/presets/cursor/svelte/agents/tech-writer.md +4 -0
  436. package/presets/cursor/svelte/commands/README.md +0 -2
  437. package/presets/cursor/svelte/commands/task-continue.md +1 -1
  438. package/presets/cursor/svelte/commands/task.md +1 -5
  439. package/presets/cursor/svelte/commands/technical-retro.md +2 -2
  440. package/presets/cursor/svelte/hooks/chain-team-phases.sh +105 -13
  441. package/presets/cursor/svelte/rules/README.md +3 -1
  442. package/presets/cursor/svelte/rules/agent-team-orchestrator.mdc +8 -5
  443. package/presets/cursor/svelte/rules/ai-local-overlay.mdc +43 -0
  444. package/presets/cursor/svelte/rules/preset-pr-checklist.mdc +5 -1
  445. package/presets/cursor/svelte/rules/preset-token-budget.mdc +7 -3
  446. package/presets/cursor/svelte/rules/preset-twin-sync.mdc +2 -0
  447. package/presets/cursor/svelte/rules/tests-e2e-structure.mdc +87 -43
  448. package/presets/cursor/svelte/rules/tests-unit.mdc +72 -23
  449. package/presets/cursor/svelte/team/README.md +0 -3
  450. package/scripts/_lib/embed-stems.json +31 -0
  451. package/scripts/aggregate-agent-task-metrics.mjs +23 -0
  452. package/scripts/check-chain-hook-coverage.sh +109 -0
  453. package/scripts/check-local-overlay.sh +136 -0
  454. package/scripts/check-preset-i18n.sh +2 -2
  455. package/scripts/check-preset-leakage.sh +4 -1
  456. package/scripts/check-preset-structure.sh +31 -1
  457. package/scripts/check-preset-token-budget.sh +120 -10
  458. package/scripts/check-rule-eval.mjs +16 -0
  459. package/scripts/check-shared-core-drift.sh +10 -32
  460. package/scripts/check-task-router-intents.sh +141 -0
  461. package/scripts/close-agent-task-human-gate.mjs +22 -5
  462. package/scripts/sync-shared-core-embeds.sh +9 -20
  463. package/scripts/test-agent-task-metrics-hooks.mjs +100 -2
  464. package/scripts/test-chain-team-phases-coverage.mjs +510 -0
  465. package/scripts/test-task-router-intents-fixtures.mjs +109 -0
  466. package/presets/claude/android-kotlin/commands/feature-continue.md +0 -23
  467. package/presets/claude/android-kotlin/commands/feature-start.md +0 -41
  468. package/presets/claude/go/commands/feature-continue.md +0 -23
  469. package/presets/claude/go/commands/feature-start.md +0 -38
  470. package/presets/claude/ios-swift/commands/feature-continue.md +0 -23
  471. package/presets/claude/ios-swift/commands/feature-start.md +0 -41
  472. package/presets/claude/java/commands/feature-continue.md +0 -23
  473. package/presets/claude/java/commands/feature-start.md +0 -38
  474. package/presets/claude/mcp-ts/commands/feature-continue.md +0 -23
  475. package/presets/claude/mcp-ts/commands/feature-start.md +0 -41
  476. package/presets/claude/next/commands/feature-continue.md +0 -23
  477. package/presets/claude/next/commands/feature-start.md +0 -38
  478. package/presets/claude/nuxt/commands/feature-continue.md +0 -23
  479. package/presets/claude/nuxt/commands/feature-start.md +0 -41
  480. package/presets/claude/php-hexagonal/commands/feature-continue.md +0 -23
  481. package/presets/claude/php-hexagonal/commands/feature-start.md +0 -38
  482. package/presets/claude/php-laravel/commands/feature-continue.md +0 -23
  483. package/presets/claude/php-laravel/commands/feature-start.md +0 -38
  484. package/presets/claude/svelte/commands/feature-continue.md +0 -23
  485. package/presets/claude/svelte/commands/feature-start.md +0 -41
  486. package/presets/cursor/android-kotlin/commands/feature-continue.md +0 -23
  487. package/presets/cursor/android-kotlin/commands/feature-start.md +0 -41
  488. package/presets/cursor/go/commands/feature-continue.md +0 -23
  489. package/presets/cursor/go/commands/feature-start.md +0 -41
  490. package/presets/cursor/ios-swift/commands/feature-continue.md +0 -23
  491. package/presets/cursor/ios-swift/commands/feature-start.md +0 -41
  492. package/presets/cursor/java/commands/feature-continue.md +0 -23
  493. package/presets/cursor/java/commands/feature-start.md +0 -41
  494. package/presets/cursor/mcp-ts/commands/feature-continue.md +0 -23
  495. package/presets/cursor/mcp-ts/commands/feature-start.md +0 -41
  496. package/presets/cursor/next/commands/feature-continue.md +0 -23
  497. package/presets/cursor/next/commands/feature-start.md +0 -41
  498. package/presets/cursor/nuxt/commands/feature-continue.md +0 -23
  499. package/presets/cursor/nuxt/commands/feature-start.md +0 -41
  500. package/presets/cursor/php-hexagonal/commands/feature-continue.md +0 -23
  501. package/presets/cursor/php-hexagonal/commands/feature-start.md +0 -41
  502. package/presets/cursor/php-laravel/commands/feature-continue.md +0 -23
  503. package/presets/cursor/php-laravel/commands/feature-start.md +0 -41
  504. package/presets/cursor/svelte/commands/feature-continue.md +0 -23
  505. package/presets/cursor/svelte/commands/feature-start.md +0 -41
@@ -64,10 +64,20 @@ const STACK = 'next';
64
64
  const PLATFORM = 'claude';
65
65
 
66
66
  function waitForMetricsLock() {
67
+ // OD-1: real advisory lock via create-exclusive (fs.openSync(_, 'wx')).
68
+ // The previous impl spun on Atomics.wait against an unrelated SharedArrayBuffer
69
+ // and never blocked on the lock file, so two concurrent subagentStop events
70
+ // could both acquire the lock and corrupt metrics.json. Retry EEXIST with a
71
+ // 10 ms sleep up to 200 attempts (2 s ceiling). On any other error, throw.
67
72
  for (let attempt = 0; attempt < 200; attempt += 1) {
68
- try { fs.mkdirSync(METRICS_LOCK); return; } catch (error) {
69
- if (error && error.code !== 'EEXIST') throw error;
70
- Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 10);
73
+ try {
74
+ const fd = fs.openSync(METRICS_LOCK, 'wx');
75
+ try { fs.closeSync(fd); } catch {}
76
+ return;
77
+ } catch (error) {
78
+ if (!error || error.code !== 'EEXIST') throw error;
79
+ const until = Date.now() + 10;
80
+ while (Date.now() < until) { /* 10 ms busy-wait */ }
71
81
  }
72
82
  }
73
83
  throw new Error('metrics lock timeout');
@@ -76,7 +86,7 @@ let taskLockHeld = false;
76
86
  function releaseTaskLock() {
77
87
  if (!taskLockHeld) return;
78
88
  taskLockHeld = false;
79
- try { fs.rmdirSync(METRICS_LOCK); } catch {}
89
+ try { fs.unlinkSync(METRICS_LOCK); } catch {}
80
90
  }
81
91
  waitForMetricsLock();
82
92
  taskLockHeld = true;
@@ -104,7 +114,7 @@ function mutateMetrics(mutator) {
104
114
  fs.writeFileSync(temporary, JSON.stringify(metrics, null, 2) + '\n');
105
115
  fs.renameSync(temporary, METRICS_PATH);
106
116
  } finally {
107
- if (acquiredHere) { try { fs.rmdirSync(METRICS_LOCK); } catch {} }
117
+ if (acquiredHere) { try { fs.unlinkSync(METRICS_LOCK); } catch {} }
108
118
  }
109
119
  }
110
120
  function appendMetric(event) { mutateMetrics((metrics) => metrics.events.push({ eventId: `${metrics.task.runId}:${Date.now()}:${Math.random().toString(16).slice(2)}`, ...event })); }
@@ -138,6 +148,14 @@ const DEFAULT_ARTIFACT_OUTPUT_IDS = {
138
148
  'mockup-reviewer': 'mockup-review',
139
149
  'api-contract-reviewer': 'api-contract-review',
140
150
  'tech-writer': 'documentation',
151
+ 'openspec-author': 'openspec-change',
152
+ 'qa-tester': 'qa',
153
+ 'unit-test-planner': 'unit-test-plan',
154
+ 'unit-test-generator': 'unit-test-spec',
155
+ 'unit-test-healer': 'unit-test-heal',
156
+ 'playwright-test-planner': 'e2e-plan',
157
+ 'playwright-test-generator': 'e2e-spec',
158
+ 'playwright-test-healer': 'e2e-heal',
141
159
  };
142
160
  function artifactOutputIdFor(step, agent) {
143
161
  if (step && typeof step.artifactOutputId === 'string') return step.artifactOutputId;
@@ -242,7 +260,17 @@ function recordSkippedStep(step, stepIndex) {
242
260
  function writeStatus(next) {
243
261
  status = { ...status, ...next, slug, updatedAt: now };
244
262
  const temporary = `${statusPath}.${process.pid}.${Date.now()}.tmp`;
245
- fs.writeFileSync(temporary, JSON.stringify(status, null, 2) + '\n');
263
+ // Open + write + fsync + rename so the durable file lands on disk before
264
+ // the orchestrator reads it. Closes the race window where a subagent that
265
+ // completed milliseconds before writeStatus() could otherwise invoke the
266
+ // next step on a stale status (in particular the human-gate write).
267
+ const fd = fs.openSync(temporary, 'w');
268
+ try {
269
+ fs.writeSync(fd, JSON.stringify(status, null, 2) + '\n');
270
+ try { fs.fsyncSync(fd); } catch {}
271
+ } finally {
272
+ fs.closeSync(fd);
273
+ }
246
274
  fs.renameSync(temporary, statusPath);
247
275
  }
248
276
 
@@ -339,6 +367,12 @@ const AGENT_HANDOFF = {
339
367
  `Use playwright MCP when available. Follow testing/playwright-agents.md and debug-investigation. Upsert the owned terminal receipt in artifact-manifest.json; do not mutate status.json lifecycle fields.`,
340
368
  'tech-writer': (s) =>
341
369
  `Invoke tech-writer for slug "${s}". Write documentation.md from task artifacts. Upsert the owned terminal receipt in artifact-manifest.json; do not mutate status.json lifecycle fields.`,
370
+ 'openspec-author': (s, scope) =>
371
+ `Invoke openspec-author for slug "${s}"${scope ? ` (scope: ${scope})` : ''}. ` +
372
+ `Read openspec/config.yaml schema + rules; if openspec/** is absent, emit blocked ("openspec/** not initialized"). ` +
373
+ `Author openspec/changes/<change-id>/{proposal.md, design.md, tasks.md, .openspec.yaml} and the capability spec delta per phase (explore|propose|apply|archive). ` +
374
+ `Run \`openspec validate <change-id> --type change --strict\` and \`openspec validate --specs --strict\` (Phase 3); surface FAIL output verbatim. ` +
375
+ `Upsert the owned terminal receipt (artifactOutputId \`openspec-change\`) in artifact-manifest.json with validator exit code + evidence paths; do not mutate status.json lifecycle fields. `,
342
376
  };
343
377
 
344
378
  const REVIEW_AGENTS = new Set([
@@ -459,7 +493,19 @@ function legacyFlow() {
459
493
 
460
494
 
461
495
  if (hookInput.action === 'end_human_gate') {
462
- status.awaitingHumanGate = false;
496
+ status.awaitingHumanGate = false;
497
+ // A2 (retro §8): pin a single runId per pipeline so subsequent events don't
498
+ // fragment the metrics ledger across multiple runId sequences. Prefer
499
+ // metrics.json.task.runId when metrics already exist, then status.metricsRunId,
500
+ // then mint a fresh seed only on first ever emit.
501
+ try {
502
+ if (fs.existsSync(METRICS_PATH)) {
503
+ const existing = JSON.parse(fs.readFileSync(METRICS_PATH, 'utf8'));
504
+ if (existing && existing.task && typeof existing.task.runId === 'string') {
505
+ status.metricsRunId = existing.task.runId;
506
+ }
507
+ }
508
+ } catch {}
463
509
  if (status.state === 'awaiting_approval') {
464
510
  status.state = 'in_progress';
465
511
  status.phase = status.phase === 'human_gate' ? 'executing' : status.phase;
@@ -498,11 +544,29 @@ if (hookInput.action === 'end_human_gate') {
498
544
  }
499
545
  }
500
546
  }
501
- writeStatus({
502
- awaitingHumanGate: false,
503
- state: status.state,
504
- phase: status.phase,
505
- });
547
+ // A2 (retro §8): if gate closes the final human gate of the pipeline
548
+ // (no resume happens, or current step's gate was the last), surface
549
+ // state="awaiting_approval" so a subsequent /task-continue doesn't misinterpret
550
+ // the post-gate idle state as "still in progress".
551
+ {
552
+ let gateWasTerminal = false;
553
+ if (!hookInput.activateNext && fs.existsSync(pipelinePath)) {
554
+ try {
555
+ const pipe = JSON.parse(fs.readFileSync(pipelinePath, 'utf8'));
556
+ const steps = pipe.steps || [];
557
+ const idx = typeof status.pipelineIndex === 'number' ? status.pipelineIndex : 0;
558
+ const cur = steps[idx];
559
+ const gates = Array.isArray(pipe.humanGates) ? pipe.humanGates : [];
560
+ const hasGate = (step) => Array.isArray(gates) && gates.some((g) => typeof g === 'string' && getStepAgents(step).some((a) => g === `after:${a}`));
561
+ if (cur && hasGate(cur)) gateWasTerminal = true;
562
+ } catch {}
563
+ }
564
+ writeStatus({
565
+ awaitingHumanGate: false,
566
+ state: gateWasTerminal ? 'awaiting_approval' : status.state,
567
+ phase: status.phase,
568
+ });
569
+ }
506
570
  process.stdout.write(JSON.stringify({ ok: true, action: 'end_human_gate', activeHumanGateEventId: status.activeHumanGateEventId || null }));
507
571
  process.exit(0);
508
572
  }
@@ -512,9 +576,37 @@ if (!fs.existsSync(pipelinePath)) {
512
576
  }
513
577
 
514
578
  let pipeline;
579
+ let pipelineParseError = null;
515
580
  try {
516
581
  pipeline = JSON.parse(fs.readFileSync(pipelinePath, 'utf8'));
517
- } catch {
582
+ } catch (error) {
583
+ pipelineParseError = error;
584
+ }
585
+ // Modern pipelines carry an `intent` field. If pipeline.json is present but
586
+ // unparseable, surface the error so the orchestrator can stop and report
587
+ // instead of falling back to legacyFlow() — which silently drops modern
588
+ // roles like `openspec-author`, `qa-tester`, and the test-planner trio.
589
+ if (pipelineParseError) {
590
+ if (fs.existsSync(pipelinePath)) {
591
+ const raw = fs.readFileSync(pipelinePath, 'utf8');
592
+ const hasModernIntent = /"intent"\s*:/.test(raw);
593
+ appendMetric({
594
+ eventId: `${status.metricsRunId || slug}:pipeline_parse_error:${Date.now()}`,
595
+ type: 'pipeline_parse_error',
596
+ at: now,
597
+ source: 'hook',
598
+ attributionConfidence: 'high',
599
+ error: String(pipelineParseError.message || pipelineParseError),
600
+ hasModernIntent,
601
+ });
602
+ if (hasModernIntent) {
603
+ writeStatus({ state: 'blocked', phase: 'blocked', currentAgent: 'task-router' });
604
+ process.stdout.write(JSON.stringify({
605
+ followup_message: `pipeline.json is malformed for slug "${slug}" — JSON parse error: ${pipelineParseError.message}. Re-run the task-router to regenerate pipeline.json, then resume via /task-continue ${slug}.`,
606
+ }));
607
+ process.exit(0);
608
+ }
609
+ }
518
610
  legacyFlow();
519
611
  }
520
612
 
@@ -38,6 +38,7 @@ When editing `app/src/ui/**/*.tsx`, a **reduced** set loads:
38
38
  | `next-app-core.mdc` | `stack/next-app-core.md` |
39
39
  | `package-manager.mdc` | `tooling-and-review/package-manager.md` |
40
40
  | `code-quality-and-refactoring.mdc` | `tooling-and-review/code-quality.md` |
41
+ | `ai-local-overlay.mdc` | `tooling-and-review/ai-local-overlay.md` |
41
42
  | `anti-sycophancy-discipline.mdc` | `tooling-and-review/anti-sycophancy-discipline.md` |
42
43
  | `react-next-anti-hallucination.mdc` | `anti-hallucination/react-next-anti-hallucination.md` |
43
44
  | `design-guidance.mdc` | `tooling-and-review/design-guidance.md` |
@@ -37,7 +37,7 @@ impact: HIGH
37
37
 
38
38
  ## Agent requirement
39
39
 
40
- - When changing the shared client implementation — **update or add behavior tests** next to the client module (`testing/tests-unit.md`).
40
+ - When changing the shared client implementation — **update or add behavior tests** under the mirrored `app/__tests__/unit/lib/clients/**` path (`testing/tests-unit.md`).
41
41
  - Do not introduce a **second full HTTP stack** without an explicit task and alignment with repo architecture.
42
42
 
43
43
  ## Incorrect
@@ -25,7 +25,7 @@ Replace **TBD** with real paths after team agreement (or on `ai-rules init` in t
25
25
  | Store slice | **TBD** `app/src/store/slices/<example>/` | slice, thunks, selectors, types |
26
26
  | API service | **TBD** `app/src/api/services/<example>/` | service, mappers, barrel |
27
27
  | Types module | **TBD** `app/src/types/<example>/` | domain types, JSDoc, barrel export |
28
- | Unit tests | **TBD** next to the reference mapper/service | `*.spec.ts`, describe/it naming |
28
+ | Unit tests | **TBD** mirrored under `app/__tests__/unit/<rel>` | `*.spec.ts`, describe/it naming |
29
29
  | E2E area | **TBD** `app/__tests__/e2e/<Area>/` | `*.cases.md`, page objects, `_shared/` |
30
30
 
31
31
  ## How to use
@@ -5,7 +5,13 @@ Unit, e2e, Playwright agents.
5
5
  | File | Contents | Loading |
6
6
  |------|----------|---------|
7
7
  | `playwright-agents.md` | Planner / generator / healer — e2e structure | session start |
8
- | `tests-unit.md` | Unit/integration; describe/it naming in Russian (locale) | `paths: app/src/**/*.spec.*`, `*.test.*` |
8
+ | `tests-unit.md` | Unit/integration; mirrored `app/__tests__/unit/**` placement; describe/it naming in Russian (locale) | `paths: app/__tests__/unit/**/*.spec.*`, `*.test.*` |
9
9
  | `tests-e2e-structure.md` | `*.cases.md`, page objects, data-testid | `paths: app/__tests__/e2e/**` |
10
10
 
11
11
  See also `.claude/agents/playwright-test-*.md` after `ai-rules init`.
12
+
13
+ ## Shared core
14
+
15
+ | Shared core | Cursor adapter | Claude twins |
16
+ |-------------|----------------|--------------|
17
+ | `testing/testing-principles.md` | `tests-unit.mdc`, `tests-e2e-structure.mdc` | `tests-unit.md`, `tests-e2e-structure.md` |
@@ -1,53 +1,91 @@
1
1
  ---
2
- paths:
3
- - app/__tests__/e2e/**
2
+ description: E2E test and plan structure (Playwright)
3
+ paths: app/__tests__/e2e/**
4
4
  ---
5
5
 
6
- # E2E structure in the project
6
+ # Testing principles
7
7
 
8
+ Stack-agnostic; concrete paths, runners, and selectors live in the stack adapter (`## Stack notes`).
9
+
10
+ ## Behavior vs. implementation
11
+
12
+ - Verify **behavior and business rules**, not implementation or internal details.
13
+
14
+ ## File naming
15
+
16
+ - For **new** tests use `*.spec.ts` / `*.spec.tsx`. Do not rename existing `*.test.ts` / `*.test.tsx` without a separate task (legacy).
17
+
18
+ ## Runner and matchers
19
+
20
+ - Use the project's runner (Jest or Vitest are common); components — the project's Testing Library integration. Reuse existing matchers — no new micro-framework.
21
+
22
+ ## Test title locale
23
+
24
+ - Consumer apps **may use the project locale** (often Russian) — clear business phrases stating what is checked and the expected outcome.
25
+ - When ESLint enforces the locale (e.g. `jest/valid-title`): each sentence must start with a **capital letter** (including after `.`, `!`, `?`); a space after `.` followed by a lowercase letter is forbidden ("capital after period" violation).
26
+
27
+ Good (Russian locale in consumer app):
28
+
29
+ - `it('Возвращает пустой список. Пользователь не авторизован', () => {})` <!-- i18n-keep: E5 --> (Returns empty list. User is not authorized)
30
+
31
+ Bad (no capital after period; or wrong locale for configured ESLint):
32
+
33
+ - `it('Возвращает пустой список. пользователь не авторизован', () => {})` <!-- i18n-keep: E5 -->
34
+ - `it('Returns empty list when user is guest', () => {})` (wrong locale if ESLint enforces Russian)
35
+
36
+ ## Isolation and mocks
37
+
38
+ - Mock at the **public-contract boundary**; use the project's accepted HTTP/API/store mock approach. Do not mock what is part of the feature's public contract if that breaks the test's meaning.
39
+
40
+ ## Coverage of cross-cutting modules
41
+
42
+ - When changing a **shared cross-cutting module** (e.g. HTTP client body parsing, headers, error / auth handling) — **update or add behavior tests** covering success, error, and edge branches relevant to the module under change.
43
+
44
+ ## Data transformation coverage
45
+
46
+ - Data transformation functions with computed fields and branches must have unit tests covering edge cases (boundary values, missing fields, unexpected value combinations).
47
+
48
+ ## Reuse fixtures over ad-hoc random data
49
+
50
+ - Prefer shared fixtures / handlers from the project's accepted mocks module; do not duplicate interfaces in tests. Use the API response types (DTO types) and the **target domain types** from the project's public type surface.
51
+
52
+ ## E2E: one canonical scenario plan per feature
53
+
54
+ - For each feature keep a **single canonical scenario plan** (distinct from implementation specs; the stack adapter names the file — typically `*.cases.md`).
55
+
56
+ ## E2E: scenario ↔ test traceability
57
+
58
+ - Every scenario has a corresponding test. **Do not weaken** assertions to match an outdated implementation — tests must reflect business expectations from the plan. Colocate plan and executable tests in the same directory.
59
+
60
+ ## E2E: page objects / shared helpers
61
+
62
+ - Prefer page objects and shared helpers over scattered selectors and per-test setup duplication.
63
+
64
+ ## E2E: stable identifiers (PREFIX-XXX)
65
+
66
+ - When scenarios need stable IDs, prefix the title with `PREFIX-XXX`: `PREFIX` = first letters of words in the entity under test (Latin uppercase); `XXX` = sequential number with three digits and leading zeros. Within one `PREFIX`, numbers must form a consistent sequence with no duplicates.
67
+ - Example: `test('OH-001 Отображается список заказов', async ({ page }) => { ... })` <!-- i18n-keep: E5 --> (Order list is displayed)
68
+
69
+ ## E2E: selector priority
70
+
71
+ - Prefer role/label selectors for accessibility and forms; fall back to `data-testid` for stable elements. Use a **hierarchical naming convention** on page roots and key interactive elements (stack adapter defines the scheme — typically `{parent}__{element}`).
72
+
73
+ ## E2E: keep plans and selectors in sync with UI
74
+
75
+ - When changing UI: update selectors in page objects and cross-check with the scenario plan. When adding/changing tests: read the matching plan and sync scenario titles first.
76
+
77
+ ## Stack notes
78
+
79
+ - Runner: Playwright (`@playwright/test`).
8
80
  - E2E folder: `app/__tests__/e2e/**`.
9
- - Scenario plans:
10
- - `*.cases.md` files — **canonical source of scenarios**.
11
- - Tests:
12
- - `*.spec.ts` files Playwright scenario implementations.
13
- - Shared utilities and abstractions:
14
- - `app/__tests__/e2e/_shared/**`constants, fluent interfaces, helpers.
15
-
16
- # Principles
17
-
18
- - Every scenario from `*.cases.md` must have a corresponding test (or set of tests).
19
- - **Do not** weaken assertions in tests if that contradicts business expectations from the plans.
20
- - Prefer:
21
- - page objects (for example, `OrderHistoryPage.ts`);
22
- - shared helpers from `_shared`.
23
-
24
- # E2E test naming
25
-
26
- - Language:
27
- - in consumer apps, `test` / `it`, `describe` block titles, and steps in `*.cases.md` **may use the project locale** (often Russian) — phrasing behavior and expected outcome;
28
- - when the repo ESLint or team convention requires Russian titles, follow that; otherwise use clear English business phrases.
29
- - E2E test title format (`test(...)` / `it(...)`):
30
- - before the scenario description, include a **numbered prefix** in the form: `PREFIX-XXX Scenario description`.
31
- - `PREFIX` — abbreviation from the **first letters of words** in the entity under test, written **in Latin uppercase**.
32
- - example: `OrderHistory` → `OH`, `BillingReport` → `BR`.
33
- - `XXX` — sequential test number **with three digits and leading zeros**: `001`, `002`, `010`, `123`, etc.
34
- - full e2e test title example (Russian locale in consumer app):
35
- - `test('OH-001 Отображается список заказов', async ({ page }) => { ... })` <!-- i18n-keep: E5 --> (Order list is displayed)
36
- - within one entity (`PREFIX`), test numbers must form a **consistent sequence** with no duplicate numbers.
37
-
38
- # data-testid for e2e
39
-
40
- - **Selector priority:** `data-testid` for stable elements; `getByRole` and `getByLabel` for forms and accessible elements.
41
- - **Naming:** `{parent}__{element}` scheme (for example, `history-page__title`, `history-page__recognition-banner__attach-files-button`).
42
- - **Where to add:** on page root containers and key interactive elements (buttons, links, fields) that page objects target.
43
- - **When changing UI:** update data-testid in components and matching selectors in page objects; cross-check with `*.cases.md`.
44
-
45
- # Agent requirement
46
-
47
- When adding/changing e2e tests:
48
-
49
- - First read the matching `*.cases.md` and sync scenario titles.
50
- - Place specs next to plans in the same directory.
51
- - Reuse shared page objects and helpers instead of copying selectors directly into every test.
52
-
53
- See also **`testing/playwright-agents.md`** for planner/generator/healer.
81
+ - Placement mirrors source paths: `app/src/<rel>` → `app/__tests__/e2e/<rel>`. Use the deepest folder of the source under test; page-wide scenarios mirror the page folder.
82
+ - Scenario plans: `*.cases.md` files — canonical source of scenarios.
83
+ - Tests: `*.spec.ts` files — Playwright scenario implementations.
84
+ - Shared utilities and abstractions: `app/__tests__/e2e/**/_shared/**`constants, fluent interfaces, helpers.
85
+ - Root exceptions that do not mirror a single source module: `_shared/`, `smoke.spec.ts`, and `seed.spec.ts`.
86
+ - `data-testid` naming scheme: `{parent}__{element}` example `history-page__title`, `history-page__recognition-banner__attach-files-button`.
87
+ - `PREFIX-XXX` example: `OrderHistory` → `OH`, `BillingReport` → `BR`; Russian example — `test('OH-001 Отображается список заказов', async ({ page }) => { ... })` <!-- i18n-keep: E5 --> (Order list is displayed).
88
+ - Page object example filename: `OrderHistoryPage.ts` (the seed test pointer lives at `app/__tests__/e2e/seed.spec.ts`).
89
+ - `## Stack notes` content is stripped by `scripts/check-shared-core-drift.sh` before byte-comparing this file against `_shared/core/testing/testing-principles.md`; keep prose above (core content) verbatim against the core file.
90
+
91
+ See also **`testing/playwright-agents.md`** for planner/generator/healer.
@@ -1,83 +1,110 @@
1
1
  ---
2
+ description: Unit and integration tests (Testing Library and project runner)
2
3
  paths:
3
- - app/src/**/*.spec.ts
4
- - app/src/**/*.spec.tsx
5
- - app/src/**/*.test.ts
6
- - app/src/**/*.test.tsx
7
- impact: MEDIUM
4
+ - app/__tests__/unit/**/*.spec.{ts,tsx}
5
+ - app/__tests__/unit/**/*.test.{ts,tsx}
8
6
  ---
9
7
 
10
- # General testing rules
8
+ # Testing principles
11
9
 
12
- - **File names:** for **new** tests use the **`*.spec.ts` / `*.spec.tsx`** suffix. Do not rename existing **`*.test.ts` / `*.test.tsx`** without a separate task (legacy).
13
- - **Runner and matchers** — as in the project (often Jest or Vitest); for components — **@testing-library/react**.
14
- - Primary goal of tests:
15
- - verify **behavior and business rules**, not implementation or internal details.
16
- - **Unit test naming** (strings in `describe` / `it` / `test`):
17
- - consumer apps **may use Russian locale** for titles — clear business phrases (what is checked and expected outcome);
18
- - when ESLint enforces Russian (see below), each sentence in the title **must start with a capital letter** (including after `.`, `!`, `?` and with multiple sentences on one line); the first letter of the whole string is capitalized too.
19
- - **CI check (when configured):** ESLint (`jest/valid-title` in `app/eslint.config.mjs`) may require titles to start with a Russian capital letter and forbid a space after `.` followed immediately by a lowercase letter (typical "capital after period" violation).
10
+ Stack-agnostic; concrete paths, runners, and selectors live in the stack adapter (`## Stack notes`).
11
+
12
+ ## Behavior vs. implementation
13
+
14
+ - Verify **behavior and business rules**, not implementation or internal details.
15
+
16
+ ## File naming
17
+
18
+ - For **new** tests use `*.spec.ts` / `*.spec.tsx`. Do not rename existing `*.test.ts` / `*.test.tsx` without a separate task (legacy).
19
+
20
+ ## Runner and matchers
21
+
22
+ - Use the project's runner (Jest or Vitest are common); components — the project's Testing Library integration. Reuse existing matchers — no new micro-framework.
23
+
24
+ ## Test title locale
25
+
26
+ - Consumer apps **may use the project locale** (often Russian) — clear business phrases stating what is checked and the expected outcome.
27
+ - When ESLint enforces the locale (e.g. `jest/valid-title`): each sentence must start with a **capital letter** (including after `.`, `!`, `?`); a space after `.` followed by a lowercase letter is forbidden ("capital after period" violation).
20
28
 
21
29
  Good (Russian locale in consumer app):
22
30
 
23
31
  - `it('Возвращает пустой список. Пользователь не авторизован', () => {})` <!-- i18n-keep: E5 --> (Returns empty list. User is not authorized)
24
- - `it('При ошибке сети показывается сообщение об ошибке', () => {})` <!-- i18n-keep: E5 --> (On network error, an error message is shown)
25
32
 
26
33
  Bad (no capital after period; or wrong locale for configured ESLint):
27
34
 
28
35
  - `it('Возвращает пустой список. пользователь не авторизован', () => {})` <!-- i18n-keep: E5 -->
29
- - `it('Returns empty list when user is guest', () => {})`
36
+ - `it('Returns empty list when user is guest', () => {})` (wrong locale if ESLint enforces Russian)
37
+
38
+ ## Isolation and mocks
39
+
40
+ - Mock at the **public-contract boundary**; use the project's accepted HTTP/API/store mock approach. Do not mock what is part of the feature's public contract if that breaks the test's meaning.
41
+
42
+ ## Coverage of cross-cutting modules
43
+
44
+ - When changing a **shared cross-cutting module** (e.g. HTTP client body parsing, headers, error / auth handling) — **update or add behavior tests** covering success, error, and edge branches relevant to the module under change.
45
+
46
+ ## Data transformation coverage
30
47
 
31
- # Component tests
48
+ - Data transformation functions with computed fields and branches must have unit tests covering edge cases (boundary values, missing fields, unexpected value combinations).
32
49
 
33
- - Use `render` from `@testing-library/react`.
34
- - Assertions:
35
- - DOM matchers for Testing Library as wired in the project (`toBeInTheDocument`, `toHaveTextContent`, etc.).
36
- - Interactions:
37
- - `userEvent` from `@testing-library/user-event`.
50
+ ## Reuse fixtures over ad-hoc random data
38
51
 
39
- # Isolation and mocks
52
+ - Prefer shared fixtures / handlers from the project's accepted mocks module; do not duplicate interfaces in tests. Use the API response types (DTO types) and the **target domain types** from the project's public type surface.
40
53
 
41
- - For API/store work:
42
- - mock the store (via test-store) or use the project's accepted HTTP/API mock approach.
43
- - Do not mock what is part of the feature's public contract if that breaks the test's meaning.
54
+ ## E2E: one canonical scenario plan per feature
44
55
 
45
- # HTTP client
56
+ - For each feature keep a **single canonical scenario plan** (distinct from implementation specs; the stack adapter names the file — typically `*.cases.md`).
46
57
 
47
- - When changing the **shared HTTP client implementation** (body parsing, headers, error branches, 401/refresh, `FormData`, `blob`, etc.) — **update or add behavior tests** next to the client module in `app/src/lib/clients/**` (prefer `*.spec.ts`; legacy `*.test.ts` — do not touch without a task).
48
- - Cover meaningful branches: successful JSON, HTTP error, network, auth scenarios relevant to the project.
58
+ ## E2E: scenario test traceability
49
59
 
50
- # Mappers and data transformation
60
+ - Every scenario has a corresponding test. **Do not weaken** assertions to match an outdated implementation — tests must reflect business expectations from the plan. Colocate plan and executable tests in the same directory.
51
61
 
52
- - Data mapping functions (DTO domain model and back), especially with computed fields and branches, must have unit tests.
53
- - In mapper tests, pay special attention to edge cases and business-rule regression (for example, boundary values, missing fields, unexpected value combinations).
62
+ ## E2E: page objects / shared helpers
54
63
 
55
- # Agent requirement
64
+ - Prefer page objects and shared helpers over scattered selectors and per-test setup duplication.
56
65
 
57
- When adding tests:
66
+ ## E2E: stable identifiers (PREFIX-XXX)
67
+
68
+ - When scenarios need stable IDs, prefix the title with `PREFIX-XXX`: `PREFIX` = first letters of words in the entity under test (Latin uppercase); `XXX` = sequential number with three digits and leading zeros. Within one `PREFIX`, numbers must form a consistent sequence with no duplicates.
69
+ - Example: `test('OH-001 Отображается список заказов', async ({ page }) => { ... })` <!-- i18n-keep: E5 --> (Order list is displayed)
70
+
71
+ ## E2E: selector priority
72
+
73
+ - Prefer role/label selectors for accessibility and forms; fall back to `data-testid` for stable elements. Use a **hierarchical naming convention** on page roots and key interactive elements (stack adapter defines the scheme — typically `{parent}__{element}`).
74
+
75
+ ## E2E: keep plans and selectors in sync with UI
76
+
77
+ - When changing UI: update selectors in page objects and cross-check with the scenario plan. When adding/changing tests: read the matching plan and sync scenario titles first.
78
+
79
+ ## Stack notes
80
+
81
+ - `render` from `@testing-library/react` for component tests.
82
+ - `userEvent` from `@testing-library/user-event` for interactions.
83
+ - DOM matchers as wired in the project (`toBeInTheDocument`, `toHaveTextContent`, …).
84
+ - `jest/valid-title` ESLint rule in `app/eslint.config.mjs` enforces the Russian capital-after-period rule (when configured).
85
+ - `@/types` and `@/api` imports — types come from the public API surface, never duplicated in tests.
86
+ - `app/src/mocks/**` — shared fixtures and MSW handlers live here (or repo equivalent).
87
+ - Unit-test placement mirrors source paths: `app/src/<rel>` → `app/__tests__/unit/<rel>`. Do not colocate `*.spec.ts(x)` or `*.test.ts(x)` under `app/src/**`.
88
+ - HTTP-client behavior tests live under the mirrored `app/__tests__/unit/lib/clients/**` path (prefer `*.spec.ts`).
89
+ - UI tests live under the mirrored `app/__tests__/unit/ui/**` path. Import the source under test through the `@/` alias.
90
+ - `## Stack notes` content is stripped by `scripts/check-shared-core-drift.sh` before byte-comparing this file against `_shared/core/testing/testing-principles.md`; keep prose above (core content) verbatim against the core file.
58
91
 
59
- - Follow existing test structure and patterns in the repository: `*.spec.ts(x)` next to the module or in a shared test directory — as in neighboring features.
60
- - Add tests for critical logic branches and edge cases.
61
- - When working with data:
62
- - use **response types** from the API (DTO types) and **target domain types** from `@/types`; do not duplicate interfaces in tests;
63
- - when possible, rely on data and handlers from `app/src/mocks/**` (or repo equivalent), not ad-hoc random test data.
64
- - Placement:
65
- - for **UI components** — **do not create** a `__tests__` subdirectory inside the component folder; the test is a sibling `*.spec.tsx`.
66
- - in **other modules** (for example `api/services`) an existing `__tests__` layout is acceptable — do not break it for UI uniformity.
67
- - **new** files — `*.spec.ts` / `*.spec.tsx` (see "File names" above).
68
92
  ## Incorrect
69
93
 
94
+ Title violates capital-after-period rule (Russian locale). The rule's enforcement (`jest/valid-title`) will reject this in CI.
95
+
70
96
  ```ts
71
- it('returns empty list when guest', () => {})
97
+ it('возвращает пустой список. пользователь не авторизован', () => { <!-- i18n-keep: E5 -->
98
+ expect(result).toEqual([]);
99
+ });
72
100
  ```
73
101
 
74
- - `it('Возвращает пустой список. пользователь не авторизован', () => {})` <!-- i18n-keep: E5 -->
75
-
76
102
  ## Correct
77
103
 
78
- ```ts
79
- it('Возвращает пустой список. Пользователь не авторизован', () => {})
80
- ```
81
- <!-- i18n-keep: E5 -->
104
+ Title respects capital-after-period rule.
82
105
 
83
- - `it('Возвращает пустой список. Пользователь не авторизован', () => {})` <!-- i18n-keep: E5 -->
106
+ ```ts
107
+ it('Возвращает пустой список. Пользователь не авторизован', () => { <!-- i18n-keep: E5 -->
108
+ expect(result).toEqual([]);
109
+ });
110
+ ```
@@ -20,8 +20,6 @@ Work request without `/task` — see **`tooling-and-review/agent-team-intake.md`
20
20
  |---------|------|
21
21
  | **`/task <desc>`** | **Preferred** — router → dynamic pipeline → first agent |
22
22
  | `/task-continue <slug>` | After human gate or pause |
23
- | `/feature-start <desc>` | Legacy: analyst-only start (no router) |
24
- | `/feature-continue <slug>` | Alias of task-continue |
25
23
  | `/spec-start [desc]` | Generate/bootstrap `docs/specs` — router intent `spec-gen` → analyst author mode → human gate |
26
24
  | `/technical-retro [slug]` | Retro with agent team block |
27
25
 
@@ -51,6 +49,7 @@ Work request without `/task` — see **`tooling-and-review/agent-team-intake.md`
51
49
  | `playwright-test-generator` | tests only | e2e spec generation |
52
50
  | `playwright-test-healer` | tests only | failing/flaky e2e fixes |
53
51
  | `tech-writer` | docs only | docs-only, feature/migration docs |
52
+ | `openspec-author` | `openspec/**` only | openspec-change (`/opsx:propose`, `/opsx:apply`, `/opsx:archive`, openspec refresh) |
54
53
 
55
54
  Full prompts: `.claude/agents/*.md`. Artifact conventions: `.claude/team/README.md`; schema SoT: **agent-artifact-contracts**.
56
55
 
@@ -173,7 +172,7 @@ After each agent completes, verify its terminal manifest receipt, then let the o
173
172
 
174
173
  ## Legacy mode
175
174
 
176
- If `pipeline.json` is missing (old `/feature-start` tasks), fall back to fixed phases: analysis → development → review → testing.
175
+ If `pipeline.json` is missing, fall back to fixed phases: analysis → development → review → testing.
177
176
 
178
177
  ## Skip pipeline when
179
178
 
@@ -192,6 +191,6 @@ When user describes a **non-trivial task** (not a question), suggest `/task <mes
192
191
 
193
192
  ## Preset authoring
194
193
 
195
- **Product specs:** When `/task`, `/feature-start`, or `/spec-start` touches pages/features/`docs/specs`: if INDEX exists and no generate intent → instruct next agent to load requestable **`product-specs`** (consume; soft-fail; never invent). If generate/bootstrap/`spec-gen` → load **`product-specs-authoring`** + skill **`spec-authoring`** inside **task-analyst** (not a separate pipeline step); pass created spec paths + INDEX diff in handoff; human gate must approve before feature-developer. No-op if INDEX absent and no author intent.
194
+ **Product specs:** When `/task` or `/spec-start` touches pages/features/`docs/specs`: if INDEX exists and no generate intent → instruct next agent to load requestable **`product-specs`** (consume; soft-fail; never invent). If generate/bootstrap/`spec-gen` → load **`product-specs-authoring`** + skill **`spec-authoring`** inside **task-analyst** (not a separate pipeline step); pass created spec paths + INDEX diff in handoff; human gate must approve before feature-developer. No-op if INDEX absent and no author intent.
196
195
 
197
196
  When editing `packages/ai-rules/presets/**`, follow **`tooling-and-review/preset-pr-checklist.md`** (+ twin-sync / layering / token-budget / leakage).
@@ -0,0 +1,48 @@
1
+ ---
2
+ description: Local overlay from .ai.local/ (consumer-owned rules with priority over preset rules) — MANDATORY
3
+ paths:
4
+ - "**/.ai.local/**"
5
+ - "**/AGENTS.md"
6
+ - "**/CLAUDE.md"
7
+ alwaysApply: false
8
+ impact: CRITICAL
9
+ ---
10
+
11
+ # Local overlay (`.ai.local/`) — MANDATORY
12
+
13
+ This rule is mandatory. **You MUST** obey it on every turn, without exception.
14
+
15
+ ## On every turn
16
+
17
+ 1. **Probe** — before answering, run `ls -la .ai.local` from the repository root.
18
+ 2. **Walk** — if `.ai.local/` exists at multiple levels (monorepo), read every level from root to leaf. **Deeper wins** in practice: more specific rules appear later in the assembled context and take precedence.
19
+ 3. **Apply** — treat every `.ai.local/rules/*.md` and `.ai.local/conventions.md` as a higher-priority rule for this repo. The block below ("Authoring `.ai.local/rules/*.md`") defines the conventions.
20
+ 4. **Conflict** — if a local rule conflicts with a preset rule, **the local rule wins**. If a local rule body contains `override: kill <preset-rule-name>`, drop that preset rule from your context window entirely.
21
+ 5. **Acknowledge** — when answering a user question, briefly state which `.ai.local/` rules apply to the current task (one line is enough). Format: `Using .ai.local: <rule-name>(, <rule-name>)*`. If no `.ai.local/` exists, do NOT mention this rule.
22
+
23
+ If `.ai.local/` does not exist → **no-op**, do not error. Do not produce any log line about its absence.
24
+
25
+ ## Authoring `.ai.local/rules/*.md` (consumer-side reference)
26
+
27
+ Each `.ai.local/rules/<name>.md` is a plain-markdown rule body. The model parses it as:
28
+
29
+ - Lines before `## Body` are scope metadata. Only `glob:` / `globs:` / `override:` lines are recognised.
30
+ - Everything from `## Body` onward is the rule body.
31
+ - `glob: always` → always-on. Counts against your context budget.
32
+ - `globs: <comma-separated globs>` → on-demand; applies only when matching files are in focus.
33
+ - `override: kill <preset-rule-name>` → drop that preset rule from context.
34
+
35
+ Keep files ≤ 120 lines. Match the style of preset rules (short sections, bullets, code examples).
36
+
37
+ ## Limitations (read this)
38
+
39
+ - Cursor/Claude do **not** natively read `.ai.local/`. This rule is a **prompt-only** mechanism: it asks you, the model, to read and apply the files. Reliability is high but not 100%.
40
+ - If a user adds a file to `.ai.local/` mid-session, **restart the session** to be sure it is picked up.
41
+ - "Priority" is **contextual**, not enforced. Always re-read the local rule before answering questions that touch it.
42
+ - This rule is **not** session-start (Claude convention); it loads on touch of `.ai.local/**` or `AGENTS.md`/`CLAUDE.md`. The "every turn" mandate is enforced by the body text, not by Cursor/Claude loading semantics.
43
+
44
+ ## Pointers
45
+
46
+ - Authoring guide: `docs/LOCAL-OVERLAY.md` in the `@bonesofspring/ai-rules` package.
47
+ - Living gotchas alternative: `.claude/team/conventions.md`.
48
+ - Root `AGENTS.md` reinforces this rule with a `MANDATORY` section.
@@ -19,11 +19,15 @@ Checklist for PRs that touch `packages/ai-rules/presets/**` (and dogfood `.curso
19
19
  - [ ] **Core:** if `_shared/core/**` changed — all `<!-- shared-core: … -->` consumers updated (or documented intentional fork)
20
20
  - [ ] **Twin:** Cursor change → Claude twin **same PR** (**FAIL** if missing on next, nuxt, svelte, ios-swift, android-kotlin, go, java, mcp-ts, php-hexagonal, and php-laravel — see `preset-twin-sync`)
21
21
  - [ ] **Mapping:** `claude/<stack>/rules/README.md` mapping table is current
22
- - [ ] **Token budget:** alwaysApply / session-start 3; meta rules not always-on
22
+ - [ ] **Token budget:** Cursor `alwaysApply` 4 (4th slot reserved for `ai-local-overlay`); Claude session-start exactly 3; meta rules not always-on
23
+ - [ ] **Local overlay coverage:** every installable stack ships `ai-local-overlay.mdc` (Cursor) and `ai-local-overlay.md` (Claude) with `MANDATORY` + acknowledgement format + `docs/LOCAL-OVERLAY.md` pointer; Claude twin listed in `claude/<stack>/rules/README.md` mapping table. Run `packages/ai-rules/scripts/check-local-overlay.sh`.
23
24
  - [ ] **Leakage:** no foreign stack agent stems / handoff strings (`preset-no-cross-stack-leakage`)
25
+ - [ ] **Hook-only lifecycle:** `status.json` / `metrics.json` writes happen only inside `hooks/`; agents read but never rewrite lifecycle fields. Run `packages/ai-rules/scripts/check-hook-only-lifecycle.sh`.
26
+ - [ ] **Chain fork:** the byte-wise MD5 uniqueness of `chain-team-phases.sh` across the 10 stacks × 2 platforms (20 hooks) holds. Run `packages/ai-rules/scripts/check-chain-hook-coverage.sh` and `packages/ai-rules/scripts/test-chain-team-phases-coverage.mjs`.
24
27
  - [ ] **Twin depth:** domain ≥15 lines; thin aliases documented
25
28
  - [ ] **README:** stack `rules/README.md` core→stack mapping / catalog updated if stems added
26
29
  - [ ] **CHANGELOG / package README:** note when public preset paths or install surface change
30
+ - [ ] **i18n anchors:** kept-marked Cyrillic fragments in `tests-unit.md(c)` stay consistent with their English counterparts. Run `packages/ai-rules/scripts/check-preset-i18n.sh`.
27
31
  - [ ] **Dogfood:** run `packages/ai-rules/scripts/sync-dogfood-cursor.sh` (or document intentional skip) when maintaining this monorepo
28
32
  - [ ] **shared-core drift:** for embed-mode stems, run `packages/ai-rules/scripts/check-shared-core-drift.sh` (or document intentional fork)
29
33