soloforge 1.1.46 → 1.1.48

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 (451) hide show
  1. package/README.md +23 -7
  2. package/dist/cli/adapter_writers.d.ts +5 -0
  3. package/dist/cli/adapter_writers.d.ts.map +1 -1
  4. package/dist/cli/adapter_writers.js +25 -0
  5. package/dist/cli/adapter_writers.js.map +1 -1
  6. package/dist/cli/init.d.ts.map +1 -1
  7. package/dist/cli/init.js +3 -1
  8. package/dist/cli/init.js.map +1 -1
  9. package/dist/cli/scope_check.d.ts +4 -0
  10. package/dist/cli/scope_check.d.ts.map +1 -0
  11. package/dist/cli/scope_check.js +41 -0
  12. package/dist/cli/scope_check.js.map +1 -0
  13. package/dist/context/adapters/claude_code/hooks.d.ts +5 -7
  14. package/dist/context/adapters/claude_code/hooks.d.ts.map +1 -1
  15. package/dist/context/adapters/claude_code/hooks.js +11 -9
  16. package/dist/context/adapters/claude_code/hooks.js.map +1 -1
  17. package/dist/context/adapters/shared/integration_guide.js +18 -6
  18. package/dist/context/adapters/shared/integration_guide.js.map +1 -1
  19. package/dist/context/adapters/shared/workflow_template.js +1 -1
  20. package/dist/context/config/intent_schema.d.ts +793 -6
  21. package/dist/context/config/intent_schema.d.ts.map +1 -1
  22. package/dist/context/config/intent_schema.js +9 -0
  23. package/dist/context/config/intent_schema.js.map +1 -1
  24. package/dist/context/config/resolver.d.ts +9 -0
  25. package/dist/context/config/resolver.d.ts.map +1 -1
  26. package/dist/context/config/resolver.js +5 -0
  27. package/dist/context/config/resolver.js.map +1 -1
  28. package/dist/core/adversarial_review_store.d.ts +133 -0
  29. package/dist/core/adversarial_review_store.d.ts.map +1 -0
  30. package/dist/core/adversarial_review_store.js +161 -0
  31. package/dist/core/adversarial_review_store.js.map +1 -0
  32. package/dist/core/domain_transition.d.ts.map +1 -1
  33. package/dist/core/domain_transition.js +3 -0
  34. package/dist/core/domain_transition.js.map +1 -1
  35. package/dist/core/gate_record_store.d.ts +13 -7
  36. package/dist/core/gate_record_store.d.ts.map +1 -1
  37. package/dist/core/gate_record_store.js +39 -17
  38. package/dist/core/gate_record_store.js.map +1 -1
  39. package/dist/core/git_utils.d.ts +1 -1
  40. package/dist/core/git_utils.js +1 -1
  41. package/dist/core/observer.d.ts.map +1 -1
  42. package/dist/core/observer.js +33 -6
  43. package/dist/core/observer.js.map +1 -1
  44. package/dist/core/task_context/constants.js +1 -1
  45. package/dist/core/task_context/constants.js.map +1 -1
  46. package/dist/core/task_context/manager.d.ts +4 -0
  47. package/dist/core/task_context/manager.d.ts.map +1 -1
  48. package/dist/core/task_context/manager.js +48 -30
  49. package/dist/core/task_context/manager.js.map +1 -1
  50. package/dist/core/task_context/manager_setters.d.ts +2 -0
  51. package/dist/core/task_context/manager_setters.d.ts.map +1 -1
  52. package/dist/core/task_context/manager_setters.js +10 -0
  53. package/dist/core/task_context/manager_setters.js.map +1 -1
  54. package/dist/core/types.d.ts +19 -0
  55. package/dist/core/types.d.ts.map +1 -1
  56. package/dist/domain/asset_registry/derived_registry.d.ts.map +1 -1
  57. package/dist/domain/asset_registry/derived_registry.js +20 -5
  58. package/dist/domain/asset_registry/derived_registry.js.map +1 -1
  59. package/dist/domain/asset_registry/derived_types.d.ts +22 -1
  60. package/dist/domain/asset_registry/derived_types.d.ts.map +1 -1
  61. package/dist/domain/build/contract.d.ts.map +1 -1
  62. package/dist/domain/build/contract.js +3 -8
  63. package/dist/domain/build/contract.js.map +1 -1
  64. package/dist/domain/build/engine.d.ts +4 -2
  65. package/dist/domain/build/engine.d.ts.map +1 -1
  66. package/dist/domain/build/engine.js +38 -5
  67. package/dist/domain/build/engine.js.map +1 -1
  68. package/dist/domain/contracts/design_lifecycle_contract.d.ts.map +1 -1
  69. package/dist/domain/contracts/design_lifecycle_contract.js +11 -4
  70. package/dist/domain/contracts/design_lifecycle_contract.js.map +1 -1
  71. package/dist/domain/design/contract.d.ts.map +1 -1
  72. package/dist/domain/design/contract.js +13 -31
  73. package/dist/domain/design/contract.js.map +1 -1
  74. package/dist/domain/design/engine.d.ts +4 -2
  75. package/dist/domain/design/engine.d.ts.map +1 -1
  76. package/dist/domain/design/engine.js +39 -4
  77. package/dist/domain/design/engine.js.map +1 -1
  78. package/dist/domain/engine_helpers.d.ts +55 -2
  79. package/dist/domain/engine_helpers.d.ts.map +1 -1
  80. package/dist/domain/engine_helpers.js +173 -8
  81. package/dist/domain/engine_helpers.js.map +1 -1
  82. package/dist/domain/operate/contract.js +1 -1
  83. package/dist/domain/operate/contract.js.map +1 -1
  84. package/dist/domain/operate/engine.d.ts +4 -2
  85. package/dist/domain/operate/engine.d.ts.map +1 -1
  86. package/dist/domain/operate/engine.js +23 -3
  87. package/dist/domain/operate/engine.js.map +1 -1
  88. package/dist/domain/types.d.ts +6 -0
  89. package/dist/domain/types.d.ts.map +1 -1
  90. package/dist/domain/types.js.map +1 -1
  91. package/dist/domain/verify/engine.d.ts +4 -2
  92. package/dist/domain/verify/engine.d.ts.map +1 -1
  93. package/dist/domain/verify/engine.js +22 -2
  94. package/dist/domain/verify/engine.js.map +1 -1
  95. package/dist/gate/contracts/tool_actions.d.ts +2 -2
  96. package/dist/gate/contracts/tool_actions.d.ts.map +1 -1
  97. package/dist/gate/contracts/tool_actions.js +2 -2
  98. package/dist/gate/contracts/tool_actions.js.map +1 -1
  99. package/dist/gate/contracts/tool_invocation_contract_registry.js +1 -1
  100. package/dist/gate/contracts/tool_invocation_contract_registry.js.map +1 -1
  101. package/dist/gate/executors/executors_artifact.d.ts +19 -0
  102. package/dist/gate/executors/executors_artifact.d.ts.map +1 -1
  103. package/dist/gate/executors/executors_artifact.js +108 -8
  104. package/dist/gate/executors/executors_artifact.js.map +1 -1
  105. package/dist/gate/executors/executors_build.d.ts.map +1 -1
  106. package/dist/gate/executors/executors_build.js +17 -15
  107. package/dist/gate/executors/executors_build.js.map +1 -1
  108. package/dist/gate/executors/executors_external_command.d.ts.map +1 -1
  109. package/dist/gate/executors/executors_external_command.js +32 -0
  110. package/dist/gate/executors/executors_external_command.js.map +1 -1
  111. package/dist/gate/executors/executors_field_mapping.d.ts +7 -0
  112. package/dist/gate/executors/executors_field_mapping.d.ts.map +1 -0
  113. package/dist/gate/executors/executors_field_mapping.js +179 -0
  114. package/dist/gate/executors/executors_field_mapping.js.map +1 -0
  115. package/dist/gate/executors/executors_prerequisite.d.ts.map +1 -1
  116. package/dist/gate/executors/executors_prerequisite.js +27 -7
  117. package/dist/gate/executors/executors_prerequisite.js.map +1 -1
  118. package/dist/gate/executors/executors_regex_scan.d.ts.map +1 -1
  119. package/dist/gate/executors/executors_regex_scan.js +36 -15
  120. package/dist/gate/executors/executors_regex_scan.js.map +1 -1
  121. package/dist/gate/executors/executors_scope.js +4 -4
  122. package/dist/gate/executors/executors_scope.js.map +1 -1
  123. package/dist/gate/executors/executors_trace.d.ts +5 -0
  124. package/dist/gate/executors/executors_trace.d.ts.map +1 -1
  125. package/dist/gate/executors/executors_trace.js +186 -3
  126. package/dist/gate/executors/executors_trace.js.map +1 -1
  127. package/dist/gate/executors/index.d.ts.map +1 -1
  128. package/dist/gate/executors/index.js +2 -0
  129. package/dist/gate/executors/index.js.map +1 -1
  130. package/dist/gate/gate_engine.d.ts +9 -0
  131. package/dist/gate/gate_engine.d.ts.map +1 -1
  132. package/dist/gate/gate_engine.js +15 -0
  133. package/dist/gate/gate_engine.js.map +1 -1
  134. package/dist/gate/gate_registry_bridge.d.ts +9 -8
  135. package/dist/gate/gate_registry_bridge.d.ts.map +1 -1
  136. package/dist/gate/gate_registry_bridge.js +57 -16
  137. package/dist/gate/gate_registry_bridge.js.map +1 -1
  138. package/dist/gate/middleware_gates.js +1 -1
  139. package/dist/gate/middleware_gates.js.map +1 -1
  140. package/dist/gate/scope_resolver.d.ts +7 -0
  141. package/dist/gate/scope_resolver.d.ts.map +1 -1
  142. package/dist/gate/scope_resolver.js +1 -1
  143. package/dist/gate/scope_resolver.js.map +1 -1
  144. package/dist/index.js +5 -0
  145. package/dist/index.js.map +1 -1
  146. package/dist/server/tools/sf_doctor.d.ts +2 -0
  147. package/dist/server/tools/sf_doctor.d.ts.map +1 -1
  148. package/dist/server/tools/sf_doctor.js +35 -1
  149. package/dist/server/tools/sf_doctor.js.map +1 -1
  150. package/dist/server/tools/sf_gate.d.ts +1 -1
  151. package/dist/server/tools/sf_gate.js +2 -2
  152. package/dist/server/tools/sf_gate.js.map +1 -1
  153. package/dist/server/tools/sf_task.d.ts +83 -0
  154. package/dist/server/tools/sf_task.d.ts.map +1 -1
  155. package/dist/server/tools/sf_task.js +121 -4
  156. package/dist/server/tools/sf_task.js.map +1 -1
  157. package/dist/server/tools/sf_work.d.ts +203 -0
  158. package/dist/server/tools/sf_work.d.ts.map +1 -1
  159. package/dist/server/tools/sf_work.js +549 -46
  160. package/dist/server/tools/sf_work.js.map +1 -1
  161. package/dist/shared/traceability_id_utils.js +3 -3
  162. package/dist/shared/traceability_id_utils.js.map +1 -1
  163. package/dist/verify/contracts/decision_workshop.d.ts.map +1 -1
  164. package/dist/verify/contracts/decision_workshop.js +4 -3
  165. package/dist/verify/contracts/decision_workshop.js.map +1 -1
  166. package/package.json +2 -1
  167. package/templates/build/enforced.md +299 -39
  168. package/templates/build//344/270/223/351/241/271/345/256/236/347/216/260.md +75 -0
  169. package/templates/build//345/256/211/345/205/250/345/212/240/345/233/272.md +75 -0
  170. package/templates/build//346/263/250/351/207/212/347/272/252/345/276/213.md +48 -0
  171. package/templates/build//346/265/213/350/257/225/344/274/230/345/205/210/347/274/226/347/240/201.md +50 -79
  172. package/templates/build//346/265/213/350/257/225/350/256/241/345/210/222.md +31 -24
  173. package/templates/build//347/274/226/347/240/201/347/272/252/345/276/213.md +101 -0
  174. package/templates/build//350/260/203/350/257/225/346/216/222/346/237/245.md +44 -75
  175. package/templates/build//351/207/215/346/236/204/346/226/271/346/263/225.md +68 -0
  176. package/templates/design/API/346/216/245/345/217/243/350/247/204/346/240/274/346/226/207/346/241/243.md +38 -28
  177. package/templates/design/enforced.md +234 -74
  178. package/templates/design//345/205/250/347/224/237/345/221/275/345/221/250/346/234/237/345/267/245/344/275/234/346/265/201/345/257/274/350/210/252.md +5 -2
  179. package/templates/design//345/205/274/345/256/271/346/200/247/344/270/216/350/277/201/347/247/273/350/257/204/344/274/260.md +71 -0
  180. package/templates/design//345/206/263/347/255/226/344/270/216/351/200/211/345/236/213.md +70 -0
  181. package/templates/design//345/210/207/347/211/207/350/247/204/345/210/222.md +51 -55
  182. package/templates/design//345/274/200/345/217/221/345/210/207/347/211/207/350/256/241/345/210/222.md +75 -0
  183. package/templates/design//346/225/260/346/215/256/345/272/223/350/256/276/350/256/241/346/226/207/346/241/243.md +35 -47
  184. package/templates/design//346/236/266/346/236/204/350/256/276/350/256/241.md +63 -81
  185. package/templates/design//350/256/276/350/256/241/345/206/263/347/255/226/347/272/252/345/276/213.md +58 -0
  186. package/templates/design//350/256/276/350/256/241/350/264/250/351/207/217/350/246/201/347/202/271.md +58 -0
  187. package/templates/design//351/234/200/346/261/202/345/210/206/346/236/220.md +49 -53
  188. package/templates/operate/UI/350/247/206/350/247/211/351/252/214/346/224/266/347/272/252/345/276/213.md +74 -0
  189. package/templates/operate/enforced.md +52 -5
  190. package/templates/operate//344/270/212/347/272/277/350/247/202/345/257/237.md +53 -32
  191. package/templates/operate//345/217/221/345/270/203/350/257/264/346/230/216.md +22 -1
  192. package/templates/operate//351/203/250/347/275/262/351/205/215/347/275/256.md +93 -0
  193. package/templates/shared/enforced.md +83 -5
  194. package/templates/shared//345/217/215/351/246/210/344/277/256/345/244/215/351/227/255/347/216/257.md +86 -0
  195. package/templates/shared//345/267/245/344/275/234/346/265/201/345/257/274/350/210/252/345/245/221/347/272/246.md +1 -1
  196. package/templates/shared//345/267/245/347/250/213/346/211/247/350/241/214/346/200/273/347/272/262.md +148 -0
  197. package/templates/shared//345/267/245/347/250/213/347/272/252/345/276/213.md +71 -0
  198. package/templates/shared//345/274/200/345/217/221/350/200/205/345/256/252/346/263/225.md +48 -43
  199. package/templates/shared//346/234/272/345/210/266/350/257/264/346/230/216.md +67 -0
  200. package/templates/shared//347/240/224/350/256/250/350/256/260/345/275/225.md +54 -0
  201. package/templates/shared//350/257/201/346/215/256/351/251/261/345/212/250/344/270/216/345/217/215/345/271/273/350/247/211.md +27 -17
  202. package/templates/shared//350/264/241/347/214/256/350/247/204/350/214/203.md +78 -0
  203. package/templates/verify/enforced.md +87 -263
  204. package/templates/verify//344/272/244/344/273/230/345/256/214/345/244/207/346/200/247/345/256/241/346/237/245.md +46 -87
  205. package/templates/verify//344/273/243/347/240/201/345/256/241/346/237/245/346/212/245/345/221/212.md +17 -0
  206. package/templates/verify//345/256/241/346/237/245/346/270/205/345/215/225.md +79 -0
  207. package/templates/verify//346/236/266/346/236/204/350/257/255/344/271/211/347/272/242/347/272/277.md +60 -0
  208. package/templates/verify//351/252/214/350/257/201/346/226/271/346/263/225.md +72 -0
  209. package/dist/core/scope_checker.d.ts +0 -29
  210. package/dist/core/scope_checker.d.ts.map +0 -1
  211. package/dist/core/scope_checker.js +0 -53
  212. package/dist/core/scope_checker.js.map +0 -1
  213. package/templates/build/Bug/345/210/206/346/236/220.md +0 -59
  214. package/templates/build/Git/346/223/215/344/275/234.md +0 -48
  215. package/templates/build/OOD/350/256/276/350/256/241/346/221/230/350/246/201.md +0 -46
  216. package/templates/build/React/346/216/245/345/217/243/351/233/206/346/210/220.md +0 -42
  217. package/templates/build/Schema/345/217/230/346/233/264/346/265/201/346/260/264/347/272/277.md +0 -52
  218. package/templates/build/TS/350/264/250/351/207/217/345/256/241/346/237/245.md +0 -78
  219. package/templates/build//344/270/212/346/270/270/344/272/244/345/217/211/351/252/214/350/257/201.md +0 -68
  220. package/templates/build//344/270/273/351/223/276/350/267/257/346/216/245/345/205/245/351/252/214/350/257/201.md +0 -56
  221. package/templates/build//344/273/243/347/240/201/351/227/250/347/246/201.md +0 -58
  222. package/templates/build//345/205/250/346/240/210/346/265/201/347/250/213/344/277/256/345/244/215.md +0 -48
  223. package/templates/build//345/210/207/347/211/207/346/211/247/350/241/214/347/272/252/345/276/213.md +0 -108
  224. package/templates/build//345/210/207/347/211/207/347/253/257/345/210/260/347/253/257/351/252/214/350/257/201.md +0 -221
  225. package/templates/build//345/212/237/350/203/275/345/274/200/345/217/221.md +0 -66
  226. package/templates/build//345/220/216/347/253/257/345/256/236/347/216/260.md +0 -39
  227. package/templates/build//345/220/216/347/253/257/345/256/236/347/216/260/345/267/245/347/250/213.md +0 -33
  228. package/templates/build//345/220/216/347/253/257/345/256/236/347/216/260/345/267/245/347/250/213/345/256/241/346/237/245.md +0 -70
  229. package/templates/build//345/220/216/347/253/257/346/216/245/345/217/243/345/256/236/347/216/260.md +0 -43
  230. package/templates/build//345/233/275/351/231/205/345/214/226.md +0 -45
  231. package/templates/build//345/256/211/345/205/250/345/212/240/345/233/272/346/265/201/346/260/264/347/272/277.md +0 -68
  232. package/templates/build//345/256/211/345/205/250/345/256/241/346/237/245.md +0 -154
  233. package/templates/build//345/256/211/345/205/250/345/256/241/350/256/241.md +0 -47
  234. package/templates/build//345/267/245/347/250/213/347/272/252/345/276/213.md +0 -56
  235. package/templates/build//346/200/247/350/203/275/345/210/206/346/236/220.md +0 -59
  236. package/templates/build//346/200/247/350/203/275/346/265/201/346/260/264/347/272/277.md +0 -53
  237. package/templates/build//346/216/245/345/217/243/351/233/206/346/210/220/346/265/201/346/260/264/347/272/277.md +0 -76
  238. package/templates/build//346/225/260/346/215/256/345/272/223/350/277/201/347/247/273.md +0 -63
  239. package/templates/build//346/226/260/350/200/201/351/200/273/350/276/221/346/257/224/345/257/271/346/227/245/345/277/227.md +0 -39
  240. package/templates/build//346/235/203/351/231/220/350/256/244/350/257/201.md +0 -49
  241. package/templates/build//346/265/213/350/257/225/350/264/250/351/207/217.md +0 -45
  242. package/templates/build//347/206/224/346/226/255/351/231/215/347/272/247.md +0 -49
  243. package/templates/build//347/212/266/346/200/201/346/265/201/350/275/254.md +0 -43
  244. package/templates/build//347/213/254/347/253/213/345/256/241/346/237/245.md +0 -45
  245. package/templates/build//347/272/246/346/235/237/345/256/236/347/216/260.md +0 -47
  246. package/templates/build//347/274/226/347/240/201/345/260/261/347/273/252/345/256/241/346/237/245.md +0 -60
  247. package/templates/build//347/274/226/347/240/201/350/201/232/345/220/210/346/243/200/346/237/245.md +0 -22
  248. package/templates/build//347/274/226/347/240/201/350/264/250/351/207/217.md +0 -46
  249. package/templates/build//347/274/226/347/240/201/351/230/266/346/256/265/346/211/247/350/241/214.md +0 -105
  250. package/templates/build//347/274/272/351/231/267/347/256/241/347/220/206.md +0 -47
  251. package/templates/build//350/200/246/345/220/210/346/243/200/346/265/213.md +0 -86
  252. package/templates/build//350/246/206/347/233/226/347/216/207/346/240/207/345/207/206.md +0 -40
  253. package/templates/build//350/264/250/351/207/217/345/256/241/346/237/245.md +0 -111
  254. package/templates/build//350/277/201/347/247/273/346/265/201/346/260/264/347/272/277.md +0 -52
  255. package/templates/build//351/200/232/347/224/250/350/264/250/351/207/217.md +0 -176
  256. package/templates/build//351/207/215/346/236/204/346/226/271/346/241/210.md +0 -61
  257. package/templates/build//351/207/215/346/236/204/346/265/201/346/260/264/347/272/277.md +0 -53
  258. package/templates/build//351/230/262/345/276/241/346/200/247/347/274/226/347/240/201.md +0 -94
  259. package/templates/build//351/233/206/346/210/220/351/252/214/350/257/201.md +0 -67
  260. package/templates/build//351/233/267/345/214/272/345/217/215/346/250/241/345/274/217.md +0 -135
  261. package/templates/build//351/252/214/346/224/266/346/240/207/345/207/206/345/256/241/346/237/245.md +0 -64
  262. package/templates/build//351/252/214/346/224/266/346/265/213/350/257/225/350/247/204/345/210/222.md +0 -75
  263. package/templates/design/API/350/256/276/350/256/241.md +0 -47
  264. package/templates/design/N/345/212/2401/346/237/245/350/257/242.md +0 -48
  265. package/templates/design/OOD/350/256/276/350/256/241.md +0 -72
  266. package/templates/design//344/270/200/350/207/264/346/200/247/346/240/241/351/252/214.md +0 -109
  267. package/templates/design//344/270/215/347/241/256/345/256/232/346/227/266/345/244/264/350/204/221/351/243/216/346/232/264.md +0 -105
  268. package/templates/design//344/273/273/345/212/241/346/213/206/350/247/243.md +0 -61
  269. package/templates/design//344/273/273/345/212/241/350/247/204/345/210/222.md +0 -84
  270. package/templates/design//344/274/232/350/257/235/346/201/242/345/244/215-procedures.md +0 -78
  271. package/templates/design//345/205/274/345/256/271/346/200/247/346/243/200/346/237/245.md +0 -89
  272. package/templates/design//345/210/207/347/211/207/350/256/241/345/210/222.md +0 -149
  273. package/templates/design//345/211/215/347/253/257/346/200/247/350/203/275.md +0 -49
  274. package/templates/design//345/216/206/345/217/262/351/201/227/347/225/231/351/233/267/345/214/272/346/270/205/345/215/225.md +0 -50
  275. package/templates/design//345/216/237/345/236/213/346/272/220/347/240/201/346/217/220/345/217/226.md +0 -78
  276. package/templates/design//345/216/237/345/236/213/350/257/264/346/230/216.md +0 -200
  277. package/templates/design//345/216/237/345/236/213/350/257/264/346/230/216/345/256/241/346/237/245.md +0 -81
  278. package/templates/design//345/220/221/345/220/216/345/205/274/345/256/271/346/200/247/345/220/210/350/247/204/346/212/245/345/221/212.md +0 -52
  279. package/templates/design//345/221/275/344/273/244/346/211/247/350/241/214-procedures.md +0 -45
  280. package/templates/design//345/221/275/344/273/244/350/267/257/347/224/261-procedures.md +0 -46
  281. package/templates/design//345/221/275/345/220/215.md +0 -49
  282. package/templates/design//345/242/236/351/207/217/350/276/271/347/225/214/347/225/214/345/256/232/346/226/207/346/241/243.md +0 -48
  283. package/templates/design//345/267/245/345/205/267/350/260/203/347/224/250-procedures.md +0 -41
  284. package/templates/design//345/271/266/345/217/221/346/216/247/345/210/266.md +0 -50
  285. package/templates/design//346/212/200/346/234/257/351/200/211/345/236/213.md +0 -33
  286. package/templates/design//346/216/245/345/217/243/345/257/271/346/216/245/346/226/271/346/241/210.md +0 -97
  287. package/templates/design//346/224/271/351/200/240/345/275/261/345/223/215/350/214/203/345/233/264/350/257/204/344/274/260.md +0 -56
  288. package/templates/design//346/225/260/346/215/256/345/272/223/345/217/230/346/233/264/346/226/271/346/241/210.md +0 -75
  289. package/templates/design//346/225/260/346/215/256/350/241/200/347/274/230/345/233/276.md +0 -49
  290. package/templates/design//346/227/240/351/232/234/347/242/215.md +0 -49
  291. package/templates/design//346/236/266/346/236/204/345/206/263/347/255/226/350/256/260/345/275/225.md +0 -53
  292. package/templates/design//346/236/266/346/236/204/345/256/241/346/237/245.md +0 -256
  293. package/templates/design//346/236/266/346/236/204/350/256/276/350/256/241-constraints.md +0 -177
  294. package/templates/design//346/236/266/346/236/204/350/256/276/350/256/241-procedures.md +0 -130
  295. package/templates/design//346/246/202/345/277/265/351/252/214/350/257/201/346/265/201/346/260/264/347/272/277.md +0 -47
  296. package/templates/design//346/272/220/347/240/201/345/216/237/345/236/213/344/272/244/344/273/230.md +0 -58
  297. package/templates/design//347/216/260/346/234/211/347/263/273/347/273/237/345/267/256/350/267/235/345/210/206/346/236/220.md +0 -114
  298. package/templates/design//347/237/245/350/257/206/347/273/264/346/212/244/346/265/201/346/260/264/347/272/277.md +0 -64
  299. package/templates/design//347/254/254/344/270/200/346/200/247/345/216/237/347/220/206/346/216/250/347/220/206.md +0 -182
  300. package/templates/design//347/264/247/346/200/245/345/233/236/346/273/232/346/211/213/345/206/214.md +0 -77
  301. package/templates/design//347/274/226/347/240/201/345/211/215/346/276/204/346/270/205.md +0 -85
  302. package/templates/design//350/200/201/347/263/273/347/273/237/345/210/207/347/211/207/350/247/204/345/210/222.md +0 -48
  303. package/templates/design//350/207/252/344/270/273/351/200/211/345/236/213.md +0 -57
  304. package/templates/design//350/256/276/350/256/241/344/270/200/350/207/264/346/200/247/351/252/214/346/224/266/346/212/245/345/221/212.md +0 -34
  305. package/templates/design//350/256/276/350/256/241/344/272/247/347/211/251/347/224/237/346/210/220/344/270/216/345/244/215/351/252/214.md +0 -60
  306. package/templates/design//350/256/276/350/256/241/350/201/232/345/220/210/346/243/200/346/237/245.md +0 -21
  307. package/templates/design//350/257/246/347/273/206/350/256/276/350/256/241-procedures.md +0 -123
  308. package/templates/design//350/257/246/347/273/206/350/256/276/350/256/241.md +0 -109
  309. package/templates/design//350/257/246/347/273/206/350/256/276/350/256/241/345/256/241/346/237/245.md +0 -88
  310. package/templates/design//350/260/203/350/257/225/346/226/271/346/263/225/350/256/272.md +0 -43
  311. package/templates/design//350/277/201/347/247/273/350/257/204/344/274/260.md +0 -67
  312. package/templates/design//351/232/224/347/246/273/351/200/202/351/205/215/345/231/250/346/226/271/346/241/210.md +0 -44
  313. package/templates/design//351/234/200/346/261/202/346/276/204/346/270/205.md +0 -65
  314. package/templates/design//351/234/200/346/261/202/350/264/250/351/207/217/345/256/241/346/237/245.md +0 -88
  315. package/templates/design//351/242/206/345/237/237/351/251/261/345/212/250/350/256/276/350/256/241.md +0 -43
  316. package/templates/operate//345/217/221/345/270/203/350/257/264/346/230/216/345/256/241/346/237/245.md +0 -60
  317. package/templates/operate//350/277/220/347/273/264/350/201/232/345/220/210/346/243/200/346/237/245.md +0 -22
  318. package/templates/operate//351/203/250/347/275/262/351/205/215/347/275/256/345/256/241/346/237/245.md +0 -59
  319. package/templates/shared/Diff/345/275/222/345/261/236/350/277/275/350/270/252.md +0 -55
  320. package/templates/shared/Java/350/264/250/351/207/217/351/227/250/347/246/201.md +0 -54
  321. package/templates/shared/OOD/344/270/216SOLID/350/256/276/350/256/241.md +0 -48
  322. package/templates/shared//344/272/247/347/211/251Schema/346/263/250/345/206/214/344/270/255/345/277/203.md +0 -57
  323. package/templates/shared//344/272/247/347/211/251/345/245/221/347/272/246.md +0 -44
  324. package/templates/shared//344/273/243/347/240/201/346/263/250/351/207/212/344/270/216/346/227/245/345/277/227/345/245/221/347/272/246.md +0 -116
  325. package/templates/shared//344/273/273/345/212/241/344/270/212/344/270/213/346/226/207/347/224/237/345/221/275/345/221/250/346/234/237.md +0 -45
  326. package/templates/shared//344/273/273/345/212/241/347/212/266/346/200/201/346/234/272.md +0 -55
  327. package/templates/shared//344/273/273/345/212/241/347/256/241/347/220/206/345/231/250.md +0 -55
  328. package/templates/shared//344/274/230/351/233/205/345/201/234/346/234/272.md +0 -43
  329. package/templates/shared//344/275/234/347/224/250/345/237/237/344/270/216/345/257/206/351/222/245/346/213/246/346/210/252.md +0 -54
  330. package/templates/shared//344/275/234/347/224/250/345/237/237/347/247/237/347/272/246.md +0 -55
  331. package/templates/shared//345/206/262/347/252/201/351/227/250/347/246/201.md +0 -55
  332. package/templates/shared//345/206/263/347/255/226/347/275/221/345/205/263.md +0 -47
  333. package/templates/shared//345/210/207/347/211/207/350/201/232/345/220/210/346/243/200/346/237/245.md +0 -72
  334. package/templates/shared//345/217/230/345/274/202/345/256/241/350/256/241.md +0 -58
  335. package/templates/shared//345/220/216/347/253/257/345/256/236/347/216/260/345/267/245/347/250/213/345/245/221/347/272/246.md +0 -40
  336. package/templates/shared//345/221/275/344/273/244/346/211/247/350/241/214.md +0 -48
  337. package/templates/shared//345/221/275/344/273/244/350/267/257/347/224/261.md +0 -45
  338. package/templates/shared//345/233/236/345/275/222/347/237/251/351/230/265.md +0 -54
  339. package/templates/shared//345/244/232/347/247/237/346/210/267.md +0 -49
  340. package/templates/shared//345/256/241/350/256/241/346/227/245/345/277/227.md +0 -46
  341. package/templates/shared//345/257/274/345/205/245/345/257/274/345/207/272.md +0 -51
  342. package/templates/shared//345/267/245/344/275/234/345/214/272/344/272/222/346/226/245/351/224/201.md +0 -52
  343. package/templates/shared//345/267/245/344/275/234/345/214/272/345/224/244/351/206/222.md +0 -54
  344. package/templates/shared//345/267/245/344/275/234/346/265/201/345/245/221/347/272/246.md +0 -42
  345. package/templates/shared//345/267/245/344/275/234/346/265/201/345/274/225/346/223/216.md +0 -50
  346. package/templates/shared//345/267/245/344/275/234/346/265/201/346/250/241/347/211/210/345/214/205.md +0 -34
  347. package/templates/shared//345/267/245/345/205/267/350/260/203/347/224/250.md +0 -48
  348. package/templates/shared//345/271/266/345/217/221/351/224/201.md +0 -57
  349. package/templates/shared//346/211/247/350/241/214/345/256/210/345/215/253/350/257/204/344/274/260.md +0 -47
  350. package/templates/shared//346/211/251/345/261/225/347/224/237/345/221/275/345/221/250/346/234/237.md +0 -34
  351. package/templates/shared//346/212/200/346/234/257/345/206/263/347/255/226/344/270/273/346/235/203.md +0 -50
  352. package/templates/shared//346/212/245/350/241/250/347/273/237/350/256/241.md +0 -50
  353. package/templates/shared//346/224/257/344/273/230.md +0 -51
  354. package/templates/shared//346/225/217/346/204/237/344/277/241/346/201/257/345/244/204/347/220/206.md +0 -77
  355. package/templates/shared//346/225/217/346/204/237/344/277/241/346/201/257/346/211/253/346/217/217.md +0 -53
  356. package/templates/shared//346/225/260/346/215/256/346/235/203/351/231/220.md +0 -47
  357. package/templates/shared//346/226/275/345/267/245/346/214/207/344/273/244/345/245/221/347/272/246.md +0 -69
  358. package/templates/shared//346/227/245/345/277/227/346/262/273/347/220/206.md +0 -31
  359. package/templates/shared//346/234/272/345/210/266/350/207/252/346/262/273/347/220/206.md +0 -31
  360. package/templates/shared//346/240/207/345/207/206/350/265/204/344/272/247/350/246/206/347/233/226.md +0 -50
  361. package/templates/shared//346/240/270/345/277/203/344/275/223/351/252/214/345/216/237/345/210/231.md +0 -38
  362. package/templates/shared//346/240/270/345/277/203/345/267/245/347/250/213/346/211/247/350/241/214/345/216/237/345/210/231.md +0 -154
  363. package/templates/shared//346/250/241/347/211/210Frontmatter.md +0 -125
  364. package/templates/shared//346/250/241/347/211/210/350/264/241/347/214/256/346/214/207/345/215/227.md +0 -282
  365. package/templates/shared//346/250/241/347/211/210/350/265/204/344/272/247/345/217/257/350/247/201/346/200/247.md +0 -48
  366. package/templates/shared//346/262/273/347/220/206/350/277/220/350/241/214/346/227/266/345/276/252/347/216/257.md +0 -56
  367. package/templates/shared//346/263/250/345/206/214/350/241/250/345/237/272/347/241/200/350/256/276/346/226/275.md +0 -49
  368. package/templates/shared//346/274/224/350/277/233/345/233/236/345/275/222/351/227/250/346/216/247.md +0 -50
  369. package/templates/shared//347/224/250/346/210/267/345/217/215/351/246/210/345/245/221/347/272/246.md +0 -86
  370. package/templates/shared//347/237/245/350/257/206/344/270/273/346/235/203.md +0 -66
  371. package/templates/shared//347/237/245/350/257/206/346/262/273/347/220/206.md +0 -31
  372. package/templates/shared//347/237/245/350/257/206/346/263/250/345/205/245/350/276/271/347/225/214.md +0 -47
  373. package/templates/shared//347/273/206/350/212/202/347/272/252/345/276/213.md +0 -54
  374. package/templates/shared//350/204/221/346/232/264/344/270/216/346/226/271/346/241/210/346/216/242/347/264/242.md +0 -51
  375. package/templates/shared//350/256/241/345/210/222/345/211/215/347/275/256/351/227/250.md +0 -47
  376. package/templates/shared//350/256/276/350/256/241/344/272/247/347/211/251/345/214/205.md +0 -58
  377. package/templates/shared//350/257/255/344/271/211/350/257/201/346/215/256.md +0 -55
  378. package/templates/shared//350/267/250/345/271/263/345/217/260/350/267/257/345/276/204/345/256/211/345/205/250.md +0 -41
  379. package/templates/shared//350/276/223/345/205/245/346/235/220/346/226/231/345/245/221/347/272/246.md +0 -50
  380. package/templates/shared//350/277/220/350/241/214/345/256/211/345/205/250/345/214/205.md +0 -58
  381. package/templates/shared//351/200/232/347/224/250/345/206/263/347/255/226/347/240/224/350/256/250.md +0 -62
  382. package/templates/shared//351/200/232/347/224/250/346/234/272/346/242/260/346/235/241/346/254/276.md +0 -47
  383. package/templates/shared//351/200/232/347/237/245.md +0 -50
  384. package/templates/shared//351/203/250/347/275/262/351/205/215/347/275/256.md +0 -14
  385. package/templates/shared//351/205/215/347/275/256/344/274/230/345/205/210/347/272/247.md +0 -67
  386. package/templates/shared//351/205/215/347/275/256/350/220/275/347/233/230/350/276/271/347/225/214.md +0 -32
  387. package/templates/shared//351/230/262/345/255/244/345/262/233/345/256/236/347/216/260.md +0 -51
  388. package/templates/shared//351/233/266/351/205/215/347/275/256/345/210/235/345/247/213/345/214/226.md +0 -57
  389. package/templates/shared//351/252/214/346/224/266/346/250/241/347/211/210/350/276/223/345/207/272/345/245/221/347/272/246.md +0 -71
  390. package/templates/shared//351/252/214/350/257/201/345/221/275/344/273/244/347/224/237/346/210/220.md +0 -55
  391. package/templates/shared//351/252/214/350/257/201/345/245/221/347/272/246.md +0 -48
  392. package/templates/verify/Docker/351/203/250/347/275/262.md +0 -46
  393. package/templates/verify/POC/347/273/223/350/256/272.md +0 -53
  394. package/templates/verify/React/345/210/227/350/241/250/350/241/250/346/240/274.md +0 -43
  395. package/templates/verify/React/347/212/266/346/200/201/347/256/241/347/220/206.md +0 -42
  396. package/templates/verify/React/347/273/204/344/273/266.md +0 -42
  397. package/templates/verify/React/350/241/250/345/215/225.md +0 -43
  398. package/templates/verify/React/350/267/257/347/224/261.md +0 -43
  399. package/templates/verify/SOLID/344/273/243/347/240/201/345/256/241/346/237/245.md +0 -74
  400. package/templates/verify/SOLID/350/256/276/350/256/241.md +0 -31
  401. package/templates/verify/Schema/345/205/274/345/256/271.md +0 -42
  402. package/templates/verify/Vue/347/212/266/346/200/201/347/256/241/347/220/206.md +0 -42
  403. package/templates/verify/Vue/347/273/204/344/273/266.md +0 -42
  404. package/templates/verify/Vue/350/267/257/347/224/261.md +0 -43
  405. package/templates/verify//344/270/212/346/270/270/350/256/276/350/256/241/344/272/244/345/217/211/351/252/214/350/257/201/345/256/241/346/237/245.md +0 -76
  406. package/templates/verify//344/270/273/351/223/276/350/267/257/346/216/245/345/205/245.md +0 -38
  407. package/templates/verify//344/272/213/344/273/266/351/251/261/345/212/250.md +0 -46
  408. package/templates/verify//344/272/213/345/212/241/346/250/241/345/274/217.md +0 -42
  409. package/templates/verify//344/273/243/347/240/201/345/217/257/347/273/264/346/212/244/346/200/247/344/270/216/345/217/257/350/247/202/346/265/213/346/200/247/345/256/241/346/237/245.md +0 -92
  410. package/templates/verify//344/273/243/347/240/201/346/263/250/351/207/212/344/270/216/346/227/245/345/277/227/351/252/214/346/224/266.md +0 -64
  411. package/templates/verify//344/274/232/350/257/235/346/201/242/345/244/215.md +0 -46
  412. package/templates/verify//345/206/263/347/255/226/345/256/214/346/225/264/346/200/247/345/256/241/346/237/245.md +0 -71
  413. package/templates/verify//345/210/206/351/241/265/346/237/245/350/257/242.md +0 -41
  414. package/templates/verify//345/211/215/347/253/257/351/241/265/351/235/242.md +0 -40
  415. package/templates/verify//345/216/206/345/217/262/346/225/260/346/215/256/346/270/205/346/264/227/350/204/232/346/234/254.md +0 -55
  416. package/templates/verify//345/217/221/345/270/203/345/220/216/345/256/241/346/237/245.md +0 -73
  417. package/templates/verify//345/220/216/347/253/257API.md +0 -39
  418. package/templates/verify//345/242/236/345/210/240/346/224/271/346/237/245.md +0 -45
  419. package/templates/verify//345/244/226/351/203/250/344/276/235/350/265/226.md +0 -43
  420. package/templates/verify//345/245/221/347/272/246/345/205/274/345/256/271.md +0 -42
  421. package/templates/verify//345/256/232/346/227/266/344/273/273/345/212/241.md +0 -39
  422. package/templates/verify//345/256/236/346/227/266/346/216/250/351/200/201.md +0 -48
  423. package/templates/verify//345/256/241/346/237/245/346/221/230/350/246/201.md +0 -58
  424. package/templates/verify//345/267/245/344/275/234/346/265/201.md +0 -38
  425. package/templates/verify//345/271/266/345/217/221/345/256/241/346/237/245.md +0 -132
  426. package/templates/verify//345/274/202/346/255/245/345/257/274/345/207/272.md +0 -41
  427. package/templates/verify//346/200/247/350/203/275/345/256/241/346/237/245.md +0 -110
  428. package/templates/verify//346/216/245/345/217/243/345/245/221/347/272/246.md +0 -44
  429. package/templates/verify//346/216/245/345/217/243/345/245/221/347/272/246/345/256/241/346/237/245.md +0 -131
  430. package/templates/verify//346/220/234/347/264/242/346/250/241/345/274/217.md +0 -47
  431. package/templates/verify//346/225/205/351/232/234/345/244/215/347/233/230.md +0 -67
  432. package/templates/verify//346/225/260/346/215/256/345/272/223/345/217/230/346/233/264.md +0 -37
  433. package/templates/verify//346/225/260/346/215/256/351/232/220/347/247/201.md +0 -46
  434. package/templates/verify//346/226/207/344/273/266/344/270/212/344/274/240.md +0 -45
  435. package/templates/verify//346/227/245/345/277/227.md +0 -45
  436. package/templates/verify//346/234/254/345/234/260/346/265/217/350/247/210/345/231/250/351/252/214/346/224/266.md +0 -94
  437. package/templates/verify//346/240/270/345/277/203/345/267/245/347/250/213/346/211/247/350/241/214.md +0 -65
  438. package/templates/verify//347/237/245/350/257/206/346/263/250/345/205/245.md +0 -38
  439. package/templates/verify//347/264/247/346/200/245/344/277/256/345/244/215/346/265/201/346/260/264/347/272/277.md +0 -76
  440. package/templates/verify//347/274/223/345/255/230/347/255/226/347/225/245.md +0 -45
  441. package/templates/verify//350/201/224/350/260/203/350/256/276/350/256/241/347/274/272/351/231/267/345/210/244/345/256/232.md +0 -67
  442. package/templates/verify//350/201/224/350/260/203/351/252/214/350/257/201.md +0 -87
  443. package/templates/verify//350/256/276/350/256/241/345/256/241/350/256/241.md +0 -184
  444. package/templates/verify//350/257/225/350/277/220/350/241/214/347/206/224/346/226/255.md +0 -74
  445. package/templates/verify//350/276/223/345/205/245/346/240/241/351/252/214.md +0 -44
  446. package/templates/verify//351/203/250/347/275/262/345/217/221/345/270/203.md +0 -101
  447. package/templates/verify//351/224/231/350/257/257/345/244/204/347/220/206.md +0 -46
  448. package/templates/verify//351/224/231/350/257/257/350/276/271/347/225/214.md +0 -38
  449. package/templates/verify//351/232/220/347/247/201/345/256/241/346/237/245.md +0 -37
  450. package/templates/verify//351/252/214/350/257/201.md +0 -38
  451. package/templates/verify//351/252/214/350/257/201/350/201/232/345/220/210/346/243/200/346/237/245.md +0 -22
