@hunter-harness/workflow-harness 0.2.1 → 0.2.2

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 (262) hide show
  1. package/harness/bundles/general/claude-code/.harness-build.json +1 -1
  2. package/harness/bundles/general/claude-code/harness-archive/SKILL.md +1 -1
  3. package/harness/bundles/general/claude-code/harness-archive/reference.md +2 -8
  4. package/harness/bundles/general/claude-code/harness-codebase-map/SKILL.md +2 -1
  5. package/harness/bundles/general/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
  6. package/harness/bundles/general/claude-code/harness-knowledge-ingest/scripts/harness_knowledge.py +474 -122
  7. package/harness/bundles/general/claude-code/harness-knowledge-query/SKILL.md +1 -1
  8. package/harness/bundles/general/claude-code/harness-plan/SKILL.md +2 -1
  9. package/harness/bundles/general/claude-code/harness-review/SKILL.md +5 -1
  10. package/harness/bundles/general/claude-code/harness-run/SKILL.md +1 -1
  11. package/harness/bundles/general/claude-code/harness-run/checklist.md +1 -1
  12. package/harness/bundles/general/claude-code/harness-submit/SKILL.md +2 -2
  13. package/harness/bundles/general/claude-code/harness-submit/checklist.md +30 -6
  14. package/harness/bundles/general/claude-code/harness-sync/SKILL.md +1 -1
  15. package/harness/bundles/general/claude-code/harness-test/SKILL.md +2 -2
  16. package/harness/bundles/general/claude-code/harness-test/checklist.md +1 -1
  17. package/harness/bundles/general/claude-code/harness-test/pitfalls.md +16 -0
  18. package/harness/bundles/general/claude-code/harness-test/scripts/runtime-helpers.mjs +216 -0
  19. package/harness/bundles/general/claude-code/protocols/archive-report-protocol.md +1 -1
  20. package/harness/bundles/general/claude-code/protocols/ledger-protocol.md +55 -2
  21. package/harness/bundles/general/claude-code/protocols/report-pipeline-protocol.md +1 -8
  22. package/harness/bundles/general/claude-code/protocols/sensitive-info-protocol.md +13 -0
  23. package/harness/bundles/general/claude-code/protocols/state-layout-protocol.md +24 -0
  24. package/harness/bundles/general/claude-code/scripts/harness_archive.py +31 -14
  25. package/harness/bundles/general/claude-code/scripts/harness_check_gate.py +103 -0
  26. package/harness/bundles/general/claude-code/scripts/harness_deploy.py +179 -4
  27. package/harness/bundles/general/claude-code/scripts/harness_ledger.py +269 -3
  28. package/harness/bundles/general/claude-code/scripts/harness_preflight.py +72 -382
  29. package/harness/bundles/general/claude-code/scripts/harness_profile.py +742 -0
  30. package/harness/bundles/general/claude-code/scripts/harness_service.py +99 -2
  31. package/harness/bundles/general/claude-code/scripts/harness_state.py +179 -0
  32. package/harness/bundles/general/codebuddy/.harness-build.json +1 -1
  33. package/harness/bundles/general/codebuddy/harness-archive/SKILL.md +1 -1
  34. package/harness/bundles/general/codebuddy/harness-archive/reference.md +2 -8
  35. package/harness/bundles/general/codebuddy/harness-codebase-map/SKILL.md +2 -1
  36. package/harness/bundles/general/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
  37. package/harness/bundles/general/codebuddy/harness-knowledge-ingest/scripts/harness_knowledge.py +474 -122
  38. package/harness/bundles/general/codebuddy/harness-knowledge-query/SKILL.md +1 -1
  39. package/harness/bundles/general/codebuddy/harness-plan/SKILL.md +2 -1
  40. package/harness/bundles/general/codebuddy/harness-review/SKILL.md +5 -1
  41. package/harness/bundles/general/codebuddy/harness-run/SKILL.md +1 -1
  42. package/harness/bundles/general/codebuddy/harness-run/checklist.md +1 -1
  43. package/harness/bundles/general/codebuddy/harness-submit/SKILL.md +2 -2
  44. package/harness/bundles/general/codebuddy/harness-submit/checklist.md +30 -6
  45. package/harness/bundles/general/codebuddy/harness-sync/SKILL.md +1 -1
  46. package/harness/bundles/general/codebuddy/harness-test/SKILL.md +2 -2
  47. package/harness/bundles/general/codebuddy/harness-test/checklist.md +1 -1
  48. package/harness/bundles/general/codebuddy/harness-test/pitfalls.md +16 -0
  49. package/harness/bundles/general/codebuddy/harness-test/scripts/runtime-helpers.mjs +216 -0
  50. package/harness/bundles/general/codebuddy/protocols/archive-report-protocol.md +1 -1
  51. package/harness/bundles/general/codebuddy/protocols/ledger-protocol.md +55 -2
  52. package/harness/bundles/general/codebuddy/protocols/report-pipeline-protocol.md +1 -8
  53. package/harness/bundles/general/codebuddy/protocols/sensitive-info-protocol.md +13 -0
  54. package/harness/bundles/general/codebuddy/protocols/state-layout-protocol.md +24 -0
  55. package/harness/bundles/general/codebuddy/scripts/harness_archive.py +31 -14
  56. package/harness/bundles/general/codebuddy/scripts/harness_check_gate.py +103 -0
  57. package/harness/bundles/general/codebuddy/scripts/harness_deploy.py +179 -4
  58. package/harness/bundles/general/codebuddy/scripts/harness_ledger.py +269 -3
  59. package/harness/bundles/general/codebuddy/scripts/harness_preflight.py +72 -382
  60. package/harness/bundles/general/codebuddy/scripts/harness_profile.py +742 -0
  61. package/harness/bundles/general/codebuddy/scripts/harness_service.py +99 -2
  62. package/harness/bundles/general/codebuddy/scripts/harness_state.py +179 -0
  63. package/harness/bundles/general/codex/.harness-build.json +1 -1
  64. package/harness/bundles/general/codex/harness-archive/SKILL.md +1 -1
  65. package/harness/bundles/general/codex/harness-archive/reference.md +2 -8
  66. package/harness/bundles/general/codex/harness-codebase-map/SKILL.md +2 -1
  67. package/harness/bundles/general/codex/harness-knowledge-ingest/SKILL.md +1 -1
  68. package/harness/bundles/general/codex/harness-knowledge-ingest/scripts/harness_knowledge.py +474 -122
  69. package/harness/bundles/general/codex/harness-knowledge-query/SKILL.md +1 -1
  70. package/harness/bundles/general/codex/harness-plan/SKILL.md +2 -1
  71. package/harness/bundles/general/codex/harness-review/SKILL.md +5 -1
  72. package/harness/bundles/general/codex/harness-run/SKILL.md +1 -1
  73. package/harness/bundles/general/codex/harness-run/checklist.md +1 -1
  74. package/harness/bundles/general/codex/harness-submit/SKILL.md +2 -2
  75. package/harness/bundles/general/codex/harness-submit/checklist.md +30 -6
  76. package/harness/bundles/general/codex/harness-sync/SKILL.md +1 -1
  77. package/harness/bundles/general/codex/harness-test/SKILL.md +2 -2
  78. package/harness/bundles/general/codex/harness-test/checklist.md +1 -1
  79. package/harness/bundles/general/codex/harness-test/pitfalls.md +16 -0
  80. package/harness/bundles/general/codex/harness-test/scripts/runtime-helpers.mjs +216 -0
  81. package/harness/bundles/general/codex/protocols/archive-report-protocol.md +1 -1
  82. package/harness/bundles/general/codex/protocols/ledger-protocol.md +55 -2
  83. package/harness/bundles/general/codex/protocols/report-pipeline-protocol.md +1 -8
  84. package/harness/bundles/general/codex/protocols/sensitive-info-protocol.md +13 -0
  85. package/harness/bundles/general/codex/protocols/state-layout-protocol.md +24 -0
  86. package/harness/bundles/general/codex/scripts/harness_archive.py +31 -14
  87. package/harness/bundles/general/codex/scripts/harness_check_gate.py +103 -0
  88. package/harness/bundles/general/codex/scripts/harness_deploy.py +179 -4
  89. package/harness/bundles/general/codex/scripts/harness_ledger.py +269 -3
  90. package/harness/bundles/general/codex/scripts/harness_preflight.py +72 -382
  91. package/harness/bundles/general/codex/scripts/harness_profile.py +742 -0
  92. package/harness/bundles/general/codex/scripts/harness_service.py +99 -2
  93. package/harness/bundles/general/codex/scripts/harness_state.py +179 -0
  94. package/harness/bundles/general/cursor/.harness-build.json +1 -1
  95. package/harness/bundles/general/cursor/harness-archive/SKILL.md +1 -1
  96. package/harness/bundles/general/cursor/harness-archive/reference.md +2 -8
  97. package/harness/bundles/general/cursor/harness-codebase-map/SKILL.md +2 -1
  98. package/harness/bundles/general/cursor/harness-knowledge-ingest/SKILL.md +1 -1
  99. package/harness/bundles/general/cursor/harness-knowledge-ingest/scripts/harness_knowledge.py +474 -122
  100. package/harness/bundles/general/cursor/harness-knowledge-query/SKILL.md +1 -1
  101. package/harness/bundles/general/cursor/harness-plan/SKILL.md +2 -1
  102. package/harness/bundles/general/cursor/harness-review/SKILL.md +5 -1
  103. package/harness/bundles/general/cursor/harness-run/SKILL.md +1 -1
  104. package/harness/bundles/general/cursor/harness-run/checklist.md +1 -1
  105. package/harness/bundles/general/cursor/harness-submit/SKILL.md +2 -2
  106. package/harness/bundles/general/cursor/harness-submit/checklist.md +30 -6
  107. package/harness/bundles/general/cursor/harness-sync/SKILL.md +1 -1
  108. package/harness/bundles/general/cursor/harness-test/SKILL.md +2 -2
  109. package/harness/bundles/general/cursor/harness-test/checklist.md +1 -1
  110. package/harness/bundles/general/cursor/harness-test/pitfalls.md +16 -0
  111. package/harness/bundles/general/cursor/harness-test/scripts/runtime-helpers.mjs +216 -0
  112. package/harness/bundles/general/cursor/protocols/archive-report-protocol.md +1 -1
  113. package/harness/bundles/general/cursor/protocols/ledger-protocol.md +55 -2
  114. package/harness/bundles/general/cursor/protocols/report-pipeline-protocol.md +1 -8
  115. package/harness/bundles/general/cursor/protocols/sensitive-info-protocol.md +13 -0
  116. package/harness/bundles/general/cursor/protocols/state-layout-protocol.md +24 -0
  117. package/harness/bundles/general/cursor/scripts/harness_archive.py +31 -14
  118. package/harness/bundles/general/cursor/scripts/harness_check_gate.py +103 -0
  119. package/harness/bundles/general/cursor/scripts/harness_deploy.py +179 -4
  120. package/harness/bundles/general/cursor/scripts/harness_ledger.py +269 -3
  121. package/harness/bundles/general/cursor/scripts/harness_preflight.py +72 -382
  122. package/harness/bundles/general/cursor/scripts/harness_profile.py +742 -0
  123. package/harness/bundles/general/cursor/scripts/harness_service.py +99 -2
  124. package/harness/bundles/general/cursor/scripts/harness_state.py +179 -0
  125. package/harness/bundles/java/claude-code/.harness-build.json +1 -1
  126. package/harness/bundles/java/claude-code/harness-apidoc/SKILL.md +1 -1
  127. package/harness/bundles/java/claude-code/harness-archive/SKILL.md +1 -1
  128. package/harness/bundles/java/claude-code/harness-archive/reference.md +2 -8
  129. package/harness/bundles/java/claude-code/harness-codebase-map/SKILL.md +2 -1
  130. package/harness/bundles/java/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
  131. package/harness/bundles/java/claude-code/harness-knowledge-ingest/scripts/harness_knowledge.py +474 -122
  132. package/harness/bundles/java/claude-code/harness-knowledge-query/SKILL.md +1 -1
  133. package/harness/bundles/java/claude-code/harness-package/SKILL.md +3 -3
  134. package/harness/bundles/java/claude-code/harness-plan/SKILL.md +2 -1
  135. package/harness/bundles/java/claude-code/harness-review/SKILL.md +5 -1
  136. package/harness/bundles/java/claude-code/harness-run/SKILL.md +4 -4
  137. package/harness/bundles/java/claude-code/harness-run/checklist.md +1 -1
  138. package/harness/bundles/java/claude-code/harness-submit/SKILL.md +3 -3
  139. package/harness/bundles/java/claude-code/harness-submit/checklist.md +30 -6
  140. package/harness/bundles/java/claude-code/harness-sync/SKILL.md +1 -1
  141. package/harness/bundles/java/claude-code/harness-test/SKILL.md +5 -5
  142. package/harness/bundles/java/claude-code/harness-test/pitfalls.md +16 -0
  143. package/harness/bundles/java/claude-code/harness-test/scripts/runtime-helpers.mjs +216 -0
  144. package/harness/bundles/java/claude-code/protocols/archive-report-protocol.md +1 -1
  145. package/harness/bundles/java/claude-code/protocols/ledger-protocol.md +55 -2
  146. package/harness/bundles/java/claude-code/protocols/report-pipeline-protocol.md +1 -8
  147. package/harness/bundles/java/claude-code/protocols/sensitive-info-protocol.md +13 -0
  148. package/harness/bundles/java/claude-code/protocols/state-layout-protocol.md +24 -0
  149. package/harness/bundles/java/claude-code/scripts/harness_archive.py +31 -14
  150. package/harness/bundles/java/claude-code/scripts/harness_check_gate.py +103 -0
  151. package/harness/bundles/java/claude-code/scripts/harness_deploy.py +179 -4
  152. package/harness/bundles/java/claude-code/scripts/harness_ledger.py +269 -3
  153. package/harness/bundles/java/claude-code/scripts/harness_preflight.py +72 -382
  154. package/harness/bundles/java/claude-code/scripts/harness_profile.py +742 -0
  155. package/harness/bundles/java/claude-code/scripts/harness_service.py +99 -2
  156. package/harness/bundles/java/claude-code/scripts/harness_state.py +179 -0
  157. package/harness/bundles/java/codebuddy/.harness-build.json +1 -1
  158. package/harness/bundles/java/codebuddy/harness-apidoc/SKILL.md +1 -1
  159. package/harness/bundles/java/codebuddy/harness-archive/SKILL.md +1 -1
  160. package/harness/bundles/java/codebuddy/harness-archive/reference.md +2 -8
  161. package/harness/bundles/java/codebuddy/harness-codebase-map/SKILL.md +2 -1
  162. package/harness/bundles/java/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
  163. package/harness/bundles/java/codebuddy/harness-knowledge-ingest/scripts/harness_knowledge.py +474 -122
  164. package/harness/bundles/java/codebuddy/harness-knowledge-query/SKILL.md +1 -1
  165. package/harness/bundles/java/codebuddy/harness-package/SKILL.md +3 -3
  166. package/harness/bundles/java/codebuddy/harness-plan/SKILL.md +2 -1
  167. package/harness/bundles/java/codebuddy/harness-review/SKILL.md +5 -1
  168. package/harness/bundles/java/codebuddy/harness-run/SKILL.md +4 -4
  169. package/harness/bundles/java/codebuddy/harness-run/checklist.md +1 -1
  170. package/harness/bundles/java/codebuddy/harness-submit/SKILL.md +3 -3
  171. package/harness/bundles/java/codebuddy/harness-submit/checklist.md +30 -6
  172. package/harness/bundles/java/codebuddy/harness-sync/SKILL.md +1 -1
  173. package/harness/bundles/java/codebuddy/harness-test/SKILL.md +5 -5
  174. package/harness/bundles/java/codebuddy/harness-test/pitfalls.md +16 -0
  175. package/harness/bundles/java/codebuddy/harness-test/scripts/runtime-helpers.mjs +216 -0
  176. package/harness/bundles/java/codebuddy/protocols/archive-report-protocol.md +1 -1
  177. package/harness/bundles/java/codebuddy/protocols/ledger-protocol.md +55 -2
  178. package/harness/bundles/java/codebuddy/protocols/report-pipeline-protocol.md +1 -8
  179. package/harness/bundles/java/codebuddy/protocols/sensitive-info-protocol.md +13 -0
  180. package/harness/bundles/java/codebuddy/protocols/state-layout-protocol.md +24 -0
  181. package/harness/bundles/java/codebuddy/scripts/harness_archive.py +31 -14
  182. package/harness/bundles/java/codebuddy/scripts/harness_check_gate.py +103 -0
  183. package/harness/bundles/java/codebuddy/scripts/harness_deploy.py +179 -4
  184. package/harness/bundles/java/codebuddy/scripts/harness_ledger.py +269 -3
  185. package/harness/bundles/java/codebuddy/scripts/harness_preflight.py +72 -382
  186. package/harness/bundles/java/codebuddy/scripts/harness_profile.py +742 -0
  187. package/harness/bundles/java/codebuddy/scripts/harness_service.py +99 -2
  188. package/harness/bundles/java/codebuddy/scripts/harness_state.py +179 -0
  189. package/harness/bundles/java/codex/.harness-build.json +1 -1
  190. package/harness/bundles/java/codex/harness-apidoc/SKILL.md +1 -1
  191. package/harness/bundles/java/codex/harness-archive/SKILL.md +1 -1
  192. package/harness/bundles/java/codex/harness-archive/reference.md +2 -8
  193. package/harness/bundles/java/codex/harness-codebase-map/SKILL.md +2 -1
  194. package/harness/bundles/java/codex/harness-knowledge-ingest/SKILL.md +1 -1
  195. package/harness/bundles/java/codex/harness-knowledge-ingest/scripts/harness_knowledge.py +474 -122
  196. package/harness/bundles/java/codex/harness-knowledge-query/SKILL.md +1 -1
  197. package/harness/bundles/java/codex/harness-package/SKILL.md +3 -3
  198. package/harness/bundles/java/codex/harness-plan/SKILL.md +2 -1
  199. package/harness/bundles/java/codex/harness-review/SKILL.md +5 -1
  200. package/harness/bundles/java/codex/harness-run/SKILL.md +4 -4
  201. package/harness/bundles/java/codex/harness-run/checklist.md +1 -1
  202. package/harness/bundles/java/codex/harness-submit/SKILL.md +3 -3
  203. package/harness/bundles/java/codex/harness-submit/checklist.md +30 -6
  204. package/harness/bundles/java/codex/harness-sync/SKILL.md +1 -1
  205. package/harness/bundles/java/codex/harness-test/SKILL.md +5 -5
  206. package/harness/bundles/java/codex/harness-test/pitfalls.md +16 -0
  207. package/harness/bundles/java/codex/harness-test/scripts/runtime-helpers.mjs +216 -0
  208. package/harness/bundles/java/codex/protocols/archive-report-protocol.md +1 -1
  209. package/harness/bundles/java/codex/protocols/ledger-protocol.md +55 -2
  210. package/harness/bundles/java/codex/protocols/report-pipeline-protocol.md +1 -8
  211. package/harness/bundles/java/codex/protocols/sensitive-info-protocol.md +13 -0
  212. package/harness/bundles/java/codex/protocols/state-layout-protocol.md +24 -0
  213. package/harness/bundles/java/codex/scripts/harness_archive.py +31 -14
  214. package/harness/bundles/java/codex/scripts/harness_check_gate.py +103 -0
  215. package/harness/bundles/java/codex/scripts/harness_deploy.py +179 -4
  216. package/harness/bundles/java/codex/scripts/harness_ledger.py +269 -3
  217. package/harness/bundles/java/codex/scripts/harness_preflight.py +72 -382
  218. package/harness/bundles/java/codex/scripts/harness_profile.py +742 -0
  219. package/harness/bundles/java/codex/scripts/harness_service.py +99 -2
  220. package/harness/bundles/java/codex/scripts/harness_state.py +179 -0
  221. package/harness/bundles/java/cursor/.harness-build.json +1 -1
  222. package/harness/bundles/java/cursor/harness-apidoc/SKILL.md +1 -1
  223. package/harness/bundles/java/cursor/harness-archive/SKILL.md +1 -1
  224. package/harness/bundles/java/cursor/harness-archive/reference.md +2 -8
  225. package/harness/bundles/java/cursor/harness-codebase-map/SKILL.md +2 -1
  226. package/harness/bundles/java/cursor/harness-knowledge-ingest/SKILL.md +1 -1
  227. package/harness/bundles/java/cursor/harness-knowledge-ingest/scripts/harness_knowledge.py +474 -122
  228. package/harness/bundles/java/cursor/harness-knowledge-query/SKILL.md +1 -1
  229. package/harness/bundles/java/cursor/harness-package/SKILL.md +3 -3
  230. package/harness/bundles/java/cursor/harness-plan/SKILL.md +2 -1
  231. package/harness/bundles/java/cursor/harness-review/SKILL.md +5 -1
  232. package/harness/bundles/java/cursor/harness-run/SKILL.md +4 -4
  233. package/harness/bundles/java/cursor/harness-run/checklist.md +1 -1
  234. package/harness/bundles/java/cursor/harness-submit/SKILL.md +3 -3
  235. package/harness/bundles/java/cursor/harness-submit/checklist.md +30 -6
  236. package/harness/bundles/java/cursor/harness-sync/SKILL.md +1 -1
  237. package/harness/bundles/java/cursor/harness-test/SKILL.md +5 -5
  238. package/harness/bundles/java/cursor/harness-test/pitfalls.md +16 -0
  239. package/harness/bundles/java/cursor/harness-test/scripts/runtime-helpers.mjs +216 -0
  240. package/harness/bundles/java/cursor/protocols/archive-report-protocol.md +1 -1
  241. package/harness/bundles/java/cursor/protocols/ledger-protocol.md +55 -2
  242. package/harness/bundles/java/cursor/protocols/report-pipeline-protocol.md +1 -8
  243. package/harness/bundles/java/cursor/protocols/sensitive-info-protocol.md +13 -0
  244. package/harness/bundles/java/cursor/protocols/state-layout-protocol.md +24 -0
  245. package/harness/bundles/java/cursor/scripts/harness_archive.py +31 -14
  246. package/harness/bundles/java/cursor/scripts/harness_check_gate.py +103 -0
  247. package/harness/bundles/java/cursor/scripts/harness_deploy.py +179 -4
  248. package/harness/bundles/java/cursor/scripts/harness_ledger.py +269 -3
  249. package/harness/bundles/java/cursor/scripts/harness_preflight.py +72 -382
  250. package/harness/bundles/java/cursor/scripts/harness_profile.py +742 -0
  251. package/harness/bundles/java/cursor/scripts/harness_service.py +99 -2
  252. package/harness/bundles/java/cursor/scripts/harness_state.py +179 -0
  253. package/harness/manifests/general/claude-code.json +44 -28
  254. package/harness/manifests/general/codebuddy.json +44 -28
  255. package/harness/manifests/general/codex.json +44 -28
  256. package/harness/manifests/general/cursor.json +44 -28
  257. package/harness/manifests/java/claude-code.json +45 -29
  258. package/harness/manifests/java/codebuddy.json +45 -29
  259. package/harness/manifests/java/codex.json +45 -29
  260. package/harness/manifests/java/cursor.json +45 -29
  261. package/hunter-workflow-family.json +2 -2
  262. package/package.json +1 -1
