audit-tools 0.45.0 → 0.48.0

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 (288) hide show
  1. package/README.md +51 -18
  2. package/dispatch/merge-results.mjs +3 -3
  3. package/dispatch/validate-result.mjs +3 -3
  4. package/dist/audit/cli/charterExtractionPrompt.d.ts.map +1 -1
  5. package/dist/audit/cli/charterExtractionPrompt.js +11 -1
  6. package/dist/audit/cli/charterExtractionPrompt.js.map +1 -1
  7. package/dist/audit/cli/cleanupCommand.d.ts +25 -0
  8. package/dist/audit/cli/cleanupCommand.d.ts.map +1 -1
  9. package/dist/audit/cli/cleanupCommand.js +76 -1
  10. package/dist/audit/cli/cleanupCommand.js.map +1 -1
  11. package/dist/audit/cli/dispatch/hostHandoff.d.ts.map +1 -1
  12. package/dist/audit/cli/dispatch/hostHandoff.js +52 -76
  13. package/dist/audit/cli/dispatch/hostHandoff.js.map +1 -1
  14. package/dist/audit/cli/dispatch/packetFilter.d.ts +1 -1
  15. package/dist/audit/cli/fanoutLanes.d.ts.map +1 -1
  16. package/dist/audit/cli/fanoutLanes.js +6 -1
  17. package/dist/audit/cli/fanoutLanes.js.map +1 -1
  18. package/dist/audit/cli/laneSubmissions.d.ts +13 -0
  19. package/dist/audit/cli/laneSubmissions.d.ts.map +1 -1
  20. package/dist/audit/cli/laneSubmissions.js +38 -27
  21. package/dist/audit/cli/laneSubmissions.js.map +1 -1
  22. package/dist/audit/cli/nextStepCommand.d.ts +12 -0
  23. package/dist/audit/cli/nextStepCommand.d.ts.map +1 -1
  24. package/dist/audit/cli/nextStepCommand.js +23 -12
  25. package/dist/audit/cli/nextStepCommand.js.map +1 -1
  26. package/dist/audit/cli/nextStepHelpers.d.ts +3 -2
  27. package/dist/audit/cli/nextStepHelpers.d.ts.map +1 -1
  28. package/dist/audit/cli/nextStepHelpers.js +65 -37
  29. package/dist/audit/cli/nextStepHelpers.js.map +1 -1
  30. package/dist/audit/cli/reviewRun.d.ts +1 -1
  31. package/dist/audit/cli/reviewRun.d.ts.map +1 -1
  32. package/dist/audit/cli/reviewRun.js +2 -9
  33. package/dist/audit/cli/reviewRun.js.map +1 -1
  34. package/dist/audit/cli/sampleRunCommand.d.ts +215 -0
  35. package/dist/audit/cli/sampleRunCommand.d.ts.map +1 -1
  36. package/dist/audit/cli/sampleRunCommand.js +60 -3
  37. package/dist/audit/cli/sampleRunCommand.js.map +1 -1
  38. package/dist/audit/cli/semanticReviewStep.d.ts.map +1 -1
  39. package/dist/audit/cli/semanticReviewStep.js +9 -1
  40. package/dist/audit/cli/semanticReviewStep.js.map +1 -1
  41. package/dist/audit/cli/steps.d.ts +6 -6
  42. package/dist/audit/contracts/workerSchemas.d.ts +36 -26
  43. package/dist/audit/contracts/workerSchemas.d.ts.map +1 -1
  44. package/dist/audit/contracts/workerSchemas.js +11 -1
  45. package/dist/audit/contracts/workerSchemas.js.map +1 -1
  46. package/dist/audit/contracts/wrapperResponse.d.ts +52 -28
  47. package/dist/audit/contracts/wrapperResponse.d.ts.map +1 -1
  48. package/dist/audit/contracts/wrapperResponse.js +8 -5
  49. package/dist/audit/contracts/wrapperResponse.js.map +1 -1
  50. package/dist/audit/decompose/sources.d.ts.map +1 -1
  51. package/dist/audit/decompose/sources.js +21 -5
  52. package/dist/audit/decompose/sources.js.map +1 -1
  53. package/dist/audit/extractors/analyzers/registry.d.ts +8 -5
  54. package/dist/audit/extractors/analyzers/registry.d.ts.map +1 -1
  55. package/dist/audit/extractors/analyzers/registry.js +28 -7
  56. package/dist/audit/extractors/analyzers/registry.js.map +1 -1
  57. package/dist/audit/extractors/designAssessment.js +1 -1
  58. package/dist/audit/extractors/gitHistory.d.ts +1 -1
  59. package/dist/audit/extractors/gitHistory.js +1 -1
  60. package/dist/audit/extractors/graph.d.ts +1 -1
  61. package/dist/audit/extractors/graph.js +1 -1
  62. package/dist/audit/extractors/risk.d.ts +1 -1
  63. package/dist/audit/extractors/risk.js +1 -1
  64. package/dist/audit/io/artifacts.d.ts.map +1 -1
  65. package/dist/audit/io/artifacts.js +5 -5
  66. package/dist/audit/io/artifacts.js.map +1 -1
  67. package/dist/audit/orchestrator/acquisitionExecutor.d.ts +12 -7
  68. package/dist/audit/orchestrator/acquisitionExecutor.d.ts.map +1 -1
  69. package/dist/audit/orchestrator/acquisitionExecutor.js +1 -1
  70. package/dist/audit/orchestrator/acquisitionExecutor.js.map +1 -1
  71. package/dist/audit/orchestrator/advance.d.ts +14 -10
  72. package/dist/audit/orchestrator/advance.d.ts.map +1 -1
  73. package/dist/audit/orchestrator/advance.js +49 -24
  74. package/dist/audit/orchestrator/advance.js.map +1 -1
  75. package/dist/audit/orchestrator/advanceTypes.d.ts +14 -0
  76. package/dist/audit/orchestrator/advanceTypes.d.ts.map +1 -1
  77. package/dist/audit/orchestrator/autoFixExecutor.d.ts +20 -1
  78. package/dist/audit/orchestrator/autoFixExecutor.d.ts.map +1 -1
  79. package/dist/audit/orchestrator/autoFixExecutor.js +77 -15
  80. package/dist/audit/orchestrator/autoFixExecutor.js.map +1 -1
  81. package/dist/audit/orchestrator/dependencyMap.js +1 -1
  82. package/dist/audit/orchestrator/dependencyMap.js.map +1 -1
  83. package/dist/audit/orchestrator/designReviewPrompt.d.ts.map +1 -1
  84. package/dist/audit/orchestrator/designReviewPrompt.js +7 -0
  85. package/dist/audit/orchestrator/designReviewPrompt.js.map +1 -1
  86. package/dist/audit/orchestrator/executorRunners.d.ts.map +1 -1
  87. package/dist/audit/orchestrator/executorRunners.js +18 -4
  88. package/dist/audit/orchestrator/executorRunners.js.map +1 -1
  89. package/dist/audit/orchestrator/executors.d.ts +54 -0
  90. package/dist/audit/orchestrator/executors.d.ts.map +1 -1
  91. package/dist/audit/orchestrator/executors.js +352 -0
  92. package/dist/audit/orchestrator/executors.js.map +1 -1
  93. package/dist/audit/orchestrator/hostInputPause.d.ts +28 -13
  94. package/dist/audit/orchestrator/hostInputPause.d.ts.map +1 -1
  95. package/dist/audit/orchestrator/hostInputPause.js +17 -11
  96. package/dist/audit/orchestrator/hostInputPause.js.map +1 -1
  97. package/dist/audit/orchestrator/intentInterpreter.d.ts +15 -18
  98. package/dist/audit/orchestrator/intentInterpreter.d.ts.map +1 -1
  99. package/dist/audit/orchestrator/intentInterpreter.js +12 -26
  100. package/dist/audit/orchestrator/intentInterpreter.js.map +1 -1
  101. package/dist/audit/orchestrator/localCommands.d.ts +24 -1
  102. package/dist/audit/orchestrator/localCommands.d.ts.map +1 -1
  103. package/dist/audit/orchestrator/localCommands.js +44 -9
  104. package/dist/audit/orchestrator/localCommands.js.map +1 -1
  105. package/dist/audit/orchestrator/nextStep.d.ts +13 -0
  106. package/dist/audit/orchestrator/nextStep.d.ts.map +1 -1
  107. package/dist/audit/orchestrator/nextStep.js +13 -0
  108. package/dist/audit/orchestrator/nextStep.js.map +1 -1
  109. package/dist/audit/orchestrator/requeueCommand.d.ts +1 -1
  110. package/dist/audit/orchestrator/runtimeCommand.d.ts +32 -1
  111. package/dist/audit/orchestrator/runtimeCommand.d.ts.map +1 -1
  112. package/dist/audit/orchestrator/runtimeCommand.js +90 -3
  113. package/dist/audit/orchestrator/runtimeCommand.js.map +1 -1
  114. package/dist/audit/orchestrator/structureExecutors.js +1 -1
  115. package/dist/audit/orchestrator/structureExecutors.js.map +1 -1
  116. package/dist/audit/orchestrator/syntaxResolutionExecutor.d.ts +11 -1
  117. package/dist/audit/orchestrator/syntaxResolutionExecutor.d.ts.map +1 -1
  118. package/dist/audit/orchestrator/syntaxResolutionExecutor.js +25 -9
  119. package/dist/audit/orchestrator/syntaxResolutionExecutor.js.map +1 -1
  120. package/dist/audit/supervisor/operatorHandoff.d.ts +0 -1
  121. package/dist/audit/supervisor/operatorHandoff.d.ts.map +1 -1
  122. package/dist/audit/supervisor/operatorHandoff.js +2 -1
  123. package/dist/audit/supervisor/operatorHandoff.js.map +1 -1
  124. package/dist/audit/types.d.ts +18 -18
  125. package/dist/remediate/contractPipeline/derive.d.ts.map +1 -1
  126. package/dist/remediate/contractPipeline/derive.js +1 -0
  127. package/dist/remediate/contractPipeline/derive.js.map +1 -1
  128. package/dist/remediate/contractPipeline/semanticProjection.d.ts +5 -4
  129. package/dist/remediate/contractPipeline/semanticProjection.d.ts.map +1 -1
  130. package/dist/remediate/contractPipeline/semanticProjection.js +34 -19
  131. package/dist/remediate/contractPipeline/semanticProjection.js.map +1 -1
  132. package/dist/remediate/index.d.ts.map +1 -1
  133. package/dist/remediate/index.js +3 -2
  134. package/dist/remediate/index.js.map +1 -1
  135. package/dist/remediate/intake.js +1 -1
  136. package/dist/remediate/intake.js.map +1 -1
  137. package/dist/remediate/phases/close.d.ts +45 -2
  138. package/dist/remediate/phases/close.d.ts.map +1 -1
  139. package/dist/remediate/phases/close.js +111 -43
  140. package/dist/remediate/phases/close.js.map +1 -1
  141. package/dist/remediate/phases/closeVerifyAnalyzerLeads.js +2 -2
  142. package/dist/remediate/phases/closeVerifyAnalyzerLeads.js.map +1 -1
  143. package/dist/remediate/phases/triage.d.ts.map +1 -1
  144. package/dist/remediate/phases/triage.js +61 -19
  145. package/dist/remediate/phases/triage.js.map +1 -1
  146. package/dist/remediate/review/autonomousGate.d.ts +3 -7
  147. package/dist/remediate/review/autonomousGate.d.ts.map +1 -1
  148. package/dist/remediate/review/autonomousGate.js +10 -24
  149. package/dist/remediate/review/autonomousGate.js.map +1 -1
  150. package/dist/remediate/riskSignal.d.ts +8 -20
  151. package/dist/remediate/riskSignal.d.ts.map +1 -1
  152. package/dist/remediate/riskSignal.js +21 -76
  153. package/dist/remediate/riskSignal.js.map +1 -1
  154. package/dist/remediate/state/accessMemory.d.ts +2 -3
  155. package/dist/remediate/state/accessMemory.d.ts.map +1 -1
  156. package/dist/remediate/state/accessMemory.js +3 -6
  157. package/dist/remediate/state/accessMemory.js.map +1 -1
  158. package/dist/remediate/state/store.d.ts +6 -7
  159. package/dist/remediate/state/store.d.ts.map +1 -1
  160. package/dist/remediate/state/store.js.map +1 -1
  161. package/dist/remediate/state/types.d.ts +2 -84
  162. package/dist/remediate/state/types.d.ts.map +1 -1
  163. package/dist/remediate/state/types.js +1 -39
  164. package/dist/remediate/state/types.js.map +1 -1
  165. package/dist/remediate/steps/contractPipeline.d.ts +13 -19
  166. package/dist/remediate/steps/contractPipeline.d.ts.map +1 -1
  167. package/dist/remediate/steps/contractPipeline.js +157 -66
  168. package/dist/remediate/steps/contractPipeline.js.map +1 -1
  169. package/dist/remediate/steps/dispatch/hostHandoff.d.ts +1 -1
  170. package/dist/remediate/steps/dispatch/hostHandoff.d.ts.map +1 -1
  171. package/dist/remediate/steps/dispatch/hostHandoff.js +297 -141
  172. package/dist/remediate/steps/dispatch/hostHandoff.js.map +1 -1
  173. package/dist/remediate/steps/nextStep.d.ts +16 -7
  174. package/dist/remediate/steps/nextStep.d.ts.map +1 -1
  175. package/dist/remediate/steps/nextStep.js +207 -216
  176. package/dist/remediate/steps/nextStep.js.map +1 -1
  177. package/dist/remediate/steps/stepUtils.d.ts +10 -2
  178. package/dist/remediate/steps/stepUtils.d.ts.map +1 -1
  179. package/dist/remediate/steps/stepUtils.js +13 -3
  180. package/dist/remediate/steps/stepUtils.js.map +1 -1
  181. package/dist/remediate/steps/types.d.ts +1 -1
  182. package/dist/remediate/steps/types.d.ts.map +1 -1
  183. package/dist/remediate/steps/types.js.map +1 -1
  184. package/dist/remediate/types/options.d.ts +1 -1
  185. package/dist/remediate/validation/artifacts.d.ts.map +1 -1
  186. package/dist/remediate/validation/artifacts.js +1 -16
  187. package/dist/remediate/validation/artifacts.js.map +1 -1
  188. package/dist/remediate/validation/remediationState.d.ts +0 -1
  189. package/dist/remediate/validation/remediationState.d.ts.map +1 -1
  190. package/dist/remediate/validation/remediationState.js +0 -51
  191. package/dist/remediate/validation/remediationState.js.map +1 -1
  192. package/dist/shared/analyzerPolicy.d.ts +18 -6
  193. package/dist/shared/analyzerPolicy.d.ts.map +1 -1
  194. package/dist/shared/analyzerPolicy.js +15 -3
  195. package/dist/shared/analyzerPolicy.js.map +1 -1
  196. package/dist/shared/analyzers/acquisitionEngine.d.ts +71 -32
  197. package/dist/shared/analyzers/acquisitionEngine.d.ts.map +1 -1
  198. package/dist/shared/analyzers/acquisitionEngine.js +86 -28
  199. package/dist/shared/analyzers/acquisitionEngine.js.map +1 -1
  200. package/dist/shared/analyzers/binaryAcquisition.d.ts +8 -2
  201. package/dist/shared/analyzers/binaryAcquisition.d.ts.map +1 -1
  202. package/dist/shared/analyzers/binaryAcquisition.js +4 -4
  203. package/dist/shared/analyzers/binaryAcquisition.js.map +1 -1
  204. package/dist/shared/constitutionalDocPaths.d.ts.map +1 -1
  205. package/dist/shared/constitutionalDocPaths.js +7 -0
  206. package/dist/shared/constitutionalDocPaths.js.map +1 -1
  207. package/dist/shared/engine/obligationEngine.d.ts +44 -3
  208. package/dist/shared/engine/obligationEngine.d.ts.map +1 -1
  209. package/dist/shared/engine/obligationEngine.js +53 -7
  210. package/dist/shared/engine/obligationEngine.js.map +1 -1
  211. package/dist/shared/findings/dedupe.d.ts.map +1 -1
  212. package/dist/shared/findings/dedupe.js +8 -0
  213. package/dist/shared/findings/dedupe.js.map +1 -1
  214. package/dist/shared/friction/frictionRecord.d.ts +42 -2
  215. package/dist/shared/friction/frictionRecord.d.ts.map +1 -1
  216. package/dist/shared/friction/frictionRecord.js +111 -3
  217. package/dist/shared/friction/frictionRecord.js.map +1 -1
  218. package/dist/shared/friction/triage.d.ts +15 -0
  219. package/dist/shared/friction/triage.d.ts.map +1 -1
  220. package/dist/shared/friction/triage.js +33 -2
  221. package/dist/shared/friction/triage.js.map +1 -1
  222. package/dist/shared/index.d.ts +15 -9
  223. package/dist/shared/index.d.ts.map +1 -1
  224. package/dist/shared/index.js +15 -7
  225. package/dist/shared/index.js.map +1 -1
  226. package/dist/shared/intent/constraintClauses.d.ts +31 -0
  227. package/dist/shared/intent/constraintClauses.d.ts.map +1 -0
  228. package/dist/shared/intent/constraintClauses.js +37 -0
  229. package/dist/shared/intent/constraintClauses.js.map +1 -0
  230. package/dist/shared/io/fileLock.d.ts.map +1 -1
  231. package/dist/shared/io/fileLock.js +22 -3
  232. package/dist/shared/io/fileLock.js.map +1 -1
  233. package/dist/shared/io/frictionCapture.d.ts +73 -19
  234. package/dist/shared/io/frictionCapture.d.ts.map +1 -1
  235. package/dist/shared/io/frictionCapture.js +21 -30
  236. package/dist/shared/io/frictionCapture.js.map +1 -1
  237. package/dist/shared/io/lockedJsonStore.d.ts +24 -3
  238. package/dist/shared/io/lockedJsonStore.d.ts.map +1 -1
  239. package/dist/shared/io/lockedJsonStore.js +35 -7
  240. package/dist/shared/io/lockedJsonStore.js.map +1 -1
  241. package/dist/shared/io/stepContractWriter.d.ts +3 -3
  242. package/dist/shared/io/stepContractWriter.d.ts.map +1 -1
  243. package/dist/shared/io/stepContractWriter.js +97 -13
  244. package/dist/shared/io/stepContractWriter.js.map +1 -1
  245. package/dist/shared/submission/expectedSubmissions.d.ts +18 -0
  246. package/dist/shared/submission/expectedSubmissions.d.ts.map +1 -1
  247. package/dist/shared/submission/expectedSubmissions.js +17 -0
  248. package/dist/shared/submission/expectedSubmissions.js.map +1 -1
  249. package/dist/shared/submission/handRecovery.d.ts.map +1 -1
  250. package/dist/shared/submission/handRecovery.js +9 -11
  251. package/dist/shared/submission/handRecovery.js.map +1 -1
  252. package/dist/shared/submission/hostHandoffCore.d.ts +155 -0
  253. package/dist/shared/submission/hostHandoffCore.d.ts.map +1 -0
  254. package/dist/shared/submission/hostHandoffCore.js +210 -0
  255. package/dist/shared/submission/hostHandoffCore.js.map +1 -0
  256. package/dist/shared/submission/submissionLedger.d.ts +5 -1
  257. package/dist/shared/submission/submissionLedger.d.ts.map +1 -1
  258. package/dist/shared/submission/submissionLedger.js +33 -3
  259. package/dist/shared/submission/submissionLedger.js.map +1 -1
  260. package/dist/shared/tooling/commandShape.d.ts +29 -0
  261. package/dist/shared/tooling/commandShape.d.ts.map +1 -1
  262. package/dist/shared/tooling/commandShape.js +82 -10
  263. package/dist/shared/tooling/commandShape.js.map +1 -1
  264. package/dist/shared/tooling/exec.d.ts +32 -0
  265. package/dist/shared/tooling/exec.d.ts.map +1 -1
  266. package/dist/shared/tooling/exec.js +189 -0
  267. package/dist/shared/tooling/exec.js.map +1 -1
  268. package/docs/audit-pkg/contracts.md +2 -1
  269. package/docs/audit-pkg/operator-guide.md +12 -6
  270. package/docs/audit-pkg/product.md +22 -6
  271. package/package.json +13 -6
  272. package/schemas/audit-code-v1alpha1.schema.json +297 -0
  273. package/schemas/audit_result.schema.json +4 -0
  274. package/schemas/audit_results.schema.json +4 -0
  275. package/scripts/audit/postinstall.mjs +4 -2
  276. package/scripts/postinstall.mjs +1 -1
  277. package/scripts/remediate/postinstall.mjs +3 -1
  278. package/scripts/shared/install-host-assets.mjs +15 -8
  279. package/skills/audit-code/SKILL.md +4 -2
  280. package/skills/audit-code/audit-code.prompt.md +5 -2
  281. package/skills/audit-code/opencode-command-template.txt +1 -1
  282. package/wrapper/audit-code-wrapper-build.mjs +3 -3
  283. package/wrapper/audit-code-wrapper-install-hosts.mjs +3 -3
  284. package/wrapper/audit-code-wrapper-lib.mjs +82 -16
  285. package/wrapper/installer-verb-help.mjs +14 -4
  286. package/wrapper/remediate-code-wrapper-install-hosts.mjs +3 -3
  287. package/docs/audit-pkg/development.md +0 -113
  288. package/docs/audit-pkg/release.md +0 -140
