@gong-ym/ai-spec-auto 0.2.13 → 0.2.15

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 (631) hide show
  1. package/.agents/commands/README.md +33 -33
  2. package/.agents/commands/claude/spec-start-review.md +88 -88
  3. package/.agents/commands/codex/spec-continue.md +74 -74
  4. package/.agents/commands/codex/spec-orchestrate.md +35 -35
  5. package/.agents/commands/codex/spec-start-review.md +88 -88
  6. package/.agents/commands/codex/spec-start.md +67 -67
  7. package/.agents/commands/codex/spec-status.md +22 -22
  8. package/.agents/commands/codex/spec-stop.md +29 -29
  9. package/.agents/commands/codex/spec-update.md +40 -40
  10. package/.agents/commands/common/branch-review.md +117 -117
  11. package/.agents/commands/common/project-init.md +25 -25
  12. package/.agents/commands/common/spec-continue.md +74 -74
  13. package/.agents/commands/common/spec-orchestrate.md +35 -35
  14. package/.agents/commands/common/spec-start-review.md +82 -82
  15. package/.agents/commands/common/spec-start.md +67 -67
  16. package/.agents/commands/common/spec-status.md +22 -22
  17. package/.agents/commands/common/spec-stop.md +29 -29
  18. package/.agents/commands/common/spec-update.md +60 -40
  19. package/.agents/commands/cursor/opsx-apply.md +55 -55
  20. package/.agents/commands/cursor/opsx-archive.md +48 -48
  21. package/.agents/commands/cursor/opsx-explore.md +45 -45
  22. package/.agents/commands/cursor/opsx-propose.md +59 -59
  23. package/.agents/commands/cursor/spec-continue.md +63 -63
  24. package/.agents/commands/cursor/spec-orchestrate.md +53 -53
  25. package/.agents/commands/cursor/spec-start-review.md +78 -78
  26. package/.agents/commands/cursor/spec-start.md +59 -59
  27. package/.agents/commands/cursor/spec-status.md +30 -30
  28. package/.agents/commands/cursor/spec-stop.md +29 -29
  29. package/.agents/commands/cursor/spec-update.md +41 -41
  30. package/.agents/flows/FRONTMATTER.md +263 -263
  31. package/.agents/flows/RUN_OUTPUT.md +263 -263
  32. package/.agents/flows/common/README.md +29 -29
  33. package/.agents/flows/common/bugfix-to-verification.md +95 -95
  34. package/.agents/flows/common/change-to-architecture-review.md +89 -89
  35. package/.agents/flows/common/change-to-release.md +94 -94
  36. package/.agents/flows/common/prd-to-delivery.md +184 -184
  37. package/.agents/flows/common/requirement-to-observability.md +97 -97
  38. package/.agents/orchestration/README.md +22 -22
  39. package/.agents/orchestration/expert-dispatch-spec.md +155 -155
  40. package/.agents/orchestration/expert-executor-spec.md +84 -84
  41. package/.agents/orchestration/expert-runtime-action-spec.md +73 -73
  42. package/.agents/orchestration/runtime-state-handoff-spec.md +264 -264
  43. package/.agents/orchestration/task-anchor-spec.md +212 -212
  44. package/.agents/orchestration/task-orchestrator-adapter-payload.md +153 -153
  45. package/.agents/orchestration/task-orchestrator-bootstrap-payload.md +145 -145
  46. package/.agents/orchestration/task-orchestrator-output-extractor-spec.md +93 -93
  47. package/.agents/orchestration/task-orchestrator-run-plan-template.md +312 -312
  48. package/.agents/orchestration/task-orchestrator-runtime-hooks.md +214 -214
  49. package/.agents/registry/README.md +63 -63
  50. package/.agents/registry/flows.json +125 -125
  51. package/.agents/registry/profiles.json +101 -101
  52. package/.agents/registry/roles.json +1265 -1265
  53. package/.agents/registry/rules.json +148 -148
  54. package/.agents/registry/scenario-packages.json +123 -123
  55. package/.agents/registry/skills.json +130 -130
  56. package/.agents/roles/INDEX.md +346 -346
  57. package/.agents/roles/common/README.md +76 -76
  58. package/.agents/roles/common/archive-change.md +80 -80
  59. package/.agents/roles/common/backend-implementer.md +92 -92
  60. package/.agents/roles/common/code-guardian.md +151 -151
  61. package/.agents/roles/common/frontend-implementer.md +146 -146
  62. package/.agents/roles/common/requirement-analyst.md +138 -138
  63. package/.agents/roles/common/task-orchestrator-routing.md +301 -301
  64. package/.agents/roles/common/task-orchestrator.md +224 -224
  65. package/.agents/roles/common/tooling-implementer.md +92 -92
  66. package/.agents/roles/domains/README.md +35 -35
  67. package/.agents/roles/domains/delivery/README.md +11 -11
  68. package/.agents/roles/domains/delivery/container-specialist.md +50 -50
  69. package/.agents/roles/domains/delivery/deployment-specialist.md +50 -50
  70. package/.agents/roles/domains/delivery/pipeline-specialist.md +50 -50
  71. package/.agents/roles/domains/demand-design/README.md +16 -16
  72. package/.agents/roles/domains/demand-design/api-contract-specialist.md +52 -52
  73. package/.agents/roles/domains/demand-design/design-collaborator.md +58 -58
  74. package/.agents/roles/domains/documentation/README.md +11 -11
  75. package/.agents/roles/domains/documentation/api-doc-specialist.md +50 -50
  76. package/.agents/roles/domains/documentation/component-doc-specialist.md +49 -49
  77. package/.agents/roles/domains/documentation/technical-writing-specialist.md +48 -48
  78. package/.agents/roles/domains/engineering/README.md +17 -17
  79. package/.agents/roles/domains/engineering/architecture-advisor.md +53 -53
  80. package/.agents/roles/domains/engineering/build-specialist.md +51 -51
  81. package/.agents/roles/domains/engineering/dependency-governor.md +52 -52
  82. package/.agents/roles/domains/governance/README.md +17 -17
  83. package/.agents/roles/domains/governance/api-governance-specialist.md +51 -51
  84. package/.agents/roles/domains/governance/lint-policy-specialist.md +49 -49
  85. package/.agents/roles/domains/governance/route-governance-specialist.md +52 -52
  86. package/.agents/roles/domains/observability/README.md +11 -11
  87. package/.agents/roles/domains/observability/error-tracker.md +50 -50
  88. package/.agents/roles/domains/observability/event-instrumentation-specialist.md +51 -51
  89. package/.agents/roles/domains/observability/rum-analyst.md +50 -50
  90. package/.agents/roles/domains/performance/README.md +11 -11
  91. package/.agents/roles/domains/performance/asset-optimizer.md +50 -50
  92. package/.agents/roles/domains/performance/performance-auditor.md +56 -56
  93. package/.agents/roles/domains/performance/vitals-analyst.md +50 -50
  94. package/.agents/roles/domains/security-a11y/README.md +11 -11
  95. package/.agents/roles/domains/security-a11y/a11y-auditor.md +50 -50
  96. package/.agents/roles/domains/security-a11y/aria-specialist.md +51 -51
  97. package/.agents/roles/domains/security-a11y/security-reviewer.md +49 -49
  98. package/.agents/roles/domains/testing/README.md +12 -12
  99. package/.agents/roles/domains/testing/coverage-analyst.md +50 -50
  100. package/.agents/roles/domains/testing/e2e-test-specialist.md +51 -51
  101. package/.agents/roles/domains/testing/unit-test-specialist.md +56 -56
  102. package/.agents/roles/domains/testing/verification-reviewer.md +67 -67
  103. package/.agents/rules/README.md +87 -87
  104. package/.agents/rules/common/02-/347/274/226/347/240/201/350/247/204/350/214/203.md +45 -45
  105. package/.agents/rules/common/08-/351/200/232/347/224/250/347/272/246/346/235/237.md +63 -63
  106. package/.agents/rules/common/10-/346/226/207/346/241/243/350/247/204/350/214/203.md +101 -101
  107. package/.agents/rules/common/12-Superpowers/346/211/247/350/241/214/350/247/204/350/214/203.md +46 -46
  108. package/.agents/rules/common/14-/345/256/241/350/256/241/346/261/207/346/212/245/350/247/204/350/214/203.md +107 -107
  109. package/.agents/rules/common/15-visual-gate-wait.md +90 -90
  110. package/.agents/rules/profiles/nestjs/01-/351/241/271/347/233/256/346/246/202/350/277/260.md +27 -27
  111. package/.agents/rules/profiles/nestjs/03-/351/241/271/347/233/256/347/273/223/346/236/204.md +20 -20
  112. package/.agents/rules/profiles/nestjs/04-/346/250/241/345/235/227/347/273/223/346/236/204/350/247/204/350/214/203.md +24 -24
  113. package/.agents/rules/profiles/nestjs/05-/346/216/245/345/217/243/344/270/216/345/245/221/347/272/246/350/247/204/350/214/203.md +24 -24
  114. package/.agents/rules/profiles/nestjs/06-/346/225/260/346/215/256/350/256/277/351/227/256/350/247/204/350/214/203.md +24 -24
  115. package/.agents/rules/profiles/nestjs/07-/351/205/215/347/275/256/344/270/216/350/277/220/350/241/214/346/227/266/350/247/204/350/214/203.md +20 -20
  116. package/.agents/rules/profiles/nestjs/09-/345/274/202/345/270/270/344/270/216/346/227/245/345/277/227/350/247/204/350/214/203.md +20 -20
  117. package/.agents/rules/profiles/nestjs/11-/346/265/213/350/257/225/350/247/204/350/214/203.md +24 -24
  118. package/.agents/rules/profiles/nestjs/13-/344/273/243/347/240/201/346/240/274/345/274/217/345/214/226/344/270/216/346/243/200/346/237/245.md +20 -20
  119. package/.agents/rules/profiles/node-tooling/01-/351/241/271/347/233/256/346/246/202/350/277/260.md +30 -30
  120. package/.agents/rules/profiles/node-tooling/03-/351/241/271/347/233/256/347/273/223/346/236/204.md +37 -37
  121. package/.agents/rules/profiles/node-tooling/04-CLI/344/270/216/346/250/241/345/235/227/350/247/204/350/214/203.md +42 -42
  122. package/.agents/rules/profiles/node-tooling/05-Contract/344/270/216Schema/350/247/204/350/214/203.md +42 -42
  123. package/.agents/rules/profiles/node-tooling/06-/350/277/220/350/241/214/346/227/266/346/226/207/344/273/266/350/247/204/350/214/203.md +30 -30
  124. package/.agents/rules/profiles/node-tooling/07-/346/227/245/345/277/227/344/270/216/351/224/231/350/257/257/345/244/204/347/220/206/350/247/204/350/214/203.md +60 -60
  125. package/.agents/rules/profiles/node-tooling/09-/350/204/232/346/234/254/344/270/216/345/205/245/345/217/243/350/247/204/350/214/203.md +45 -45
  126. package/.agents/rules/profiles/node-tooling/11-/346/265/213/350/257/225/350/247/204/350/214/203.md +41 -41
  127. package/.agents/rules/profiles/node-tooling/13-/344/273/243/347/240/201/346/240/274/345/274/217/345/214/226/344/270/216/346/243/200/346/237/245.md +55 -55
  128. package/.agents/rules/profiles/react/01-/351/241/271/347/233/256/346/246/202/350/277/260.md +29 -29
  129. package/.agents/rules/profiles/react/03-/351/241/271/347/233/256/347/273/223/346/236/204.md +104 -104
  130. package/.agents/rules/profiles/react/04-/347/273/204/344/273/266/350/247/204/350/214/203.md +46 -46
  131. package/.agents/rules/profiles/react/05-API/350/247/204/350/214/203.md +67 -67
  132. package/.agents/rules/profiles/react/06-/350/267/257/347/224/261/350/247/204/350/214/203.md +54 -54
  133. package/.agents/rules/profiles/react/07-/347/212/266/346/200/201/347/256/241/347/220/206.md +226 -226
  134. package/.agents/rules/profiles/react/09-/346/240/267/345/274/217/350/247/204/350/214/203.md +71 -71
  135. package/.agents/rules/profiles/react/11-/346/265/213/350/257/225/350/247/204/350/214/203.md +80 -80
  136. package/.agents/rules/profiles/react/13-/344/273/243/347/240/201/346/240/274/345/274/217/345/214/226/344/270/216/346/243/200/346/237/245.md +159 -159
  137. package/.agents/rules/profiles/springboot/01-/351/241/271/347/233/256/346/246/202/350/277/260.md +31 -31
  138. package/.agents/rules/profiles/springboot/03-/351/241/271/347/233/256/347/273/223/346/236/204.md +37 -37
  139. package/.agents/rules/profiles/springboot/04-/345/210/206/345/261/202/350/247/204/350/214/203.md +33 -33
  140. package/.agents/rules/profiles/springboot/05-/346/216/245/345/217/243/344/270/216/345/245/221/347/272/246/350/247/204/350/214/203.md +51 -51
  141. package/.agents/rules/profiles/springboot/06-/346/225/260/346/215/256/350/256/277/351/227/256/350/247/204/350/214/203.md +34 -34
  142. package/.agents/rules/profiles/springboot/07-/351/205/215/347/275/256/344/270/216/350/277/220/350/241/214/346/227/266/350/247/204/350/214/203.md +38 -38
  143. package/.agents/rules/profiles/springboot/09-/345/274/202/345/270/270/344/270/216/346/227/245/345/277/227/350/247/204/350/214/203.md +48 -48
  144. package/.agents/rules/profiles/springboot/11-/346/265/213/350/257/225/350/247/204/350/214/203.md +43 -43
  145. package/.agents/rules/profiles/springboot/13-/344/273/243/347/240/201/346/240/274/345/274/217/345/214/226/344/270/216/346/243/200/346/237/245.md +48 -48
  146. package/.agents/rules/profiles/vue/01-/351/241/271/347/233/256/346/246/202/350/277/260.md +47 -47
  147. package/.agents/rules/profiles/vue/03-/351/241/271/347/233/256/347/273/223/346/236/204.md +106 -106
  148. package/.agents/rules/profiles/vue/04-/347/273/204/344/273/266/350/247/204/350/214/203.md +61 -61
  149. package/.agents/rules/profiles/vue/05-API/350/247/204/350/214/203.md +67 -67
  150. package/.agents/rules/profiles/vue/06-/350/267/257/347/224/261/350/247/204/350/214/203.md +69 -69
  151. package/.agents/rules/profiles/vue/07-/347/212/266/346/200/201/347/256/241/347/220/206.md +93 -93
  152. package/.agents/rules/profiles/vue/09-/346/240/267/345/274/217/350/247/204/350/214/203.md +67 -67
  153. package/.agents/rules/profiles/vue/11-/346/265/213/350/257/225/350/247/204/350/214/203.md +80 -80
  154. package/.agents/rules/profiles/vue/13-/344/273/243/347/240/201/346/240/274/345/274/217/345/214/226/344/270/216/346/243/200/346/237/245.md +159 -159
  155. package/.agents/skills/README.md +171 -171
  156. package/.agents/skills/common/archive-change/SKILL.md +180 -180
  157. package/.agents/skills/common/branch-code-reviewer/SKILL.md +533 -459
  158. package/.agents/skills/common/branch-code-reviewer/references/business-risk-guide.md +293 -293
  159. package/.agents/skills/common/branch-code-reviewer/references/html-template-guide.md +121 -121
  160. package/.agents/skills/common/config-and-secret-scan/SKILL.md +99 -99
  161. package/.agents/skills/common/create-proposal/SKILL.md +192 -192
  162. package/.agents/skills/common/create-proposal/evals/evals.json +16 -16
  163. package/.agents/skills/common/create-proposal/evals/train_queries.json +18 -18
  164. package/.agents/skills/common/create-proposal/evals/validation_queries.json +18 -18
  165. package/.agents/skills/common/create-proposal/references/interaction-spec-template.md +42 -42
  166. package/.agents/skills/common/create-test/SKILL.md +292 -292
  167. package/.agents/skills/common/dependency-impact-graph/SKILL.md +80 -80
  168. package/.agents/skills/common/execute-task/SKILL.md +206 -206
  169. package/.agents/skills/common/execute-task/evals/evals.json +16 -16
  170. package/.agents/skills/common/execute-task/evals/train_queries.json +18 -18
  171. package/.agents/skills/common/execute-task/evals/validation_queries.json +18 -18
  172. package/.agents/skills/common/find-skills/SKILL.md +144 -144
  173. package/.agents/skills/common/install-ai-spec-auto/SKILL.md +260 -260
  174. package/.agents/skills/common/install-ai-spec-auto/evals/evals.json +17 -17
  175. package/.agents/skills/common/install-ai-spec-auto/evals/train_queries.json +18 -18
  176. package/.agents/skills/common/install-ai-spec-auto/evals/validation_queries.json +18 -18
  177. package/.agents/skills/common/project-init/SKILL.md +178 -178
  178. package/.agents/skills/common/project-init/evals/evals.json +16 -16
  179. package/.agents/skills/common/project-init/evals/train_queries.json +18 -18
  180. package/.agents/skills/common/project-init/evals/validation_queries.json +18 -18
  181. package/.agents/skills/common/project-init/references/custom-rule-generation.md +89 -89
  182. package/.agents/skills/common/project-init/references/deep-scan-rules.md +67 -67
  183. package/.agents/skills/common/project-init/references/output-contracts.md +71 -71
  184. package/.agents/skills/common/project-init/references/repo-fact-gathering.md +83 -83
  185. package/.agents/skills/common/project-init/references/scope-resolution.md +76 -76
  186. package/.agents/skills/common/project-init/scripts/inspect-project.js +112 -112
  187. package/.agents/skills/common/skill-creator/LICENSE.txt +201 -201
  188. package/.agents/skills/common/skill-creator/SKILL.md +370 -370
  189. package/.agents/skills/common/skill-creator/evals/evals.json +16 -16
  190. package/.agents/skills/common/skill-creator/evals/train_queries.json +18 -18
  191. package/.agents/skills/common/skill-creator/evals/validation_queries.json +18 -18
  192. package/.agents/skills/common/skill-creator/references/output-patterns.md +82 -82
  193. package/.agents/skills/common/skill-creator/references/workflows.md +27 -27
  194. package/.agents/skills/common/skill-creator/scripts/init_skill.py +209 -209
  195. package/.agents/skills/common/skill-creator/scripts/package_skill.py +110 -110
  196. package/.agents/skills/common/skill-creator/scripts/quick_validate.py +51 -51
  197. package/.agents/skills/common/skill-optimizer/SKILL.md +102 -102
  198. package/.agents/skills/common/skill-optimizer/evals/evals.json +16 -16
  199. package/.agents/skills/common/skill-optimizer/evals/train_queries.json +18 -18
  200. package/.agents/skills/common/skill-optimizer/evals/validation_queries.json +18 -18
  201. package/.agents/skills/common/skill-optimizer/references/design-patterns.md +26 -26
  202. package/.agents/skills/common/skill-optimizer/references/review-checklist.md +22 -22
  203. package/.agents/skills/common/using-superpowers/SKILL.md +151 -151
  204. package/.agents/skills/common/wait-for-gate-signal/SKILL.md +85 -85
  205. package/.agents/skills/domains/README.md +19 -19
  206. package/.agents/skills/domains/ui-ux-pro-max/SKILL.md +58 -58
  207. package/.agents/skills/domains/web/design-analysis/SKILL.md +89 -89
  208. package/.agents/skills/domains/web/design-analysis/rules/analysis-order.md +61 -61
  209. package/.agents/skills/domains/web/design-analysis/rules/analysis-priorities.md +136 -136
  210. package/.agents/skills/domains/web/design-analysis/rules/checklist-common-misses.md +107 -107
  211. package/.agents/skills/domains/web/design-analysis/rules/implementation-common-errors.md +204 -204
  212. package/.agents/skills/domains/web/design-analysis/rules/implementation-guidelines.md +211 -211
  213. package/.agents/skills/domains/web/design-analysis/rules/output-analysis-checklist.md +247 -247
  214. package/.agents/skills/domains/web/design-analysis/rules/tools-design-guidelines.md +108 -108
  215. package/.agents/skills/domains/web/design-analysis/rules/workflow-element-extraction.md +162 -162
  216. package/.agents/skills/domains/web/design-analysis/rules/workflow-layout-map.md +131 -131
  217. package/.agents/skills/domains/web/design-analysis/rules/workflow-output-checklist.md +70 -70
  218. package/.agents/skills/domains/web/design-analysis/rules/workflow-style-summary.md +91 -91
  219. package/.agents/skills/domains/web/route-permission-map/SKILL.md +103 -103
  220. package/.agents/skills/domains/web/ui-verification/SKILL.md +114 -114
  221. package/.agents/skills/domains/web/ui-verification/evals/evals.json +16 -16
  222. package/.agents/skills/domains/web/ui-verification/evals/train_queries.json +18 -18
  223. package/.agents/skills/domains/web/ui-verification/evals/validation_queries.json +18 -18
  224. package/.agents/skills/domains/web/ui-verification/rules/comparison-content-image.md +34 -34
  225. package/.agents/skills/domains/web/ui-verification/rules/comparison-content-text.md +30 -30
  226. package/.agents/skills/domains/web/ui-verification/rules/comparison-hierarchy.md +33 -33
  227. package/.agents/skills/domains/web/ui-verification/rules/comparison-layout.md +35 -35
  228. package/.agents/skills/domains/web/ui-verification/rules/errors-alignment.md +42 -42
  229. package/.agents/skills/domains/web/ui-verification/rules/errors-button-dimensions.md +28 -28
  230. package/.agents/skills/domains/web/ui-verification/rules/errors-button-position.md +25 -25
  231. package/.agents/skills/domains/web/ui-verification/rules/errors-css-priority.md +50 -50
  232. package/.agents/skills/domains/web/ui-verification/rules/errors-flex-column-width.md +46 -46
  233. package/.agents/skills/domains/web/ui-verification/rules/errors-flex-layout.md +46 -46
  234. package/.agents/skills/domains/web/ui-verification/rules/errors-grid-container-width.md +44 -44
  235. package/.agents/skills/domains/web/ui-verification/rules/errors-page-container-width.md +39 -39
  236. package/.agents/skills/domains/web/ui-verification/rules/tools-browser-navigation.md +53 -53
  237. package/.agents/skills/domains/web/ui-verification/rules/tools-design-guidelines.md +53 -53
  238. package/.agents/skills/domains/web/ui-verification/rules/workflow-checklist.md +27 -27
  239. package/.agents/skills/domains/web/ui-verification/rules/workflow-problem-list.md +56 -56
  240. package/.agents/skills/domains/web/ui-verification/rules/workflow-reflection.md +44 -44
  241. package/.agents/skills/domains/web/ui-verification/rules/writing-alignment.md +44 -44
  242. package/.agents/skills/domains/web/ui-verification/rules/writing-element-completeness.md +63 -63
  243. package/.agents/skills/domains/web/ui-verification/rules/writing-list-layout.md +75 -75
  244. package/.agents/skills/domains/web/ui-verification/rules/writing-page-container-width.md +37 -37
  245. package/.agents/skills/domains/web/web-design-guidelines/SKILL.md +40 -40
  246. package/.agents/skills/profiles/nestjs/README.md +4 -4
  247. package/.agents/skills/profiles/node-tooling/README.md +9 -9
  248. package/.agents/skills/profiles/react/create-api/SKILL.md +145 -145
  249. package/.agents/skills/profiles/react/create-component/SKILL.md +160 -160
  250. package/.agents/skills/profiles/react/create-route/SKILL.md +168 -168
  251. package/.agents/skills/profiles/react/create-store/SKILL.md +262 -262
  252. package/.agents/skills/profiles/react/theme-variables/SKILL.md +82 -82
  253. package/.agents/skills/profiles/react/vercel-composition-patterns/AGENTS.md +899 -899
  254. package/.agents/skills/profiles/react/vercel-composition-patterns/SKILL.md +81 -81
  255. package/.agents/skills/profiles/react/vercel-composition-patterns/rules/architecture-avoid-boolean-props.md +100 -100
  256. package/.agents/skills/profiles/react/vercel-composition-patterns/rules/architecture-compound-components.md +112 -112
  257. package/.agents/skills/profiles/react/vercel-composition-patterns/rules/patterns-children-over-render-props.md +87 -87
  258. package/.agents/skills/profiles/react/vercel-composition-patterns/rules/patterns-explicit-variants.md +100 -100
  259. package/.agents/skills/profiles/react/vercel-composition-patterns/rules/state-context-interface.md +191 -191
  260. package/.agents/skills/profiles/react/vercel-composition-patterns/rules/state-decouple-implementation.md +113 -113
  261. package/.agents/skills/profiles/react/vercel-composition-patterns/rules/state-lift-state.md +125 -125
  262. package/.agents/skills/profiles/react/vercel-react-best-practices/AGENTS.md +2934 -2934
  263. package/.agents/skills/profiles/react/vercel-react-best-practices/SKILL.md +136 -136
  264. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -55
  265. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/advanced-init-once.md +42 -42
  266. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/advanced-use-latest.md +39 -39
  267. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/async-api-routes.md +38 -38
  268. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/async-defer-await.md +80 -80
  269. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/async-dependencies.md +51 -51
  270. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/async-parallel.md +28 -28
  271. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -99
  272. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/bundle-barrel-imports.md +59 -59
  273. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/bundle-conditional.md +31 -31
  274. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/bundle-defer-third-party.md +49 -49
  275. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/bundle-dynamic-imports.md +35 -35
  276. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/bundle-preload.md +50 -50
  277. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/client-event-listeners.md +74 -74
  278. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/client-localstorage-schema.md +71 -71
  279. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -48
  280. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/client-swr-dedup.md +56 -56
  281. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/js-batch-dom-css.md +107 -107
  282. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/js-cache-function-results.md +80 -80
  283. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/js-cache-property-access.md +28 -28
  284. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/js-cache-storage.md +70 -70
  285. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/js-combine-iterations.md +32 -32
  286. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/js-early-exit.md +50 -50
  287. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -45
  288. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/js-index-maps.md +37 -37
  289. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/js-length-check-first.md +49 -49
  290. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/js-min-max-loop.md +82 -82
  291. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -24
  292. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -57
  293. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/rendering-activity.md +26 -26
  294. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -47
  295. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/rendering-conditional-render.md +40 -40
  296. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -38
  297. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/rendering-hoist-jsx.md +46 -46
  298. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +82 -82
  299. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -30
  300. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -28
  301. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -75
  302. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -39
  303. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/rerender-dependencies.md +45 -45
  304. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +40 -40
  305. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/rerender-derived-state.md +29 -29
  306. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/rerender-functional-setstate.md +74 -74
  307. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/rerender-lazy-state-init.md +58 -58
  308. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +38 -38
  309. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/rerender-memo.md +44 -44
  310. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +45 -45
  311. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -35
  312. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/rerender-transitions.md +40 -40
  313. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +73 -73
  314. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -73
  315. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/server-auth-actions.md +96 -96
  316. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/server-cache-lru.md +41 -41
  317. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/server-cache-react.md +76 -76
  318. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/server-dedup-props.md +65 -65
  319. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -83
  320. package/.agents/skills/profiles/react/vercel-react-best-practices/rules/server-serialization.md +38 -38
  321. package/.agents/skills/profiles/springboot/README.md +10 -10
  322. package/.agents/skills/profiles/vue/create-api/SKILL.md +105 -105
  323. package/.agents/skills/profiles/vue/create-component/SKILL.md +76 -76
  324. package/.agents/skills/profiles/vue/create-route/SKILL.md +141 -141
  325. package/.agents/skills/profiles/vue/create-store/SKILL.md +97 -97
  326. package/.agents/skills/profiles/vue/create-view/SKILL.md +81 -81
  327. package/.agents/skills/profiles/vue/theme-variables/SKILL.md +73 -73
  328. package/.agents/skills/profiles/vue/vue-best-practices/SKILL.md +166 -166
  329. package/.agents/skills/profiles/vue/vue-best-practices/references/animation-class-based-technique.md +254 -254
  330. package/.agents/skills/profiles/vue/vue-best-practices/references/animation-state-driven-technique.md +291 -291
  331. package/.agents/skills/profiles/vue/vue-best-practices/references/component-async.md +97 -97
  332. package/.agents/skills/profiles/vue/vue-best-practices/references/component-data-flow.md +307 -307
  333. package/.agents/skills/profiles/vue/vue-best-practices/references/component-fallthrough-attrs.md +174 -174
  334. package/.agents/skills/profiles/vue/vue-best-practices/references/component-keep-alive.md +137 -137
  335. package/.agents/skills/profiles/vue/vue-best-practices/references/component-slots.md +216 -216
  336. package/.agents/skills/profiles/vue/vue-best-practices/references/component-suspense.md +228 -228
  337. package/.agents/skills/profiles/vue/vue-best-practices/references/component-teleport.md +108 -108
  338. package/.agents/skills/profiles/vue/vue-best-practices/references/component-transition-group.md +128 -128
  339. package/.agents/skills/profiles/vue/vue-best-practices/references/component-transition.md +125 -125
  340. package/.agents/skills/profiles/vue/vue-best-practices/references/composables.md +290 -290
  341. package/.agents/skills/profiles/vue/vue-best-practices/references/directives.md +162 -162
  342. package/.agents/skills/profiles/vue/vue-best-practices/references/perf-avoid-component-abstraction-in-lists.md +159 -159
  343. package/.agents/skills/profiles/vue/vue-best-practices/references/perf-v-once-v-memo-directives.md +182 -182
  344. package/.agents/skills/profiles/vue/vue-best-practices/references/perf-virtualize-large-lists.md +187 -187
  345. package/.agents/skills/profiles/vue/vue-best-practices/references/plugins.md +166 -166
  346. package/.agents/skills/profiles/vue/vue-best-practices/references/reactivity.md +344 -344
  347. package/.agents/skills/profiles/vue/vue-best-practices/references/render-functions.md +201 -201
  348. package/.agents/skills/profiles/vue/vue-best-practices/references/sfc.md +310 -310
  349. package/.agents/skills/profiles/vue/vue-best-practices/references/state-management.md +135 -135
  350. package/.agents/skills/profiles/vue/vue-best-practices/references/updated-hook-performance.md +187 -187
  351. package/.agents/templates/common/README.md +23 -23
  352. package/.agents/templates/common/bugfix.md +22 -22
  353. package/.agents/templates/common/create-expert-package.md +458 -458
  354. package/.agents/templates/common/mock-page.md +28 -28
  355. package/.agents/templates/common/new-component.md +25 -25
  356. package/.agents/templates/common/new-page.md +31 -31
  357. package/.cursor/mcp.json +35 -35
  358. package/.qoder/mcp.json +26 -26
  359. package/bin/archive-change.js +560 -474
  360. package/bin/check-command.js +62 -62
  361. package/bin/cli.js +0 -0
  362. package/bin/command-template-renderer.js +40 -40
  363. package/bin/context-command.js +102 -102
  364. package/bin/demo-runtime-smoke.js +760 -760
  365. package/bin/execution-semantics.js +821 -821
  366. package/bin/executor-command.js +93 -93
  367. package/bin/expert-dispatch.js +334 -334
  368. package/bin/expert-executor.js +1148 -1148
  369. package/bin/guard-command.js +52 -52
  370. package/bin/hub-command.js +876 -876
  371. package/bin/ide-command.js +242 -242
  372. package/bin/init-command.js +193 -193
  373. package/bin/install-workflow.js +35 -3
  374. package/bin/manifest-export.js +34 -34
  375. package/bin/profile-registry.js +90 -90
  376. package/bin/protocol-workflow.js +452 -446
  377. package/bin/repair-command.js +161 -161
  378. package/bin/repo-map.js +177 -177
  379. package/bin/report-command.js +236 -236
  380. package/bin/runtime-bootstrap.js +428 -428
  381. package/bin/runtime-embedded.js +101 -101
  382. package/bin/runtime-fallback.js +106 -106
  383. package/bin/runtime-launcher.js +116 -116
  384. package/bin/runtime-paths.js +177 -177
  385. package/bin/runtime-registry.js +289 -289
  386. package/bin/runtime-state.js +2541 -2541
  387. package/bin/scan.js +96 -96
  388. package/bin/self-upgrade.js +206 -206
  389. package/bin/skill-spec-validator.js +457 -457
  390. package/bin/spec-command.js +366 -366
  391. package/bin/superpowers.js +384 -384
  392. package/bin/sync-command.js +59 -59
  393. package/bin/sync.js +1904 -1904
  394. package/bin/task-orchestrator-adapter.js +341 -341
  395. package/bin/task-orchestrator-extractor.js +274 -274
  396. package/bin/task-orchestrator-runner.js +1208 -1208
  397. package/bin/telemetry/README.md +66 -66
  398. package/bin/telemetry/aspect.js +153 -153
  399. package/bin/telemetry/collect.js +67 -67
  400. package/bin/telemetry/config.js +114 -114
  401. package/bin/telemetry/defaults.json +5 -5
  402. package/bin/telemetry/healthcheck.js +195 -195
  403. package/bin/telemetry/identity.js +53 -53
  404. package/bin/telemetry/index.js +25 -25
  405. package/bin/telemetry/reporter.js +83 -83
  406. package/bin/telemetry/safe.js +39 -39
  407. package/bin/validate-registry.js +740 -740
  408. package/bin/visual-bridge-config.js +117 -117
  409. package/bin/visual-bridge.js +287 -287
  410. package/bin/visual-command.js +432 -432
  411. package/bin/worktree-command.js +194 -194
  412. package/configs/common/.editorconfig +15 -15
  413. package/configs/common/.husky/commit-msg +4 -4
  414. package/configs/common/.husky/pre-commit +4 -4
  415. package/configs/common/.lintstagedrc +11 -11
  416. package/configs/common/.prettierignore +11 -11
  417. package/configs/common/.prettierrc.json +11 -11
  418. package/configs/common/.stylelintignore +14 -14
  419. package/configs/common/.stylelintrc.json +21 -21
  420. package/configs/common/commitlint.config.js +3 -3
  421. package/configs/profiles/nestjs/.gitkeep +1 -1
  422. package/configs/profiles/node-tooling/.gitkeep +1 -1
  423. package/configs/profiles/react/.eslintignore +6 -6
  424. package/configs/profiles/react/.eslintrc.js +16 -16
  425. package/configs/profiles/react/.stylelintrc.json +18 -18
  426. package/configs/profiles/springboot/.gitkeep +1 -1
  427. package/configs/profiles/vue/.eslintignore +6 -6
  428. package/configs/profiles/vue/.eslintrc.cjs +17 -17
  429. package/contracts/README.md +28 -28
  430. package/contracts/fixtures/asset-package.fixture.json +26 -26
  431. package/contracts/fixtures/asset-usage-feedback.fixture.json +14 -14
  432. package/contracts/fixtures/evidence-report.fixture.json +28 -28
  433. package/contracts/fixtures/manifest.fixture.json +20 -20
  434. package/contracts/fixtures/run-event.fixture.json +15 -15
  435. package/contracts/schemas/asset-package.schema.json +76 -76
  436. package/contracts/schemas/asset-usage-feedback.schema.json +57 -57
  437. package/contracts/schemas/evidence-report.schema.json +60 -60
  438. package/contracts/schemas/manifest.schema.json +63 -63
  439. package/contracts/schemas/run-event.schema.json +72 -72
  440. package/install.ps1 +35 -35
  441. package/install.sh +17 -17
  442. package/internal/ai-protocol-workflow.js +5824 -5600
  443. package/internal/hub-client.js +98 -98
  444. package/internal/hub-sync-selection.js +69 -69
  445. package/internal/visual-hooks/README.md +481 -481
  446. package/internal/visual-hooks/config-loader.js +218 -218
  447. package/internal/visual-hooks/control-puller.js +206 -206
  448. package/internal/visual-hooks/gate-signal.js +150 -150
  449. package/internal/visual-hooks/inbox-consumer.js +469 -469
  450. package/internal/visual-hooks/index.js +197 -197
  451. package/internal/visual-hooks/push-client.js +189 -189
  452. package/internal/visual-hooks/receipt-pusher.js +176 -176
  453. package/internal/visual-hooks/runtime-state-pusher.js +128 -128
  454. package/openspec/config.yaml.template +52 -52
  455. package/openspec/schemas/expert-delivery/schema.yaml +68 -68
  456. package/openspec/schemas/expert-delivery/templates/checklist.md +39 -39
  457. package/openspec/schemas/expert-delivery/templates/design.md +61 -61
  458. package/openspec/schemas/expert-delivery/templates/iterations.md +25 -25
  459. package/openspec/schemas/expert-delivery/templates/proposal.md +45 -45
  460. package/openspec/schemas/expert-delivery/templates/spec.md +29 -29
  461. package/openspec/schemas/expert-delivery/templates/tasks.md +24 -24
  462. package/package.json +1 -1
  463. package/scripts/acceptance-zero-intrusion.sh +168 -168
  464. package/scripts/hub-sync-assets.config.example.json +296 -296
  465. package/scripts/hub-sync-assets.js +2038 -2038
  466. package/scripts/local-verify.sh +280 -280
  467. package/scripts/post-publish-auto-fix-check.js +404 -404
  468. package/scripts/post-publish-verify.sh +175 -175
  469. package/scripts/setup-cursor-manual-test.sh +107 -107
  470. package/scripts/setup-cursor-spec-archive-test.sh +111 -111
  471. package/scripts/setup-visual-integration.sh +225 -225
  472. package/scripts/test-integration.sh +176 -176
  473. package/scripts/update-test-project.sh +93 -93
  474. package/scripts/upload-four-web.sh +57 -57
  475. package/scripts/verify-install-ps1-bom.js +26 -26
  476. package/src/agent/agent-context.js +259 -259
  477. package/src/agent/agent-profile.js +185 -185
  478. package/src/agent/agent-templates.js +161 -161
  479. package/src/agent/agent-types.js +108 -108
  480. package/src/agent/collaboration-protocol.js +333 -333
  481. package/src/agent/conflict-handler.js +364 -364
  482. package/src/agent/file-permission.js +121 -121
  483. package/src/agent/index.js +38 -38
  484. package/src/agent/permission-audit.js +151 -151
  485. package/src/agent/review-repair-loop.js +270 -270
  486. package/src/agent/tool-permission.js +101 -101
  487. package/src/asset/asset-dependency.js +322 -322
  488. package/src/asset/asset-feedback.js +350 -350
  489. package/src/asset/asset-fork.js +300 -300
  490. package/src/asset/asset-install.js +278 -278
  491. package/src/asset/asset-installer.js +497 -497
  492. package/src/asset/asset-lifecycle.js +324 -324
  493. package/src/asset/asset-manager.js +245 -245
  494. package/src/asset/asset-package-manager.js +349 -349
  495. package/src/asset/asset-package.js +186 -186
  496. package/src/asset/asset-quality.js +262 -262
  497. package/src/asset/asset-registry.js +387 -387
  498. package/src/asset/asset-version.js +293 -293
  499. package/src/asset/index.js +86 -86
  500. package/src/cache/agent-profile-cache.js +59 -59
  501. package/src/cache/asset-cache.js +63 -63
  502. package/src/cache/global-cache.js +61 -61
  503. package/src/cache/manifest-cache.js +30 -30
  504. package/src/check/check-service.js +32 -32
  505. package/src/config/config-layer.js +343 -343
  506. package/src/config/config-loader.js +60 -60
  507. package/src/config/defaults.js +49 -49
  508. package/src/connectors/hub/asset-package.js +72 -72
  509. package/src/connectors/hub/asset-usage-feedback.js +46 -46
  510. package/src/connectors/hub/hub-connector.js +44 -44
  511. package/src/connectors/hub/index.js +21 -21
  512. package/src/connectors/visual/evidence-report.js +49 -49
  513. package/src/connectors/visual/index.js +15 -15
  514. package/src/connectors/visual/queue.js +41 -41
  515. package/src/connectors/visual/run-event.js +81 -81
  516. package/src/connectors/visual/visual-connector.js +77 -77
  517. package/src/context/context-budget.js +59 -59
  518. package/src/context/context-builder.js +285 -285
  519. package/src/context/context-loader.js +116 -116
  520. package/src/context/context-planner.js +158 -158
  521. package/src/context/types.js +96 -96
  522. package/src/contracts/index.js +63 -63
  523. package/src/executor/executor-registry.js +78 -78
  524. package/src/executor/executor-result-parser.js +44 -44
  525. package/src/executor/executor-runner.js +141 -141
  526. package/src/executor/executor-selector.js +139 -139
  527. package/src/executor/executor-timeout.js +36 -36
  528. package/src/executor/providers/base-provider-utils.js +189 -189
  529. package/src/executor/providers/claude-code-executor-provider.js +128 -128
  530. package/src/executor/providers/codex-executor-provider.js +126 -126
  531. package/src/executor/providers/cursor-executor-provider.js +99 -99
  532. package/src/executor/types.js +137 -137
  533. package/src/git/branch-manager.js +71 -71
  534. package/src/git/dirty-checker.js +43 -43
  535. package/src/git/dirty-strategy-handler.js +29 -29
  536. package/src/git/git-command.js +37 -37
  537. package/src/git/git-repository-detector.js +45 -45
  538. package/src/git/multi-repo-worktree-planner.js +88 -88
  539. package/src/git/policy.js +19 -19
  540. package/src/git/strategies/block-dirty-strategy.js +34 -34
  541. package/src/git/strategies/ignore-dirty-strategy.js +33 -33
  542. package/src/git/strategies/patch-snapshot-strategy.js +53 -53
  543. package/src/git/strategies/wip-commit-strategy.js +38 -38
  544. package/src/git/types.js +71 -71
  545. package/src/git/worktree-manager.js +85 -85
  546. package/src/governance/asset-review.js +351 -351
  547. package/src/governance/audit-log.js +368 -368
  548. package/src/governance/gray-release.js +312 -312
  549. package/src/governance/index.js +31 -31
  550. package/src/governance/policy-types.js +56 -56
  551. package/src/governance/rbac-types.js +171 -171
  552. package/src/governance/rbac.js +382 -382
  553. package/src/governance/rollback.js +360 -360
  554. package/src/governance/security-policy.js +354 -354
  555. package/src/hook/hook-config-writer.js +125 -125
  556. package/src/hub/hub-client.js +186 -186
  557. package/src/hub/hub-config.js +39 -39
  558. package/src/hub/project-facts.js +31 -31
  559. package/src/hub/runtime-feedback-reporter.js +55 -55
  560. package/src/ide/adapters/adapter-protocol.js +385 -385
  561. package/src/ide/adapters/claude-adapter.js +419 -419
  562. package/src/ide/adapters/codex-adapter.js +60 -60
  563. package/src/ide/adapters/cursor-adapter.js +484 -484
  564. package/src/ide/adapters/index.js +24 -24
  565. package/src/ide/anchors/markdown-anchor-writer.js +152 -152
  566. package/src/ide/ide-service.js +270 -270
  567. package/src/ide/ide-types.js +94 -94
  568. package/src/ide/links/link-mode-resolver.js +160 -160
  569. package/src/ide/registry/ide-registry-builder.js +165 -165
  570. package/src/incident/incident-writer.js +47 -47
  571. package/src/incident/types.js +22 -22
  572. package/src/init/ide-linker.js +126 -126
  573. package/src/init/ide-pointer-injector.js +75 -75
  574. package/src/init/init-applier.js +197 -197
  575. package/src/init/init-plan.js +294 -294
  576. package/src/init/init-service.js +65 -65
  577. package/src/init/manifest-installer.js +302 -302
  578. package/src/init/types.js +26 -26
  579. package/src/project/config-writer.js +83 -83
  580. package/src/project/context-index-writer.js +82 -82
  581. package/src/project/json-utils.js +72 -72
  582. package/src/project/local-state-writer.js +50 -50
  583. package/src/project/lock-file-writer.js +98 -98
  584. package/src/project/manifest-writer.js +126 -126
  585. package/src/project/policy-config-writer.js +91 -91
  586. package/src/project/project-config-writer.js +74 -74
  587. package/src/project/project-files.js +39 -39
  588. package/src/project/registry-index-writer.js +43 -43
  589. package/src/project/workspace-config-writer.js +63 -63
  590. package/src/run/index.js +11 -11
  591. package/src/run/run-id.js +32 -32
  592. package/src/run/run-service.js +269 -269
  593. package/src/run/run-store.js +80 -80
  594. package/src/scanner/aggregator/detection-aggregator.js +23 -23
  595. package/src/scanner/boundary/boundary-resolver.js +229 -229
  596. package/src/scanner/detectors/detector-registry.js +44 -44
  597. package/src/scanner/detectors/fastapi-detector.js +46 -46
  598. package/src/scanner/detectors/go-detector.js +46 -46
  599. package/src/scanner/detectors/nestjs-detector.js +57 -57
  600. package/src/scanner/detectors/nextjs-detector.js +52 -52
  601. package/src/scanner/detectors/react-vite-detector.js +52 -52
  602. package/src/scanner/detectors/react-webpack-detector.js +57 -57
  603. package/src/scanner/detectors/springboot-detector.js +46 -46
  604. package/src/scanner/detectors/springcloud-detector.js +46 -46
  605. package/src/scanner/detectors/springmvc-detector.js +46 -46
  606. package/src/scanner/detectors/vue-vite-detector.js +52 -52
  607. package/src/scanner/engine.js +72 -72
  608. package/src/scanner/facts/fact-extractor.js +211 -211
  609. package/src/scanner/types.js +30 -30
  610. package/src/security/asset-tamper-checker.js +188 -188
  611. package/src/security/checksum.js +40 -40
  612. package/src/spec/spec-writer.js +302 -302
  613. package/src/state-machine/circuit-breaker.js +112 -112
  614. package/src/state-machine/escape-hatch.js +49 -49
  615. package/src/state-machine/stage-runner.js +281 -281
  616. package/src/state-machine/state-machine.js +24 -24
  617. package/src/state-machine/transition-guard.js +36 -36
  618. package/src/state-machine/types.js +37 -37
  619. package/src/sync/sync-service.js +192 -192
  620. package/src/visual/agent-visual.js +142 -142
  621. package/src/visual/event-gateway.js +357 -357
  622. package/src/visual/event-mapper.js +128 -128
  623. package/src/visual/hook-dashboard.js +216 -216
  624. package/src/visual/index.js +27 -27
  625. package/src/visual/metrics.js +287 -287
  626. package/src/visual/privacy-filter.js +100 -100
  627. package/src/visual/risk-board.js +252 -252
  628. package/src/visual/timeline.js +245 -245
  629. package/src/visual/visual-client.js +94 -94
  630. package/src/visual/visual-config.js +40 -40
  631. package/src/visual/visual-reporter.js +88 -88