@@ -3,7 +3,7 @@ name: harness-knowledge-query
3
3
  description: 根据新需求、设计任务、代码修改请求或问题排查,在规划和编码前查询 .harness/knowledge
4
4
  历史上下文。适用场景:query knowledge、查找历史需求、根据归档理解需求、继续之前类似开发、生成需求上下文包。
5
5
  ---
6
- <!-- generated by harness_deploy.py; core=7b81effe1faaef85; overlay=java; agent=cursor; do not edit -->
6
+ <!-- generated by harness_deploy.py; core=d437039c3207693b; overlay=java; agent=cursor; do not edit -->
7
7
  # harness-knowledge-query
8
8
 
9
9
  根据用户的新需求或排查问题,从项目本地 `.harness/knowledge` 中检索历史需求、决策、实现、风险和测试证据,并生成 AI 可读的 context pack。
@@ -2,7 +2,7 @@
2
2
  name: harness-package
3
3
  description: 增量模块打包:拉取最新→编译验证→mvn package→汇总 jar/war。使用场景:打包、package、发版准备
4
4
  ---
5
- <!-- generated by harness_deploy.py; core=7b81effe1faaef85; overlay=java; agent=cursor; do not edit -->
5
+ <!-- generated by harness_deploy.py; core=d437039c3207693b; overlay=java; agent=cursor; do not edit -->
6
6
  # harness-package — 增量模块打包(Java overlay)