package/README.md CHANGED
@@ -81,27 +81,47 @@ You'll confirm scope, depth, and which lenses to apply (security, correctness, r
81
81
  data_integrity, etc.), then it runs autonomously to completion and leaves
82
82
  `audit-findings.json` + `audit-report.md` in `.audit-tools/`.
83
83
 
84
- Every finding in the report is adversarially verified against current source by an
85
- independent reviewer before it's kept. The report opens with a triaged summary and
86
- drills down by severity:
84
+ Every finding is re-verified against the source on disk before the report is written. A finding a
85
+ tool-executable check disproves is excluded outright; a finding that cannot be confirmed stays in
86
+ the report, explicitly marked not-confirmed, so an unverifiable claim is surfaced rather than either
87
+ hidden or asserted. The report opens with a summary; each finding then carries its severity,
88
+ confidence, lens, and grounding:
87
89
 
88
- *(Illustrative sample — the counts and the `file:line` citation below are fabricated for the example, not a real finding.)*
90
+ <!-- BEGIN sample-reportgenerated by scripts/check-readme-sample-report.mjs from the real renderer; do not hand-edit -->
91
+
92
+ *(Illustrative excerpt — rendered by the real report renderer from a fabricated sample repo and one fixture finding; the cited src/api/auth.ts path belongs to that fabricated repo, not to this repository. A real report carries more sections between Summary and Findings.)*
89
93
 