@@ -12,18 +12,22 @@
12
12
  * 持久化:verify 时写 GateRecord
13
13
  */
14
14
  import { existsSync } from "node:fs";
15
+ import { join } from "node:path";
15
16
  import { z } from "zod";
16
17
  import { createToolRegistrar } from "./middleware.js";
17
18
  import { initializeDomainEngines, ALL_CONTRACTS } from "../../domain/index.js";
18
19
  import { DomainRegistry } from "../../domain/registry.js";
19
20
  import { GateRecordStore } from "../../core/gate_record_store.js";
21
+ import { AdversarialReviewStore, MAX_REVIEW_ROUNDS, checkConvergence, checkOscillation, diffErrors, countBySeverity, } from "../../core/adversarial_review_store.js";
20
22
  import { isTransitionAllowed, detectLoop } from "../../core/domain_transition.js";
21
- import { checkScope } from "../../core/scope_checker.js";
22
23
  import { getFileGitHash } from "../../core/git_utils.js";
23
- import { loadGatesForDomain, evaluateGate } from "../../gate/gate_engine.js";
24
+ import { loadGatesForDomain, evaluateGate, computeRulesetHash } from "../../gate/gate_engine.js";
24
25
  import { resolveConfig } from "../../context/config/resolver.js";
25
26
  import { debug } from "../../shared/logger.js";