7
7
 
8
8
  ## Purpose
@@ -36,9 +36,9 @@ description: 增量模块打包:拉取最新→编译验证→mvn package→
36
36
 
37
37
  ## Workflow
38
38
 
39
- 1. 读 ledger + build-profile 的 `buildCommands.package`
39
+ 1. 读 ledger + build-profile 的 `commands.package`(v2,按 profile key resolve)
40
40
  2. 识别变更模块(git diff + pom 结构)
41
- 3. `mvn package -DskipTests`(ledger 不可复用时先跑必要测试)
41
+ 3. **单次** Maven package lifecycle(spec §3.3 去重,不预先 compile/test):full test 可复用(`can-reuse unitTestFull=true`)→ 按 `commands.package` resolve 执行一次 skip-tests package;不可复用 → 按 `commands.package` resolve 执行一次含测试 package
42
42
  4. 写打包报告 + append 事件
43
43
 
44
44
  ## P0 执行可信度规则
@@ -2,7 +2,7 @@
2
2
  name: harness-plan
3
3
  description: 将需求转化为设计文档+实施计划+完整测试场景表,必须在编码前完成。使用场景:需求分析、feature plan、技术方案设计、实现方案规划
4
4
  ---
5
- <!-- generated by harness_deploy.py; core=7b81effe1faaef85; overlay=java; agent=cursor; do not edit -->
5
+ <!-- generated by harness_deploy.py; core=d437039c3207693b; overlay=java; agent=cursor; do not edit -->
6
6
  # harness-plan — 需求规划
7
7
 
8
8
  ## Purpose