90
94
  ```text
91
- # Audit findings — verified & pruned
92
-
93
- - Verified-real findings: 186 (of 204 extracted; 10 false, 8 uncertain)
94
- - By severity: high 7 · medium 97 · low 78 · info 4
95
- - By lens: tests 69 · maintainability 68 · correctness 24 · observability 17 · ...
96
-
97
- ## High (7)
98
- ### Citation-grounding retry leaves extracted plan completion marker
99
- - Lens: correctness · Category: incorrect-state-transition · Confidence: high
100
- - Summary: The promotion path writes the plan before running the citation-grounding
101
- backstop ... a later step treats the pipeline as complete, bypassing the retry.
102
- - Affected: src/remediate/steps/contractPipeline.ts:540-548
95
+ # Audit Report
96
+
97
+ ## Summary
98
+
99
+ - Findings: 1
100
+ - Work blocks: 1
101
+ - Severity breakdown: high: 1
102
+ - Lens breakdown: security: 1
103
+ - Grounding (S7): grounded: 1
104
+ - Fully audited files: 0
105
+ - Excluded non-auditable files: 1
106
+
107
+ ## Findings
108
+
109
+ ### SEC-1e37facc — Expired session tokens are accepted on the refresh path
110
+
111
+ refreshSession() checks the token signature but never the expiry, so an expired token mints a fresh session.
112
+
113
+ - Severity: high
114
+ - Confidence: high
115
+ - Lens: security
116
+ - Grounding: grounded
117
+ - Impact: A leaked token stays usable indefinitely.
118
+ - Likelihood: Any expired token replayed against the refresh endpoint.
119
+ - Files: src/api/auth.ts:41–58
120
+ - Evidence: 4 items (top: "The expiry field read at line 44 is never compared against the clock.") — see audit-findings.json for the full list
103
121
  ```