26
27
  import { SF_WORK_ACTIONS } from "../../gate/contracts/tool_actions.js";
28
+ import { CROSS_VALIDATION_ARTIFACT_PATHS } from "../../gate/executors/executors_trace.js";
29
+ import { discoverSourceRoots } from "../../gate/scope_resolver.js";
30
+ import { aggregateMultiSrcHash } from "../../domain/engine_helpers.js";
27
31
  /** system_context(greenfield/brownfield)→ SystemType(新系统/老系统)映射 */
28
32
  function toSystemType(ctx) {
29
33
  return ctx === "brownfield" ? "老系统" : "新系统";
@@ -31,16 +35,20 @@ function toSystemType(ctx) {
31
35
  /** sf_work 参数 schema */
32
36
  const sfWorkSchema = {
33
37
  domain: z.enum(["design", "build", "verify", "operate"]).describe("目标域"),
34
- action: z.enum(SF_WORK_ACTIONS).describe("动作:observe=查看状态 / act=获取 prompt / verify=执行门禁"),
38
+ action: z.enum(SF_WORK_ACTIONS).describe("动作:observe=查看状态 / deliberate=产出前条件研讨(有疑问才触发头脑风暴+第一性原理,无疑问举证一行) / act=获取 prompt / verify=执行门禁 / adversarial_review=对抗审查(per-artifact 单产物 / cross-artifact 跨产物,loop-until-dry 零 error 收敛、多利益方独立对抗)"),
35
39
  target: z.string().optional().describe("目标产物 kind(act 时必填)"),
36
40
  artifact_path: z.string().optional().describe("产物路径(verify 时指定)"),
41
+ artifact: z.string().optional().describe("对抗审查指定单产物 kind(adversarial_review per-artifact 模式;不传=cross-artifact 跨产物)"),
42
+ round: z.number().optional().describe("对抗审查轮次(1=首轮新建会话;>=2=后续轮,须带 review_id + findings)"),
43
+ review_id: z.string().optional().describe("对抗审查会话 ID(round>=2 必填,首轮返回)"),
44
+ findings: z.array(z.any()).optional().describe("对抗审查本轮发现(round>=2 客户端结构化提交:[{severity:'error|warning|info', artifact, location, quote, issue, suggestion}])"),
37
45
  };
38
46
  // 缓存域引擎注册表(每个 projectRoot 一个)
39
47
  const registryCache = new Map();
40
48
  export async function registerSfWorkTools(ctx) {
41
49
  const { registerSafeTool } = createToolRegistrar(ctx);
42
50
  const projectRoot = ctx.projectPath;
43
- registerSafeTool("sf_work", "域工作工具。observe:派生当前域状态。act:获取工作 prompt(AI 按此写文件)。verify:执行门禁检查。", sfWorkSchema, async (args) => {
51
+ registerSafeTool("sf_work", "域工作工具。observe:派生当前域状态。act:获取工作 prompt(AI 按此写文件)。verify:执行门禁检查。adversarial_review:排独立 agent 对抗审查所有产物(产物校验标准环节,不论门禁通过与否)。", sfWorkSchema, async (args) => {
44
52
  const domain = args.domain;
45
53
  const action = args.action;
46
54
  try {
@@ -83,9 +91,15 @@ export async function registerSfWorkTools(ctx) {
83
91
  if (action === "observe") {
84
92
  return await handleObserve(engine, task);
85
93
  }
94
+ else if (action === "deliberate") {
95
+ return await handleDeliberate(engine, task, args, projectRoot);
96
+ }
86
97
  else if (action === "act") {
87
98
  return await handleAct(engine, task, args, projectRoot);
88
99
  }
100
+ else if (action === "adversarial_review") {
101
+ return await handleAdversarialReview(projectRoot, task, args, taskContext);
102
+ }
89
103
  else {
90
104
  return await handleVerify(engine, task, projectRoot, taskContext, args);
91
105
  }
@@ -117,48 +131,189 @@ async function handleObserve(engine, task) {
117
131
  verified_artifacts: state.verified_artifacts.map((a) => a.kind),
118
132
  missing_upstream: state.missing_upstream,
119
133
  stale_gates: state.stale_gates.length,
134
+ blocked_artifacts: state.blocked_artifacts?.map((b) => ({ artifact: b.artifact.kind, blocked_by: b.blocked_by })),
135
+ ordered_plan: state.ordered_plan,
120
136
  pending_return: state.pending_return,
121
- next_step: state.pending_artifacts.length > 0
122
- ? `调用 sf_work domain="${state.current_domain}" action="act" target="${state.pending_artifacts[0].kind}"`
123
- : state.unverified_artifacts.length > 0
124
- ? `调用 sf_work domain="${state.current_domain}" action="verify"`
125
- : "所有产物已验证通过",
137
+ next_step: !state.ordered_plan || state.ordered_plan.length === 0
138
+ ? "所有产物已验证通过"
139
+ : state.ordered_plan[0].action === "wait"
140
+ ? `等待:${state.ordered_plan[0].kind}(${state.ordered_plan[0].reason})`
141
+ : `按 ordered_plan 推进,当前:sf_work domain="${state.current_domain}" action="${state.ordered_plan[0].action}" target="${state.ordered_plan[0].kind}"`,
126
142
  },
127
143
  };
128
144
  }
129
145
  /** act:组装 prompt */
130
- async function handleAct(engine, task, args, projectRoot) {
146
+ export async function handleAct(engine, task, args, projectRoot) {
131
147
  const target = args.target;
132
148
  if (!target) {
133
149
  return { result: { success: false, error: "act 时 target 必填(产物 kind)" } };
134
150
  }
151
+ // target 须是当前域产物(否则 engine.act 抛错,非 graceful)— 门禁前校验,返回可用清单
152
+ if (!engine.contract.produces.some((a) => a.kind === target)) {
153
+ return { result: {
154
+ success: false,
155
+ error: `「${target}」非本域(${engine.contract.name})产物。可用:${engine.contract.produces.map((a) => a.kind).join(", ")}`,
156
+ } };
157
+ }
158
+ // 架构决策研讨门禁(仅 design 域;内部 requiresArchitectureDecisionWorkshop 按 intent 判断是否真进,非架构意图自动放行)
159
+ if (engine.contract.name === "design") {
160
+ const { checkArchitectureDecisionWorkshopGate } = await import("../../gate/gate_checks.js");
161
+ const gateResult = await checkArchitectureDecisionWorkshopGate({ ctx: task, workflowIntent: task.intent });
162
+ if (!gateResult.allowed) {
163
+ return { result: {
164
+ success: false,
165
+ error: gateResult.findings?.join("; ") ?? "架构决策研讨门禁未通过",
166
+ gate_blocked: true,
167
+ recovery_guide: gateResult.recovery_guide_zh,
168
+ next_domain: gateResult.next_domain,
169
+ next_step: gateResult.recovery_guide_zh
170
+ ? `按恢复指引逐域确认。下一个待确认域: ${gateResult.next_domain},调 sf_task action=confirm_decisions`
171
+ : "架构决策研讨未完成",
172
+ } };
173
+ }
174
+ }
175
+ // ── act 可做性门禁(①②③ 确定性 enforced,复用 observe 派生,闭环「以 ordered_plan 为准」)──
176
+ // ④ 按序不强制(ordered_plan 仅软指引),避免误伤合法顺序调整
177
+ const eligibility = await engine.observe(task);
178
+ // 共用:target 已存在(重写:未验证 Reflexion 修复 / 已验证演进)→ ②③放行
179
+ // 重写不依赖上游新增(②)、不算并行开新产物(③)
180
+ const isRewrite = eligibility.unverified_artifacts.some((a) => a.kind === target)
181
+ || eligibility.verified_artifacts.some((a) => a.kind === target);
182
+ // ② 跨域缺上游 + 新产物 → 拒(重写放行:Reflexion 修复/演进不依赖上游新增,如 design 未验时 build code 重写修 lazy)
183
+ if (eligibility.missing_upstream.length > 0 && !isRewrite) {
184
+ const missing = eligibility.missing_upstream.map((u) => `${u.from_domain}.${u.artifact_kind}`).join("、");
185
+ return { result: {
186
+ success: false,
187
+ gate_blocked: true,
188
+ error: `本域缺上游产物(${missing})未通过门禁,不能 act 新产物「${target}」。先回上游域产出并 verify。(重写已有产物不拦:target 传该产物)`,
189
+ next_step: `先在上游域产出并 verify:${missing},再回本域 act`,
190
+ } };
191
+ }
192
+ // ① target 被同域依赖阻塞 → 拒(depends_on 未 verify)
193
+ const blockedBy = eligibility.blocked_artifacts?.find((b) => b.artifact.kind === target)?.blocked_by;
194
+ if (blockedBy) {
195
+ return { result: {
196
+ success: false,
197
+ gate_blocked: true,
198
+ error: `产物「${target}」被同域依赖阻塞,需先 verify:${blockedBy.join("、")}`,
199
+ next_step: `先 sf_work action="verify" 验证:${blockedBy.join("、")},再 act「${target}」`,
200
+ } };
201
+ }
202
+ // ③ 不并行/不跳步:存在未验证产物且 target 是新产物(pending,非重写)→ 拒(单产物推进)
203
+ // target ∈ unverified|verified → 放行(重写:Reflexion 修复 / 已验证演进,单产物迭代不算并行)
204
+ if (!isRewrite && eligibility.unverified_artifacts.length > 0) {
205
+ const unverified = eligibility.unverified_artifacts.map((a) => a.kind).join("、");
206
+ return { result: {
207
+ success: false,
208
+ gate_blocked: true,
209
+ error: `存在未验证产物(${unverified}),先 verify 再 act 新产物(单产物推进,不并行/不跳步)。若要重写产物(未验证修复 / 已验证演进),target 传该产物。`,
210
+ next_step: `先 sf_work action="verify" 验证:${unverified}`,
211
+ } };
212
+ }
213
+ // ④ 对抗审查不可省(新产物 act 前):当前域 + 上游域 verified 产物须都有 per_artifact 对抗审查
214
+ // enforce 第80行「adversarial_review 独立审查不可省」——防 AI 选择性跳审(如 db/api/slice_plan)
215
+ // 跨域 act(进 build)时查上游域(design)全 verified,堵每域最后产物漏审
216
+ // (design slice_plan 是 design 最后产物,无后续同域 act 触发④,靠跨域 build act 时查上游补)
217
+ // isRewrite(重写修复/演进)放行:单产物迭代不算开新产物,不截断 Reflexion(同②③,对称)
218
+ if (!isRewrite) {
219
+ const adversarialStore = new AdversarialReviewStore(projectRoot);
220
+ const reviews = await adversarialStore.listByTask(task.task_id);
221
+ // converged 收敛 或 escalated 升级人工 都算「审过」(oscillated 震荡未收敛不算,须再审)
222
+ const reviewedKinds = new Set(reviews.filter((r) => r.mode === "per_artifact" && (r.converged || r.status === "escalated")).map((r) => r.artifact_path));
223
+ // 需审 verified:当前域 + 上游域(跨域查上游堵最后产物漏审)
224
+ const domainsToCheck = new Set([engine.contract.name]);
225
+ for (const req of engine.contract.requires_upstream)
226
+ domainsToCheck.add(req.from_domain);
227
+ const reviewRegistry = getOrCreateRegistry(projectRoot);
228
+ const unreviewed = [];
229
+ for (const dName of domainsToCheck) {
230
+ const dEngine = dName === engine.contract.name ? engine : reviewRegistry.get(dName);
231
+ if (!dEngine)
232
+ continue;
233
+ let dState = eligibility;
234
+ if (dName !== engine.contract.name) {
235
+ // observe 按 task.domain_focus 取域(observer.deriveState 用 ALL_CONTRACTS + domain_focus),
236
+ // 查上游域须临时切 domain_focus 到 dName,observe 后恢复(try/finally,单线程无并发)
237
+ const origDomain = task.domain_focus;
238
+ task.domain_focus = dName;
239
+ try {
240
+ dState = await dEngine.observe(task);
241
+ }
242
+ finally {
243
+ task.domain_focus = origDomain;
244
+ }
245
+ }
246
+ for (const a of dState.verified_artifacts) {
247
+ if (!reviewedKinds.has(a.kind))
248
+ unreviewed.push(a.kind);
249
+ }
250
+ }
251
+ if (unreviewed.length > 0) {
252
+ const unreviewedList = unreviewed.join("、");
253
+ return { result: {
254
+ success: false,
255
+ gate_blocked: true,
256
+ error: `已验证产物未做 per_artifact 对抗审查:${unreviewedList}。adversarial_review 独立审查不可省(所有域所有产物),先审再推进下一个产物。`,
257
+ next_step: `逐个调 sf_work action="adversarial_review" artifact="<kind>" 审:${unreviewedList}`,
258
+ } };
259
+ }
260
+ }
261
+ // ⑤ cross-artifact 不可省(跨域推进前,上游域所有产物做跨产物独立审查:多利益方独立对抗 + 跨产物一致性 + 完整性 + 研讨充分性)
262
+ // 触发:!isRewrite(新产物)+ requires_upstream 非空(进下游域 build/verify/operate)。design 域无上游不触发(域内推进)。
263
+ if (!isRewrite && engine.contract.requires_upstream.length > 0) {
264
+ const xStore = new AdversarialReviewStore(projectRoot);
265
+ const xReviews = await xStore.listByTask(task.task_id);
266
+ const xPerArtifacts = xReviews.filter((r) => r.mode === "per_artifact");
267
+ const xCrossArtifacts = xReviews.filter((r) => r.mode === "cross_artifact" && (r.converged || r.status === "escalated"));
268
+ const xCrossLatest = xCrossArtifacts.sort((a, b) => b.updated_at - a.updated_at)[0];
269
+ if (!xCrossLatest) {
270
+ return { result: {
271
+ success: false,
272
+ gate_blocked: true,
273
+ error: `跨域推进前须做 cross-artifact 对抗审查(上游域所有产物:多利益方独立对抗 + 跨产物一致性 + 完整性 + 研讨充分性),当前无收敛记录。`,
274
+ next_step: `调 sf_work action="adversarial_review"(不传 artifact,cross-artifact 审当前域所有产物),loop-until-dry 零 error 收敛后再推进下一域`,
275
+ } };
276
+ }
277
+ const xLatestPer = xPerArtifacts.sort((a, b) => b.updated_at - a.updated_at)[0];
278
+ if (xLatestPer && xCrossLatest.updated_at < xLatestPer.updated_at) {
279
+ return { result: {
280
+ success: false,
281
+ gate_blocked: true,
282
+ error: `cross-artifact 审查已过时(在最新 per-artifact 审查之前)。上游域最新产物产出后须重新 cross-artifact 审。`,
283
+ next_step: `调 sf_work action="adversarial_review"(不传 artifact)重审当前域所有产物,收敛后再推进`,
284
+ } };
285
+ }
286
+ }
135
287
  // 加载上游产物内容(从文件系统读取真实内容)
136
288
  const upstream = await loadUpstreamContent(task, engine, args, projectRoot);
289
+ // 注入域内研讨记录为上游(deliberate 对话研讨后总结留痕,act 承接研讨结论;研讨记录在 docs/研讨记录/{域中文}/)
290
+ const actArtifact = engine.contract.produces.find((a) => a.kind === target);
291
+ if (actArtifact) {
292
+ const { deliberationRecordPath } = await import("../../domain/engine_helpers.js");
293
+ const deliberationPath = deliberationRecordPath(engine.contract.name, actArtifact);
294
+ if (existsSync(join(projectRoot, deliberationPath))) {
295
+ try {
296
+ const { readFileSync } = await import("node:fs");
297
+ const content = readFileSync(join(projectRoot, deliberationPath), "utf-8");
298
+ upstream["研讨记录"] = content.length > 8000 ? content.slice(0, 8000) + "\n...(研讨记录已截断)" : content;
299
+ }
300
+ catch {
301
+ // 读取失败忽略,act 仍可进行(研讨记录非必需上游)
302
+ }
303
+ }
304
+ }
137
305
  // 加载上次验证反馈(Reflexion 闭环:上次 verify 失败的真实 findings → 注入 prompt 让 AI 针对修复)
138
- const feedback = await loadLastVerifyFeedback(task, engine.contract.name, projectRoot);
306
+ // per-产物:只取当前 target 产物的失败记录(修 D8:多产物场景避免返回别的产物 findings 注入错位)
307
+ const actArtifactPath = engine.contract.produces.find((a) => a.kind === target)?.path_pattern;
308
+ const feedback = await loadLastVerifyFeedback(task, engine.contract.name, projectRoot, actArtifactPath);
139
309
  const result = await engine.act(task, target, upstream, feedback);
140
310
  // 注入工程指导(guidance)+ 自评清单
141
311
  const { loadGuidance } = await import("../../domain/engine_helpers.js");
142
- const guidance = loadGuidance(projectRoot, engine.contract.name, task.intent);
312
+ const guidance = loadGuidance(projectRoot, engine.contract.name, task.intent, target);
143
313
  if (guidance.fullText) {
144
314
  result.prompt = result.prompt.replace("## 要求", `## 工程参考\n\n### 本阶段可用经验\n${guidance.summary}\n\n${guidance.fullText}\n\n## 要求`);
145
315
  }
146
316
  result.self_review_checklist = guidance.checklist;
147
- // scope 硬检查:校验 act 返回的 allowed_paths
148
- if (result.scope?.allowed_paths && result.scope.allowed_paths.length > 0) {
149
- for (const p of result.scope.allowed_paths) {
150
- const scopeResult = checkScope(p, result.scope.allowed_paths, result.scope.read_only_paths);
151
- if (!scopeResult.allowed) {
152
- return {
153
- result: {
154
- success: false,
155
- error: `scope 检查失败:${scopeResult.reason}`,
156
- scope_violation: p,
157
- },
158
- };
159
- }
160
- }
161
- }
162
317
  return {
163
318
  result: {
164
319
  success: true,
@@ -170,6 +325,26 @@ async function handleAct(engine, task, args, projectRoot) {
170
325
  },
171
326
  };
172
327
  }
328
+ /** deliberate:组装产出前条件研讨 prompt(有疑问才触发头脑风暴+第一性原理,无疑问举证一行)。
329
+ * 产出研讨记录到 docs/deliberation/{domain}/{kind}-研讨记录.md,供后续 act 承接。
330
+ * SoloForge 不调 LLM——只组装 prompt,AI 自己写研讨记录。 */
331
+ export async function handleDeliberate(engine, task, args, projectRoot) {
332
+ const target = args.target;
333
+ if (!target) {
334
+ return { result: { success: false, error: "deliberate 时 target 必填(产物 kind)" } };
335
+ }
336
+ const upstream = await loadUpstreamContent(task, engine, args, projectRoot);
337
+ const result = await engine.deliberate(task, target, upstream);
338
+ return {
339
+ result: {
340
+ success: true,
341
+ prompt: result.prompt,
342
+ template: result.template,
343
+ scope: result.scope,
344
+ next_step: `按研讨纪律产出研讨记录(有疑问走四步法、无疑问举证一行),然后调 sf_work action="act" target="${target}" 承接研讨结论产出实际产物`,
345
+ },
346
+ };
347
+ }
173
348
  /** verify:执行门禁检查并持久化 GateRecord */
174
349
  async function handleVerify(engine, task, projectRoot, taskContext, args) {
175
350
  const gateStore = new GateRecordStore(projectRoot);
@@ -183,27 +358,40 @@ async function handleVerify(engine, task, projectRoot, taskContext, args) {
183
358
  return { result: { success: false, error: "未找到匹配的产物声明" } };
184
359
  }
185
360
  // 读取已有门禁记录,计算 retry_count
186
- const existingRecord = await gateStore.read(domain, artifact.gate);
361
+ const existingRecord = await gateStore.read(domain, artifact.gate, artifact.path_pattern);
187
362
  const retryCount = existingRecord ? existingRecord.retry_count : 0;
188
363
  // 检查是否超过重试限制
189
364
  if (retryCount >= 5) {
190
- // 治本:重试超限升级为业务终态 escalated(原 TaskStore.update({status:escalated}))
191
- await taskContext.updateStatus(task.task_id, "escalated");
192
- return {
193
- result: {
194
- success: false,
195
- error: `门禁重试次数已达上限(${retryCount}/5),任务已升级处理`,
196
- },
197
- };
365
+ // retry 超限:若产物已修复(git hash 变 = stale),允许重验(retry_count 通过时重置,给人工修复后恢复);
366
+ // 未修复(hash 同)→ 真超限升级 escalated(防无限重试)。
367
+ const fullChk = join(projectRoot, artifact.path_pattern);
368
+ const currentHash = existsSync(fullChk) ? await getFileGitHash(artifact.path_pattern, projectRoot) : "";
369
+ const fixed = !!existingRecord && existingRecord.artifact_git_hash !== currentHash;
370
+ if (!fixed) {
371
+ await taskContext.updateStatus(task.task_id, "escalated");
372
+ return {
373
+ result: {
374
+ success: false,
375
+ error: `门禁重试次数已达上限(${retryCount}/5),任务已升级处理。修复产物(改文件内容使 git hash 变)后重新 verify 可重置计数恢复`,
376
+ },
377
+ };
378
+ }
379
+ // 已修复 → 继续重验(passed 时 retry_count 写 0 重置,见下)
198
380
  }
199
- // 检查产物文件是否存在
381
+ // 检查产物文件是否存在。code 产物(path_pattern=src/)多工程下代码分布在 根/{端}/src/,
382
+ // 任一工程 src/ 存在即算产出(discoverSourceRoots 探测);其他产物按精确路径。
200
383
  const fullArtifactPath = `${projectRoot}/${artifact.path_pattern}`;
201
- const artifactExists = existsSync(fullArtifactPath);
384
+ const isMultiSrcArtifact = /(^|\/)src\/?$/.test(artifact.path_pattern);
385
+ const artifactExists = isMultiSrcArtifact
386
+ ? discoverSourceRoots(projectRoot).length > 0 || existsSync(fullArtifactPath)
387
+ : existsSync(fullArtifactPath);
202
388
  // 获取产物 git hash(防漂移)
203
389
  let artifactGitHash = "";
204
390
  if (artifactExists) {
205
391
  try {
206
- artifactGitHash = await getFileGitHash(artifact.path_pattern, projectRoot);
392
+ artifactGitHash = isMultiSrcArtifact
393
+ ? await aggregateMultiSrcHash(projectRoot)
394
+ : await getFileGitHash(artifact.path_pattern, projectRoot);
207
395
  }
208
396
  catch {
209
397
  artifactGitHash = "untracked";
@@ -234,7 +422,16 @@ async function handleVerify(engine, task, projectRoot, taskContext, args) {
234
422
  taskContext: task,
235
423
  };
236
424
  for (const gate of gates) {
237
- const result = await evaluateGate(gate, evalCtx);
425
+ // per-产物路由:只跑无 required_artifact 的通用 check + 命中当前 verify 产物的专属 check。
426
+ // 修复 per-域缺陷:此前 verify 任一产物跑整个 domain-gate,逐个产出时前面产物被后面章节检查阻断。
427
+ const filteredChecks = gate.checks.filter((c) => {
428
+ if (!c.required_artifact)
429
+ return true;
430
+ if (c.required_artifact === artifact.path_pattern)
431
+ return true;
432
+ return (CROSS_VALIDATION_ARTIFACT_PATHS[c.required_artifact] || []).includes(artifact.path_pattern);
433
+ });
434
+ const result = await evaluateGate({ ...gate, checks: filteredChecks }, evalCtx);
238
435
  if (!result.passed) {
239
436
  gatePassed = false;
240
437
  recoverySummary = result.recovery_summary || recoverySummary;
@@ -273,7 +470,32 @@ async function handleVerify(engine, task, projectRoot, taskContext, args) {
273
470
  });
274
471
  }
275
472
  }
473
+ // 完整性校验(根因治本:所有域所有产物的 references + companion_files 须存在,防引用悬空/附件遗漏)。
474
+ // 不靠手填 check.evidence_required,从 contract 声明派生——所有域所有产物 verify 时自动全覆盖。
475
+ const bundleMissing = [];
476
+ for (const ref of artifact.references ?? []) {
477
+ if (!existsSync(join(projectRoot, ref)))
478
+ bundleMissing.push(`引用悬空: ${ref}`);
479
+ }
480
+ for (const cf of artifact.companion_files ?? []) {
481
+ if (!existsSync(join(projectRoot, cf)))
482
+ bundleMissing.push(`附件缺失: ${cf}`);
483
+ }
484
+ for (const m of bundleMissing) {
485
+ gateFindings.push({
486
+ check_id: "bundle_integrity",
487
+ check_name: "产物完整性(引用/附件)",
488
+ passed: false,
489
+ severity: "error",
490
+ message: `产物 ${artifact.kind} ${m}`,
491
+ });
492
+ gatePassed = false;
493
+ }
276
494
  const passed = artifactExists && gatePassed;
495
+ // retry 超限恢复:任务因 retry 5 升级 escalated,人工修复后 verify 通过 → 恢复 executing(继续推进)
496
+ if (passed && task.status === "escalated") {
497
+ await taskContext.updateStatus(task.task_id, "executing");
498
+ }
277
499
  // 构建并持久化 GateRecord(task_id 用于 Reflexion 反馈闭环按 task 查询)
278
500
  const record = {
279
501
  domain: domain,
@@ -282,7 +504,7 @@ async function handleVerify(engine, task, projectRoot, taskContext, args) {
282
504
  artifact_path: artifact.path_pattern,
283
505
  artifact_git_hash: artifactGitHash,
284
506
  passed,
285
- retry_count: passed ? retryCount : retryCount + 1,
507
+ retry_count: passed ? 0 : retryCount + 1, // 通过则重置计数(新一轮),失败累计
286
508
  max_retries: 5,
287
509
  findings: !artifactExists
288
510
  ? [{ check_id: "artifact_exists", check_name: "产物存在性检查", passed: false, severity: "error", message: `产物文件 ${artifact.path_pattern} 不存在` }]
@@ -291,6 +513,7 @@ async function handleVerify(engine, task, projectRoot, taskContext, args) {
291
513
  ? `请先调用 sf_work domain="${domain}" action="act" target="${artifact.kind}" 生成产物`
292
514
  : (recoverySummary || undefined),
293
515
  evaluated_at: Date.now(),
516
+ ruleset_hash: computeRulesetHash(domain),
294
517
  };
295
518
  await gateStore.write(record);
296
519
  // 治本:检查 pending_return 恢复(通过后才恢复)
@@ -319,12 +542,292 @@ async function handleVerify(engine, task, projectRoot, taskContext, args) {
319
542
  gate_record: record,
320
543
  retry_count: record.retry_count,
321
544
  next_step: passed
322
- ? "门禁通过。可继续下一个产物或切换域。"
323
- : "门禁未通过。按 recovery_guidance 修复后重新 verify",
545
+ ? "门禁通过。建议调 sf_work action=adversarial_review 排独立 agent 对抗复审(产物校验标准环节,全新视角复核,不论门禁通过与否)。复审后再继续下一个产物或切换域。"
546
+ : "门禁未通过。按 recovery_guidance 修复后重新 verify;修复后建议 sf_work action=adversarial_review 排独立 agent 对抗复审。",
547
+ },
548
+ };
549
+ }
550
+ /** adversarial_review:对抗性独立审查(per-artifact 单产物 / cross-artifact 跨产物一致性)。
551
+ * SoloForge 不调 LLM——只组装 prompt 返回,AI 用独立 session/subagent 执行(避免确认偏见)。
552
+ * loop-until-dry:不限轮数,新一轮零 error 才达标;warning 软收敛记遗留;震荡/超轮熔断升级。
553
+ * 多利益方独立对抗:用户/攻击者/维护者/性能/合规 各自独立目标函数,避免单一视角确认偏见。 */
554
+ export async function handleAdversarialReview(projectRoot, task, args, taskContext) {
555
+ const store = new AdversarialReviewStore(projectRoot);
556
+ const round = typeof args.round === "number" ? args.round : 1;
557
+ const artifactKind = args.artifact;
558
+ // ── 首轮:创建会话,组装多利益方审查 prompt ──
559
+ if (round <= 1) {
560
+ const mode = artifactKind ? "per_artifact" : "cross_artifact";
561
+ const artifacts = await collectReviewArtifacts(projectRoot, mode, artifactKind);
562
+ const reviewId = store.generateReviewId();
563
+ const now = Date.now();
564
+ const record = {
565
+ review_id: reviewId,
566
+ task_id: task.task_id,
567
+ mode,
568
+ artifact_path: mode === "per_artifact" ? artifactKind : undefined, // per_artifact 模式此字段存 artifact **kind**(非文件路径);④门禁 reviewedKinds 据此比 verified_artifacts.kind——名实澄清(domain/core 审查),改存储格式需同步 ④比较+迁移旧记录
569
+ artifacts,
570
+ rounds: [],
571
+ total_rounds: 0,
572
+ converged: false,
573
+ oscillation_detected: false,
574
+ remaining_warnings: [],
575
+ status: "in_progress",
576
+ created_at: now,
577
+ updated_at: now,
578
+ };
579
+ await store.create(record);
580
+ const prompt = buildReviewPrompt(artifacts, mode, "");
581
+ return {
582
+ result: {
583
+ success: true,
584
+ action: "adversarial_review",
585
+ review_id: reviewId,
586
+ round: 1,
587
+ mode,
588
+ review_mode: mode === "per_artifact" ? "per-artifact 单产物深度对抗审查" : "cross-artifact 跨产物一致性对抗审查",
589
+ artifact_count: artifacts.length,
590
+ artifacts,
591
+ prompt,
592
+ next_step: `用独立 session/subagent 执行上述 prompt(勿在产出产物的同一 session 审查,避免确认偏见)。审查完把 findings 结构化带回:sf_work action="adversarial_review" round=2 review_id="${reviewId}" findings=[{severity,artifact,location,quote,issue,suggestion},...]`,
593
+ },
594
+ };
595
+ }
596
+ // ── 后续轮:处理 findings,判定收敛/震荡/超轮 ──
597
+ const reviewId = args.review_id;
598
+ if (!reviewId) {
599
+ return { result: { success: false, error: `round=${round} 须带 review_id(首轮返回的会话 ID)` } };
600
+ }
601
+ const record = await store.read(reviewId);
602
+ if (!record) {
603
+ return { result: { success: false, error: `review_id ${reviewId} 不存在(可能跨会话丢失)` } };
604
+ }
605
+ const findings = normalizeFindings(args.findings);
606
+ const prevRound = record.rounds[record.rounds.length - 1];
607
+ const { new_errors, fixed_errors } = diffErrors(prevRound, findings);
608
+ const { error_count, warning_count } = countBySeverity(findings);
609
+ const roundRecord = {
610
+ round,
611
+ findings,
612
+ error_count,
613
+ warning_count,
614
+ new_errors,
615
+ fixed_errors,
616
+ reviewed_at: Date.now(),
617
+ };
618
+ record.rounds.push(roundRecord);
619
+ record.total_rounds = round;
620
+ record.updated_at = Date.now();
621
+ // 收敛达标(连续一轮零 error;warning 软收敛记遗留)
622
+ if (checkConvergence(record.rounds)) {
623
+ record.status = "converged";
624
+ record.converged = true;
625
+ record.converged_round = round;
626
+ record.remaining_warnings = findings.filter((f) => f.severity === "warning");
627
+ await store.write(record);
628
+ return {
629
+ result: {
630
+ success: true,
631
+ action: "adversarial_review",
632
+ review_id: reviewId,
633
+ round,
634
+ review_status: "converged",
635
+ round_summary: { errors: error_count, warnings: warning_count, new_errors, fixed_errors },
636
+ remaining_warnings: record.remaining_warnings.length,
637
+ converged: true,
638
+ next_step: `对抗审查达标(连续一轮零 error)。${record.remaining_warnings.length} 个 warning 记为遗留项(软收敛,不阻断交付)。可继续下一产物或切换域。`,
639
+ },
640
+ };
641
+ }
642
+ // 震荡熔断(连续多轮修一个引入一个,问题集合不收敛)
643
+ if (checkOscillation(record.rounds)) {
644
+ record.status = "oscillated";
645
+ record.oscillation_detected = true;
646
+ record.oscillation_round = round;
647
+ await store.write(record);
648
+ await taskContext.updateStatus(task.task_id, "escalated");
649
+ return {
650
+ result: {
651
+ success: false,
652
+ action: "adversarial_review",
653
+ review_id: reviewId,
654
+ round,
655
+ review_status: "oscillated",
656
+ round_summary: { errors: error_count, warnings: warning_count, new_errors, fixed_errors },
657
+ next_step: "检测到震荡(连续多轮修一个引入一个,问题集合不收敛),任务已升级处理。建议人工介入排查根因。",
658
+ },
659
+ };
660
+ }
661
+ // 超轮次兜底(对齐 verify max_retries=5)
662
+ if (round >= MAX_REVIEW_ROUNDS) {
663
+ record.status = "escalated";
664
+ await store.write(record);
665
+ await taskContext.updateStatus(task.task_id, "escalated");
666
+ return {
667
+ result: {
668
+ success: false,
669
+ action: "adversarial_review",
670
+ review_id: reviewId,
671
+ round,
672
+ review_status: "escalated",
673
+ round_summary: { errors: error_count, warnings: warning_count, new_errors, fixed_errors },
674
+ next_step: `已达轮次上限(${MAX_REVIEW_ROUNDS})仍有 ${error_count} 个 error 未清零,任务已升级处理。建议人工介入。`,
675
+ },
676
+ };
677
+ }
678
+ // 继续:注入上轮 findings 反馈,组装下一轮 prompt(Reflexion 模式)
679
+ await store.write(record);
680
+ const prompt = buildReviewPrompt(record.artifacts, record.mode, formatRoundFeedback(roundRecord));
681
+ return {
682
+ result: {
683
+ success: true,
684
+ action: "adversarial_review",
685
+ review_id: reviewId,
686
+ round,
687
+ review_status: "in_progress",
688
+ round_summary: { errors: error_count, warnings: warning_count, new_errors, fixed_errors },
689
+ prompt,
690
+ next_step: `本轮仍有 ${error_count} 个 error 未达标。修复后继续:sf_work action="adversarial_review" round=${round + 1} review_id="${reviewId}" findings=[...]`,
324
691
  },
325
692
  };
326
693
  }
327
- /** 加载上游产物内容(从文件系统读取) */
694
+ /** 收集审查产物:per=指定单产物 / cross=所有域所有已产出 docs/ 产物;二者都额外收集研讨记录(审查充分性维度) */
695
+ async function collectReviewArtifacts(projectRoot, mode, artifactKind) {
696
+ const artifacts = [];
697
+ if (mode === "per_artifact" && artifactKind) {
698
+ for (const c of ALL_CONTRACTS) {
699
+ const p = c.produces.find((a) => a.kind === artifactKind);
700
+ if (p && p.path_pattern.startsWith("docs/") && existsSync(join(projectRoot, p.path_pattern))) {
701
+ artifacts.push(`${p.path_pattern}(${c.name}/${p.kind})`);
702
+ }
703
+ }
704
+ }
705
+ else {
706
+ for (const c of ALL_CONTRACTS) {
707
+ for (const p of c.produces) {
708
+ if (!p.path_pattern.startsWith("docs/"))
709
+ continue;
710
+ if (existsSync(join(projectRoot, p.path_pattern))) {
711
+ artifacts.push(`${p.path_pattern}(${c.name}/${p.kind})`);
712
+ }
713
+ }
714
+ }
715
+ }
716
+ // 研讨记录(docs/deliberation/):审查"研讨充分性"维度——产物决策是否真承接研讨结论
717
+ await collectDeliberationRecords(projectRoot, artifacts);
718
+ return artifacts;
719
+ }
720
+ /** 扫描 docs/deliberation/ 收集研讨记录(条件触发的研讨留痕,cross 审查复核充分性) */
721
+ async function collectDeliberationRecords(projectRoot, artifacts) {
722
+ const { readdirSync, statSync } = await import("node:fs");
723
+ const root = join(projectRoot, "docs", "研讨记录");
724
+ if (!existsSync(root))
725
+ return;
726
+ const walk = (dir) => {
727
+ for (const entry of readdirSync(dir)) {
728
+ const full = join(dir, entry);
729
+ if (statSync(full).isDirectory()) {
730
+ walk(full);
731
+ }
732
+ else if (entry.endsWith(".md")) {
733
+ const rel = full.replace(join(projectRoot) + "/", "");
734
+ artifacts.push(`${rel}(研讨记录)`);
735
+ }
736
+ }
737
+ };
738
+ walk(root);
739
+ }
740
+ /** 组装多利益方独立对抗审查 prompt。
741
+ * 5 方(用户/攻击者/维护者/性能/合规)各自独立目标函数,审查前不得互参,最后交叉汇总。
742
+ * loop-until-dry 收敛语义写进 prompt:连续一轮零 error 才达标。 */
743
+ function buildReviewPrompt(artifacts, mode, prevFeedback) {
744
+ const modeLabel = mode === "per_artifact" ? "per-artifact 单产物深度" : "cross-artifact 跨产物一致性";
745
+ const extraDim = mode === "cross_artifact"
746
+ ? `### 跨产物一致性(cross 专项)
747
+ - REQ→API→测试 覆盖链是否**语义**对齐(不只 ID 在,而是意图满足;确定性 cross_validation 只抓 ID/字段名,语义层矛盾只有你能抓)
748
+ - 同一事物跨产物描述是否一致(需求 vs 架构 vs API vs 数据库)
749
+ - **完整性方审查**:REQ→API→DB→切片→代码 全链路覆盖——每个 REQ 有对应 API?每个 API 操作的表在 DB 存在?每个 API 有代码方法实现?有无遗漏致业务断裂?
750
+ - **前端承接完整性**(涉及 FE-* 时):架构 §6.3 每个 FE-* 端有骨架切片?骨架切片落地了路由/状态/API service 壳/认证拦截器?前端各端覆盖需求 §9 声明的所有端?前后端 API 契约一致?
751
+ - **研讨记录充分性**:复杂产物的研讨记录(docs/deliberation/)若全是"无疑问一行举证"——质疑:这个点真无疑问吗?产出是否真承接研讨结论?`
752
+ : `### 单产物内部深度(per 专项)
753
+ - 该产物内部逻辑自洽、章节完整、无空章节/TODO/占位符
754
+ - 按产物类型重点关注:API 文档→字段映射与 schema 对齐;架构→决策依据/回滚/兼容;测试→REQ 覆盖/可执行性`;
755
+ const feedbackSection = prevFeedback
756
+ ? `\n## ⚠️ 上轮审查发现(必须先验证是否已修复,再继续找新问题)\n${prevFeedback}\n`
757
+ : "";
758
+ return `# 对抗性独立审查(${modeLabel},loop-until-dry)
759
+
760
+ 你是**独立审查 agent**,与产物创建 agent 完全隔离(不同 session、全新视角)。**默认所有产物有问题**,禁止说"看起来没问题"。每条发现必须 \`quote\` 引用原文——空泛=凑数=无效,会被丢弃。
761
+
762
+ ## 审查范围
763
+ ${artifacts.length > 0 ? artifacts.map((a) => `- \`${a}\``).join("\n") : "(暂无已产出产物,先产出再审查,本轮返回空 findings)"}
764
+
765
+ ## 多利益方独立对抗(每方独立审查,审查前不得参考他方结论,最后才交叉汇总)
766
+
767
+ ### 用户方审查
768
+ 根本需求是否被承接?REQ→产物 覆盖链是否语义对齐(需求 → 实现 的意图满足)?
769
+
770
+ ### 攻击者方审查
771
+ 越权 / 注入 / 路径穿越 / 敏感信息泄露 / 破坏性操作无确认?
772
+
773
+ ### 维护者方审查
774
+ 可读性 / 可改性 / 技术债 / 未接入主链路的孤岛 / 空章节 / TODO?
775
+
776
+ ### 性能方审查
777
+ N+1 / 瓶颈 / 资源泄漏 / 锁竞争 / 扩展性?
778
+
779
+ ### 合规方审查
780
+ 规范一致性 / 隐私 / 回滚方案 / 字段契约对齐 / 破坏性变更确认?
781
+
782
+ ### 前端架构方审查(涉及 FE-* 时)
783
+ 骨架完整性(路由/状态/组件分层/API service 壳)?前端权限承接后端 RBAC?前后端 API 契约一致?多端 shared 边界清晰?状态管理合理?
784
+
785
+ ${extraDim}
786
+ ${feedbackSection}
787
+ ## 收敛规则(loop-until-dry)
788
+ - 本轮发现 error 级 → 修复后继续下一轮;**连续一整轮零 error 才达标**(warning/info 不阻断,记遗留)
789
+ - 禁止凑数提前停,禁止为省事放过 error,禁止用 warning 冒充 error 凑数
790
+
791
+ ## 输出格式(严格 JSON 数组,引擎据此判定收敛)
792
+ \`\`\`json
793
+ [
794
+ {"severity":"error|warning|info","artifact":"产物路径","location":"章节/行","quote":"引用原文","issue":"问题","suggestion":"修复建议"}
795
+ ]
796
+ \`\`\`
797
+ - 无问题也必须返回 \`[]\`(这是达标的信号,不是"没问题"四个字)
798
+ - error 优先,按 severity 排序`;
799
+ }
800
+ /** 格式化上轮 findings 为反馈文本(Reflexion:上轮发现 → 注入下轮 prompt 针对性复核) */
801
+ function formatRoundFeedback(round) {
802
+ if (round.findings.length === 0)
803
+ return "";
804
+ const lines = round.findings.map((f) => `- [${f.severity}] ${f.artifact} ${f.location}:${f.issue}${f.suggestion ? ` → 建议:${f.suggestion}` : ""}`);
805
+ return `第 ${round.round} 轮发现 ${round.error_count} error / ${round.warning_count} warning:\n${lines.join("\n")}`;
806
+ }
807
+ /** 规范化客户端提交的 findings(容错:校验 severity + 补全字符串字段 + 过滤无效条目) */
808
+ function normalizeFindings(raw) {
809
+ if (!Array.isArray(raw))
810
+ return [];
811
+ const findings = [];
812
+ for (const item of raw) {
813
+ if (!item || typeof item !== "object")
814
+ continue;
815
+ const f = item;
816
+ const severity = f.severity;
817
+ if (severity !== "error" && severity !== "warning" && severity !== "info")
818
+ continue;
819
+ findings.push({
820
+ severity,
821
+ artifact: String(f.artifact ?? ""),
822
+ location: String(f.location ?? ""),
823
+ quote: String(f.quote ?? ""),
824
+ issue: String(f.issue ?? ""),
825
+ suggestion: String(f.suggestion ?? ""),
826
+ });
827
+ }
828
+ return findings;
829
+ }
830
+ /** 加载上游产物内容(从文件系统读取真实内容) */
328
831
  async function loadUpstreamContent(task, engine, _args, projectRoot) {
329
832
  const upstream = {};
330
833
  const { readFileSync } = await import("node:fs");
@@ -370,9 +873,9 @@ async function loadUpstreamContent(task, engine, _args, projectRoot) {
370
873
  * 无失败记录 / findings 为空 → 返回空串(首次执行或上次通过,无需反馈)。
371
874
  * 截断策略与 loadUpstreamContent 一致(8000 字符),避免 prompt 膨胀。
372
875
  */
373
- async function loadLastVerifyFeedback(task, domain, projectRoot) {
876
+ async function loadLastVerifyFeedback(task, domain, projectRoot, artifactPath) {
374
877
  const gateStore = new GateRecordStore(projectRoot);
375
- const record = await gateStore.readLatestFailed(domain, task.task_id);
878
+ const record = await gateStore.readLatestFailed(domain, task.task_id, artifactPath);
376
879
  if (!record || record.findings.length === 0)
377
880
  return "";
378
881
  const parts = [];