@@ -81,6 +81,7 @@ change-name 范围变更 → 提示重命名或记 🟡WARN(→ `reference.md`
81
81
  | 阶段 8 | spec/plan/detail/scenarios/worktree.json/logs/events 缺一不可 → ❌FAIL |
82
82
  | Plan 结束 | **禁止**询问执行模式;只提示 `/harness-run` |
83
83
  | 知识查询 | 0.5 失败不得假装已读历史 |
84
+ | state snapshot | 读取 `state-snapshot.json`(`harness_state.py` / state-layout-protocol §state-snapshot.json)了解 project/worktree root、HEAD/base、profile/rules/map/knowledge 指纹;失效由脚本刷新,**不得仅凭缓存跳过代码探索或验证门禁**(design §3.6) |
84
85
  | 协议 | sensitive-info / evidence-based-reporting / state-layout |
85
86
 
86
87
  产出物表、frontmatter、legacy 兼容、结束输出模板 → `reference.md`
@@ -3,7 +3,7 @@ name: harness-review
3
3
  description: 6维度代码审查(架构/安全/规范/兼容/测试/性能),对照项目规则(见
4
4
  .harness/context-index.json)和测试场景表,在隔离上下文运行。使用场景:代码审查、提交前检查、合并评审
5
5
  ---
6
- <!-- generated by harness_deploy.py; core=7b81effe1faaef85; overlay=java; agent=cursor; do not edit -->
6
+ <!-- generated by harness_deploy.py; core=d437039c3207693b; overlay=java; agent=cursor; do not edit -->
7
7
  # harness-review — 代码审查
8
8
 
9
9
  ## Purpose
@@ -120,6 +120,10 @@ review 结果默认只作参考,不阻塞 submit/archive;报告措辞遵循
120
120
 
121
121
  git diff/log 命令通过 `powershell.exe -Command "..."` 执行;review-report 中如发现明文 token/密码/密钥,必须列入 RED 问题并在报告中以 `<TOKEN_REDACTED>` 等占位符引用;RED/YELLOW/OK 结论必须基于实际 diff 内容,不得凭印象判断。代码探索必须优先使用 CodeGraph MCP 工具(`mcp__codegraph__codegraph_explore`),不允许通过普通 Bash 调 codegraph 命令(已列入 `disallowed-tools`);MCP 不可用时降级为 Grep/Glob + Read,并在执行日志记录降级原因。遵循 `../protocols/powershell-protocol.md` / `sensitive-info-protocol.md` / `evidence-based-reporting-protocol.md`。
122
122
 
123
+ ### 五、state snapshot 与源码重验
124
+
125
+ review 读取 `state-snapshot.json`(`harness_state.py` / state-layout-protocol §state-snapshot.json)的 code/diff 段确定审查范围;snapshot 失效或代码段变化时**必须重新读取实际变更源码**,不得仅凭缓存快照跳过源码审查(design §3.6)。
126
+
123
127
  ## 交互白名单
124
128
 
125
129
  **无** AskUserQuestion(审查全自动)。委派失败 → 主会话审查 + `decision` 事件。
@@ -2,7 +2,7 @@
2
2
  name: harness-run
3
3
  description: 按变更簇执行 TDD 编码循环(RED→GREEN→REFACTOR→编译验证),逐变更簇实现计划中的任务。使用场景:开始编码、实现功能、写代码、TDD 编码
4
4
  ---
5
- <!-- generated by harness_deploy.py; core=7b81effe1faaef85; overlay=java; agent=cursor; do not edit -->
5
+ <!-- generated by harness_deploy.py; core=d437039c3207693b; overlay=java; agent=cursor; do not edit -->
6
6
  # harness-run — 需求编码
7
7
 
8
8
  ## Purpose
@@ -64,9 +64,9 @@ description: 按变更簇执行 TDD 编码循环(RED→GREEN→REFACTOR→编
64
64
 
65
65
  ### Java 构建验证(Maven)
66
66
 
67
- - 所有 `mvn`/`git` 经 `powershell.exe -NoProfile -Command`;命令读 `.harness/config/build-profile.json` 的 `buildCommands`(**禁止 hardcode 模块名/端口**)
68
- - 增量编译:`buildCommands.compile`(典型 `mvn compile -pl <module> -o -q`)
69
- - 变更簇 TDD:多测试类合并一次 `mvn test -pl <module> -Dtest=A,B,C -o`;每簇最多一次 RED + 一次 GREEN Maven
67
+ - 所有 `mvn`/`git` 经 `powershell.exe -NoProfile -Command`;命令读 `.harness/config/build-profile.json` 的 `commands`(v2,按 profile key resolve;**禁止 hardcode 模块名/端口**)
68
+ - 增量编译:`commands.compile`(典型 `mvn compile -pl <module> -o -q`)
69
+ - 变更簇 TDD:多测试类合并一次按 `commands.unitTest` resolve(典型 `mvn test -pl <module> -Dtest=A,B,C -o`);每簇最多一次 RED + 一次 GREEN Maven
70
70
  - **轻量 run**:默认只 compile;全量 `mvn test` 仅当改了 mapper/sql/权限/controller/公共模块或用户要求 full-run-validation
71
71
  - **install -am**:仅 worktree 首建或上游模块文件变化时(见 ledger-protocol);非每次 run 强制
72
72
  - worktree 中确认 `.mvn/maven.config` 等构建配置存在;缺失时从主目录复制
@@ -45,7 +45,7 @@
45
45
  - [ ] 探测 1:`src/test/java` 目录是否存在
46
46
  - [ ] 探测 2:`pom.xml` 是否包含 `spring-boot-starter-test` / `junit` / `mockito` 依赖
47
47
  - [ ] 探测 3:是否存在已有测试文件(`*Test.java` 或 `*Tests.java`)
48
- - [ ] 探测 4:目标模块测试命令是否可运行(`mvn test -pl <module> -o -q` 试运行)
48
+ - [ ] 探测 4:目标模块测试基础设施是否可用(`mvn test-compile -pl <module> -o -q` 验证测试可编译,或测试枚举/秒级 smoke;**禁止完整模块测试**,spec §3.3)
49
49
  - [ ] 四项证据收集完毕 → 写结论:✅ 测试基础设施可用 / 🟡 测试基础设施部分可用 / ❌ 测试基础设施不可用
50
50
  - [ ] 如果 ❌ 不可用 → 记录 TDD 降级原因(必须引用具体证据,如"模块 X 无 src/test/java 目录")
51
51
 
@@ -3,7 +3,7 @@ name: harness-submit
3
3
  description: 最终提交封装:验证→中文 commit→提交/推送;worktree 模式含 --no-ff
4
4
  合并回主分支。使用场景:提交代码、commit、push、合并分支、merge to main、完成开发
5
5
  ---
6
- <!-- generated by harness_deploy.py; core=7b81effe1faaef85; overlay=java; agent=cursor; do not edit -->
6
+ <!-- generated by harness_deploy.py; core=d437039c3207693b; overlay=java; agent=cursor; do not edit -->
7
7
  # harness-submit — 最终提交(含 worktree 合并)
8
8
 
9
9
  ## Purpose
@@ -55,7 +55,7 @@ description: 最终提交封装:验证→中文 commit→提交/推送;workt
55
55
 
56
56
  0. **启动准备** — 确定变更名;读 ledger + 计算 diffHash + post-test 7 类分类;append `phase.start`
57
57
  1. **合并最新代码** — 主目录:`stash` → `pull --rebase` → `stash pop`;**worktree:N/A**(远端同步在合并段主分支完成)
58
- 2. **最终验证** — ledger 复用优先;**提交前最终门禁**:`harness_ledger.py can-reuse --verification unitTestFull --scope module --project . --profile-input unitTestFull --command <build-profile.json buildCommands.unitTestFull>`(`--profile-input unitTestFull` 从 `build-profile.json` `verificationInputs.unitTestFull` 展开依赖闭包文件集,**禁止用仅含 staged 文件的 `--files` 快捷方式**冒充全量闭包;`<command>` 直接读 `buildCommands.unitTestFull`,不复制示例模块名)。不可复用则执行 `buildCommands.unitTestFull` 模块级全量单元测试,成功后用同一文件集、command、`scope=module` 写回 ledger `unitTestFull` 项。增量 `unitTest` 永远不能冒充 `unitTestFull` 门禁。
58
+ 2. **最终验证** — ledger 复用优先;**提交前最终门禁只调 `can-reuse`**(删除与 coverage 冲突的二次全量门禁):`harness_ledger.py can-reuse --verification unitTestFull --scope module --project . --profile-input unitTestFull --command <resolved commands.unitTestFull.command>`。`--command` **按 profile key resolve**:读 `build-profile.json` 的 `commands.unitTestFull.command`(v2),或 `harness_profile.py resolve --project . --key unitTestFull --json` 取 resolved command,**不复制示例模块名**(文档示例只展示 key)。`--profile-input unitTestFull` 从 `verificationInputs.unitTestFull`(v2 `commands.unitTestFull.inputs` 派生)展开依赖闭包,**禁止用仅含 staged 文件的 `--files` 快捷方式**冒充全量闭包。`reuse=true` 不再执行二次全量测试;仅 `reuse=false` 时执行**同一 resolved verification**(profile `unitTestFull` 命令),成功后用同一文件集、command、`scope=module` 写回 ledger `unitTestFull` 项。增量 `unitTest` 永远不能冒充 `unitTestFull` 门禁。
59
59
  3. **.gitignore + 暂存** ⚠️ — 检查 `.harness/` 在 `.gitignore`;**禁止 `git add -A`**
60
60
  4. **提交方式** — 主目录:AskUserQuestion 三选项(commit+push / 仅本地 / 取消);**worktree:固定仅本地 commit**
61
61
  5. **commit-message.txt** ⚠️ — 展示 staged、diff stat、完整中文 message;用户确认
@@ -80,7 +80,7 @@ M8. **ledger + 收尾** — 写入 `mergeFinalHash`;append `phase.end`;提
80
80
 
81
81
  通用 `harness-submit` 的最终门禁已统一为 `unitTestFull`(见通用 SKILL.md 步骤 2 / checklist 步骤 2)。Java overlay **不重复定义门禁规则**,只补两点:
82
82
 
83
- - **Maven 命令来源**:`--command` 取 `build-profile.json` 的 `buildCommands.unitTestFull`,典型 `mvn test -pl <module> -o`。`mvn test` 不带 `-Dtest=` 即模块级全量 → 记 `scope=module` 可复用;带 `-Dtest=<类>` 是增量 `unitTest`,**不能**冒充 `unitTestFull`。
83
+ - **Maven 命令来源**:`--command` 按 profile key resolve 取 `build-profile.json` 的 `commands.unitTestFull.command`(或 `harness_profile.py resolve --key unitTestFull`),典型 `mvn test -pl <module> -o`。`mvn test` 不带 `-Dtest=` 即模块级全量 → 记 `scope=module` 可复用;带 `-Dtest=<类>` 是增量 `unitTest`,**不能**冒充 `unitTestFull`。
84
84
  - **Java 依赖闭包**:`verificationInputs.unitTestFull` 必须覆盖完整编译+测试依赖闭包,建议 `["pom.xml", "<module>/pom.xml", "<module>/src/main/**", "<module>/src/test/**"]`,避免只哈希 staged 文件而漏掉 pom 依赖变化导致误复用。`harness_preflight.py detect` 对单模块项目写入根级默认 `["pom.xml", "src/main/**", "src/test/**"]`,多模块项目需手工改为 module 专属 glob。
85
85
  - **可选 package 前置**:若团队发版前需 jar 验证,在 submit 后接 `/harness-package`(默认时序 submit → package → archive)
86
86
  ## P0 执行可信度规则
@@ -89,21 +89,21 @@ powershell.exe -NoProfile -Command "<项目测试命令>"
89
89
 
90
90
  **重跑后必须把结果写回 ledger** 的 `compile`/`unitTest` 项,并更新 `diffHash`/`currentHead`。
91
91
 
92
- **提交前最终门禁**(步骤 2 末尾,commit 前强制,`unitTestFull` 模块级全量):
92
+ **提交前最终门禁**(步骤 2 末尾,commit 前强制,`unitTestFull` 模块级全量)——**只调 `can-reuse`,删除二次全量门禁**:
93
93
 
94
94
  ```powershell
95
95
  python <skills-root>/scripts/harness_ledger.py can-reuse `
96
96
  --change-dir ".harness/changes/<change-name>" `
97
97
  --verification unitTestFull --scope module `
98
98
  --project . --profile-input unitTestFull `
99
- --command "<build-profile.json buildCommands.unitTestFull>" --json
99
+ --command "<resolved commands.unitTestFull.command>" --json
100
100
  ```
101
101
 
102
- - `--profile-input unitTestFull` `build-profile.json` 的 `verificationInputs.unitTestFull` 展开**依赖闭包**文件集,**禁止用仅含 staged 业务文件的 `--files` 快捷方式**冒充全量闭包。
103
- - `--command` 必须直接读取当前项目 `build-profile.json` 的 `buildCommands.unitTestFull`,禁止原样复制示例模块名。
102
+ - `--command` **按 profile key resolve**:读 `build-profile.json` 的 `commands.unitTestFull.command`(v2),或 `python <skills-root>/scripts/harness_profile.py resolve --project . --key unitTestFull --json` 取 resolved command。**禁止原样复制示例模块名**(命令按 profile key resolve,文档示例只展示 key)。
103
+ - `--profile-input unitTestFull` `build-profile.json` 的 `verificationInputs.unitTestFull`(v2 由 `commands.unitTestFull.inputs` 派生)展开**依赖闭包**文件集,**禁止用仅含 staged 业务文件的 `--files` 快捷方式**冒充全量闭包。
104
104
  - 增量 `unitTest`(scope=测试类)永远不能冒充 `unitTestFull` 门禁;ledger 只有 `unitTest` 时返回 `insufficient-evidence`。
105
- - `reuse=false` → 执行 `buildCommands.unitTestFull`(模块级全量单元测试),成功后用**同一文件集、command、`scope=module`** 写回 ledger 的 `unitTestFull` 项,再继续步骤 3。
106
- - profile 缺 `verificationInputs.unitTestFull` / glob 无匹配 / 结果为空 → 返回 `insufficient-evidence`(exit 0),仍须执行全量测试但**不允许缓存复用**,直到 profile 正确配置。
105
+ - `reuse=true` → **不再执行二次全量测试**(删除与 coverage 冲突的二次门禁,spec §3.3);仅 `reuse=false`(can-reuse 明确失败)时执行**同一 resolved verification**(profile `unitTestFull` 命令,模块级全量单元测试),成功后用**同一文件集、command、`scope=module`** 写回 ledger 的 `unitTestFull` 项,再继续步骤 3。
106
+ - profile 缺 `commands.unitTestFull` / `verificationInputs.unitTestFull` / glob 无匹配 / 结果为空 → 返回 `insufficient-evidence`(exit 0),仍须执行全量测试但**不允许缓存复用**,直到 profile 正确配置。
107
107
 
108
108
  **编译/测试成功必须有明确证据**:
109
109
  - 构建命令输出必须包含构建成功证据(如 `BUILD SUCCESS` / `Finished` / exit code 0)
@@ -337,6 +337,21 @@ powershell.exe -Command "git -C '<项目路径>' pull --rebase"
337
337
 
338
338
  pull 输出非 `Already up to date.` → 引入他人提交 → M4 必须重跑验证。
339
339
 
340
+ **CRLF 预检**(pull 后强制):旧 working copy 的 `.gitattributes eol=lf` 文件可能是 CRLF(.gitattributes 后加未重新检出),曾导致 `core_content_hash` 跨工作树不一致 → sync 产生 dirty → M5 失败重跑。检测并修复:
341
+
342
+ ```powershell
343
+ # 1. renormalize 暴露 CRLF 漂移(仅规范化行尾,不改内容语义)
344
+ powershell.exe -Command "git -C '<项目路径>' add --renormalize ."
345
+ # 2. 若 git status --porcelain 非空 → working copy 存在 CRLF 漂移
346
+ powershell.exe -Command "git -C '<项目路径>' status --porcelain"
347
+ # 3. 有漂移 → 弃 staging + 强制 LF 重检(worktree 合并段 M2 在主仓库 main,应 clean,安全)
348
+ powershell.exe -Command "git -C '<项目路径>' reset -q; git -C '<项目路径>' checkout -- ."
349
+ # 4. 重新 renormalize 确认 clean(git status --porcelain 应空)
350
+ powershell.exe -Command "git -C '<项目路径>' add --renormalize .; git status --porcelain"
351
+ ```
352
+
353
+ > cluster 1 的 `core_content_hash` 改用 git blob sha 后,CRLF 不再影响 core hash,但 working copy CRLF 仍可能影响 workflow-data 包内容 hash,预检仍有价值。
354
+
340
355
  ### 步骤 M3:合并 worktree 分支
341
356
 
342
357
  ```powershell
@@ -365,6 +380,15 @@ powershell.exe -Command "git -C '<项目路径>' diff --name-only --diff-filter=
365
380
 
366
381
  重跑后写回 ledger 的 `compile`/`unitTest`,更新 `diffHash`/`currentHead`。
367
382
 
383
+ **写 check-ok marker**(npm run check exit 0 后强制):让 pre-push hook 跳过重复 check(省 ~350s)。三重校验(marker ts<10min + command + HEAD),任一不满足照跑。
384
+
385
+ ```powershell
386
+ # npm run check exit 0 后立即写 marker(M5 或 REUSED 后均可)
387
+ powershell.exe -Command "python harness/scripts/harness_check_gate.py --write"
388
+ ```
389
+
390
+ > marker 写入 `.harness/check-ok.marker`(gitignored,本地)。push 时 pre-push hook 读 marker:HEAD 自写 marker 后未变 + ts<10min + command 匹配 → 跳过 npm run check;否则照跑(安全默认)。
391
+
368
392
  ### 步骤 M6:push 主分支
369
393
 
370
394
  ```powershell
@@ -2,7 +2,7 @@
2
2
  name: harness-sync
3
3
  description: 检查并更新项目AI元数据(CodeGraph索引、harness-codebase-map分析、CLAUDE.md、AGENTS.md、.harness/完整性),确保Claude对代码库的理解与最新代码一致。当用户说'同步/更新索引/刷新元数据/检查一致性'时使用
4
4
  ---
5
- <!-- generated by harness_deploy.py; core=7b81effe1faaef85; overlay=java; agent=cursor; do not edit -->
5
+ <!-- generated by harness_deploy.py; core=d437039c3207693b; overlay=java; agent=cursor; do not edit -->
6
6
  # harness-sync — 元数据同步
7
7
 
8
8
  ## Purpose
@@ -2,7 +2,7 @@
2
2
  name: harness-test
3
3
  description: 测试执行:读取场景表,执行单元测试+API接口测试+数据兼容验证,输出测试报告。当用户说'跑测试/验证/跑用例/接口测试/单元测试'时使用
4
4
  ---
5
- <!-- generated by harness_deploy.py; core=7b81effe1faaef85; overlay=java; agent=cursor; do not edit -->
5
+ <!-- generated by harness_deploy.py; core=d437039c3207693b; overlay=java; agent=cursor; do not edit -->
6
6
  # harness-test — 测试执行
7
7
 
8
8
  ## Purpose
@@ -78,9 +78,9 @@ description: 测试执行:读取场景表,执行单元测试+API接口测试
78
78
  ### Java 测试环境补充
79
79
 
80
80
  - **preflight 0.1**:写入 `runtime/preflight.json` 的 `executorPath`/`mvnVersion` 等;Maven 可用性 `mvn -version` exit 0
81
- - **编译门禁**:测试前按 `build-profile.json` 的 `buildCommands.compile`;输出须含 `BUILD SUCCESS` 或 exit 0 证据
82
- - **条件 install**:worktree 首建或上游模块变更时按 profile 执行 `buildCommands.install`(非每次强制 `-am`)
83
- - **单元测试**:可复用 ledger unitTest 则跳过;否则 `buildCommands.unitTest`(典型 `mvn test -pl <module>`)
81
+ - **编译门禁**:测试前按 `build-profile.json` 的 `commands.compile`(v2,profile key resolve);输出须含 `BUILD SUCCESS` 或 exit 0 证据
82
+ - **条件 install**:worktree 首建或上游模块变更时按 profile 执行 `commands.install`(非每次强制 `-am`)
83
+ - **单元测试**:可复用 ledger unitTest 则跳过;否则 `commands.unitTest`(典型 `mvn test -pl <module>`);执行模块全量 `commands.unitTestFull` 成功 → 记 `unitTestFull`(scope=module,供 submit 复用)
84
84
  - **服务启动**:`build-profile.json` 的 `serviceStartTemplate`(典型 `spring-boot:run` + profile);**禁止 hardcode 端口/模块路径**
85
85
  - **服务指纹输入**(Task 3 §5.1):`serviceStart.inputFiles` 必须列出 module 源 glob(如 `["<module>/pom.xml", "<module>/src/main/**/*.java", "<module>/src/main/resources/**"]`);`harness_service.py ensure` 取 CLI `--files` ∪ `inputFiles` 计算 `moduleInputsHash`。**空输入被拒绝**,不得生成可复用空指纹。源码/command/profile/overlayPath 任一变化即 restart
86
86
  - **runtime overlay**:`-Dspring.config.additional-location=file:<ascii-abs-path>/application-harness-test.yml`;禁止默认 Edit tracked `application*.yml`
@@ -111,7 +111,7 @@ description: 测试执行:读取场景表,执行单元测试+API接口测试
111
111
 
112
112
  ### 四、单元测试复用 + 写入 ledger
113
113
 
114
- Phase 1 前先读 `.harness/changes/<change-name>/evidence/verification-ledger.json`:run 的 unitTest 满足(diffHash 一致 + module/profile 一致 + scope 一致或更严格 + run 后无行为性修改 + run 跑了全量测试)则复用,否则重跑测试命令(按技术栈,如 `mvn test -pl <module>`)。Phase 1/2 完成后必须写回 ledger `unitTest`/`apiTest` 项。详见 `checklist.md`「单元测试复用」、`../protocols/ledger-protocol.md`。
114
+ Phase 1 前先读 `.harness/changes/<change-name>/evidence/verification-ledger.json`:run 的 unitTest 满足(diffHash 一致 + module/profile 一致 + scope 一致或更严格 + run 后无行为性修改 + run 跑了全量测试)则复用,否则按 **profile key resolve** 执行测试命令(`python <skills-root>/scripts/harness_profile.py resolve --project . --key unitTest|unitTestFull --json`,**不复制示例 `-pl` 命令**)。Phase 1/2 完成后必须写回 ledger:执行增量测试类 `unitTest`(scope=incremental);执行 profile 模块全量命令 → 记 `unitTestFull`(scope=module,可供 submit 复用);接口测试 → 记 `apiTest`。详见 `checklist.md`「单元测试复用」、`../protocols/ledger-protocol.md`。
115
115
 
116
116
  ### 五、命令与请求超时治理
117
117
 
@@ -258,3 +258,19 @@ $cred = $resp.data.accessToken
258
258
  **正确做法**:用 `git diff --binary` 生成 patch 并计算 SHA-256,ledger 只认 `sha256:<hash>` 格式。diffHash 不一致时必须重跑相关测试。
259
259
 
260
260
  > diffHash/ledger 复用规则遵循 `../protocols/ledger-protocol.md`;结果证据要求遵循 `../protocols/evidence-based-reporting-protocol.md`。
261
+
262
+ ## BOM-safe JSON / identifier sanitizer / 凭据扫描 (runtime-helpers.mjs)
263
+
264
+ > 变更簇 5 (spec §3.4):Node runtime helper 集中处理 PS5.1 BOM、非法测试标识符、凭据边界三类返工。源码 `scripts/runtime-helpers.mjs`,测试 `scripts/tests/runtime-helpers.test.mjs`(`node --test`)。
265
+
266
+ | 函数 | 用途 | 规避的坑 |
267
+ |------|------|----------|
268
+ | `readJsonUtf8BomSafe(path)` | 读 credential-cache.json / api-test-results.json,容忍 U+FEFF BOM | PS5.1 `Out-File -Encoding utf8` 写入 BOM 导致 `JSON.parse` 失败 |
269
+ | `writeJsonUtf8NoBom(path, value)` | 原子写 (temp+rename),UTF-8 no BOM,LF,2-space 缩进 | 结果文件被 BOM/换行符污染破坏字节稳定;半写入文件被并发读到 |
270
+ | `sanitizeTestIdentifier({name, pattern, maxLength, prefix})` | change-name → 稳定标识(清洗非法字符 + 超长截断 + 原文名短 hash 防碰撞) | 中文/连字符/超长 change-name 生成非法 identifier 触发服务端 400 |
271
+ | `validateRunnerPayload(payload, {identifierPattern})` | Runner 生成前本地校验 payload schema/必填/identifier/重复 id,返回结构化错误码 | 测试脚本错误(缺字段/非法 id)直到请求服务后才暴露,返工成本高 |
272
+ | `findCredentialValues(text)` | 扫描 profile/Markdown/docs 中的凭据明文值(password/token/secret/Authorization/jdbc password),占位符 `<*_REDACTED>` 与 env 引用 `${ENV}`/`$ENV` 不报 | profile/规则文档误含明文凭据被发布 |
273
+
274
+ **Runner 生成前强制**(spec §3.4 point 3):生成 `api-test-runner.mjs` 前用 `validateRunnerPayload` 校验全部场景;`ok=false` → 修复脚本错误,**不得带错请求服务**。场景 id 用 `sanitizeTestIdentifier` 生成(profile v2 `identifier.pattern/maxLength/prefix` 已声明)。
275
+
276
+ **凭据边界**(spec §3.4 point 4):credential 配置只含 env key(如 `${TEST_TOKEN}`)、cache path、角色,不含值。发布前用 `findCredentialValues` 扫 profile/规则/Markdown,命中即 ❌FAIL。详见 `../protocols/sensitive-info-protocol.md` §6。
@@ -0,0 +1,216 @@
1
+ #!/usr/bin/env node
2
+ // runtime-helpers.mjs — BOM-safe JSON I/O + test-identifier sanitizer + runner payload validation + credential scan.
3
+ // 变更簇 5 (spec §3.4): BOM-safe Runner, identifier sanitizer, 凭据边界.
4
+ //
5
+ // 设计目标:
6
+ // - readJsonUtf8BomSafe: 容忍 UTF-8 BOM (U+FEFF), credential-cache.json 等文件可能被 PS5.1 写入 BOM
7
+ // - writeJsonUtf8NoBom: 原子写 (temp+rename), UTF-8 no BOM, LF — 结果/报告文件字节稳定
8
+ // - sanitizeTestIdentifier: 按 pattern/maxLength/prefix 生成稳定标识; 超长截断 + 原文名短 hash 防碰撞
9
+ // - validateRunnerPayload: Runner 生成前本地校验 payload schema/必填/identifier, 测试脚本错误不得请求服务后才发现
10
+ // - findCredentialValues: 扫描 profile/Markdown/docs 中的凭据明文值 (sensitive-info-protocol §1)
11
+ //
12
+ // Node ≥18 ESM, stdlib only. 输出 JSON 内容确定性 (不含 Math.random); 仅临时文件名用 randomBytes.
13
+
14
+ import fs from 'node:fs';
15
+ import path from 'node:path';
16
+ import crypto from 'node:crypto';
17
+
18
+ export const BOM = 0xfeff;
19
+ export const DEFAULT_IDENTIFIER_PATTERN = '^[A-Za-z][A-Za-z0-9_-]*$';
20
+ export const DEFAULT_IDENTIFIER_MAX_LENGTH = 64;
21
+ const HASH_LEN = 8;
22
+
23
+ // ---------------------------------------------------------------------------
24
+ // BOM-safe JSON I/O
25
+ // ---------------------------------------------------------------------------
26
+
27
+ /** Strip a single leading UTF-8 BOM (U+FEFF) from text. No-op if absent. */
28
+ export function stripBom(text) {
29
+ return text.codePointAt(0) === BOM ? text.slice(1) : text;
30
+ }
31
+
32
+ /** Read a JSON file, tolerating a leading UTF-8 BOM. Throws on invalid JSON. */
33
+ export function readJsonUtf8BomSafe(filePath) {
34
+ const raw = fs.readFileSync(filePath, 'utf8');
35
+ return JSON.parse(stripBom(raw));
36
+ }
37
+
38
+ /** Atomically write JSON as UTF-8 (no BOM), LF, 2-space indent, trailing newline.
39
+ * Writes to a temp file then renames — readers never see a half-written file. */
40
+ export function writeJsonUtf8NoBom(filePath, value) {
41
+ const json = JSON.stringify(value, null, 2) + '\n';
42
+ const dir = path.dirname(filePath);
43
+ fs.mkdirSync(dir, { recursive: true });
44
+ const tmp = `${filePath}.${process.pid}.${crypto.randomBytes(6).toString('hex')}.tmp`;
45
+ fs.writeFileSync(tmp, json, 'utf8');
46
+ try {
47
+ fs.renameSync(tmp, filePath);
48
+ } catch (err) {
49
+ try {
50
+ fs.unlinkSync(tmp);
51
+ } catch {
52
+ /* best-effort cleanup */
53
+ }
54
+ throw err;
55
+ }
56
+ }
57
+
58
+ // ---------------------------------------------------------------------------
59
+ // sanitizeTestIdentifier
60
+ // ---------------------------------------------------------------------------
61
+
62
+ /**
63
+ * Sanitize a change/test name into a stable identifier matching the default
64
+ * pattern `^[A-Za-z][A-Za-z0-9_-]*$`.
65
+ *
66
+ * - runs of chars outside [A-Za-z0-9_-] → '_'
67
+ * - prepend `prefix_` when prefix given; ensure leading letter (prepend 'T')
68
+ * - if over maxLength: truncate and append a short sha256 hash of the ORIGINAL
69
+ * name, so two near-identical long names that collide after truncation stay
70
+ * distinct (UT-023). Hash is deterministic — no Math.random.
71
+ *
72
+ * @returns {string} identifier matching the default pattern, length ≤ maxLength.
73
+ */
74
+ export function sanitizeTestIdentifier({
75
+ name,
76
+ pattern = DEFAULT_IDENTIFIER_PATTERN,
77
+ maxLength = DEFAULT_IDENTIFIER_MAX_LENGTH,
78
+ prefix = '',
79
+ }) {
80
+ const raw = String(name ?? '');
81
+ let base = prefix ? `${prefix}_` : '';
82
+ base += raw.replace(/[^A-Za-z0-9_-]+/g, '_');
83
+ // leading letter (pattern ^[A-Za-z]); prepend 'T' if first char is _ or digit
84
+ if (!/^[A-Za-z]/.test(base)) base = `T${base}`;
85
+ if (base.length <= maxLength) return base;
86
+ const hash = crypto.createHash('sha256').update(raw, 'utf8').digest('hex').slice(0, HASH_LEN);
87
+ const reserve = HASH_LEN + 1; // '_' + hash
88
+ const cap = Math.max(1, maxLength - reserve);
89
+ let truncated = base.slice(0, cap).replace(/_+$/, '');
90
+ // if truncation removed the leading letter guarantee, restore it
91
+ if (!/^[A-Za-z]/.test(truncated)) truncated = `T${truncated}`;
92
+ return `${truncated}_${hash}`;
93
+ }
94
+
95
+ /** Compile a pattern safely; returns null if invalid. */
96
+ function safeRegex(pattern) {
97
+ try {
98
+ return new RegExp(`^(?:${pattern})$`);
99
+ } catch {
100
+ return null;
101
+ }
102
+ }
103
+
104
+ /** True if id matches pattern. Invalid pattern → false. */
105
+ export function matchesPattern(id, pattern = DEFAULT_IDENTIFIER_PATTERN) {
106
+ const re = safeRegex(pattern);
107
+ return re ? re.test(String(id)) : false;
108
+ }
109
+
110
+ // ---------------------------------------------------------------------------
111
+ // validateRunnerPayload — Runner 生成前本地校验
112
+ // ---------------------------------------------------------------------------
113
+
114
+ const HTTP_METHODS = /^(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)$/i;
115
+
116
+ /**
117
+ * Validate a runner payload (array of API test scenarios) BEFORE generating or
118
+ * executing the runner. Catches script/schema errors locally so they don't
119
+ * surface only after a service request (spec §3.4 point 3).
120
+ *
121
+ * Scenario required fields: id, method, url. id must match identifierPattern
122
+ * and be unique. method must be a known HTTP method.
123
+ *
124
+ * @returns {{ ok: boolean, errors: Array<{code: string, field: string, message: string}> }}
125
+ */
126
+ export function validateRunnerPayload(payload, opts = {}) {
127
+ const errors = [];
128
+ const pattern = opts.identifierPattern || DEFAULT_IDENTIFIER_PATTERN;
129
+ const re = safeRegex(pattern);
130
+
131
+ if (!Array.isArray(payload)) {
132
+ return {
133
+ ok: false,
134
+ errors: [{ code: 'PAYLOAD_NOT_ARRAY', field: 'payload', message: 'payload must be an array of scenarios' }],
135
+ };
136
+ }
137
+ if (payload.length === 0) {
138
+ errors.push({ code: 'PAYLOAD_EMPTY', field: 'payload', message: 'payload has no scenarios' });
139
+ }
140
+
141
+ const seenIds = new Set();
142
+ payload.forEach((scn, i) => {
143
+ const where = `scenarios[${i}]`;
144
+ if (!scn || typeof scn !== 'object' || Array.isArray(scn)) {
145
+ errors.push({ code: 'SCENARIO_NOT_OBJECT', field: where, message: 'scenario must be an object' });
146
+ return;
147
+ }
148
+ for (const f of ['id', 'method', 'url']) {
149
+ if (scn[f] === undefined || scn[f] === null || scn[f] === '') {
150
+ errors.push({ code: 'MISSING_FIELD', field: `${where}.${f}`, message: `required field '${f}' missing or empty` });
151
+ }
152
+ }
153
+ if (scn.id !== undefined && scn.id !== null && scn.id !== '') {
154
+ const idStr = String(scn.id);
155
+ if (re && !re.test(idStr)) {
156
+ errors.push({ code: 'INVALID_IDENTIFIER', field: `${where}.id`, message: `id '${idStr}' does not match pattern ${pattern}` });
157
+ }
158
+ if (seenIds.has(idStr)) {
159
+ errors.push({ code: 'DUPLICATE_ID', field: `${where}.id`, message: `duplicate id '${idStr}'` });
160
+ } else {
161
+ seenIds.add(idStr);
162
+ }
163
+ }
164
+ if (scn.method !== undefined && scn.method !== null && scn.method !== '') {
165
+ if (!HTTP_METHODS.test(String(scn.method))) {
166
+ errors.push({ code: 'INVALID_METHOD', field: `${where}.method`, message: `unknown HTTP method '${scn.method}'` });
167
+ }
168
+ }
169
+ });
170
+
171
+ return { ok: errors.length === 0, errors };
172
+ }
173
+
174
+ // ---------------------------------------------------------------------------
175
+ // findCredentialValues — 凭据明文扫描 (sensitive-info-protocol §1)
176
+ // ---------------------------------------------------------------------------
177
+
178
+ // 值占位符或 env 引用 (不会被当作凭据明文): <*_REDACTED> / ${ENV} / $ENV
179
+ // 前缀匹配 ${ENV (无需闭合 }) — value 正则在 } 处停止, 仍应识别为 env 引用。
180
+ const SAFE_VALUE = /<\w+_REDACTED>|\$\{[A-Z0-9_]+|\$[A-Z][A-Z0-9_]*\b/;
181
+
182
+ const CRED_PATTERNS = [
183
+ // password / passwd / pwd = 或 : 后跟值 (字段名可带 JSON/YAML 引号)
184
+ { code: 'PASSWORD_VALUE', re: /"?password"?\s*[:=]\s*(['"]?)([^'"\s,;)}\n]+)\1/i, group: 2 },
185
+ // token / access_token / api_key / apikey / secret / accessKey / secretAccessKey
186
+ { code: 'SECRET_VALUE', re: /(?:"?(?:access_token|apikey|api_key|secretAccessKey|accessKey|secret|token)"?)\s*[:=]\s*(['"]?)([^'"\s,;)}\n]+)\1/i, group: 2 },
187
+ // Authorization: Bearer <jwt-ish>
188
+ { code: 'AUTH_HEADER', re: /Authorization\s*:\s*Bearer\s+([A-Za-z0-9_.-]{10,})/i, group: 1 },
189
+ // jdbc url with password=
190
+ { code: 'DB_PASSWORD', re: /jdbc:[^\s?]*[?&]password=([^&\s]+)/i, group: 1 },
191
+ ];
192
+
193
+ /**
194
+ * Scan text for credential VALUES per sensitive-info-protocol §1.
195
+ * Placeholders (`<TOKEN_REDACTED>`) and env refs (`${DB_PASSWORD}` / `$DB_PASSWORD`)
196
+ * are NOT flagged — credential config may carry env keys, not values (spec §3.4 point 4).
197
+ *
198
+ * @returns {Array<{ line: number, code: string, snippet: string }>}
199
+ */
200
+ export function findCredentialValues(text) {
201
+ const findings = [];
202
+ const lines = String(text ?? '').split(/\r?\n/);
203
+ lines.forEach((line, idx) => {
204
+ for (const { code, re, group } of CRED_PATTERNS) {
205
+ const m = line.match(re);
206
+ if (!m) continue;
207
+ const value = m[group] || '';
208
+ if (SAFE_VALUE.test(value)) continue; // placeholder / env ref — safe
209
+ // Redact the captured credential value in the snippet so reports/logs
210
+ // never leak it; field name + line number remain for locating the finding.
211
+ const snippet = (value ? line.replace(value, '<REDACTED>') : line).trim().slice(0, 80);
212
+ findings.push({ line: idx + 1, code, snippet });
213
+ }
214
+ });
215
+ return findings;
216
+ }
@@ -139,7 +139,7 @@ PowerShell HTML renderer 仅作 legacy fallback。该脚本以 UTF-8 with BOM
139
139
 
140
140
  **Python fallback(`harness_archive.py` 内置)**:Node 不可用/超时/exit 非 0/未产出文件时,`harness_archive.py render_final_summary` 自动降级为内置 Python fallback(`render_fallback_html`),渲染含 changeName、finalStatus、`reportPipeline.commands`(command/exitCode)、`verification`(unitTests/apiTests/dbCompatibility)、changedFiles、archiveManifest、knownRisks、manualActions、maintenanceNotes 的确定性 HTML;USER_SKIPPED/BLOCKED_BY_DBA/失败状态可见,所有动态值 HTML 转义。返回结构统一为 `{ok, renderer: node|python-fallback|none, fallbackReason, out_path}`。Node 与 Python fallback **都失败**(`renderer=none, ok=false`)时,finalize 立即恢复原 change 目录并 exit 非 0,**绝不归档无 final-summary.html 的变更**。
141
141
 
142
- 渲染后必须运行 report validatevalidate error 存在时,archive 不得删除原 changes 目录。**缺 final-summary.html 恒为 validate error**(不再有"没有 HTML 但只 warning"的分支)。
142
+ `validate` 是 `harness_archive.py finalize` 的内嵌同进程步骤(不存在独立 `report validate` CLI);validate error 存在时,finalize 恢复原 changes 目录并 exit 非 0,绝不删除原 changes 目录。**缺 final-summary.html 恒为 validate error**(不再有"没有 HTML 但只 warning"的分支)。
143
143
 
144
144
  ## 归档与知识维护解耦(§8)
145
145
 
@@ -182,7 +182,7 @@ verification-ledger 把每次验证(compile / unit test / api test / package
182
182
  ```text
183
183
  harness_ledger.py can-reuse --verification unitTestFull --scope module \
184
184
  --project . --profile-input unitTestFull \
185
- --command "<build-profile.json buildCommands.unitTestFull>" --json
185
+ --command "<resolved build-profile.json commands.unitTestFull.command>" --json
186
186
  ```
187
187
 
188
188
  `build-profile.json` 新增 `verificationInputs.unitTestFull`(glob 列表,相对 project 展开,只保留 project 内文件、去重排序):
@@ -201,7 +201,17 @@ profile key 缺失 / glob 无匹配 / 结果为空 → `insufficient-evidence`
201
201
 
202
202
  必须基于真实 diff 计算 SHA-256,且**必须是 commit-invariant 的**——覆盖本变更集相对 `baseCommit` 的全部内容变更(已提交 + 未提交 + 未跟踪),使 checkpoint commit 前后指纹一致,保证 run→test 复用链不断。
203
203
 
204
- `<baseCommit>` 从 ledger 读取(harness-plan 阶段写入);缺失时用 `git merge-base HEAD <默认分支>` 兜底。推荐命令:
204
+ `<baseCommit>` 从 ledger 读取(harness-plan 阶段写入);缺失时用 `git merge-base HEAD <默认分支>` 兜底。
205
+
206
+ **canonical 命令(cluster 2 起脚本化,推荐)**:
207
+
208
+ ```text
209
+ harness_ledger.py diff-hash --repo <projectRoot> --base <baseCommit> --json
210
+ ```
211
+
212
+ `diff-hash` 用 subprocess 直接捕获 Git bytes,基于**内容变更集**计算 SHA-256:working tree 相对 base 的所有变化文件 + 未跟踪文件,按 repo-relative path 排序、长度 framing(`path-len | path | exists | content-len | content`),独立于 shell/控制台编码/BOM/系统换行,且 **commit-invariant**(checkpoint commit 不改 working tree → 指纹不变,UT-011)。算法版本 `content-changeset-1`,输出 `diffHash`/`algorithmVersion`/`fileCount`/`base`/`head`。
213
+
214
+ > 旧 v1 PowerShell 拼接命令(下方)已废弃:依赖文本编码,且未跟踪文件提交后表示从 framed-content 切换为 diff-format 会破坏 commit-invariance。仅作历史参考。
205
215
 
206
216
  ```powershell
207
217
  powershell.exe -NoProfile -Command "$base = '<baseCommit>'; $patch = '.harness/changes/<change>/runtime/current-diff.patch'; & { git diff $base HEAD --binary; git diff --binary; git ls-files --others --exclude-standard | ForEach-Object { Get-Content -Raw -LiteralPath $_ } } | Out-File -Encoding utf8 $patch; (Get-FileHash $patch -Algorithm SHA256).Hash"
@@ -268,3 +278,46 @@ ledger 的 `status` 与 final-summary 展示状态对应:
268
278
  | postTestClassification=NON_BEHAVIORAL_CLEANUP | 小清理 | 🧹NON_BEHAVIORAL_CLEANUP |
269
279
 
270
280
  **强制规则**:任何阶段若复用了前一阶段结果,final-summary 必须显示 `🔁REUSED`,**不得伪装成重新执行**。
281
+
282
+ ## 九、Ledger v2(cluster 2)
283
+
284
+ `harness_ledger.py` v2 引入确定性 `diff-hash`(§五)、v2 entry 字段、coverage lattice、`package` verification 与结构化错误码。Skill 只调用 `record`/`can-reuse`/`diff-hash`,不再手工判断或解释自由文本。
285
+
286
+ ### 9.1 v2 entry 字段
287
+
288
+ `record` 自动写入:
289
+
290
+ | 字段 | 含义 |
291
+ |------|------|
292
+ | `algorithmVersion` | 固定 `harness-ledger-2`;缺失即 v1 entry |
293
+ | `coverage` | 覆盖层级 `incremental`/`module`/`module-am`/`full`,由 verification+scope 派生或 `--coverage` 显式指定 |
294
+ | `toolchainHash`/`profileHash`/`environmentHash` | 可选;`record --toolchain-hash` 等写入,`can-reuse --toolchain-hash` 等比对(UT-017) |
295
+
296
+ ### 9.2 coverage lattice
297
+
298
+ `COVERAGE_RANK = {incremental:0, module:1, module-am:2, full:3}`。各 verification 最低要求:`unitTest`=0、`unitTestFull`/`compile`/`apiTest`=1、`install`/`package`=2。entry.coverage rank < 要求 → `insufficient-evidence`(code `COVERAGE_INSUFFICIENT`),**禁止增量证据提升为全量门禁**(UT-015/API-005)。
299
+
300
+ ### 9.3 package verification
301
+
302
+ `package` 加入 `VERIFICATIONS`。`record --verification package` 额外记录 `deployArtifact`/`sha256`/`testsExecuted`/`testsReusedFrom`。API-006/007 的 package 生命周期复用编排由 cluster 4 负责,cluster 2 仅提供 record/can-reuse 能力(UT-018)。
303
+
304
+ ### 9.4 结构化错误码
305
+
306
+ `can-reuse` 每个非 reuse 结果携带 `code` 字段,Skill 据 `code` 决策,不解析 `detail` 自由文本:
307
+
308
+ | code | reason | 含义 |
309
+ |------|--------|------|
310
+ | `LEDGER_MISSING`/`VALIDATIONS_MISSING`/`VALIDATION_MISSING` | insufficient-evidence | ledger/条目缺失 |
311
+ | `MISSING_V2_FIELDS` | insufficient-evidence | v1 entry 缺 algorithmVersion/coverage,**一次性保守失效**(COM-002),重记录 v2 后可复用 |
312
+ | `MISSING_FIELDS` | insufficient-evidence | 缺 status/evidence/inputsHash/scope 等基础字段 |
313
+ | `COVERAGE_INSUFFICIENT` | insufficient-evidence | coverage rank 不足 |
314
+ | `SCOPE_INSUFFICIENT` | insufficient-evidence | unitTest scope 不覆盖请求 |
315
+ | `INPUT_FILE_MISSING` | insufficient-evidence | 当前文件集读取失败 |
316
+ | `COMMAND_CHANGED` | rerun | 命令变化 |
317
+ | `TOOLCHAIN_CHANGED`/`PROFILE_CHANGED`/`ENVIRONMENT_CHANGED` | rerun | 对应 hash 变化(UT-017) |
318
+ | `INPUTS_HASH_CHANGED` | rerun | inputsHash 变化 |
319
+ | `REUSED` | reuse | 复用 |
320
+
321
+ ### 9.5 v1→v2 兼容
322
+
323
+ v1 ledger 可读;entry 缺 v2 字段时 `can-reuse` 返回 `MISSING_V2_FIELDS`(insufficient-evidence),**不静默升级证据**。重新 `record`(自动补 v2 字段)后恢复复用。diffHash 算法升级后旧 ledger 一次性失效,不危险复用。
@@ -24,14 +24,7 @@ python <skills-root>/scripts/harness_archive.py replay --archive-dir ".harness/a
24
24
  python <skills-root>/scripts/harness_events.py append --change-dir ".harness/changes/<change-name>" --phase "<phase>" --type <type> [--note "..."]
25
25
  ```
26
26
 
27
- 若项目安装 Hunter-Harness CLIcollect/validate 亦可使用(与 finalize 内嵌步骤等价):
28
-
29
- ```powershell
30
- powershell.exe -NoProfile -Command "npx hunter-harness report collect --change-id '<change-name>' --json"
31
- powershell.exe -NoProfile -Command "npx hunter-harness report validate --change-id '<change-name>' --json"
32
- ```
33
-
34
- CLI 不可用时,agent 仍必须按本协议生成等价的 `summary-data.json` 并执行一致性校验,不得退回手写汇总。
27
+ 归档报告流水线只有两个入口,均由 `harness_archive.py` 提供:`collect`/`render`/`validate` 是 `finalize` 的内嵌同进程步骤,**不再作为独立 CLI 暴露**(不存在 `report collect`/`report validate` 子命令)。`summary-data.json` 只能由 `finalize`(归档时)或 `replay`(回放时)生成;**禁止 agent 临场手写或拼装等价的 `summary-data.json`**。`harness_archive.py` 不可用时归档失败退出,不得退回手写汇总。
35
28
 
36
29
  ## events.ndjson
37
30
 
@@ -90,3 +90,16 @@ spring:
90
90
  - API 测试报告的持久化记录中
91
91
 
92
92
  > 对于 API 测试中获取的 token,在测试执行过程中可临时使用(如 Playwright 请求),但测试报告中必须用 `<TOKEN_REDACTED>` 替换。
93
+
94
+ ## 6. profile / 规则 / Markdown 凭据扫描
95
+
96
+ profile `build-profile.json`、规则文档、Skill Markdown **不得包含凭据明文值**(spec §3.4 凭据边界:配置只含 env key、cache path、角色,不含值)。发布前用 `harness-test/scripts/runtime-helpers.mjs` 的 `findCredentialValues(text)` 扫描:
97
+
98
+ - 命中 `password/token/secret/accessKey/Authorization: Bearer/jdbc password=` 等明文值 → ❌FAIL,必须改为占位符 `<*_REDACTED>` 或 env 引用 `${ENV}` / `$ENV`。
99
+ - 占位符 `<TOKEN_REDACTED>` 与 env 引用 `${TEST_TOKEN}` / `$DB_PASSWORD` 不报(credential 配置允许 env key)。
100
+
101
+ ```js
102
+ import { findCredentialValues } from '<skills-root>/harness-test/scripts/runtime-helpers.mjs';
103
+ const findings = findCredentialValues(fs.readFileSync('build-profile.json', 'utf8'));
104
+ if (findings.length > 0) { /* ❌FAIL: 列出 line/code/snippet,改为 env key 或占位符 */ }
105
+ ```