104
122
 
123
+ <!-- END sample-report -->
124
+
105
125
  **Remediate issues or implement changes:**
106
126
 
107
127
  ```text
@@ -212,8 +232,21 @@ npm test # build + test
212
232
  Missing `node_modules` makes `audit-tools/shared` resolve a stale `dist/`, producing
213
233
  misleading "no exported member" type errors, so install before build/check/test.
214
234
 
215
- See [`CLAUDE.md`](CLAUDE.md) for architecture and design decisions, the specs in
216
- [`spec/`](spec/), and the product/operator/contract guides in `docs/audit-pkg/`.
235
+ The published package carries the consumer-facing guides only:
236
+
237
+ - [Product overview](docs/audit-pkg/product.md)
238
+ - [Operator guide](docs/audit-pkg/operator-guide.md)
239
+ - [Contract reference](docs/audit-pkg/contracts.md)
240
+
241
+ Everything else is repository-only and therefore linked absolutely: architecture
242
+ and design decisions
243
+ ([`CLAUDE.md`](https://github.com/OhOkThisIsFine/audit-tools/blob/HEAD/CLAUDE.md)),
244
+ the normative specs
245
+ ([`spec/`](https://github.com/OhOkThisIsFine/audit-tools/tree/HEAD/spec)), the
246
+ contributor guide
247
+ ([`docs/audit-pkg/development.md`](https://github.com/OhOkThisIsFine/audit-tools/blob/HEAD/docs/audit-pkg/development.md)),
248
+ and the release runbook
249
+ ([`docs/audit-pkg/release.md`](https://github.com/OhOkThisIsFine/audit-tools/blob/HEAD/docs/audit-pkg/release.md)).
217
250
 
218
251
  ## License
219
252
 
@@ -65,7 +65,7 @@ export function mergeResults({ artifactsDir, runId }) {
65
65
  ok: false,
66
66
  fatal: {
67
67
  message:
68
- `Cannot read pending manifest ${tasksPath}: ${e.message}\n` +
68
+ `Cannot read pending manifest ${tasksPath}: ${/** @type {any} */ (e).message}\n` +
69
69
  "merge-results judges acceptance against the pending manifest (fail-closed); aborting before any write.",
70
70
  },
71
71
  passing: [],
@@ -102,7 +102,7 @@ export function mergeResults({ artifactsDir, runId }) {
102
102
  try {
103
103
  parsed = JSON.parse(readFileSync(filePath, "utf8"));
104
104
  } catch (e) {
105
- failing.push({ task_id: filename, errors: [`Invalid JSON: ${e.message}`] });
105
+ failing.push({ task_id: filename, errors: [`Invalid JSON: ${/** @type {any} */ (e).message}`] });
106
106
  continue;
107
107
  }
108
108
 
@@ -206,7 +206,7 @@ function runCli() {
206
206
  const result = mergeResults({ artifactsDir, runId });
207
207
 
208
208
  if (!result.ok) {
209
- console.error(result.fatal.message);
209
+ console.error((/** @type {any} */ (result.fatal)).message);
210
210
  process.exit(1);
211
211
  }
212
212
 
@@ -25,7 +25,7 @@ export function resolveTaskContext({ artifactsDir, runId, taskId }) {
25
25
  } catch (e) {
26
26
  return {
27
27
  task: null,
28
- warning: `[warn] Could not read pending-audit-tasks.json; line-count validation will be skipped: ${e.message}`,
28
+ warning: `[warn] Could not read pending-audit-tasks.json; line-count validation will be skipped: ${/** @type {any} */ (e).message}`,
29
29
  };
30
30
  }
31
31
  }
@@ -59,7 +59,7 @@ export function validateOneResult({ artifactsDir, runId, taskId }) {
59
59
  try {
60
60
  resultObj = JSON.parse(readFileSync(resultPath, "utf8"));
61
61
  } catch (e) {
62
- return { ok: false, fatal: { message: `Invalid JSON in ${resultPath}: ${e.message}` }, resultPath };
62
+ return { ok: false, fatal: { message: `Invalid JSON in ${resultPath}: ${/** @type {any} */ (e).message}` }, resultPath };
63
63
  }
64
64
 
65
65
  const { task, warning } = resolveTaskContext({ artifactsDir, runId, taskId });
@@ -86,7 +86,7 @@ function runCli() {
86
86
  const result = validateOneResult({ artifactsDir, runId, taskId });
87
87
 
88
88
  if (!result.ok) {
89
- console.error(result.fatal.message);
89
+ console.error((/** @type {any} */ (result.fatal)).message);
90
90
  process.exit(1);
91
91
  }
92
92
 
@@ -1 +1 @@
1
- {"version":3,"file":"charterExtractionPrompt.d.ts","sourceRoot":"","sources":["../../../src/audit/cli/charterExtractionPrompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAE/D;;;;;;;;;;;;;;;GAeG;AAEH,uEAAuE;AACvE,MAAM,MAAM,oBAAoB,GAAG,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;AAEhE;;;;GAIG;AACH,wBAAgB,gCAAgC,CAC9C,QAAQ,EAAE,OAAO,GAChB,oBAAoB,EAAE,CAExB;AA2CD;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE;IACJ,IAAI,EAAE,oBAAoB,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB,GACA,MAAM,CAsFR"}
1
+ {"version":3,"file":"charterExtractionPrompt.d.ts","sourceRoot":"","sources":["../../../src/audit/cli/charterExtractionPrompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAK/D;;;;;;;;;;;;;;;GAeG;AAEH,uEAAuE;AACvE,MAAM,MAAM,oBAAoB,GAAG,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;AAEhE;;;;GAIG;AACH,wBAAgB,gCAAgC,CAC9C,QAAQ,EAAE,OAAO,GAChB,oBAAoB,EAAE,CAExB;AA2CD;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE;IACJ,IAAI,EAAE,oBAAoB,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB,GACA,MAAM,CA6FR"}
@@ -1,3 +1,6 @@
1
+ import { CharterProvenanceSchema } from "audit-tools/shared";
2
+ /** The provenance-kind alternation, DERIVED from the schema at render time. */
3
+ const PROVENANCE_KINDS = CharterProvenanceSchema.shape.kind.options.join("|");
1
4
  /**
2
5
  * The extraction kinds a run's ceiling requests, in canonical order. The three
3
6
  * estimator channels extract at every charter-authorizing ceiling; `deepest`
@@ -123,7 +126,14 @@ export function renderCharterKindLanePrompt(bundle, opts) {
123
126
  ' "purpose": "<telos, not mechanism>",',
124
127
  ' "premise_height": 0,',
125
128
  ' "files": ["<repo-relative path>", "..."],',
126
- ' "provenance": [{ "kind": "doc|code|comment|inferred|...", "ref": "<path/id>", "quote": "<optional>" }],',
129
+ // Closed enum, exhaustive, NO trailing ellipsis DERIVED from
130
+ // CharterProvenanceSchema at render time, so a schema enum change flows into
131
+ // the prompt automatically; the behavioral pin in
132
+ // tests/shared/prompt-renders-its-contract.test.ts holds exhaustiveness and
133
+ // closedness of the RENDERED text instead of teaching a worker a smaller
134
+ // contract (an open list here coined a member and quarantined a 34-minute
135
+ // lane run).
136
+ ` "provenance": [{ "kind": "${PROVENANCE_KINDS}", "ref": "<path/id>", "quote": "<optional>" }],`,
127
137
  ' "confidence": "high|medium|low"',
128
138
  " }",
129
139
  " ]",
@@ -1 +1 @@
1
- {"version":3,"file":"charterExtractionPrompt.js","sourceRoot":"","sources":["../../../src/audit/cli/charterExtractionPrompt.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"charterExtractionPrompt.js","sourceRoot":"","sources":["../../../src/audit/cli/charterExtractionPrompt.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,27 @@
1
+ export type CleanupTargetValidation = {
2
+ ok: true;
3
+ } | {
4
+ ok: false;
5
+ reason: string;
6
+ };
7
+ /**
8
+ * Validate the cleanup TARGET itself — a purely structural check, independent
9
+ * of audit state, flags, and eligibility (CP-NODE-16). `--force` overrides the
10
+ * interactive/status confirmation inside cleanupStaleArtifactsDir; it must
11
+ * never override this: a mistyped or overly broad `--artifacts-dir` (`.`, a
12
+ * checkout root, a filesystem root) reaching a recursive rm is exactly the
13
+ * accident this verb has to make impossible.
14
+ *
15
+ * Two rules:
16
+ * 1. the path must BE an artifacts dir — `<X>/.audit-tools/audit`, never a
17
+ * filesystem root — decided from the path shape alone, so it holds even
18
+ * when the directory does not exist yet;
19
+ * 2. `--force` additionally requires the `audit_state.json` marker on disk:
20
+ * force waives the STATUS evidence, never the IDENTITY evidence. Without
21
+ * `--force` a missing marker changes nothing — the eligibility gate in
22
+ * cleanupStaleArtifactsDir already refuses to delete, so the verb's
23
+ * skipped / crashed-audit contract is untouched.
24
+ */
25
+ export declare function validateCleanupTarget(artifactsDir: string): CleanupTargetValidation;
1
26
  export declare function cmdCleanup(argv: string[]): Promise<void>;
2
27
  //# sourceMappingURL=cleanupCommand.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cleanupCommand.d.ts","sourceRoot":"","sources":["../../../src/audit/cli/cleanupCommand.ts"],"names":[],"mappings":"AAGA,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAoC9D"}
1
+ {"version":3,"file":"cleanupCommand.d.ts","sourceRoot":"","sources":["../../../src/audit/cli/cleanupCommand.ts"],"names":[],"mappings":"AAiBA,MAAM,MAAM,uBAAuB,GAC/B;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,MAAM,GACnB,uBAAuB,CAqBzB;AAsBD,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA4D9D"}
@@ -1,15 +1,90 @@
1
+ import { existsSync } from "node:fs";
2
+ import { basename, dirname, parse, resolve } from "node:path";
3
+ import { AUDIT_TOOLS_DIRNAME, auditArtifactsDir } from "audit-tools/shared";
1
4
  import { getArtifactsDir, hasFlag } from "./args.js";
2
5
  import { cleanupStaleArtifactsDir } from "./cleanup.js";
6
+ // The structural identity of an audit artifacts directory, which the `cleanup`
7
+ // verb has to PROVE a target carries before recursively deleting it
8
+ // (CP-NODE-16). Both segments come from the single-sourced layout in
9
+ // audit-tools/shared (src/shared/io/auditToolsPaths.ts): the dirname constant
10
+ // directly, the area segment derived from the helper that builds it — so a
11
+ // layout change moves this guard with it instead of silently disarming it.
12
+ const AUDIT_AREA_DIRNAME = basename(auditArtifactsDir("."));
13
+ // The supervisor state marker; audit-tools/shared exposes no constant for it yet
14
+ // (the literal is spelled at every producer/consumer site), so it is named here.
15
+ const AUDIT_STATE_FILENAME = "audit_state.json";
16
+ /**
17
+ * Validate the cleanup TARGET itself — a purely structural check, independent
18
+ * of audit state, flags, and eligibility (CP-NODE-16). `--force` overrides the
19
+ * interactive/status confirmation inside cleanupStaleArtifactsDir; it must
20
+ * never override this: a mistyped or overly broad `--artifacts-dir` (`.`, a
21
+ * checkout root, a filesystem root) reaching a recursive rm is exactly the
22
+ * accident this verb has to make impossible.
23
+ *
24
+ * Two rules:
25
+ * 1. the path must BE an artifacts dir — `<X>/.audit-tools/audit`, never a
26
+ * filesystem root — decided from the path shape alone, so it holds even
27
+ * when the directory does not exist yet;
28
+ * 2. `--force` additionally requires the `audit_state.json` marker on disk:
29
+ * force waives the STATUS evidence, never the IDENTITY evidence. Without
30
+ * `--force` a missing marker changes nothing — the eligibility gate in
31
+ * cleanupStaleArtifactsDir already refuses to delete, so the verb's
32
+ * skipped / crashed-audit contract is untouched.
33
+ */
34
+ export function validateCleanupTarget(artifactsDir) {
35
+ const resolved = resolve(artifactsDir);
36
+ if (resolved === parse(resolved).root) {
37
+ return {
38
+ ok: false,
39
+ reason: `refusing to delete ${resolved}: it is a filesystem root, not an ${AUDIT_TOOLS_DIRNAME}/${AUDIT_AREA_DIRNAME} artifacts directory`,
40
+ };
41
+ }
42
+ if (basename(resolved) !== AUDIT_AREA_DIRNAME ||
43
+ basename(dirname(resolved)) !== AUDIT_TOOLS_DIRNAME) {
44
+ return {
45
+ ok: false,
46
+ reason: `refusing to delete ${resolved}: not an ${AUDIT_TOOLS_DIRNAME}/${AUDIT_AREA_DIRNAME} artifacts directory — pass --artifacts-dir pointing at the audit artifacts dir`,
47
+ };
48
+ }
49
+ return { ok: true };
50
+ }
51
+ function emitRefusal(artifactsDir, reason, dryRun) {
52
+ console.log(JSON.stringify({
53
+ artifacts_dir: artifactsDir,
54
+ action: "refused",
55
+ reason,
56
+ dry_run: dryRun,
57
+ }, null, 2));
58
+ process.exitCode = 1;
59
+ }
3
60
  export async function cmdCleanup(argv) {
4
61
  const artifactsDir = getArtifactsDir(argv);
5
62
  const dryRun = hasFlag(argv, "--dry-run");
6
63
  const force = hasFlag(argv, "--force");
64
+ // Target validation precedes EVERY recursive-delete path (CP-NODE-16):
65
+ // --force relaxes the status confirmation only, never the structural check.
66
+ const validation = validateCleanupTarget(artifactsDir);
67
+ if (!validation.ok) {
68
+ emitRefusal(artifactsDir, validation.reason, dryRun);
69
+ return;
70
+ }
71
+ const markerPath = resolve(artifactsDir, AUDIT_STATE_FILENAME);
72
+ if (force && !existsSync(markerPath)) {
73
+ emitRefusal(artifactsDir, `--force given, but ${markerPath} does not exist — the directory carries no audit_state.json marker, so it is not provably an audit artifacts dir; refusing to delete`, dryRun);
74
+ return;
75
+ }
7
76
  const result = await cleanupStaleArtifactsDir(artifactsDir, { force, dryRun });
8
77
  if (result.action === "skipped") {
9
78
  console.log(JSON.stringify({
10
79
  artifacts_dir: artifactsDir,
11
80
  action: "skipped",
12
- reason: result.reason ?? "no audit_state.json found; artifacts may be from a crashed audit — use --force to delete anyway",
81
+ // Do NOT advise --force here. This fallback covers the
82
+ // status="unknown" branch — a directory with no audit_state.json
83
+ // marker — and that is the one case --force does NOT waive: the
84
+ // marker check above refuses a forced delete outright. Force waives
85
+ // the run's STATUS evidence, never its IDENTITY evidence.
86
+ reason: result.reason ??
87
+ "no audit_state.json found — the directory carries no audit-run marker, so it is not provably an audit artifacts dir; --force does not waive this (force waives run STATUS evidence, never IDENTITY evidence)",
13
88
  dry_run: dryRun,
14
89
  }, null, 2));
15
90
  process.exitCode = 1;
@@ -1 +1 @@
1
- {"version":3,"file":"cleanupCommand.js","sourceRoot":"","sources":["../../../src/audit/cli/cleanupCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAExD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAc;IAC7C,MAAM,YAAY,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAEvC,MAAM,MAAM,GAAG,MAAM,wBAAwB,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IAE/E,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,CAAC,GAAG,CACT,IAAI,CAAC,SAAS,CACZ;YACE,aAAa,EAAE,YAAY;YAC3B,MAAM,EAAE,SAAS;YACjB,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,iGAAiG;YAC1H,OAAO,EAAE,MAAM;SAChB,EACD,IAAI,EACJ,CAAC,CACF,CACF,CAAC;QACF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CACT,IAAI,CAAC,SAAS,CACZ;QACE,aAAa,EAAE,YAAY;QAC3B,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,OAAO,EAAE,MAAM;KAChB,EACD,IAAI,EACJ,CAAC,CACF,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"cleanupCommand.js","sourceRoot":"","sources":["../../../src/audit/cli/cleanupCommand.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"hostHandoff.d.ts","sourceRoot":"","sources":["../../../../src/audit/cli/dispatch/hostHandoff.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hostHandoff.d.ts","sourceRoot":"","sources":["../../../../src/audit/cli/dispatch/hostHandoff.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { mkdir } from "node:fs/promises";
2
- import { join, resolve } from "node:path";
3
- import { createMemoizedSourceReader, appendSubmissionEvent, SUBMISSION_LEDGER_EVENT_CONTRACT_VERSION, assertSubmissionRunId, hashContent, isFileMissingError, readJsonFile, readSubmissionDocument, repoRelativePath, resolveContainedPath, stableStringify, submissionPathFor, verifyFindingGrounding, withFileLock, writeBlockedStepContract, writeJsonFile, } from "audit-tools/shared";
2
+ import { join } from "node:path";
3
+ import { createMemoizedSourceReader, appendSubmissionEvent, SUBMISSION_LEDGER_EVENT_CONTRACT_VERSION, bindingIdentity, compareCodeUnits, contentSha256, firstDuplicateIdentity, hasExactKeys, hostHandoffResultPath, isFileMissingError, isRecord, isSha256, parseAllWorkloadItems, parseWorkloadEnvelope, promptSha256, readJsonFile, readSubmissionDocument, repoRelativePath, requireNonEmptyString, resolveContainedPath, resolveHostHandoffPaths, resultMapIdentity, siblingLockPath, sameStrings, stableStringify, verifyFindingGrounding, withFileLock, writeBlockedStepContract, writeJsonFile, } from "audit-tools/shared";
4
4
  import { findingContractPromptLines } from "../../contracts/findingContractPrompt.js";
5
5
  import { WorkerFindingSchema } from "../../contracts/workerSchemas.js";
6
6
  import { AuditResultSchema } from "../../types.js";
@@ -10,40 +10,33 @@ const RESULT_MAP_CONTRACT_VERSION = "audit-host-result-map/v1alpha1";
10
10
  const RESULT_CONTRACT_VERSION = "audit-host-result/v1alpha1";
11
11
  const TASK_BINDINGS_CONTRACT_VERSION = "audit-host-task-bindings/v1alpha1";
12
12
  const ACCEPTED_RESULTS_CONTRACT_VERSION = "audit-host-accepted-results/v1alpha1";
13
- function compareCodeUnits(left, right) {
14
- return left < right ? -1 : left > right ? 1 : 0;
15
- }
16
- function isRecord(value) {
17
- return value !== null && typeof value === "object" && !Array.isArray(value);
18
- }
19
- function hasExactKeys(value, expected) {
20
- const actual = Object.keys(value).sort(compareCodeUnits);
21
- return (actual.length === expected.length &&
22
- actual.every((key, index) => key === [...expected].sort(compareCodeUnits)[index]));
23
- }
24
- function isSha256(value) {
25
- return typeof value === "string" && /^[0-9a-f]{64}$/u.test(value);
26
- }
13
+ /**
14
+ * The audit draw's boundary paths: the SHARED resolution (run-id grammar,
15
+ * containment, `runs/<id>`), plus the four files this boundary persists beyond
16
+ * the workload — the result map, the trusted task bindings, and the
17
+ * accepted-results pair with its one serializing lock.
18
+ */
27
19
  function resolveBoundaryPaths(params) {
28
- assertSubmissionRunId(params.runId, "audit host run id");
29
- const root = resolve(params.root);
30
- const artifactsDir = resolveContainedPath(root, params.artifactsDir, "artifactsDir");
31
- const runDir = resolveContainedPath(artifactsDir, join("runs", params.runId), "audit host run directory");
20
+ const core = resolveHostHandoffPaths({
21
+ ...params,
22
+ runDirSegments: [],
23
+ runIdLabel: "audit host run id",
24
+ });
32
25
  return {
33
- root,
26
+ root: core.root,
34
27
  runId: params.runId,
35
- artifactsDir,
36
- runDir,
37
- resultDir: join(runDir, "host-results"),
38
- workloadPath: join(runDir, "host-workload.json"),
39
- resultMapPath: join(runDir, "host-result-map.json"),
40
- taskBindingsPath: join(runDir, "host-task-bindings.json"),
41
- acceptedLedgerPath: join(runDir, "host-accepted-results-ledger.json"),
42
- acceptedResultsPath: join(runDir, "host-accepted-results.json"),
28
+ artifactsDir: core.artifactsDir,
29
+ runDir: core.runDir,
30
+ resultDir: core.resultDir,
31
+ workloadPath: core.workloadPath,
32
+ resultMapPath: join(core.runDir, "host-result-map.json"),
33
+ taskBindingsPath: join(core.runDir, "host-task-bindings.json"),
34
+ acceptedLedgerPath: join(core.runDir, "host-accepted-results-ledger.json"),
35
+ acceptedResultsPath: join(core.runDir, "host-accepted-results.json"),
43
36
  // Named off the pair's own stem, so the lock is visibly the lock FOR those
44
37
  // two files rather than an independently-invented name. It is transient
45
38
  // infrastructure, not a run artifact anything cites.
46
- acceptedLockPath: `${join(runDir, "host-accepted-results")}.lock`,
39
+ acceptedLockPath: siblingLockPath(join(core.runDir, "host-accepted-results")),
47
40
  };
48
41
  }
49
42
  /**
@@ -82,18 +75,11 @@ async function writeAcceptedResults(paths, ledger) {
82
75
  }
83
76
  /**
84
77
  * The bound path for one work item's submission — the SHARED rule, not a local
85
- * copy of it. The audit and remediate handoffs both derived
86
- * `<resultDir>/<sha256(id)>.json` in their own private helpers; a divergence
87
- * between the two would have been silent on both sides.
78
+ * copy of it. This and the remediate twin were byte-equivalent private helpers;
79
+ * a divergence between them would have been silent on both sides.
88
80
  */
89
81
  function resultPathFor(paths, workItemId) {
90
- return submissionPathFor({ root: paths.root, submissionDir: paths.resultDir }, workItemId);
91
- }
92
- function requireNonEmptyString(value, label) {
93
- if (typeof value !== "string" || value.length === 0) {
94
- throw new Error(`${label} must be a non-empty string`);
95
- }
96
- return value;
82
+ return hostHandoffResultPath({ root: paths.root, artifactsDir: paths.artifactsDir, runDir: paths.runDir, resultDir: paths.resultDir, workloadPath: paths.workloadPath }, workItemId);
97
83
  }
98
84
  function normalizeTask(task, root) {
99
85
  if (!isRecord(task)) {
@@ -188,7 +174,7 @@ function buildWorkItem(paths, task) {
188
174
  token_estimate: task.token_estimate,
189
175
  },
190
176
  prompt: {
191
- sha256: hashContent(promptText),
177
+ sha256: promptSha256(promptText),
192
178
  text: promptText,
193
179
  },
194
180
  scope: {
@@ -217,7 +203,7 @@ function validateAcceptedEntry(value) {
217
203
  typeof value.result_id === "string" &&
218
204
  isSha256(value.result_sha256) &&
219
205
  isRecord(value.result) &&
220
- value.result_sha256 === hashContent(stableStringify(value.result)) &&
206
+ value.result_sha256 === contentSha256(value.result) &&
221
207
  value.result.work_item_id === value.work_item_id &&
222
208
  value.result.prompt_sha256 === value.prompt_sha256 &&
223
209
  value.result.result_id === value.result_id &&
@@ -248,19 +234,12 @@ async function loadAcceptedResults(path, runId) {
248
234
  !value.entries.every(validateAcceptedEntry)) {
249
235
  throw new Error(`Invalid accepted audit host results ledger: ${path}`);
250
236
  }
251
- const identities = new Set();
252
- for (const entry of value.entries) {
253
- const identity = `${entry.work_item_id}\u0000${entry.prompt_sha256}`;
254
- if (identities.has(identity)) {
255
- throw new Error(`Duplicate accepted audit host result binding: ${entry.work_item_id}`);
256
- }
257
- identities.add(identity);
237
+ const duplicate = firstDuplicateIdentity(value.entries, bindingIdentity);
238
+ if (duplicate !== null) {
239
+ throw new Error(`Duplicate accepted audit host result binding: ${duplicate.work_item_id}`);
258
240
  }
259
241
  return value;
260
242
  }
261
- function bindingIdentity(entry) {
262
- return `${entry.work_item_id}\u0000${entry.prompt_sha256}`;
263
- }
264
243
  export async function prepareAuditHostHandoff(params) {
265
244
  if (!Array.isArray(params.tasks)) {
266
245
  throw new Error("Audit host tasks must be an array");
@@ -356,7 +335,7 @@ function parseWorkItem(value) {
356
335
  !hasExactKeys(value.prompt, ["sha256", "text"]) ||
357
336
  !isSha256(value.prompt.sha256) ||
358
337
  typeof value.prompt.text !== "string" ||
359
- hashContent(value.prompt.text) !== value.prompt.sha256 ||
338
+ promptSha256(value.prompt.text) !== value.prompt.sha256 ||
360
339
  !isRecord(value.scope) ||
361
340
  !hasExactKeys(value.scope, ["files", "unit_ids"]) ||
362
341
  !Array.isArray(value.scope.files) ||
@@ -368,15 +347,17 @@ function parseWorkItem(value) {
368
347
  return value;
369
348
  }
370
349
  function parseWorkload(value, runId) {
371
- if (!isRecord(value) ||
372
- !hasExactKeys(value, ["contract_version", "run_id", "work_items"]) ||
373
- value.contract_version !== WORKLOAD_CONTRACT_VERSION ||
374
- value.run_id !== runId ||
375
- !Array.isArray(value.work_items)) {
350
+ // Envelope + all-items parsing is the CORE's scaffolding; the audit draw
351
+ // selects only its own contract version and item parser.
352
+ const envelope = parseWorkloadEnvelope(value, {
353
+ contractVersion: WORKLOAD_CONTRACT_VERSION,
354
+ runId,
355
+ });
356
+ if (!envelope.ok) {
376
357
  throw new Error("Invalid audit host workload");
377
358
  }
378
- const workItems = value.work_items.map(parseWorkItem);
379
- if (workItems.some((entry) => entry === null)) {
359
+ const workItems = parseAllWorkloadItems(envelope.rawItems, parseWorkItem);
360
+ if (workItems === null) {
380
361
  throw new Error("Invalid audit host work item");
381
362
  }
382
363
  return value;
@@ -457,25 +438,20 @@ function validateHandoffBinding(paths, workload, resultMap, taskBindings) {
457
438
  binding.lens !== item.lens ||
458
439
  item.scope.unit_ids.length !== 1 ||
459
440
  binding.unit_id !== item.scope.unit_ids[0] ||
460
- Object.keys(binding.file_line_counts).sort(compareCodeUnits).join("\u0000") !==
461
- [...item.scope.files].sort(compareCodeUnits).join("\u0000")) {
441
+ !sameStrings(Object.keys(binding.file_line_counts).sort(compareCodeUnits), [...item.scope.files].sort(compareCodeUnits))) {
462
442
  throw new Error(`Invalid audit host task binding: ${item.id}`);
463
443
  }
464
444
  items.set(item.id, item);
465
445
  }
466
- if (resultMap.entries.length !== items.size) {
467
- throw new Error("Audit host result map does not cover the workload exactly");
468
- }
469
- const mapped = new Set();
470
- for (const entry of resultMap.entries) {
471
- const item = items.get(entry.work_item_id);
472
- if (item === undefined ||
473
- mapped.has(entry.work_item_id) ||
474
- entry.prompt_sha256 !== item.prompt.sha256 ||
475
- entry.result_path !== item.result_path) {
476
- throw new Error(`Invalid audit host result binding: ${entry.work_item_id}`);
477
- }
478
- mapped.add(entry.work_item_id);
446
+ // The result-map identity half is the CORE's check, with its failure
447
+ // CLASSIFIED: a coverage miss says the MAP is wrong; an identity miss names
448
+ // the entry whose prompt digest or bound path broke. Both of the audit
449
+ // draw's original refusals survive — they are not collapsed into one.
450
+ const identity = resultMapIdentity([...items.values()], resultMap.entries);
451
+ if (!identity.ok) {
452
+ throw new Error(identity.reason === "coverage"
453
+ ? "Audit host result map does not cover the workload exactly"
454
+ : `Invalid audit host result binding: ${identity.workItemId ?? "unknown"}`);
479
455
  }
480
456
  return items;
481
457
  }
@@ -787,7 +763,7 @@ export async function ingestAuditHostResults(params) {
787
763
  prompt_sha256: entry.prompt_sha256,
788
764
  result_path: entry.result_path,
789
765
  result_id: result.result_id,
790
- result_sha256: hashContent(stableStringify(result)),
766
+ result_sha256: contentSha256(result),
791
767
  result,
792
768
  audit_result: converted.auditResult,
793
769
  });