@@ -1,821 +1,821 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const runtimeState = require('./runtime-state');
4
- const { resolveRuntimePaths, getCandidatePaths } = require('./runtime-paths');
5
- const {
6
- getRoleRuntimeConfig,
7
- getFlowRuntimeConfig,
8
- resolveRuntimeProfileId,
9
- } = require('./runtime-registry');
10
-
11
- const AUTO_ADVANCE_EXECUTION_STATUSES = new Set(['done', 'success', 'completed']);
12
- const DEFAULT_REVIEW_POLICY = 'none';
13
-
14
- const FLOW_RUNTIME_TRANSITIONS = {
15
- 'prd-to-delivery': {
16
- 'requirement-analyst': {
17
- action: 'handoff',
18
- to_role: 'frontend-implementer',
19
- next_role: 'code-guardian',
20
- message: 'handoff to frontend-implementer after requirement convergence',
21
- },
22
- 'design-collaborator': {
23
- action: 'handoff',
24
- to_role: 'frontend-implementer',
25
- next_role: 'code-guardian',
26
- message: 'handoff to frontend-implementer after design collaboration',
27
- },
28
- 'api-contract-specialist': {
29
- action: 'handoff',
30
- to_role: 'frontend-implementer',
31
- next_role: 'code-guardian',
32
- message: 'handoff to frontend-implementer after API contract clarification',
33
- },
34
- 'frontend-implementer': {
35
- action: 'handoff',
36
- to_role: 'code-guardian',
37
- next_role: null,
38
- message: 'handoff to code-guardian after implementation delivery',
39
- },
40
- 'unit-test-specialist': {
41
- action: 'handoff',
42
- to_role: 'code-guardian',
43
- next_role: null,
44
- message: 'handoff to code-guardian after targeted test supplementation',
45
- },
46
- 'verification-reviewer': {
47
- action: 'handoff',
48
- to_role: 'code-guardian',
49
- next_role: null,
50
- message: 'handoff to code-guardian after verification review',
51
- },
52
- 'performance-auditor': {
53
- action: 'handoff',
54
- to_role: 'code-guardian',
55
- next_role: null,
56
- message: 'handoff to code-guardian after performance audit',
57
- },
58
- 'code-guardian': {
59
- action: 'gate-blocked',
60
- to_role: 'code-guardian',
61
- next_role: 'archive-change',
62
- pending_gate: 'before-archive',
63
- status: 'waiting-approval',
64
- message: 'waiting for user decision before archive-change closeout',
65
- },
66
- 'archive-change': {
67
- action: 'complete',
68
- to_role: 'archive-change',
69
- next_role: null,
70
- message: 'run completed after archive-change closeout',
71
- },
72
- },
73
- 'bugfix-to-verification': {
74
- 'frontend-implementer': {
75
- action: 'handoff',
76
- to_role: 'code-guardian',
77
- next_role: null,
78
- message: 'handoff to code-guardian after lightweight bugfix delivery',
79
- },
80
- 'unit-test-specialist': {
81
- action: 'handoff',
82
- to_role: 'code-guardian',
83
- next_role: null,
84
- message: 'handoff to code-guardian after lightweight test supplementation',
85
- },
86
- 'verification-reviewer': {
87
- action: 'handoff',
88
- to_role: 'code-guardian',
89
- next_role: null,
90
- message: 'handoff to code-guardian after lightweight verification review',
91
- },
92
- 'performance-auditor': {
93
- action: 'handoff',
94
- to_role: 'code-guardian',
95
- next_role: null,
96
- message: 'handoff to code-guardian after lightweight performance review',
97
- },
98
- 'code-guardian': {
99
- action: 'complete',
100
- to_role: 'code-guardian',
101
- next_role: null,
102
- message: 'run completed after lightweight verification closeout',
103
- },
104
- },
105
- };
106
-
107
- const ROLE_OPENSPEC_ACTIONS = {
108
- 'requirement-analyst': 'propose',
109
- 'frontend-implementer': 'apply',
110
- 'code-guardian': 'verify',
111
- 'archive-change': 'archive',
112
- };
113
-
114
- const ROLE_REQUIRED_INPUTS = {
115
- 'frontend-implementer': ['proposal', 'specs', 'design', 'tasks'],
116
- 'code-guardian': ['proposal', 'specs', 'design', 'tasks'],
117
- 'archive-change': ['proposal', 'specs', 'design', 'tasks', 'checklist', 'iterations'],
118
- };
119
-
120
- const ROLE_REQUIRED_OUTPUTS = {
121
- 'requirement-analyst': ['proposal', 'specs', 'design', 'tasks'],
122
- 'code-guardian': ['checklist', 'iterations'],
123
- };
124
-
125
- function normalizeReviewPolicy(value) {
126
- const normalized = String(value || '').trim().toLowerCase();
127
- return normalized === 'none' || normalized === 'main-flow-blocking'
128
- ? normalized
129
- : DEFAULT_REVIEW_POLICY;
130
- }
131
-
132
- function isMainFlowBlocking(currentRun, flowId) {
133
- return flowId === 'prd-to-delivery' && normalizeReviewPolicy(currentRun?.review_policy || currentRun?.plan?.review_policy || null) === 'main-flow-blocking';
134
- }
135
-
136
- const FLOW_ROLE_REQUIRED_INPUTS = {
137
- 'bugfix-to-verification': {
138
- 'frontend-implementer': [],
139
- 'code-guardian': ['bugfix', 'implementation_notes'],
140
- 'unit-test-specialist': ['bugfix', 'implementation_notes'],
141
- 'verification-reviewer': ['bugfix', 'implementation_notes'],
142
- 'performance-auditor': ['bugfix', 'implementation_notes'],
143
- },
144
- };
145
-
146
- const FLOW_ROLE_REQUIRED_OUTPUTS = {
147
- 'bugfix-to-verification': {
148
- 'frontend-implementer': ['bugfix', 'implementation_notes'],
149
- 'code-guardian': ['checklist', 'iterations'],
150
- },
151
- };
152
-
153
- function readJsonFile(filePath, label) {
154
- const raw = fs.readFileSync(filePath, 'utf8');
155
- try {
156
- return JSON.parse(raw);
157
- } catch (error) {
158
- throw new Error(`${label} is not valid JSON: ${filePath}`);
159
- }
160
- }
161
-
162
- function readCurrentRun(targetDir) {
163
- const runtimePaths = resolveRuntimePaths(targetDir);
164
- if (!fs.existsSync(runtimePaths.currentRun.path)) {
165
- return null;
166
- }
167
- return readJsonFile(runtimePaths.currentRun.path, 'current run-state');
168
- }
169
-
170
- function readCurrentExecution(targetDir) {
171
- const runtimePaths = resolveRuntimePaths(targetDir);
172
- for (const candidatePath of getCandidatePaths(runtimePaths.currentExecutionJson)) {
173
- if (fs.existsSync(candidatePath)) {
174
- return readJsonFile(candidatePath, 'current expert execution');
175
- }
176
- }
177
- return null;
178
- }
179
-
180
- function normalizeExecutionStatus(value) {
181
- return String(value || '').trim().toLowerCase();
182
- }
183
-
184
- function isCompletedExecutionStatus(value) {
185
- return AUTO_ADVANCE_EXECUTION_STATUSES.has(normalizeExecutionStatus(value));
186
- }
187
-
188
- function normalizeRuntimeAction(value) {
189
- const action = String(value || '').trim().toLowerCase();
190
- if (action === 'archive' || action === 'completed') {
191
- return 'complete';
192
- }
193
- if (action === 'blocked') {
194
- return 'gate-blocked';
195
- }
196
- return action;
197
- }
198
-
199
- function guardRuntimeActionForIncompleteExecution(targetDir, payload) {
200
- const runtimeAction = normalizeRuntimeAction(payload?.action || payload?.event);
201
- if (runtimeAction !== 'handoff' && runtimeAction !== 'complete') {
202
- return payload;
203
- }
204
-
205
- const currentExecution = readCurrentExecution(targetDir);
206
- if (!currentExecution) {
207
- return payload;
208
- }
209
-
210
- const status = normalizeExecutionStatus(currentExecution.status);
211
- if (isCompletedExecutionStatus(status)) {
212
- return payload;
213
- }
214
-
215
- const roleId = currentExecution.role?.id || payload?.from_role || payload?.to_role || null;
216
- if (!roleId) {
217
- return payload;
218
- }
219
-
220
- const originalToRole = payload?.to_role || payload?.toRole || null;
221
- const originalNextRole = payload?.next_role || payload?.nextRole || null;
222
- const nextRole = originalToRole && originalToRole !== roleId
223
- ? originalToRole
224
- : originalNextRole;
225
- const message = `当前专家状态为 ${status || 'unknown'},尚未达到 done / success / completed,已留在 ${roleId} 继续补齐后再交接。`;
226
-
227
- return {
228
- ...(payload || {}),
229
- schema_version: payload?.schema_version || 1,
230
- kind: 'task-orchestrator-runtime-action',
231
- action: 'handoff',
232
- run_id: payload?.run_id || currentExecution.run_id || null,
233
- from_role: payload?.from_role || currentExecution.role?.id || roleId,
234
- to_role: roleId,
235
- next_role: nextRole || null,
236
- status: 'running',
237
- clear_pending_gate: true,
238
- message,
239
- blocked_reason: payload?.blocked_reason || message,
240
- source: payload?.source || 'incomplete-execution-guard',
241
- verification: payload?.verification || currentExecution.verification || null,
242
- auto_fix: payload?.auto_fix || null,
243
- };
244
- }
245
-
246
- function loadPackageManifest(targetDir) {
247
- const packagePath = path.join(targetDir, 'package.json');
248
- if (!fs.existsSync(packagePath)) {
249
- return null;
250
- }
251
- return readJsonFile(packagePath, 'package manifest');
252
- }
253
-
254
- function hasDependency(pkg, names) {
255
- if (!pkg) {
256
- return false;
257
- }
258
- const deps = {
259
- ...(pkg.dependencies || {}),
260
- ...(pkg.devDependencies || {}),
261
- ...(pkg.peerDependencies || {}),
262
- };
263
- return names.some((name) => Object.prototype.hasOwnProperty.call(deps, name));
264
- }
265
-
266
- function detectProjectProfile(targetDir) {
267
- const manifestPath = path.join(targetDir, '.ai-spec', 'manifest.json');
268
- if (fs.existsSync(manifestPath)) {
269
- try {
270
- const manifest = readJsonFile(manifestPath, 'runtime manifest');
271
- const manifestProfile = resolveRuntimeProfileId(targetDir, manifest?.profile);
272
- if (manifestProfile) {
273
- return manifestProfile;
274
- }
275
- } catch (_error) {
276
- // ignore invalid manifest and continue with package detection
277
- }
278
- }
279
-
280
- const pkg = loadPackageManifest(targetDir);
281
- if (hasDependency(pkg, ['vue', 'vue-router', 'pinia'])) {
282
- return 'vue';
283
- }
284
- if (hasDependency(pkg, ['react', 'react-dom', 'react-router-dom'])) {
285
- return 'react';
286
- }
287
- return 'default';
288
- }
289
-
290
- function resolveTransitionRoleValue(targetDir, transition, field) {
291
- const raw = transition?.[field];
292
- if (raw !== 'resolve-from-profile') {
293
- return raw || null;
294
- }
295
-
296
- const projectProfile = detectProjectProfile(targetDir);
297
- const profileMap = transition?.[`${field}_by_profile`];
298
- if (profileMap && typeof profileMap === 'object' && !Array.isArray(profileMap)) {
299
- return profileMap[projectProfile] || null;
300
- }
301
-
302
- return null;
303
- }
304
-
305
- function listMarkdownBullets(content) {
306
- return content
307
- .split('\n')
308
- .map((line) => line.trim())
309
- .filter((line) => /^[-*]\s+/.test(line) || /^\d+\.\s+/.test(line));
310
- }
311
-
312
- function normalizeStringList(value) {
313
- if (!Array.isArray(value)) {
314
- return [];
315
- }
316
- return value.map((item) => String(item || '').trim()).filter(Boolean);
317
- }
318
-
319
- function trimExcerpt(value, maxLength = 240) {
320
- const text = String(value || '').trim();
321
- if (!text) {
322
- return null;
323
- }
324
- return text.length > maxLength ? `${text.slice(0, maxLength)}...` : text;
325
- }
326
-
327
- function normalizeAutoFixState(value) {
328
- const merged = value && typeof value === 'object'
329
- ? value
330
- : {};
331
- const maxAttempts = Number.isFinite(Number(merged.max_attempts))
332
- ? Math.max(1, Number(merged.max_attempts))
333
- : 1;
334
- const attempts = Number.isFinite(Number(merged.attempts))
335
- ? Math.max(0, Math.min(Number(merged.attempts), maxAttempts))
336
- : 0;
337
- const lastFailedSteps = Array.isArray(merged.last_failed_steps)
338
- ? merged.last_failed_steps
339
- .map((step) => ({
340
- name: typeof step?.name === 'string' && step.name.trim() ? step.name.trim() : 'unknown',
341
- status: typeof step?.status === 'string' && step.status.trim() ? step.status.trim() : null,
342
- command: typeof step?.command === 'string' && step.command.trim() ? step.command.trim() : null,
343
- exit_code: typeof step?.exit_code === 'number' ? step.exit_code : null,
344
- reason: typeof step?.reason === 'string' && step.reason.trim() ? step.reason.trim() : null,
345
- error: typeof step?.error === 'string' && step.error.trim() ? step.error.trim() : null,
346
- stdout_excerpt: trimExcerpt(step?.stdout_excerpt),
347
- stderr_excerpt: trimExcerpt(step?.stderr_excerpt),
348
- }))
349
- .filter(Boolean)
350
- : [];
351
-
352
- return {
353
- attempts,
354
- max_attempts: maxAttempts,
355
- active: Boolean(merged.active),
356
- last_failed_steps: lastFailedSteps,
357
- };
358
- }
359
-
360
- function extractFailedVerificationSteps(verification) {
361
- if (!verification || !Array.isArray(verification.steps)) {
362
- return [];
363
- }
364
-
365
- return verification.steps
366
- .filter((step) => String(step?.status || '').trim().toLowerCase() === 'failed')
367
- .map((step) => ({
368
- name: typeof step?.name === 'string' && step.name.trim() ? step.name.trim() : 'unknown',
369
- status: 'failed',
370
- command: typeof step?.command === 'string' && step.command.trim() ? step.command.trim() : null,
371
- exit_code: typeof step?.exit_code === 'number' ? step.exit_code : null,
372
- reason: typeof step?.reason === 'string' && step.reason.trim() ? step.reason.trim() : null,
373
- error: typeof step?.error === 'string' && step.error.trim() ? step.error.trim() : null,
374
- stdout_excerpt: trimExcerpt(step?.stdout_excerpt),
375
- stderr_excerpt: trimExcerpt(step?.stderr_excerpt),
376
- }));
377
- }
378
-
379
- function listMarkdownFilesRecursive(rootDir) {
380
- if (!rootDir || !fs.existsSync(rootDir)) {
381
- return [];
382
- }
383
-
384
- const rootStat = fs.statSync(rootDir);
385
- if (!rootStat.isDirectory()) {
386
- return rootDir.endsWith('.md') ? [rootDir] : [];
387
- }
388
-
389
- const files = [];
390
- const stack = [rootDir];
391
- while (stack.length > 0) {
392
- const current = stack.pop();
393
- const entries = fs.readdirSync(current, { withFileTypes: true });
394
- for (const entry of entries) {
395
- const nextPath = path.join(current, entry.name);
396
- if (entry.isDirectory()) {
397
- stack.push(nextPath);
398
- } else if (entry.isFile() && entry.name.endsWith('.md')) {
399
- files.push(nextPath);
400
- }
401
- }
402
- }
403
-
404
- return files.sort();
405
- }
406
-
407
- function readMarkdownArtifactContent(artifactPath) {
408
- if (!artifactPath || !fs.existsSync(artifactPath)) {
409
- return {
410
- files: [],
411
- content: '',
412
- };
413
- }
414
-
415
- const files = listMarkdownFilesRecursive(artifactPath);
416
- return {
417
- files,
418
- content: files
419
- .map((filePath) => fs.readFileSync(filePath, 'utf8').trim())
420
- .filter(Boolean)
421
- .join('\n\n'),
422
- };
423
- }
424
-
425
- function getRoleArtifactRequirements(targetDir, roleId, flowId = null) {
426
- const flowRequiredInputs = normalizeStringList(FLOW_ROLE_REQUIRED_INPUTS[flowId]?.[roleId]);
427
- const flowRequiredOutputs = normalizeStringList(FLOW_ROLE_REQUIRED_OUTPUTS[flowId]?.[roleId]);
428
- if (flowRequiredInputs.length > 0 || flowRequiredOutputs.length > 0) {
429
- return {
430
- required_inputs: flowRequiredInputs,
431
- required_outputs: flowRequiredOutputs,
432
- };
433
- }
434
-
435
- const registryEntry = getRoleRuntimeConfig(targetDir, roleId);
436
- const requiredInputs = normalizeStringList(registryEntry?.required_inputs);
437
- const requiredOutputs = normalizeStringList(registryEntry?.required_outputs);
438
-
439
- return {
440
- required_inputs: requiredInputs.length > 0 ? requiredInputs : (ROLE_REQUIRED_INPUTS[roleId] || []),
441
- required_outputs: requiredOutputs.length > 0 ? requiredOutputs : (ROLE_REQUIRED_OUTPUTS[roleId] || []),
442
- };
443
- }
444
-
445
- function inferExecutionOpenSpecAction(payload, targetDir = null) {
446
- if (payload?.openspec_action) {
447
- return String(payload.openspec_action).trim().toLowerCase();
448
- }
449
-
450
- if (targetDir && payload?.role?.id) {
451
- const registryEntry = getRoleRuntimeConfig(targetDir, payload.role.id);
452
- const configuredActions = normalizeStringList(registryEntry?.openspec_actions);
453
- if (configuredActions.length > 0) {
454
- return configuredActions[0].toLowerCase();
455
- }
456
- }
457
-
458
- return ROLE_OPENSPEC_ACTIONS[payload?.role?.id] || null;
459
- }
460
-
461
- function inferRuntimeActionOpenSpecAction(payload) {
462
- if (payload?.openspec_action) {
463
- return String(payload.openspec_action).trim().toLowerCase();
464
- }
465
-
466
- const action = String(payload?.action || '').trim().toLowerCase();
467
- if (action === 'archive' || action === 'complete' || action === 'completed') {
468
- return 'archive';
469
- }
470
-
471
- return null;
472
- }
473
-
474
- function validatePreImplementationGate(targetDir, currentRun, executionPayload) {
475
- if (!currentRun || currentRun.flow?.id !== 'prd-to-delivery') {
476
- return { ok: true, reasons: [] };
477
- }
478
-
479
- if (executionPayload.role?.id !== 'requirement-analyst') {
480
- return { ok: true, reasons: [] };
481
- }
482
-
483
- const deliveryProfile = currentRun.delivery_profile || 'standard';
484
- const riskLevel = String(currentRun.task?.risk_level || '').trim().toLowerCase();
485
- const rawInput = String(currentRun.trigger?.raw_input || '');
486
- const proposalPath = currentRun.artifacts?.proposal
487
- ? path.join(targetDir, currentRun.artifacts.proposal)
488
- : null;
489
- const specsPath = currentRun.artifacts?.specs
490
- ? path.join(targetDir, runtimeState.normalizeSpecsArtifactPath(currentRun.artifacts.specs))
491
- : null;
492
- const designPath = currentRun.artifacts?.design
493
- ? path.join(targetDir, currentRun.artifacts.design)
494
- : null;
495
- const tasksPath = currentRun.artifacts?.tasks
496
- ? path.join(targetDir, currentRun.artifacts.tasks)
497
- : null;
498
- const reasons = [];
499
-
500
- if (!proposalPath || !fs.existsSync(proposalPath)) {
501
- reasons.push('proposal.md 缺失');
502
- }
503
- if (!specsPath || !fs.existsSync(specsPath)) {
504
- reasons.push('specs/ 缺失');
505
- }
506
- if (!designPath || !fs.existsSync(designPath)) {
507
- reasons.push('design.md 缺失');
508
- }
509
- if (!tasksPath || !fs.existsSync(tasksPath)) {
510
- reasons.push('tasks.md 缺失');
511
- }
512
-
513
- if (reasons.length > 0) {
514
- return { ok: false, reasons };
515
- }
516
-
517
- const proposalContent = fs.readFileSync(proposalPath, 'utf8').trim();
518
- const specsArtifact = readMarkdownArtifactContent(specsPath);
519
- const designContent = fs.readFileSync(designPath, 'utf8').trim();
520
- const tasksContent = fs.readFileSync(tasksPath, 'utf8').trim();
521
- const taskItems = listMarkdownBullets(tasksContent);
522
-
523
- if (specsArtifact.files.length === 0) {
524
- reasons.push('specs/ 缺少 spec 文件');
525
- }
526
-
527
- if (riskLevel === 'high') {
528
- reasons.push('当前任务涉及支付/认证/安全/合规等高风险领域,进入实现前必须人工审批');
529
- }
530
-
531
- if (/先不说|先不提供|暂不说|暂不提供|暂未确定|未明确|待定|后续再说|后面再说/.test(rawInput)) {
532
- reasons.push('原始需求已明确存在未说明的关键流程或安全约束,进入实现前必须人工审批');
533
- }
534
-
535
- const missingInputs = Array.isArray(currentRun.missing_inputs)
536
- ? currentRun.missing_inputs.map((item) => String(item || ''))
537
- : [];
538
- if (
539
- riskLevel === 'high' &&
540
- missingInputs.some((item) => /支付|认证|oauth|短信|权限|安全|合规|风控|收款|交易/.test(item))
541
- ) {
542
- reasons.push('高风险任务仍存在关键缺失输入,进入实现前必须人工审批');
543
- }
544
-
545
- if (deliveryProfile === 'micro') {
546
- if (proposalContent.length < 60) {
547
- reasons.push('proposal.md 过短,未达到 compact 最小信息量');
548
- }
549
- if (specsArtifact.content.length < 40) {
550
- reasons.push('specs/ 过短,未达到 compact 最小信息量');
551
- }
552
- if (designContent.length < 40) {
553
- reasons.push('design.md 过短,未达到 compact 最小信息量');
554
- }
555
- if (taskItems.length < 3) {
556
- reasons.push('tasks.md 任务条目不足 3 条');
557
- }
558
- } else {
559
- const headingCount = proposalContent
560
- .split('\n')
561
- .filter((line) => /^#{1,6}\s+/.test(line.trim()))
562
- .length;
563
- if (proposalContent.length < 120) {
564
- reasons.push('proposal.md 过短,未达到 standard 最小信息量');
565
- }
566
- if (specsArtifact.content.length < 80) {
567
- reasons.push('specs/ 过短,未达到 standard 最小信息量');
568
- }
569
- if (designContent.length < 80) {
570
- reasons.push('design.md 过短,未达到 standard 最小信息量');
571
- }
572
- if (headingCount < 2) {
573
- reasons.push('proposal.md 缺少足够的小节结构');
574
- }
575
- if (taskItems.length < 4) {
576
- reasons.push('tasks.md 任务条目不足 4 条');
577
- }
578
- }
579
-
580
- return {
581
- ok: reasons.length === 0,
582
- reasons,
583
- };
584
- }
585
-
586
- function getRuntimeTransition(targetDir, flowId, roleId) {
587
- const flowConfig = getFlowRuntimeConfig(targetDir, flowId);
588
- const flowTransition = flowConfig?.runtime_transitions?.[roleId];
589
- if (flowTransition && typeof flowTransition === 'object' && flowTransition.action) {
590
- return {
591
- ...flowTransition,
592
- to_role: resolveTransitionRoleValue(targetDir, flowTransition, 'to_role'),
593
- next_role: resolveTransitionRoleValue(targetDir, flowTransition, 'next_role'),
594
- };
595
- }
596
-
597
- const roleConfig = getRoleRuntimeConfig(targetDir, roleId);
598
- const roleTransition = roleConfig?.runtime_transition;
599
- if (roleTransition && typeof roleTransition === 'object' && roleTransition.action) {
600
- return {
601
- ...roleTransition,
602
- to_role: resolveTransitionRoleValue(targetDir, roleTransition, 'to_role'),
603
- next_role: resolveTransitionRoleValue(targetDir, roleTransition, 'next_role'),
604
- };
605
- }
606
-
607
- return FLOW_RUNTIME_TRANSITIONS[flowId]?.[roleId] || null;
608
- }
609
-
610
- function buildAutoRuntimeAction(targetDir, executionPayload) {
611
- const currentRun = readCurrentRun(targetDir);
612
- if (!currentRun) {
613
- return null;
614
- }
615
-
616
- if (!AUTO_ADVANCE_EXECUTION_STATUSES.has(String(executionPayload.status || '').toLowerCase())) {
617
- return null;
618
- }
619
-
620
- if (currentRun.pending_gate) {
621
- return null;
622
- }
623
-
624
- const flowId = executionPayload.flow?.id || currentRun.flow?.id || null;
625
- const roleId = executionPayload.role?.id || null;
626
- if (!flowId || !roleId) {
627
- return null;
628
- }
629
- const mainFlowBlocking = isMainFlowBlocking(currentRun, flowId);
630
-
631
- const transition = getRuntimeTransition(targetDir, flowId, roleId);
632
- if (!transition) {
633
- return null;
634
- }
635
-
636
- if (roleId === 'frontend-implementer') {
637
- const verification = executionPayload.verification || currentRun.verification || null;
638
- const failedSteps = extractFailedVerificationSteps(verification);
639
- const autoFixState = normalizeAutoFixState(currentRun.auto_fix);
640
-
641
- if (failedSteps.length > 0) {
642
- if (autoFixState.attempts < autoFixState.max_attempts) {
643
- const nextAttempts = autoFixState.attempts + 1;
644
- return {
645
- schema_version: 1,
646
- kind: 'task-orchestrator-runtime-action',
647
- action: 'handoff',
648
- run_id: executionPayload.run_id,
649
- from_role: roleId,
650
- to_role: roleId,
651
- next_role: transition.to_role || 'code-guardian',
652
- status: 'running',
653
- clear_pending_gate: true,
654
- message: `verification failed; retry frontend-implementer auto-fix (${nextAttempts}/${autoFixState.max_attempts})`,
655
- source: 'expert-executor-auto-transition',
656
- verification,
657
- auto_fix: {
658
- attempts: nextAttempts,
659
- max_attempts: autoFixState.max_attempts,
660
- active: true,
661
- last_failed_steps: failedSteps,
662
- },
663
- };
664
- }
665
-
666
- return {
667
- schema_version: 1,
668
- kind: 'task-orchestrator-runtime-action',
669
- action: 'handoff',
670
- run_id: executionPayload.run_id,
671
- from_role: roleId,
672
- to_role: transition.to_role || 'code-guardian',
673
- next_role: transition.next_role || null,
674
- status: 'running',
675
- clear_pending_gate: true,
676
- message: 'verification still failed after auto-fix; handoff to code-guardian for blocking review',
677
- source: 'expert-executor-auto-transition',
678
- verification,
679
- auto_fix: {
680
- attempts: autoFixState.attempts,
681
- max_attempts: autoFixState.max_attempts,
682
- active: false,
683
- last_failed_steps: failedSteps,
684
- },
685
- };
686
- }
687
- }
688
-
689
- if (transition.action === 'handoff' && roleId === 'requirement-analyst') {
690
- const gateCheck = validatePreImplementationGate(targetDir, currentRun, executionPayload);
691
- if (mainFlowBlocking || !gateCheck.ok) {
692
- const blockedReason = gateCheck.ok
693
- ? '内测阶段启用 main-flow-blocking 审核策略,需求收敛完成后需要先人工审核再进入实现。'
694
- : gateCheck.reasons.join(';');
695
- return {
696
- schema_version: 1,
697
- kind: 'task-orchestrator-runtime-action',
698
- action: 'gate-blocked',
699
- run_id: executionPayload.run_id,
700
- from_role: roleId,
701
- to_role: roleId,
702
- next_role: transition.to_role,
703
- pending_gate: 'before-implementation',
704
- blocked_by_role: roleId,
705
- resume_to_role: transition.to_role || null,
706
- required_user_action: '明确批准或拒绝当前 proposal / specs / design / tasks 的实现范围与限制条件。',
707
- blocked_reason: blockedReason,
708
- status: 'waiting-approval',
709
- clear_pending_gate: false,
710
- message: `requirement gate blocked: ${blockedReason}`,
711
- source: 'expert-executor-auto-transition',
712
- };
713
- }
714
- }
715
-
716
- if (transition.action === 'handoff' && roleId === 'frontend-implementer' && mainFlowBlocking) {
717
- return {
718
- schema_version: 1,
719
- kind: 'task-orchestrator-runtime-action',
720
- action: 'gate-blocked',
721
- run_id: executionPayload.run_id,
722
- from_role: roleId,
723
- to_role: roleId,
724
- next_role: transition.to_role || 'code-guardian',
725
- pending_gate: 'before-guardian',
726
- blocked_by_role: roleId,
727
- resume_to_role: transition.to_role || 'code-guardian',
728
- required_user_action: '明确批准当前实现结果进入 code-guardian 守护审查,或说明需要回退修正的方向。',
729
- blocked_reason: '内测阶段启用 main-flow-blocking 审核策略,前端实现完成后需要先人工审核再进入守护阶段。',
730
- status: 'waiting-approval',
731
- clear_pending_gate: false,
732
- message: 'frontend delivery is waiting for manual review before code-guardian',
733
- source: 'expert-executor-auto-transition',
734
- verification: executionPayload.verification || null,
735
- };
736
- }
737
-
738
- if (transition.action === 'gate-blocked' && roleId === 'code-guardian' && !mainFlowBlocking) {
739
- return {
740
- schema_version: 1,
741
- kind: 'task-orchestrator-runtime-action',
742
- action: 'handoff',
743
- run_id: executionPayload.run_id,
744
- from_role: roleId,
745
- to_role: transition.next_role || 'archive-change',
746
- next_role: null,
747
- status: 'running',
748
- clear_pending_gate: true,
749
- message: 'handoff to archive-change after code-guardian closeout',
750
- source: 'expert-executor-auto-transition',
751
- };
752
- }
753
-
754
- if (transition.action === 'gate-blocked') {
755
- return {
756
- schema_version: 1,
757
- kind: 'task-orchestrator-runtime-action',
758
- action: 'gate-blocked',
759
- run_id: executionPayload.run_id,
760
- from_role: roleId,
761
- to_role: transition.to_role || roleId,
762
- next_role: transition.next_role || null,
763
- pending_gate: transition.pending_gate || 'before-archive',
764
- blocked_by_role: roleId,
765
- resume_to_role: transition.next_role || null,
766
- required_user_action: '明确告诉系统是否执行归档;同意则进入归档专家,不归档则直接结束本次运行。',
767
- blocked_reason: executionPayload.next_action || transition.message,
768
- status: transition.status || 'waiting-approval',
769
- clear_pending_gate: false,
770
- message: executionPayload.next_action || transition.message,
771
- source: 'expert-executor-auto-transition',
772
- };
773
- }
774
-
775
- const nextRole = executionPayload.next_role !== undefined
776
- ? executionPayload.next_role
777
- : transition.next_role;
778
- const toRole = executionPayload.next_role || transition.to_role || null;
779
- const action = transition.action;
780
- const currentAutoFix = roleId === 'frontend-implementer'
781
- ? normalizeAutoFixState(currentRun.auto_fix)
782
- : null;
783
- const normalizedAutoFix = currentAutoFix && (currentAutoFix.active || currentAutoFix.attempts > 0 || currentAutoFix.last_failed_steps.length > 0)
784
- ? {
785
- ...currentAutoFix,
786
- active: false,
787
- }
788
- : null;
789
-
790
- return {
791
- schema_version: 1,
792
- kind: 'task-orchestrator-runtime-action',
793
- action,
794
- run_id: executionPayload.run_id,
795
- from_role: roleId,
796
- to_role: action === 'handoff' ? toRole : transition.to_role || roleId,
797
- next_role: nextRole,
798
- status: action === 'complete' ? 'success' : 'running',
799
- clear_pending_gate: true,
800
- message: executionPayload.next_action || transition.message,
801
- source: 'expert-executor-auto-transition',
802
- openspec_action: action === 'complete' ? 'archive' : null,
803
- skip_artifact_check: action === 'complete' && roleId === 'archive-change',
804
- verification: executionPayload.verification || null,
805
- auto_fix: normalizedAutoFix,
806
- };
807
- }
808
-
809
- module.exports = {
810
- AUTO_ADVANCE_EXECUTION_STATUSES,
811
- FLOW_RUNTIME_TRANSITIONS,
812
- ROLE_OPENSPEC_ACTIONS,
813
- getRoleArtifactRequirements,
814
- getRuntimeTransition,
815
- inferExecutionOpenSpecAction,
816
- inferRuntimeActionOpenSpecAction,
817
- validatePreImplementationGate,
818
- guardRuntimeActionForIncompleteExecution,
819
- buildAutoRuntimeAction,
820
- readCurrentRun,
821
- };
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const runtimeState = require('./runtime-state');
4
+ const { resolveRuntimePaths, getCandidatePaths } = require('./runtime-paths');
5
+ const {
6
+ getRoleRuntimeConfig,
7
+ getFlowRuntimeConfig,
8
+ resolveRuntimeProfileId,
9
+ } = require('./runtime-registry');
10
+
11
+ const AUTO_ADVANCE_EXECUTION_STATUSES = new Set(['done', 'success', 'completed']);
12
+ const DEFAULT_REVIEW_POLICY = 'none';
13
+
14
+ const FLOW_RUNTIME_TRANSITIONS = {
15
+ 'prd-to-delivery': {
16
+ 'requirement-analyst': {
17
+ action: 'handoff',
18
+ to_role: 'frontend-implementer',
19
+ next_role: 'code-guardian',
20
+ message: 'handoff to frontend-implementer after requirement convergence',
21
+ },
22
+ 'design-collaborator': {
23
+ action: 'handoff',
24
+ to_role: 'frontend-implementer',
25
+ next_role: 'code-guardian',
26
+ message: 'handoff to frontend-implementer after design collaboration',
27
+ },
28
+ 'api-contract-specialist': {
29
+ action: 'handoff',
30
+ to_role: 'frontend-implementer',
31
+ next_role: 'code-guardian',
32
+ message: 'handoff to frontend-implementer after API contract clarification',
33
+ },
34
+ 'frontend-implementer': {
35
+ action: 'handoff',
36
+ to_role: 'code-guardian',
37
+ next_role: null,
38
+ message: 'handoff to code-guardian after implementation delivery',
39
+ },
40
+ 'unit-test-specialist': {
41
+ action: 'handoff',
42
+ to_role: 'code-guardian',
43
+ next_role: null,
44
+ message: 'handoff to code-guardian after targeted test supplementation',
45
+ },
46
+ 'verification-reviewer': {
47
+ action: 'handoff',
48
+ to_role: 'code-guardian',
49
+ next_role: null,
50
+ message: 'handoff to code-guardian after verification review',
51
+ },
52
+ 'performance-auditor': {
53
+ action: 'handoff',
54
+ to_role: 'code-guardian',
55
+ next_role: null,
56
+ message: 'handoff to code-guardian after performance audit',
57
+ },
58
+ 'code-guardian': {
59
+ action: 'gate-blocked',
60
+ to_role: 'code-guardian',
61
+ next_role: 'archive-change',
62
+ pending_gate: 'before-archive',
63
+ status: 'waiting-approval',
64
+ message: 'waiting for user decision before archive-change closeout',
65
+ },
66
+ 'archive-change': {
67
+ action: 'complete',
68
+ to_role: 'archive-change',
69
+ next_role: null,
70
+ message: 'run completed after archive-change closeout',
71
+ },
72
+ },
73
+ 'bugfix-to-verification': {
74
+ 'frontend-implementer': {
75
+ action: 'handoff',
76
+ to_role: 'code-guardian',
77
+ next_role: null,
78
+ message: 'handoff to code-guardian after lightweight bugfix delivery',
79
+ },
80
+ 'unit-test-specialist': {
81
+ action: 'handoff',
82
+ to_role: 'code-guardian',
83
+ next_role: null,
84
+ message: 'handoff to code-guardian after lightweight test supplementation',
85
+ },
86
+ 'verification-reviewer': {
87
+ action: 'handoff',
88
+ to_role: 'code-guardian',
89
+ next_role: null,
90
+ message: 'handoff to code-guardian after lightweight verification review',
91
+ },
92
+ 'performance-auditor': {
93
+ action: 'handoff',
94
+ to_role: 'code-guardian',
95
+ next_role: null,
96
+ message: 'handoff to code-guardian after lightweight performance review',
97
+ },
98
+ 'code-guardian': {
99
+ action: 'complete',
100
+ to_role: 'code-guardian',
101
+ next_role: null,
102
+ message: 'run completed after lightweight verification closeout',
103
+ },
104
+ },
105
+ };
106
+
107
+ const ROLE_OPENSPEC_ACTIONS = {
108
+ 'requirement-analyst': 'propose',
109
+ 'frontend-implementer': 'apply',
110
+ 'code-guardian': 'verify',
111
+ 'archive-change': 'archive',
112
+ };
113
+
114
+ const ROLE_REQUIRED_INPUTS = {
115
+ 'frontend-implementer': ['proposal', 'specs', 'design', 'tasks'],
116
+ 'code-guardian': ['proposal', 'specs', 'design', 'tasks'],
117
+ 'archive-change': ['proposal', 'specs', 'design', 'tasks', 'checklist', 'iterations'],
118
+ };
119
+
120
+ const ROLE_REQUIRED_OUTPUTS = {
121
+ 'requirement-analyst': ['proposal', 'specs', 'design', 'tasks'],
122
+ 'code-guardian': ['checklist', 'iterations'],
123
+ };
124
+
125
+ function normalizeReviewPolicy(value) {
126
+ const normalized = String(value || '').trim().toLowerCase();
127
+ return normalized === 'none' || normalized === 'main-flow-blocking'
128
+ ? normalized
129
+ : DEFAULT_REVIEW_POLICY;
130
+ }
131
+
132
+ function isMainFlowBlocking(currentRun, flowId) {
133
+ return flowId === 'prd-to-delivery' && normalizeReviewPolicy(currentRun?.review_policy || currentRun?.plan?.review_policy || null) === 'main-flow-blocking';
134
+ }
135
+
136
+ const FLOW_ROLE_REQUIRED_INPUTS = {
137
+ 'bugfix-to-verification': {
138
+ 'frontend-implementer': [],
139
+ 'code-guardian': ['bugfix', 'implementation_notes'],
140
+ 'unit-test-specialist': ['bugfix', 'implementation_notes'],
141
+ 'verification-reviewer': ['bugfix', 'implementation_notes'],
142
+ 'performance-auditor': ['bugfix', 'implementation_notes'],
143
+ },
144
+ };
145
+
146
+ const FLOW_ROLE_REQUIRED_OUTPUTS = {
147
+ 'bugfix-to-verification': {
148
+ 'frontend-implementer': ['bugfix', 'implementation_notes'],
149
+ 'code-guardian': ['checklist', 'iterations'],
150
+ },
151
+ };
152
+
153
+ function readJsonFile(filePath, label) {
154
+ const raw = fs.readFileSync(filePath, 'utf8');
155
+ try {
156
+ return JSON.parse(raw);
157
+ } catch (error) {
158
+ throw new Error(`${label} is not valid JSON: ${filePath}`);
159
+ }
160
+ }
161
+
162
+ function readCurrentRun(targetDir) {
163
+ const runtimePaths = resolveRuntimePaths(targetDir);
164
+ if (!fs.existsSync(runtimePaths.currentRun.path)) {
165
+ return null;
166
+ }
167
+ return readJsonFile(runtimePaths.currentRun.path, 'current run-state');
168
+ }
169
+
170
+ function readCurrentExecution(targetDir) {
171
+ const runtimePaths = resolveRuntimePaths(targetDir);
172
+ for (const candidatePath of getCandidatePaths(runtimePaths.currentExecutionJson)) {
173
+ if (fs.existsSync(candidatePath)) {
174
+ return readJsonFile(candidatePath, 'current expert execution');
175
+ }
176
+ }
177
+ return null;
178
+ }
179
+
180
+ function normalizeExecutionStatus(value) {
181
+ return String(value || '').trim().toLowerCase();
182
+ }
183
+
184
+ function isCompletedExecutionStatus(value) {
185
+ return AUTO_ADVANCE_EXECUTION_STATUSES.has(normalizeExecutionStatus(value));
186
+ }
187
+
188
+ function normalizeRuntimeAction(value) {
189
+ const action = String(value || '').trim().toLowerCase();
190
+ if (action === 'archive' || action === 'completed') {
191
+ return 'complete';
192
+ }
193
+ if (action === 'blocked') {
194
+ return 'gate-blocked';
195
+ }
196
+ return action;
197
+ }
198
+
199
+ function guardRuntimeActionForIncompleteExecution(targetDir, payload) {
200
+ const runtimeAction = normalizeRuntimeAction(payload?.action || payload?.event);
201
+ if (runtimeAction !== 'handoff' && runtimeAction !== 'complete') {
202
+ return payload;
203
+ }
204
+
205
+ const currentExecution = readCurrentExecution(targetDir);
206
+ if (!currentExecution) {
207
+ return payload;
208
+ }
209
+
210
+ const status = normalizeExecutionStatus(currentExecution.status);
211
+ if (isCompletedExecutionStatus(status)) {
212
+ return payload;
213
+ }
214
+
215
+ const roleId = currentExecution.role?.id || payload?.from_role || payload?.to_role || null;
216
+ if (!roleId) {
217
+ return payload;
218
+ }
219
+
220
+ const originalToRole = payload?.to_role || payload?.toRole || null;
221
+ const originalNextRole = payload?.next_role || payload?.nextRole || null;
222
+ const nextRole = originalToRole && originalToRole !== roleId
223
+ ? originalToRole
224
+ : originalNextRole;
225
+ const message = `当前专家状态为 ${status || 'unknown'},尚未达到 done / success / completed,已留在 ${roleId} 继续补齐后再交接。`;
226
+
227
+ return {
228
+ ...(payload || {}),
229
+ schema_version: payload?.schema_version || 1,
230
+ kind: 'task-orchestrator-runtime-action',
231
+ action: 'handoff',
232
+ run_id: payload?.run_id || currentExecution.run_id || null,
233
+ from_role: payload?.from_role || currentExecution.role?.id || roleId,
234
+ to_role: roleId,
235
+ next_role: nextRole || null,
236
+ status: 'running',
237
+ clear_pending_gate: true,
238
+ message,
239
+ blocked_reason: payload?.blocked_reason || message,
240
+ source: payload?.source || 'incomplete-execution-guard',
241
+ verification: payload?.verification || currentExecution.verification || null,
242
+ auto_fix: payload?.auto_fix || null,
243
+ };
244
+ }
245
+
246
+ function loadPackageManifest(targetDir) {
247
+ const packagePath = path.join(targetDir, 'package.json');
248
+ if (!fs.existsSync(packagePath)) {
249
+ return null;
250
+ }
251
+ return readJsonFile(packagePath, 'package manifest');
252
+ }
253
+
254
+ function hasDependency(pkg, names) {
255
+ if (!pkg) {
256
+ return false;
257
+ }
258
+ const deps = {
259
+ ...(pkg.dependencies || {}),
260
+ ...(pkg.devDependencies || {}),
261
+ ...(pkg.peerDependencies || {}),
262
+ };
263
+ return names.some((name) => Object.prototype.hasOwnProperty.call(deps, name));
264
+ }
265
+
266
+ function detectProjectProfile(targetDir) {
267
+ const manifestPath = path.join(targetDir, '.ai-spec', 'manifest.json');
268
+ if (fs.existsSync(manifestPath)) {
269
+ try {
270
+ const manifest = readJsonFile(manifestPath, 'runtime manifest');
271
+ const manifestProfile = resolveRuntimeProfileId(targetDir, manifest?.profile);
272
+ if (manifestProfile) {
273
+ return manifestProfile;
274
+ }
275
+ } catch (_error) {
276
+ // ignore invalid manifest and continue with package detection
277
+ }
278
+ }
279
+
280
+ const pkg = loadPackageManifest(targetDir);
281
+ if (hasDependency(pkg, ['vue', 'vue-router', 'pinia'])) {
282
+ return 'vue';
283
+ }
284
+ if (hasDependency(pkg, ['react', 'react-dom', 'react-router-dom'])) {
285
+ return 'react';
286
+ }
287
+ return 'default';
288
+ }
289
+
290
+ function resolveTransitionRoleValue(targetDir, transition, field) {
291
+ const raw = transition?.[field];
292
+ if (raw !== 'resolve-from-profile') {
293
+ return raw || null;
294
+ }
295
+
296
+ const projectProfile = detectProjectProfile(targetDir);
297
+ const profileMap = transition?.[`${field}_by_profile`];
298
+ if (profileMap && typeof profileMap === 'object' && !Array.isArray(profileMap)) {
299
+ return profileMap[projectProfile] || null;
300
+ }
301
+
302
+ return null;
303
+ }
304
+
305
+ function listMarkdownBullets(content) {
306
+ return content
307
+ .split('\n')
308
+ .map((line) => line.trim())
309
+ .filter((line) => /^[-*]\s+/.test(line) || /^\d+\.\s+/.test(line));
310
+ }
311
+
312
+ function normalizeStringList(value) {
313
+ if (!Array.isArray(value)) {
314
+ return [];
315
+ }
316
+ return value.map((item) => String(item || '').trim()).filter(Boolean);
317
+ }
318
+
319
+ function trimExcerpt(value, maxLength = 240) {
320
+ const text = String(value || '').trim();
321
+ if (!text) {
322
+ return null;
323
+ }
324
+ return text.length > maxLength ? `${text.slice(0, maxLength)}...` : text;
325
+ }
326
+
327
+ function normalizeAutoFixState(value) {
328
+ const merged = value && typeof value === 'object'
329
+ ? value
330
+ : {};
331
+ const maxAttempts = Number.isFinite(Number(merged.max_attempts))
332
+ ? Math.max(1, Number(merged.max_attempts))
333
+ : 1;
334
+ const attempts = Number.isFinite(Number(merged.attempts))
335
+ ? Math.max(0, Math.min(Number(merged.attempts), maxAttempts))
336
+ : 0;
337
+ const lastFailedSteps = Array.isArray(merged.last_failed_steps)
338
+ ? merged.last_failed_steps
339
+ .map((step) => ({
340
+ name: typeof step?.name === 'string' && step.name.trim() ? step.name.trim() : 'unknown',
341
+ status: typeof step?.status === 'string' && step.status.trim() ? step.status.trim() : null,
342
+ command: typeof step?.command === 'string' && step.command.trim() ? step.command.trim() : null,
343
+ exit_code: typeof step?.exit_code === 'number' ? step.exit_code : null,
344
+ reason: typeof step?.reason === 'string' && step.reason.trim() ? step.reason.trim() : null,
345
+ error: typeof step?.error === 'string' && step.error.trim() ? step.error.trim() : null,
346
+ stdout_excerpt: trimExcerpt(step?.stdout_excerpt),
347
+ stderr_excerpt: trimExcerpt(step?.stderr_excerpt),
348
+ }))
349
+ .filter(Boolean)
350
+ : [];
351
+
352
+ return {
353
+ attempts,
354
+ max_attempts: maxAttempts,
355
+ active: Boolean(merged.active),
356
+ last_failed_steps: lastFailedSteps,
357
+ };
358
+ }
359
+
360
+ function extractFailedVerificationSteps(verification) {
361
+ if (!verification || !Array.isArray(verification.steps)) {
362
+ return [];
363
+ }
364
+
365
+ return verification.steps
366
+ .filter((step) => String(step?.status || '').trim().toLowerCase() === 'failed')
367
+ .map((step) => ({
368
+ name: typeof step?.name === 'string' && step.name.trim() ? step.name.trim() : 'unknown',
369
+ status: 'failed',
370
+ command: typeof step?.command === 'string' && step.command.trim() ? step.command.trim() : null,
371
+ exit_code: typeof step?.exit_code === 'number' ? step.exit_code : null,
372
+ reason: typeof step?.reason === 'string' && step.reason.trim() ? step.reason.trim() : null,
373
+ error: typeof step?.error === 'string' && step.error.trim() ? step.error.trim() : null,
374
+ stdout_excerpt: trimExcerpt(step?.stdout_excerpt),
375
+ stderr_excerpt: trimExcerpt(step?.stderr_excerpt),
376
+ }));
377
+ }
378
+
379
+ function listMarkdownFilesRecursive(rootDir) {
380
+ if (!rootDir || !fs.existsSync(rootDir)) {
381
+ return [];
382
+ }
383
+
384
+ const rootStat = fs.statSync(rootDir);
385
+ if (!rootStat.isDirectory()) {
386
+ return rootDir.endsWith('.md') ? [rootDir] : [];
387
+ }
388
+
389
+ const files = [];
390
+ const stack = [rootDir];
391
+ while (stack.length > 0) {
392
+ const current = stack.pop();
393
+ const entries = fs.readdirSync(current, { withFileTypes: true });
394
+ for (const entry of entries) {
395
+ const nextPath = path.join(current, entry.name);
396
+ if (entry.isDirectory()) {
397
+ stack.push(nextPath);
398
+ } else if (entry.isFile() && entry.name.endsWith('.md')) {
399
+ files.push(nextPath);
400
+ }
401
+ }
402
+ }
403
+
404
+ return files.sort();
405
+ }
406
+
407
+ function readMarkdownArtifactContent(artifactPath) {
408
+ if (!artifactPath || !fs.existsSync(artifactPath)) {
409
+ return {
410
+ files: [],
411
+ content: '',
412
+ };
413
+ }
414
+
415
+ const files = listMarkdownFilesRecursive(artifactPath);
416
+ return {
417
+ files,
418
+ content: files
419
+ .map((filePath) => fs.readFileSync(filePath, 'utf8').trim())
420
+ .filter(Boolean)
421
+ .join('\n\n'),
422
+ };
423
+ }
424
+
425
+ function getRoleArtifactRequirements(targetDir, roleId, flowId = null) {
426
+ const flowRequiredInputs = normalizeStringList(FLOW_ROLE_REQUIRED_INPUTS[flowId]?.[roleId]);
427
+ const flowRequiredOutputs = normalizeStringList(FLOW_ROLE_REQUIRED_OUTPUTS[flowId]?.[roleId]);
428
+ if (flowRequiredInputs.length > 0 || flowRequiredOutputs.length > 0) {
429
+ return {
430
+ required_inputs: flowRequiredInputs,
431
+ required_outputs: flowRequiredOutputs,
432
+ };
433
+ }
434
+
435
+ const registryEntry = getRoleRuntimeConfig(targetDir, roleId);
436
+ const requiredInputs = normalizeStringList(registryEntry?.required_inputs);
437
+ const requiredOutputs = normalizeStringList(registryEntry?.required_outputs);
438
+
439
+ return {
440
+ required_inputs: requiredInputs.length > 0 ? requiredInputs : (ROLE_REQUIRED_INPUTS[roleId] || []),
441
+ required_outputs: requiredOutputs.length > 0 ? requiredOutputs : (ROLE_REQUIRED_OUTPUTS[roleId] || []),
442
+ };
443
+ }
444
+
445
+ function inferExecutionOpenSpecAction(payload, targetDir = null) {
446
+ if (payload?.openspec_action) {
447
+ return String(payload.openspec_action).trim().toLowerCase();
448
+ }
449
+
450
+ if (targetDir && payload?.role?.id) {
451
+ const registryEntry = getRoleRuntimeConfig(targetDir, payload.role.id);
452
+ const configuredActions = normalizeStringList(registryEntry?.openspec_actions);
453
+ if (configuredActions.length > 0) {
454
+ return configuredActions[0].toLowerCase();
455
+ }
456
+ }
457
+
458
+ return ROLE_OPENSPEC_ACTIONS[payload?.role?.id] || null;
459
+ }
460
+
461
+ function inferRuntimeActionOpenSpecAction(payload) {
462
+ if (payload?.openspec_action) {
463
+ return String(payload.openspec_action).trim().toLowerCase();
464
+ }
465
+
466
+ const action = String(payload?.action || '').trim().toLowerCase();
467
+ if (action === 'archive' || action === 'complete' || action === 'completed') {
468
+ return 'archive';
469
+ }
470
+
471
+ return null;
472
+ }
473
+
474
+ function validatePreImplementationGate(targetDir, currentRun, executionPayload) {
475
+ if (!currentRun || currentRun.flow?.id !== 'prd-to-delivery') {
476
+ return { ok: true, reasons: [] };
477
+ }
478
+
479
+ if (executionPayload.role?.id !== 'requirement-analyst') {
480
+ return { ok: true, reasons: [] };
481
+ }
482
+
483
+ const deliveryProfile = currentRun.delivery_profile || 'standard';
484
+ const riskLevel = String(currentRun.task?.risk_level || '').trim().toLowerCase();
485
+ const rawInput = String(currentRun.trigger?.raw_input || '');
486
+ const proposalPath = currentRun.artifacts?.proposal
487
+ ? path.join(targetDir, currentRun.artifacts.proposal)
488
+ : null;
489
+ const specsPath = currentRun.artifacts?.specs
490
+ ? path.join(targetDir, runtimeState.normalizeSpecsArtifactPath(currentRun.artifacts.specs))
491
+ : null;
492
+ const designPath = currentRun.artifacts?.design
493
+ ? path.join(targetDir, currentRun.artifacts.design)
494
+ : null;
495
+ const tasksPath = currentRun.artifacts?.tasks
496
+ ? path.join(targetDir, currentRun.artifacts.tasks)
497
+ : null;
498
+ const reasons = [];
499
+
500
+ if (!proposalPath || !fs.existsSync(proposalPath)) {
501
+ reasons.push('proposal.md 缺失');
502
+ }
503
+ if (!specsPath || !fs.existsSync(specsPath)) {
504
+ reasons.push('specs/ 缺失');
505
+ }
506
+ if (!designPath || !fs.existsSync(designPath)) {
507
+ reasons.push('design.md 缺失');
508
+ }
509
+ if (!tasksPath || !fs.existsSync(tasksPath)) {
510
+ reasons.push('tasks.md 缺失');
511
+ }
512
+
513
+ if (reasons.length > 0) {
514
+ return { ok: false, reasons };
515
+ }
516
+
517
+ const proposalContent = fs.readFileSync(proposalPath, 'utf8').trim();
518
+ const specsArtifact = readMarkdownArtifactContent(specsPath);
519
+ const designContent = fs.readFileSync(designPath, 'utf8').trim();
520
+ const tasksContent = fs.readFileSync(tasksPath, 'utf8').trim();
521
+ const taskItems = listMarkdownBullets(tasksContent);
522
+
523
+ if (specsArtifact.files.length === 0) {
524
+ reasons.push('specs/ 缺少 spec 文件');
525
+ }
526
+
527
+ if (riskLevel === 'high') {
528
+ reasons.push('当前任务涉及支付/认证/安全/合规等高风险领域,进入实现前必须人工审批');
529
+ }
530
+
531
+ if (/先不说|先不提供|暂不说|暂不提供|暂未确定|未明确|待定|后续再说|后面再说/.test(rawInput)) {
532
+ reasons.push('原始需求已明确存在未说明的关键流程或安全约束,进入实现前必须人工审批');
533
+ }
534
+
535
+ const missingInputs = Array.isArray(currentRun.missing_inputs)
536
+ ? currentRun.missing_inputs.map((item) => String(item || ''))
537
+ : [];
538
+ if (
539
+ riskLevel === 'high' &&
540
+ missingInputs.some((item) => /支付|认证|oauth|短信|权限|安全|合规|风控|收款|交易/.test(item))
541
+ ) {
542
+ reasons.push('高风险任务仍存在关键缺失输入,进入实现前必须人工审批');
543
+ }
544
+
545
+ if (deliveryProfile === 'micro') {
546
+ if (proposalContent.length < 60) {
547
+ reasons.push('proposal.md 过短,未达到 compact 最小信息量');
548
+ }
549
+ if (specsArtifact.content.length < 40) {
550
+ reasons.push('specs/ 过短,未达到 compact 最小信息量');
551
+ }
552
+ if (designContent.length < 40) {
553
+ reasons.push('design.md 过短,未达到 compact 最小信息量');
554
+ }
555
+ if (taskItems.length < 3) {
556
+ reasons.push('tasks.md 任务条目不足 3 条');
557
+ }
558
+ } else {
559
+ const headingCount = proposalContent
560
+ .split('\n')
561
+ .filter((line) => /^#{1,6}\s+/.test(line.trim()))
562
+ .length;
563
+ if (proposalContent.length < 120) {
564
+ reasons.push('proposal.md 过短,未达到 standard 最小信息量');
565
+ }
566
+ if (specsArtifact.content.length < 80) {
567
+ reasons.push('specs/ 过短,未达到 standard 最小信息量');
568
+ }
569
+ if (designContent.length < 80) {
570
+ reasons.push('design.md 过短,未达到 standard 最小信息量');
571
+ }
572
+ if (headingCount < 2) {
573
+ reasons.push('proposal.md 缺少足够的小节结构');
574
+ }
575
+ if (taskItems.length < 4) {
576
+ reasons.push('tasks.md 任务条目不足 4 条');
577
+ }
578
+ }
579
+
580
+ return {
581
+ ok: reasons.length === 0,
582
+ reasons,
583
+ };
584
+ }
585
+
586
+ function getRuntimeTransition(targetDir, flowId, roleId) {
587
+ const flowConfig = getFlowRuntimeConfig(targetDir, flowId);
588
+ const flowTransition = flowConfig?.runtime_transitions?.[roleId];
589
+ if (flowTransition && typeof flowTransition === 'object' && flowTransition.action) {
590
+ return {
591
+ ...flowTransition,
592
+ to_role: resolveTransitionRoleValue(targetDir, flowTransition, 'to_role'),
593
+ next_role: resolveTransitionRoleValue(targetDir, flowTransition, 'next_role'),
594
+ };
595
+ }
596
+
597
+ const roleConfig = getRoleRuntimeConfig(targetDir, roleId);
598
+ const roleTransition = roleConfig?.runtime_transition;
599
+ if (roleTransition && typeof roleTransition === 'object' && roleTransition.action) {
600
+ return {
601
+ ...roleTransition,
602
+ to_role: resolveTransitionRoleValue(targetDir, roleTransition, 'to_role'),
603
+ next_role: resolveTransitionRoleValue(targetDir, roleTransition, 'next_role'),
604
+ };
605
+ }
606
+
607
+ return FLOW_RUNTIME_TRANSITIONS[flowId]?.[roleId] || null;
608
+ }
609
+
610
+ function buildAutoRuntimeAction(targetDir, executionPayload) {
611
+ const currentRun = readCurrentRun(targetDir);
612
+ if (!currentRun) {
613
+ return null;
614
+ }
615
+
616
+ if (!AUTO_ADVANCE_EXECUTION_STATUSES.has(String(executionPayload.status || '').toLowerCase())) {
617
+ return null;
618
+ }
619
+
620
+ if (currentRun.pending_gate) {
621
+ return null;
622
+ }
623
+
624
+ const flowId = executionPayload.flow?.id || currentRun.flow?.id || null;
625
+ const roleId = executionPayload.role?.id || null;
626
+ if (!flowId || !roleId) {
627
+ return null;
628
+ }
629
+ const mainFlowBlocking = isMainFlowBlocking(currentRun, flowId);
630
+
631
+ const transition = getRuntimeTransition(targetDir, flowId, roleId);
632
+ if (!transition) {
633
+ return null;
634
+ }
635
+
636
+ if (roleId === 'frontend-implementer') {
637
+ const verification = executionPayload.verification || currentRun.verification || null;
638
+ const failedSteps = extractFailedVerificationSteps(verification);
639
+ const autoFixState = normalizeAutoFixState(currentRun.auto_fix);
640
+
641
+ if (failedSteps.length > 0) {
642
+ if (autoFixState.attempts < autoFixState.max_attempts) {
643
+ const nextAttempts = autoFixState.attempts + 1;
644
+ return {
645
+ schema_version: 1,
646
+ kind: 'task-orchestrator-runtime-action',
647
+ action: 'handoff',
648
+ run_id: executionPayload.run_id,
649
+ from_role: roleId,
650
+ to_role: roleId,
651
+ next_role: transition.to_role || 'code-guardian',
652
+ status: 'running',
653
+ clear_pending_gate: true,
654
+ message: `verification failed; retry frontend-implementer auto-fix (${nextAttempts}/${autoFixState.max_attempts})`,
655
+ source: 'expert-executor-auto-transition',
656
+ verification,
657
+ auto_fix: {
658
+ attempts: nextAttempts,
659
+ max_attempts: autoFixState.max_attempts,
660
+ active: true,
661
+ last_failed_steps: failedSteps,
662
+ },
663
+ };
664
+ }
665
+
666
+ return {
667
+ schema_version: 1,
668
+ kind: 'task-orchestrator-runtime-action',
669
+ action: 'handoff',
670
+ run_id: executionPayload.run_id,
671
+ from_role: roleId,
672
+ to_role: transition.to_role || 'code-guardian',
673
+ next_role: transition.next_role || null,
674
+ status: 'running',
675
+ clear_pending_gate: true,
676
+ message: 'verification still failed after auto-fix; handoff to code-guardian for blocking review',
677
+ source: 'expert-executor-auto-transition',
678
+ verification,
679
+ auto_fix: {
680
+ attempts: autoFixState.attempts,
681
+ max_attempts: autoFixState.max_attempts,
682
+ active: false,
683
+ last_failed_steps: failedSteps,
684
+ },
685
+ };
686
+ }
687
+ }
688
+
689
+ if (transition.action === 'handoff' && roleId === 'requirement-analyst') {
690
+ const gateCheck = validatePreImplementationGate(targetDir, currentRun, executionPayload);
691
+ if (mainFlowBlocking || !gateCheck.ok) {
692
+ const blockedReason = gateCheck.ok
693
+ ? '内测阶段启用 main-flow-blocking 审核策略,需求收敛完成后需要先人工审核再进入实现。'
694
+ : gateCheck.reasons.join(';');
695
+ return {
696
+ schema_version: 1,
697
+ kind: 'task-orchestrator-runtime-action',
698
+ action: 'gate-blocked',
699
+ run_id: executionPayload.run_id,
700
+ from_role: roleId,
701
+ to_role: roleId,
702
+ next_role: transition.to_role,
703
+ pending_gate: 'before-implementation',
704
+ blocked_by_role: roleId,
705
+ resume_to_role: transition.to_role || null,
706
+ required_user_action: '明确批准或拒绝当前 proposal / specs / design / tasks 的实现范围与限制条件。',
707
+ blocked_reason: blockedReason,
708
+ status: 'waiting-approval',
709
+ clear_pending_gate: false,
710
+ message: `requirement gate blocked: ${blockedReason}`,
711
+ source: 'expert-executor-auto-transition',
712
+ };
713
+ }
714
+ }
715
+
716
+ if (transition.action === 'handoff' && roleId === 'frontend-implementer' && mainFlowBlocking) {
717
+ return {
718
+ schema_version: 1,
719
+ kind: 'task-orchestrator-runtime-action',
720
+ action: 'gate-blocked',
721
+ run_id: executionPayload.run_id,
722
+ from_role: roleId,
723
+ to_role: roleId,
724
+ next_role: transition.to_role || 'code-guardian',
725
+ pending_gate: 'before-guardian',
726
+ blocked_by_role: roleId,
727
+ resume_to_role: transition.to_role || 'code-guardian',
728
+ required_user_action: '明确批准当前实现结果进入 code-guardian 守护审查,或说明需要回退修正的方向。',
729
+ blocked_reason: '内测阶段启用 main-flow-blocking 审核策略,前端实现完成后需要先人工审核再进入守护阶段。',
730
+ status: 'waiting-approval',
731
+ clear_pending_gate: false,
732
+ message: 'frontend delivery is waiting for manual review before code-guardian',
733
+ source: 'expert-executor-auto-transition',
734
+ verification: executionPayload.verification || null,
735
+ };
736
+ }
737
+
738
+ if (transition.action === 'gate-blocked' && roleId === 'code-guardian' && !mainFlowBlocking) {
739
+ return {
740
+ schema_version: 1,
741
+ kind: 'task-orchestrator-runtime-action',
742
+ action: 'handoff',
743
+ run_id: executionPayload.run_id,
744
+ from_role: roleId,
745
+ to_role: transition.next_role || 'archive-change',
746
+ next_role: null,
747
+ status: 'running',
748
+ clear_pending_gate: true,
749
+ message: 'handoff to archive-change after code-guardian closeout',
750
+ source: 'expert-executor-auto-transition',
751
+ };
752
+ }
753
+
754
+ if (transition.action === 'gate-blocked') {
755
+ return {
756
+ schema_version: 1,
757
+ kind: 'task-orchestrator-runtime-action',
758
+ action: 'gate-blocked',
759
+ run_id: executionPayload.run_id,
760
+ from_role: roleId,
761
+ to_role: transition.to_role || roleId,
762
+ next_role: transition.next_role || null,
763
+ pending_gate: transition.pending_gate || 'before-archive',
764
+ blocked_by_role: roleId,
765
+ resume_to_role: transition.next_role || null,
766
+ required_user_action: '明确告诉系统是否执行归档;同意则进入归档专家,不归档则直接结束本次运行。',
767
+ blocked_reason: executionPayload.next_action || transition.message,
768
+ status: transition.status || 'waiting-approval',
769
+ clear_pending_gate: false,
770
+ message: executionPayload.next_action || transition.message,
771
+ source: 'expert-executor-auto-transition',
772
+ };
773
+ }
774
+
775
+ const nextRole = executionPayload.next_role !== undefined
776
+ ? executionPayload.next_role
777
+ : transition.next_role;
778
+ const toRole = executionPayload.next_role || transition.to_role || null;
779
+ const action = transition.action;
780
+ const currentAutoFix = roleId === 'frontend-implementer'
781
+ ? normalizeAutoFixState(currentRun.auto_fix)
782
+ : null;
783
+ const normalizedAutoFix = currentAutoFix && (currentAutoFix.active || currentAutoFix.attempts > 0 || currentAutoFix.last_failed_steps.length > 0)
784
+ ? {
785
+ ...currentAutoFix,
786
+ active: false,
787
+ }
788
+ : null;
789
+
790
+ return {
791
+ schema_version: 1,
792
+ kind: 'task-orchestrator-runtime-action',
793
+ action,
794
+ run_id: executionPayload.run_id,
795
+ from_role: roleId,
796
+ to_role: action === 'handoff' ? toRole : transition.to_role || roleId,
797
+ next_role: nextRole,
798
+ status: action === 'complete' ? 'success' : 'running',
799
+ clear_pending_gate: true,
800
+ message: executionPayload.next_action || transition.message,
801
+ source: 'expert-executor-auto-transition',
802
+ openspec_action: action === 'complete' ? 'archive' : null,
803
+ skip_artifact_check: action === 'complete' && roleId === 'archive-change',
804
+ verification: executionPayload.verification || null,
805
+ auto_fix: normalizedAutoFix,
806
+ };
807
+ }
808
+
809
+ module.exports = {
810
+ AUTO_ADVANCE_EXECUTION_STATUSES,
811
+ FLOW_RUNTIME_TRANSITIONS,
812
+ ROLE_OPENSPEC_ACTIONS,
813
+ getRoleArtifactRequirements,
814
+ getRuntimeTransition,
815
+ inferExecutionOpenSpecAction,
816
+ inferRuntimeActionOpenSpecAction,
817
+ validatePreImplementationGate,
818
+ guardRuntimeActionForIncompleteExecution,
819
+ buildAutoRuntimeAction,
820
+ readCurrentRun,
821
+ };