@nimiplatform/nimi-coding 0.2.8 → 0.3.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 (205) hide show
  1. package/CHANGELOG.md +8 -92
  2. package/CONTRIBUTING.md +5 -34
  3. package/README.md +47 -350
  4. package/README.zh-CN.md +33 -287
  5. package/cli/commands/start.mjs +48 -688
  6. package/cli/commands/validate-spec-audit.mjs +1 -5
  7. package/cli/constants.mjs +9 -417
  8. package/cli/help.mjs +28 -145
  9. package/cli/index.mjs +5 -33
  10. package/cli/lib/blueprint-audit.mjs +5 -12
  11. package/cli/lib/bootstrap.mjs +0 -9
  12. package/cli/lib/contracts.mjs +0 -163
  13. package/cli/lib/doctor.mjs +155 -10
  14. package/cli/lib/entrypoints.mjs +63 -167
  15. package/cli/lib/internal/contracts-loaders.mjs +0 -85
  16. package/cli/lib/internal/contracts-parse.mjs +84 -520
  17. package/cli/lib/internal/governance/ai/check-agents-freshness.mjs +13 -8
  18. package/cli/lib/internal/surface-taxonomy-validators.mjs +316 -66
  19. package/cli/lib/internal/validators-shared.mjs +0 -16
  20. package/cli/lib/internal/validators-spec-helpers.mjs +7 -140
  21. package/cli/lib/internal/validators-spec.mjs +103 -342
  22. package/cli/lib/shared.mjs +1 -42
  23. package/cli/lib/validators.mjs +0 -48
  24. package/cli/seeds/seed-policy.yaml +0 -3
  25. package/config/bootstrap.yaml +4 -4
  26. package/config/spec-generation-inputs.yaml +6 -12
  27. package/contracts/domain-admission.schema.yaml +3 -3
  28. package/contracts/migration-inventory.schema.yaml +12 -75
  29. package/contracts/negative-fixtures.yaml +19 -99
  30. package/contracts/placement-contract.schema.yaml +49 -78
  31. package/contracts/projection-edge.schema.yaml +37 -121
  32. package/contracts/shared-enums.yaml +4 -8
  33. package/contracts/spec-generation-inputs.schema.yaml +15 -112
  34. package/contracts/spec-layout.schema.yaml +32 -0
  35. package/contracts/surface-taxonomy.schema.yaml +43 -94
  36. package/contracts/table-family.schema.yaml +1 -1
  37. package/contracts/tracked-output-admission.schema.yaml +13 -66
  38. package/methodology/core.yaml +33 -25
  39. package/methodology/four-closure-policy.yaml +18 -26
  40. package/methodology/role-separation-policy.yaml +21 -27
  41. package/methodology/spec-reconstruction.yaml +17 -34
  42. package/package.json +2 -4
  43. package/spec/_meta/spec-tree-model.yaml +5 -101
  44. package/spec/product-scope.yaml +25 -57
  45. package/adapters/README.md +0 -25
  46. package/adapters/claude/README.md +0 -89
  47. package/adapters/claude/profile.yaml +0 -70
  48. package/adapters/codex/README.md +0 -53
  49. package/adapters/codex/profile.yaml +0 -78
  50. package/adapters/oh-my-codex/README.md +0 -184
  51. package/adapters/oh-my-codex/profile.yaml +0 -46
  52. package/cli/commands/admit-high-risk-decision.mjs +0 -108
  53. package/cli/commands/audit-sweep.mjs +0 -364
  54. package/cli/commands/closeout.mjs +0 -186
  55. package/cli/commands/decide-high-risk-execution.mjs +0 -124
  56. package/cli/commands/handoff.mjs +0 -123
  57. package/cli/commands/ingest-high-risk-execution.mjs +0 -95
  58. package/cli/commands/review-high-risk-execution.mjs +0 -95
  59. package/cli/commands/sweep-design.mjs +0 -295
  60. package/cli/commands/sweep.mjs +0 -22
  61. package/cli/commands/topic-formatters.mjs +0 -382
  62. package/cli/commands/topic-goal.mjs +0 -33
  63. package/cli/commands/topic-options-shared.mjs +0 -27
  64. package/cli/commands/topic-options-workflow.mjs +0 -767
  65. package/cli/commands/topic-options.mjs +0 -626
  66. package/cli/commands/topic-runner.mjs +0 -169
  67. package/cli/commands/topic.mjs +0 -795
  68. package/cli/commands/validate-acceptance.mjs +0 -5
  69. package/cli/commands/validate-execution-packet.mjs +0 -5
  70. package/cli/commands/validate-orchestration-state.mjs +0 -5
  71. package/cli/commands/validate-prompt.mjs +0 -5
  72. package/cli/commands/validate-worker-output.mjs +0 -5
  73. package/cli/lib/adapter-profiles.mjs +0 -403
  74. package/cli/lib/audit-execution.mjs +0 -52
  75. package/cli/lib/audit-sweep-runtime/admissions.mjs +0 -508
  76. package/cli/lib/audit-sweep-runtime/audit-validity.mjs +0 -356
  77. package/cli/lib/audit-sweep-runtime/chunks.mjs +0 -697
  78. package/cli/lib/audit-sweep-runtime/claude-auditor.mjs +0 -658
  79. package/cli/lib/audit-sweep-runtime/closeout.mjs +0 -144
  80. package/cli/lib/audit-sweep-runtime/codex-auditor-evidence.mjs +0 -654
  81. package/cli/lib/audit-sweep-runtime/codex-auditor.mjs +0 -527
  82. package/cli/lib/audit-sweep-runtime/common.mjs +0 -341
  83. package/cli/lib/audit-sweep-runtime/coverage-quality.mjs +0 -172
  84. package/cli/lib/audit-sweep-runtime/evidence-assignment.mjs +0 -155
  85. package/cli/lib/audit-sweep-runtime/format.mjs +0 -57
  86. package/cli/lib/audit-sweep-runtime/ingest.mjs +0 -486
  87. package/cli/lib/audit-sweep-runtime/inventory-spec-chunks.mjs +0 -425
  88. package/cli/lib/audit-sweep-runtime/inventory.mjs +0 -798
  89. package/cli/lib/audit-sweep-runtime/ledger.mjs +0 -315
  90. package/cli/lib/audit-sweep-runtime/p0p1-profile.mjs +0 -101
  91. package/cli/lib/audit-sweep-runtime/remediation.mjs +0 -349
  92. package/cli/lib/audit-sweep-runtime/rerun.mjs +0 -129
  93. package/cli/lib/audit-sweep-runtime/risk-budget.mjs +0 -300
  94. package/cli/lib/audit-sweep-runtime/status.mjs +0 -62
  95. package/cli/lib/audit-sweep-runtime/validators-ledger.mjs +0 -215
  96. package/cli/lib/audit-sweep-runtime/validators.mjs +0 -797
  97. package/cli/lib/audit-sweep.mjs +0 -19
  98. package/cli/lib/authority-convergence.mjs +0 -720
  99. package/cli/lib/closeout.mjs +0 -732
  100. package/cli/lib/codex-sdk-runner.mjs +0 -76
  101. package/cli/lib/external-execution.mjs +0 -101
  102. package/cli/lib/handoff.mjs +0 -812
  103. package/cli/lib/high-risk-admission.mjs +0 -512
  104. package/cli/lib/high-risk-decision.mjs +0 -353
  105. package/cli/lib/high-risk-ingest.mjs +0 -321
  106. package/cli/lib/high-risk-review.mjs +0 -267
  107. package/cli/lib/internal/contracts-parse-high-risk.mjs +0 -131
  108. package/cli/lib/internal/contracts-validators.mjs +0 -399
  109. package/cli/lib/internal/doctor-bootstrap-surface.mjs +0 -406
  110. package/cli/lib/internal/doctor-delegated-surface.mjs +0 -256
  111. package/cli/lib/internal/doctor-finalize.mjs +0 -383
  112. package/cli/lib/internal/doctor-format.mjs +0 -286
  113. package/cli/lib/internal/doctor-inspectors.mjs +0 -327
  114. package/cli/lib/internal/doctor-state.mjs +0 -205
  115. package/cli/lib/internal/validators-artifacts.mjs +0 -515
  116. package/cli/lib/sweep-design-runtime/common.mjs +0 -246
  117. package/cli/lib/sweep-design-runtime/engine.mjs +0 -733
  118. package/cli/lib/sweep-design-runtime/fix-topic.mjs +0 -414
  119. package/cli/lib/sweep-design-runtime/lifecycle.mjs +0 -54
  120. package/cli/lib/sweep-design-runtime/results.mjs +0 -324
  121. package/cli/lib/sweep-design.mjs +0 -8
  122. package/cli/lib/topic-artifacts.mjs +0 -186
  123. package/cli/lib/topic-authority-coverage.mjs +0 -73
  124. package/cli/lib/topic-closeout.mjs +0 -560
  125. package/cli/lib/topic-common.mjs +0 -404
  126. package/cli/lib/topic-decisions.mjs +0 -332
  127. package/cli/lib/topic-draft-packets.mjs +0 -167
  128. package/cli/lib/topic-execution.mjs +0 -533
  129. package/cli/lib/topic-goal.mjs +0 -440
  130. package/cli/lib/topic-ledger.mjs +0 -281
  131. package/cli/lib/topic-lifecycle-artifacts.mjs +0 -173
  132. package/cli/lib/topic-root-validation.mjs +0 -288
  133. package/cli/lib/topic-runner-commands.mjs +0 -174
  134. package/cli/lib/topic-runner-deferral.mjs +0 -532
  135. package/cli/lib/topic-runner-stale-gates.mjs +0 -114
  136. package/cli/lib/topic-runner-validation.mjs +0 -138
  137. package/cli/lib/topic-runner.mjs +0 -727
  138. package/cli/lib/topic-scaffold.mjs +0 -252
  139. package/cli/lib/topic-waves.mjs +0 -403
  140. package/cli/lib/topic.mjs +0 -81
  141. package/config/audit-execution-artifacts.yaml +0 -20
  142. package/config/external-execution-artifacts.yaml +0 -16
  143. package/config/host-adapter.yaml +0 -30
  144. package/config/host-profile.yaml +0 -29
  145. package/config/installer-evidence.yaml +0 -31
  146. package/config/skill-installer.yaml +0 -23
  147. package/config/skill-manifest.yaml +0 -48
  148. package/config/skills.yaml +0 -30
  149. package/contracts/acceptance.schema.yaml +0 -16
  150. package/contracts/admission-checklist.schema.yaml +0 -15
  151. package/contracts/audit-chunk.schema.yaml +0 -123
  152. package/contracts/audit-closeout.schema.yaml +0 -51
  153. package/contracts/audit-finding.schema.yaml +0 -61
  154. package/contracts/audit-ledger.schema.yaml +0 -138
  155. package/contracts/audit-plan.schema.yaml +0 -138
  156. package/contracts/audit-remediation-map.schema.yaml +0 -52
  157. package/contracts/audit-rerun.schema.yaml +0 -31
  158. package/contracts/audit-sweep-result.yaml +0 -53
  159. package/contracts/authority-convergence-audit.schema.yaml +0 -19
  160. package/contracts/closeout.schema.yaml +0 -25
  161. package/contracts/decision-review.schema.yaml +0 -16
  162. package/contracts/doc-spec-audit-result.yaml +0 -19
  163. package/contracts/execution-packet.schema.yaml +0 -49
  164. package/contracts/external-host-compatibility.yaml +0 -22
  165. package/contracts/forbidden-shortcuts.catalog.yaml +0 -23
  166. package/contracts/high-risk-admission.schema.yaml +0 -23
  167. package/contracts/high-risk-execution-result.yaml +0 -20
  168. package/contracts/orchestration-state.schema.yaml +0 -41
  169. package/contracts/overflow-continuation.schema.yaml +0 -12
  170. package/contracts/packet.schema.yaml +0 -30
  171. package/contracts/pending-note.schema.yaml +0 -17
  172. package/contracts/prompt.schema.yaml +0 -12
  173. package/contracts/remediation.schema.yaml +0 -16
  174. package/contracts/result.schema.yaml +0 -24
  175. package/contracts/spec-reconstruction-result.yaml +0 -41
  176. package/contracts/sweep-design-result.yaml +0 -349
  177. package/contracts/topic-goal.schema.yaml +0 -87
  178. package/contracts/topic-run-ledger.schema.yaml +0 -72
  179. package/contracts/topic-step-decision.schema.yaml +0 -45
  180. package/contracts/topic.schema.yaml +0 -65
  181. package/contracts/true-close.schema.yaml +0 -15
  182. package/contracts/wave.schema.yaml +0 -29
  183. package/contracts/worker-output.schema.yaml +0 -15
  184. package/contracts/workflow-consumer.schema.yaml +0 -110
  185. package/methodology/audit-sweep-p0p1-recall.yaml +0 -45
  186. package/methodology/authority-convergence-policy.yaml +0 -42
  187. package/methodology/overflow-continuation-policy.yaml +0 -14
  188. package/methodology/skill-exchange-projection.yaml +0 -114
  189. package/methodology/skill-handoff.yaml +0 -34
  190. package/methodology/skill-installer-result.yaml +0 -27
  191. package/methodology/skill-installer-summary-projection.yaml +0 -181
  192. package/methodology/skill-runtime.yaml +0 -23
  193. package/methodology/spec-target-truth-profile.yaml +0 -46
  194. package/methodology/topic-lifecycle-report.yaml +0 -144
  195. package/methodology/topic-lifecycle.yaml +0 -37
  196. package/methodology/topic-naming-ontology.yaml +0 -21
  197. package/methodology/topic-ontology.yaml +0 -38
  198. package/methodology/topic-validation-policy.yaml +0 -9
  199. package/methodology/wave-dag-policy.yaml +0 -14
  200. package/spec/_meta/command-gating-matrix.yaml +0 -143
  201. package/spec/_meta/generate-drift-migration-checklist.yaml +0 -137
  202. package/spec/_meta/governance-routing-cutover-checklist.yaml +0 -35
  203. package/spec/_meta/phase2-impacted-surface-matrix.yaml +0 -44
  204. package/spec/_meta/spec-authority-cutover-readiness.yaml +0 -102
  205. package/spec/bootstrap-state.yaml +0 -99
@@ -1,733 +0,0 @@
1
- import {
2
- assertDesignArtifact,
3
- AUDITOR_FAMILIES,
4
- AUDITOR_MODES,
5
- AUDITOR_RESULT_ORIGINS,
6
- deriveRunId,
7
- designRef,
8
- FINAL_OUTCOME_STATES,
9
- findingAuthorityRef,
10
- findingCodeRefs,
11
- inputError,
12
- loadAuditFindings,
13
- loadYamlRef,
14
- LLM_AUDITOR_RESULT_ORIGINS,
15
- normalizeFindingForDesign,
16
- nowIso,
17
- PRIOR_DESIGN_STATE_MARKERS,
18
- requireRunId,
19
- REVISION_TYPES,
20
- safeDesignId,
21
- sha256Object,
22
- TRANSIENT_STATES,
23
- writeYamlRef,
24
- } from "./common.mjs";
25
- import { sweepDesignWaveAuthorityRefs } from "../topic-authority-coverage.mjs";
26
-
27
- const ZERO_HASH = "0".repeat(64);
28
-
29
- function inventoryRef(runId) {
30
- return designRef(runId, "inventory.yaml");
31
- }
32
-
33
- export function packetRef(runId, packetId) {
34
- return designRef(runId, "design-auditor-packets", `${packetId}.yaml`);
35
- }
36
-
37
- export function resultRef(runId, resultId) {
38
- return designRef(runId, "design-auditor-results", `${resultId}.yaml`);
39
- }
40
-
41
- function auditorPromptRef(runId, packetId) {
42
- return designRef(runId, "auditor-prompts", `${packetId}.yaml`);
43
- }
44
-
45
- function batchManifestRef(runId, manifestId) {
46
- return designRef(runId, "batch-manifests", `${manifestId}.yaml`);
47
- }
48
-
49
- export function ledgerRef(runId) {
50
- return designRef(runId, "revision-ledger.yaml");
51
- }
52
-
53
- export function finalStateReportRef(runId) {
54
- return designRef(runId, "final-state-report.yaml");
55
- }
56
-
57
- export function wavePlanRef(runId) {
58
- return designRef(runId, "wave-plan.yaml");
59
- }
60
-
61
- export function decisionQueueRef(runId) {
62
- return designRef(runId, "decision-queue.yaml");
63
- }
64
-
65
- export async function loadInventory(projectRoot, runId) {
66
- return assertDesignArtifact(projectRoot, inventoryRef(runId), "sweep-design-inventory", "inventory");
67
- }
68
-
69
- function splitList(value) {
70
- return String(value ?? "")
71
- .split(",")
72
- .map((item) => item.trim())
73
- .filter(Boolean);
74
- }
75
-
76
- function normalizeIdList(value) {
77
- return [...new Set(splitList(value))].sort();
78
- }
79
-
80
- function parsePositiveInteger(value, label) {
81
- const parsed = Number.parseInt(String(value ?? ""), 10);
82
- if (!Number.isSafeInteger(parsed) || parsed <= 0) {
83
- return { ok: false, error: `nimicoding sweep design refused: ${label} must be a positive integer.\n` };
84
- }
85
- return { ok: true, value: parsed };
86
- }
87
-
88
- function chunkArray(values, size) {
89
- const chunks = [];
90
- for (let index = 0; index < values.length; index += size) {
91
- chunks.push(values.slice(index, index + size));
92
- }
93
- return chunks;
94
- }
95
-
96
- function requireArray(value, label, errors) {
97
- if (!Array.isArray(value)) {
98
- errors.push(`${label} must be an array`);
99
- return [];
100
- }
101
- return value;
102
- }
103
-
104
- export function requireNonEmptyArray(value, label, errors) {
105
- const array = requireArray(value, label, errors);
106
- if (array.length === 0) errors.push(`${label} must not be empty`);
107
- return array;
108
- }
109
-
110
- function requireString(value, label, errors) {
111
- if (typeof value !== "string" || value.length === 0) {
112
- errors.push(`${label} must be a non-empty string`);
113
- return "";
114
- }
115
- return value;
116
- }
117
-
118
- function validateRequiredFields(value, fields, label, errors) {
119
- for (const field of fields) {
120
- if (value[field] === undefined || value[field] === null) {
121
- errors.push(`${label}.${field} is required`);
122
- }
123
- }
124
- }
125
-
126
- function findInventoryFindings(inventory, findingIds) {
127
- const byId = new Map(inventory.findings.map((finding) => [finding.finding_id, finding]));
128
- return findingIds.map((findingId) => byId.get(findingId)).filter(Boolean);
129
- }
130
-
131
- function relatedFindingCandidates(inventory, selectedIds) {
132
- const selected = findInventoryFindings(inventory, selectedIds);
133
- const selectedOwners = new Set(selected.map((finding) => finding.owner_domain).filter(Boolean));
134
- const selectedCategories = new Set(selected.map((finding) => finding.category).filter(Boolean));
135
- return inventory.findings
136
- .filter((finding) => !selectedIds.includes(finding.finding_id))
137
- .filter((finding) => selectedOwners.has(finding.owner_domain) || selectedCategories.has(finding.category))
138
- .map((finding) => finding.source_finding_ref)
139
- .slice(0, 12);
140
- }
141
-
142
- function initialLedger(runId, timestamp) {
143
- const ledger = {
144
- version: 1,
145
- kind: "sweep-design-revision-ledger",
146
- run_id: runId,
147
- ledger_id: `${runId}-revision-ledger`,
148
- append_only: true,
149
- entries: [],
150
- previous_ledger_snapshot_hash: null,
151
- entries_root_hash: ZERO_HASH,
152
- ledger_snapshot_hash: null,
153
- created_at: timestamp,
154
- updated_at: timestamp,
155
- };
156
- ledger.ledger_snapshot_hash = computeLedgerSnapshotHash(ledger);
157
- return ledger;
158
- }
159
-
160
- function entryHashPayload(entry) {
161
- const clone = { ...entry };
162
- delete clone.entry_hash;
163
- return clone;
164
- }
165
-
166
- function computeEntryHash(entry) {
167
- return sha256Object(entryHashPayload(entry));
168
- }
169
-
170
- function computeEntriesRootHash(entries) {
171
- return sha256Object(entries.map((entry) => entry.entry_hash));
172
- }
173
-
174
- function computeLedgerSnapshotHash(ledger) {
175
- return sha256Object({
176
- run_id: ledger.run_id,
177
- ledger_id: ledger.ledger_id,
178
- append_only: ledger.append_only,
179
- entries_root_hash: ledger.entries_root_hash,
180
- entry_count: ledger.entries.length,
181
- previous_ledger_snapshot_hash: ledger.previous_ledger_snapshot_hash ?? null,
182
- });
183
- }
184
-
185
- export function validateLedger(ledger) {
186
- const errors = [];
187
- if (!ledger || ledger.kind !== "sweep-design-revision-ledger") {
188
- return ["revision ledger is missing or malformed"];
189
- }
190
- if (ledger.append_only !== true) errors.push("revision ledger append_only must be true");
191
- if (!Array.isArray(ledger.entries)) errors.push("revision ledger entries must be an array");
192
- const entries = Array.isArray(ledger.entries) ? ledger.entries : [];
193
- let previous = ZERO_HASH;
194
- entries.forEach((entry, index) => {
195
- if (entry.entry_index !== index + 1) errors.push(`revision entry ${index + 1} has non-monotonic entry_index`);
196
- if (entry.previous_entry_hash !== previous) errors.push(`revision entry ${entry.revision_entry_id ?? index + 1} has invalid previous_entry_hash`);
197
- const actual = computeEntryHash(entry);
198
- if (entry.entry_hash !== actual) errors.push(`revision entry ${entry.revision_entry_id ?? index + 1} has invalid entry_hash`);
199
- previous = entry.entry_hash;
200
- });
201
- if (entries.length > 0 && ledger.entries_root_hash !== computeEntriesRootHash(entries)) {
202
- errors.push("revision ledger entries_root_hash is invalid");
203
- }
204
- if (entries.length === 0 && ledger.entries_root_hash !== ZERO_HASH) {
205
- errors.push("empty revision ledger entries_root_hash must be zero hash");
206
- }
207
- if (ledger.ledger_snapshot_hash !== computeLedgerSnapshotHash(ledger)) {
208
- errors.push("revision ledger ledger_snapshot_hash is invalid");
209
- }
210
- return errors;
211
- }
212
-
213
- export async function loadOrCreateLedger(projectRoot, runId, timestamp) {
214
- const existing = await loadYamlRef(projectRoot, ledgerRef(runId));
215
- if (!existing) {
216
- const ledger = initialLedger(runId, timestamp);
217
- const ref = await writeYamlRef(projectRoot, ledgerRef(runId), ledger);
218
- return { ok: true, ref, value: ledger };
219
- }
220
- const errors = validateLedger(existing);
221
- if (errors.length > 0) {
222
- return inputError(`nimicoding sweep design refused: ${errors.join("; ")}.\n`);
223
- }
224
- return { ok: true, ref: ledgerRef(runId), value: existing };
225
- }
226
-
227
- export function normalizeRevisionEntry(entry, context) {
228
- const nextIndex = context.ledger.entries.length + context.normalized.length + 1;
229
- const previousHash = context.normalized.length > 0
230
- ? context.normalized[context.normalized.length - 1].entry_hash
231
- : context.ledger.entries.at(-1)?.entry_hash ?? ZERO_HASH;
232
- const revisionType = requireString(entry.revision_type, "revision_entries[].revision_type", context.errors);
233
- if (revisionType && !REVISION_TYPES.has(revisionType)) {
234
- context.errors.push(`unsupported revision_type ${revisionType}`);
235
- }
236
- const replacementArtifactRefs = Array.isArray(entry.replacement_artifact_refs) ? entry.replacement_artifact_refs : [];
237
- if (!replacementArtifactRefs.includes(context.resultArtifactRef)) {
238
- replacementArtifactRefs.push(context.resultArtifactRef);
239
- }
240
- const normalized = {
241
- version: 1,
242
- kind: "sweep-design-revision-entry",
243
- revision_entry_id: entry.revision_entry_id ?? `${context.resultId}-revision-${String(nextIndex).padStart(4, "0")}`,
244
- entry_index: nextIndex,
245
- revision_type: revisionType,
246
- created_at: entry.created_at ?? context.timestamp,
247
- previous_entry_hash: previousHash,
248
- previous_artifact_refs: Array.isArray(entry.previous_artifact_refs) ? entry.previous_artifact_refs : [],
249
- replacement_artifact_refs: replacementArtifactRefs,
250
- affected_finding_ids: Array.isArray(entry.affected_finding_ids) ? entry.affected_finding_ids : [],
251
- affected_cluster_ids: Array.isArray(entry.affected_cluster_ids) ? entry.affected_cluster_ids : [],
252
- affected_wave_ids: Array.isArray(entry.affected_wave_ids) ? entry.affected_wave_ids : [],
253
- reason_code: requireString(entry.reason_code, "revision_entries[].reason_code", context.errors),
254
- evidence_refs: Array.isArray(entry.evidence_refs) ? entry.evidence_refs : [],
255
- auditor_provenance: entry.auditor_provenance ?? context.auditorProvenance,
256
- human_gate_status: entry.human_gate_status ?? "not_required",
257
- projection_refs_changed: Array.isArray(entry.projection_refs_changed) ? entry.projection_refs_changed : [],
258
- };
259
- normalized.entry_hash = computeEntryHash(normalized);
260
- return normalized;
261
- }
262
-
263
- export function updateLedgerHashes(ledger, previousSnapshotHash, timestamp) {
264
- ledger.previous_ledger_snapshot_hash = previousSnapshotHash ?? ledger.previous_ledger_snapshot_hash ?? null;
265
- ledger.entries_root_hash = ledger.entries.length > 0 ? computeEntriesRootHash(ledger.entries) : ZERO_HASH;
266
- ledger.updated_at = timestamp;
267
- ledger.ledger_snapshot_hash = computeLedgerSnapshotHash(ledger);
268
- return ledger;
269
- }
270
-
271
- export function finalOutcomeState(outcome) {
272
- return outcome.final_outcome ?? outcome.state ?? outcome.outcome ?? null;
273
- }
274
-
275
- export function validateOutcome(outcome, context) {
276
- const errors = context.errors;
277
- const state = finalOutcomeState(outcome);
278
- requireString(outcome.finding_id, "finding_outcomes[].finding_id", errors);
279
- if (!FINAL_OUTCOME_STATES.has(state)) {
280
- errors.push(`finding_outcomes[] has unsupported final outcome ${state}`);
281
- return;
282
- }
283
- for (const field of [
284
- "design_auditor_packet_ref",
285
- "design_auditor_result_ref",
286
- "revision_ledger_entry_refs",
287
- "related_finding_ids_considered",
288
- "code_refs_considered",
289
- "authority_refs_considered",
290
- ]) {
291
- if (outcome[field] === undefined || outcome[field] === null) errors.push(`finding_outcomes[].${field} is required for ${state}`);
292
- }
293
- requireNonEmptyArray(outcome.revision_ledger_entry_refs, "finding_outcomes[].revision_ledger_entry_refs", errors);
294
- requireArray(outcome.related_finding_ids_considered, "finding_outcomes[].related_finding_ids_considered", errors);
295
- requireArray(outcome.code_refs_considered, "finding_outcomes[].code_refs_considered", errors);
296
- requireArray(outcome.authority_refs_considered, "finding_outcomes[].authority_refs_considered", errors);
297
- if (state === "duplicate" && !outcome.canonical_finding_or_cluster_ref) errors.push("duplicate outcome requires canonical_finding_or_cluster_ref");
298
- if (state === "superseded" && !outcome.superseding_finding_or_cluster_ref) errors.push("superseded outcome requires superseding_finding_or_cluster_ref");
299
- if (state === "false_positive" && !outcome.human_gate_ref) errors.push("false_positive outcome requires human_gate_ref");
300
- if (state === "ready_for_implementation_wave") {
301
- for (const field of ["wave_id_ref", "preflight_ref", "validation_command_refs", "closeout_criteria_ref"]) {
302
- if (outcome[field] === undefined || outcome[field] === null) errors.push(`ready_for_implementation_wave outcome requires ${field}`);
303
- }
304
- requireNonEmptyArray(outcome.validation_command_refs, "ready_for_implementation_wave.validation_command_refs", errors);
305
- }
306
- if (state === "needs_user_decision") {
307
- for (const field of ["decision_queue_item_ref", "decision_packet_ref", "recommended_decision", "queue_status", "blocked_downstream_wave_refs"]) {
308
- if (outcome[field] === undefined || outcome[field] === null) errors.push(`needs_user_decision outcome requires ${field}`);
309
- }
310
- requireNonEmptyArray(outcome.blocked_downstream_wave_refs, "needs_user_decision.blocked_downstream_wave_refs", errors);
311
- if (["accepted", "closed"].includes(outcome.queue_status) && !outcome.human_gate_decision_ref) {
312
- errors.push("accepted or closed needs_user_decision requires human_gate_decision_ref");
313
- }
314
- }
315
- if (state === "needs_more_audit" && !outcome.extra_audit_request_ref) errors.push("needs_more_audit outcome requires extra_audit_request_ref");
316
- if (state === "needs_authority_alignment" && !outcome.authority_convergence_ref) errors.push("needs_authority_alignment outcome requires authority_convergence_ref");
317
- if (state === "blocked") requireNonEmptyArray(outcome.blocking_cause_refs, "blocked.blocking_cause_refs", errors);
318
- }
319
-
320
- export function validateAuditorResult(result) {
321
- const errors = [];
322
- if (!result || result.kind !== "sweep-design-design-auditor-result") {
323
- errors.push("result kind must be sweep-design-design-auditor-result");
324
- return errors;
325
- }
326
- validateRequiredFields(result, [
327
- "run_id",
328
- "packet_id",
329
- "result_id",
330
- "auditor",
331
- "auditor_family",
332
- "auditor_mode",
333
- "auditor_result_origin",
334
- "methodology_ref",
335
- "packet_ref",
336
- "session_ref",
337
- "transcript_ref",
338
- "result_schema_version",
339
- "provenance",
340
- "evidence_read",
341
- "finding_outcomes",
342
- "cluster_changes",
343
- "wave_changes",
344
- "revision_entries",
345
- "human_decision_requests",
346
- "extra_audit_requests",
347
- "validation_recommendations",
348
- "closeout_recommendations",
349
- "rejection_status",
350
- ], "result", errors);
351
- if (!AUDITOR_FAMILIES.has(result.auditor_family)) errors.push(`unsupported auditor_family ${result.auditor_family}`);
352
- if (!AUDITOR_MODES.has(result.auditor_mode)) errors.push(`unsupported auditor_mode ${result.auditor_mode}`);
353
- if (!AUDITOR_RESULT_ORIGINS.has(result.auditor_result_origin)) errors.push(`unsupported auditor_result_origin ${result.auditor_result_origin}`);
354
- if (LLM_AUDITOR_RESULT_ORIGINS.has(result.auditor_result_origin)) {
355
- for (const field of ["llm_session_ref", "llm_transcript_ref", "llm_prompt_ref"]) {
356
- requireString(result[field], `result.${field}`, errors);
357
- }
358
- }
359
- for (const field of [
360
- "evidence_read",
361
- "finding_outcomes",
362
- "cluster_changes",
363
- "wave_changes",
364
- "revision_entries",
365
- "human_decision_requests",
366
- "extra_audit_requests",
367
- "validation_recommendations",
368
- "closeout_recommendations",
369
- ]) {
370
- requireArray(result[field], `result.${field}`, errors);
371
- }
372
- return errors;
373
- }
374
-
375
- export function isLlmAuditorResult(result) {
376
- return LLM_AUDITOR_RESULT_ORIGINS.has(result?.auditor_result_origin);
377
- }
378
-
379
- export function isSyntheticAuditorResult(result) {
380
- return result?.auditor_result_origin === "synthetic_trial";
381
- }
382
-
383
- export function validatePacket(packet) {
384
- const errors = [];
385
- validateRequiredFields(packet, [
386
- "run_id",
387
- "packet_id",
388
- "source_audit_sweep_id",
389
- "included_finding_ids",
390
- "source_finding_refs",
391
- "related_finding_refs",
392
- "related_code_refs",
393
- "authority_refs",
394
- "prior_design_state_refs",
395
- "prior_design_state_marker",
396
- "revision_ledger_refs",
397
- "current_cluster_refs",
398
- "current_wave_refs",
399
- "explicit_questions",
400
- "expected_result_shape_ref",
401
- "evidence_gap_policy",
402
- "stop_conditions",
403
- ], "packet", errors);
404
- requireNonEmptyArray(packet.included_finding_ids, "packet.included_finding_ids", errors);
405
- requireNonEmptyArray(packet.source_finding_refs, "packet.source_finding_refs", errors);
406
- if (!packet.authority_only_packet) requireNonEmptyArray(packet.related_code_refs, "packet.related_code_refs", errors);
407
- requireArray(packet.authority_refs, "packet.authority_refs", errors);
408
- requireArray(packet.related_finding_refs, "packet.related_finding_refs", errors);
409
- if (!PRIOR_DESIGN_STATE_MARKERS.has(packet.prior_design_state_marker)) {
410
- errors.push(`unsupported prior_design_state_marker ${packet.prior_design_state_marker}`);
411
- }
412
- if (packet.prior_design_state_marker !== "empty" && (!Array.isArray(packet.prior_design_state_refs) || packet.prior_design_state_refs.length === 0)) {
413
- errors.push("non-empty prior_design_state_marker requires prior_design_state_refs");
414
- }
415
- if (packet.prior_design_state_marker === "empty" && Array.isArray(packet.prior_design_state_refs) && packet.prior_design_state_refs.length > 0) {
416
- errors.push("prior_design_state_marker empty requires no prior_design_state_refs");
417
- }
418
- if (Array.isArray(packet.evidence_gaps) && packet.evidence_gaps.length > 0 && !packet.evidence_gap_result) {
419
- errors.push("material evidence gaps require evidence_gap_result");
420
- }
421
- return errors;
422
- }
423
-
424
- async function ensureRefAbsent(projectRoot, ref, label) {
425
- const existing = await loadYamlRef(projectRoot, ref);
426
- if (existing) {
427
- return inputError(`nimicoding sweep design refused: ${label} already exists at ${ref}.\n`);
428
- }
429
- return { ok: true };
430
- }
431
-
432
- function buildPacketValue(inventory, ledger, runId, packetId, includedFindingIds, options, timestamp) {
433
- const selected = findInventoryFindings(inventory, includedFindingIds);
434
- if (selected.length !== includedFindingIds.length) {
435
- const found = new Set(selected.map((finding) => finding.finding_id));
436
- const missing = includedFindingIds.filter((findingId) => !found.has(findingId));
437
- return { ok: false, error: `nimicoding sweep design refused: finding not found: ${missing.join(", ")}.\n` };
438
- }
439
- const relatedCodeRefs = [...new Set(selected.flatMap((finding) => findingCodeRefs({
440
- ...finding,
441
- implementation_refs: finding.evidence_refs,
442
- })))].sort();
443
- const authorityRefs = [...new Set(selected.map((finding) => finding.authority_ref).filter(Boolean))].sort();
444
- const priorDesignStateRefs = splitList(options.priorDesignStateRefs);
445
- const priorDesignStateMarker = options.priorDesignStateMarker ?? (priorDesignStateRefs.length > 0 ? "present" : "empty");
446
- const evidenceGaps = [];
447
- if (!options.authorityOnly && relatedCodeRefs.length === 0) evidenceGaps.push("related_code_refs_missing");
448
- const packet = {
449
- version: 2,
450
- kind: "sweep-design-design-auditor-packet",
451
- run_id: runId,
452
- packet_id: packetId,
453
- source_audit_sweep_id: inventory.source_audit_sweep_id,
454
- included_finding_ids: includedFindingIds,
455
- source_finding_refs: selected.map((finding) => finding.source_finding_ref),
456
- related_finding_refs: relatedFindingCandidates(inventory, includedFindingIds),
457
- related_code_refs: relatedCodeRefs,
458
- authority_refs: authorityRefs,
459
- authority_only_packet: Boolean(options.authorityOnly),
460
- prior_design_state_refs: priorDesignStateRefs,
461
- prior_design_state_marker: priorDesignStateMarker,
462
- revision_ledger_refs: [ledger.ref],
463
- current_cluster_refs: splitList(options.currentClusterRefs),
464
- current_wave_refs: splitList(options.currentWaveRefs),
465
- explicit_questions: splitList(options.explicitQuestions || options.explicitQuestion),
466
- expected_result_shape_ref: ".nimi/contracts/sweep-design-result.yaml#artifact_kinds.design_auditor_result",
467
- evidence_gap_policy: "missing_material_input_requires_explicit_gap_result_or_refusal",
468
- evidence_gaps: evidenceGaps,
469
- evidence_gap_result: evidenceGaps.length > 0 ? "blocked_until_material_input_supplied" : null,
470
- stop_conditions: [
471
- "product_fork",
472
- "authority_fork",
473
- "semantic_fork",
474
- "missing_evidence",
475
- "extra_audit_required",
476
- "authority_alignment_required",
477
- "human_decision_required",
478
- ],
479
- created_at: timestamp,
480
- };
481
- const errors = validatePacket(packet);
482
- if (errors.length > 0) return { ok: false, error: `nimicoding sweep design refused: ${errors.join("; ")}.\n` };
483
- return { ok: true, packet, selected };
484
- }
485
-
486
- function buildAuditorPromptValue(runId, packetId, packetRefValue, packet, timestamp) {
487
- return {
488
- version: 2,
489
- kind: "sweep-design-auditor-prompt",
490
- run_id: runId,
491
- packet_id: packetId,
492
- packet_ref: packetRefValue,
493
- expected_result_shape_ref: ".nimi/contracts/sweep-design-result.yaml#artifact_kinds.design_auditor_result",
494
- required_result_origin: "external_llm_session",
495
- synthetic_result_policy: "synthetic_trial_results_are_load_tests_only_and_do_not_satisfy_true_llm_closeout",
496
- required_llm_provenance_fields: [
497
- "auditor_result_origin",
498
- "llm_session_ref",
499
- "llm_transcript_ref",
500
- "llm_prompt_ref",
501
- ],
502
- task: [
503
- "Read every included source finding, related code ref, authority ref, related finding candidate, prior design state ref, current cluster ref, and current wave ref in the packet.",
504
- "Return a sweep-design-design-auditor-result with final outcomes for every included finding.",
505
- "Queue product, semantic, or authority forks instead of accepting them.",
506
- "Use needs_authority_alignment when implementation cannot safely proceed until authority ownership is aligned.",
507
- "Emit implementation-ready waves only when scope, authority owner, validation commands, negative checks, closeout criteria, and provenance are concrete.",
508
- "Do not mutate source audit findings.",
509
- ],
510
- packet_summary: {
511
- included_finding_count: packet.included_finding_ids.length,
512
- source_finding_refs: packet.source_finding_refs,
513
- related_code_refs: packet.related_code_refs,
514
- authority_refs: packet.authority_refs,
515
- related_finding_refs: packet.related_finding_refs,
516
- prior_design_state_refs: packet.prior_design_state_refs,
517
- current_cluster_refs: packet.current_cluster_refs,
518
- current_wave_refs: packet.current_wave_refs,
519
- explicit_questions: packet.explicit_questions,
520
- },
521
- created_at: timestamp,
522
- };
523
- }
524
-
525
- function waveIncludedCount(wave) {
526
- const counts = [
527
- Array.isArray(wave.finding_ids) ? wave.finding_ids.length : 0,
528
- Array.isArray(wave.merged_cluster_ids) ? wave.merged_cluster_ids.length : 0,
529
- ];
530
- return Math.max(...counts);
531
- }
532
-
533
- export function validateWave(wave, errors) {
534
- for (const field of [
535
- "wave_id",
536
- "scope",
537
- "owner_domain",
538
- "authority_owner",
539
- "dependencies",
540
- "preflight_ref",
541
- "non_goals",
542
- "validation_commands",
543
- "negative_checks",
544
- "drift_resistance_checks",
545
- "closeout_criteria",
546
- "source_design_packet_refs",
547
- "design_auditor_result_refs",
548
- "revision_ledger_entry_refs",
549
- "blocked_gate_refs",
550
- "merged_cluster_ids",
551
- "merged_root_cause_keys",
552
- ]) {
553
- if (wave[field] === undefined || wave[field] === null) errors.push(`wave.${field} is required`);
554
- }
555
- for (const field of ["validation_commands", "negative_checks", "drift_resistance_checks", "closeout_criteria", "source_design_packet_refs", "design_auditor_result_refs", "revision_ledger_entry_refs"]) {
556
- requireNonEmptyArray(wave[field], `wave.${field}`, errors);
557
- }
558
- const count = waveIncludedCount(wave);
559
- if (count > 1 && !wave.consolidation_rationale) errors.push("multi-finding or multi-cluster wave requires consolidation_rationale");
560
- if (count <= 1 && !wave.isolation_justification) errors.push("single-finding or single-cluster wave requires isolation_justification");
561
- const requiredAuthorityRefs = sweepDesignWaveAuthorityRefs(wave);
562
- const declaredAuthorityOwners = new Set(typeof wave.authority_owner === "string"
563
- ? [wave.authority_owner]
564
- : Array.isArray(wave.authority_owner)
565
- ? wave.authority_owner
566
- : []);
567
- const missingAuthorityRefs = requiredAuthorityRefs.filter((ref) => !declaredAuthorityOwners.has(ref));
568
- if (missingAuthorityRefs.length > 0) {
569
- errors.push(`wave.authority_owner must cover source authority refs: ${missingAuthorityRefs.join(", ")}`);
570
- }
571
- }
572
-
573
- export function stopClassForResult(result) {
574
- const outcomes = result.finding_outcomes ?? [];
575
- if (outcomes.some((outcome) => finalOutcomeState(outcome) === "needs_user_decision") || (result.human_decision_requests ?? []).length > 0) {
576
- return "require_human_confirmation";
577
- }
578
- if (outcomes.some((outcome) => finalOutcomeState(outcome) === "needs_authority_alignment")) {
579
- return "authority_alignment_required";
580
- }
581
- if (outcomes.some((outcome) => finalOutcomeState(outcome) === "needs_more_audit") || (result.extra_audit_requests ?? []).length > 0) {
582
- return "extra_audit_required";
583
- }
584
- if (outcomes.some((outcome) => finalOutcomeState(outcome) === "blocked")) {
585
- return "blocked";
586
- }
587
- return null;
588
- }
589
-
590
- export async function runIntake(projectRoot, options) {
591
- const sweepId = safeDesignId(options.sweepId);
592
- if (!sweepId) return inputError("nimicoding sweep design refused: --sweep-id must be a stable id.\n");
593
- const audit = await loadAuditFindings(projectRoot, sweepId);
594
- if (!audit.ok) return audit;
595
- const runId = options.runId ? safeDesignId(options.runId) : deriveRunId(sweepId);
596
- if (!runId) return inputError("nimicoding sweep design refused: --run-id must be a stable id.\n");
597
- const timestamp = options.verifiedAt ?? nowIso();
598
- const findings = audit.store.findings.map((finding) => normalizeFindingForDesign(finding, audit.ref));
599
- const inventory = {
600
- version: 2,
601
- kind: "sweep-design-inventory",
602
- run_id: runId,
603
- artifact_role: "forked_design_workset",
604
- source_audit_sweep_id: sweepId,
605
- source_findings_ref: audit.ref,
606
- source_findings_sha256: audit.sourceSha256,
607
- source_findings_mutation_policy: "read_only_never_update_from_sweep_design",
608
- design_judgement_policy: "llm_auditor_result_required_for_final_outcomes",
609
- finding_count: findings.length,
610
- findings,
611
- created_at: timestamp,
612
- updated_at: timestamp,
613
- };
614
- const ref = await writeYamlRef(projectRoot, inventoryRef(runId), inventory);
615
- await loadOrCreateLedger(projectRoot, runId, timestamp);
616
- return { ok: true, exitCode: 0, runId, sourceAuditSweepId: sweepId, inventoryRef: ref, ledgerRef: ledgerRef(runId), findingCount: findings.length };
617
- }
618
-
619
- export async function runPacketBuild(projectRoot, options) {
620
- const run = requireRunId(options);
621
- if (!run.ok) return run;
622
- const packetId = safeDesignId(options.packetId);
623
- if (!packetId) return inputError("nimicoding sweep design refused: --packet-id must be a stable id.\n");
624
- const includedFindingIds = normalizeIdList(options.findingIds || options.findingId);
625
- if (includedFindingIds.length === 0) {
626
- return inputError("nimicoding sweep design refused: packet-build requires --finding-id or --finding-ids.\n");
627
- }
628
- const inventory = await loadInventory(projectRoot, run.runId);
629
- if (!inventory.ok) return inventory;
630
- const ledger = await loadOrCreateLedger(projectRoot, run.runId, options.verifiedAt ?? nowIso());
631
- if (!ledger.ok) return ledger;
632
- const built = buildPacketValue(inventory.value, ledger, run.runId, packetId, includedFindingIds, options, options.verifiedAt ?? nowIso());
633
- if (!built.ok) return inputError(built.error);
634
- const { packet } = built;
635
- const ref = await writeYamlRef(projectRoot, packetRef(run.runId, packetId), packet);
636
- return { ok: true, exitCode: 0, runId: run.runId, packetRef: ref, packetId, findingCount: includedFindingIds.length };
637
- }
638
-
639
- export async function runPacketBuildBatch(projectRoot, options) {
640
- const run = requireRunId(options);
641
- if (!run.ok) return run;
642
- const batchSize = parsePositiveInteger(options.batchSize, "--batch-size");
643
- if (!batchSize.ok) return inputError(batchSize.error);
644
- const inventory = await loadInventory(projectRoot, run.runId);
645
- if (!inventory.ok) return inventory;
646
- const timestamp = options.verifiedAt ?? nowIso();
647
- const ledger = await loadOrCreateLedger(projectRoot, run.runId, timestamp);
648
- if (!ledger.ok) return ledger;
649
- const selectedFindingIds = normalizeIdList(options.findingIds)
650
- || inventory.value.findings.map((finding) => finding.finding_id).sort();
651
- const ids = selectedFindingIds.length > 0 ? selectedFindingIds : inventory.value.findings.map((finding) => finding.finding_id).sort();
652
- const found = new Set(inventory.value.findings.map((finding) => finding.finding_id));
653
- const missing = ids.filter((findingId) => !found.has(findingId));
654
- if (missing.length > 0) return inputError(`nimicoding sweep design refused: finding not found: ${missing.join(", ")}.\n`);
655
- const packetPrefix = options.packetPrefix || "packet";
656
- if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]{1,80}$/.test(packetPrefix)) {
657
- return inputError("nimicoding sweep design refused: --packet-prefix must be a stable id prefix.\n");
658
- }
659
- const manifestId = options.manifestId || `${packetPrefix}-manifest`;
660
- if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]{2,120}$/.test(manifestId)) {
661
- return inputError("nimicoding sweep design refused: --manifest-id must be a stable artifact id.\n");
662
- }
663
- const manifestRef = batchManifestRef(run.runId, manifestId);
664
- const manifestAbsent = await ensureRefAbsent(projectRoot, manifestRef, "batch manifest");
665
- if (!manifestAbsent.ok) return manifestAbsent;
666
- const batches = chunkArray(ids, batchSize.value);
667
- const packetEntries = [];
668
- for (const [index, findingIds] of batches.entries()) {
669
- const packetId = `${packetPrefix}-${String(index + 1).padStart(4, "0")}`;
670
- const packetArtifactRef = packetRef(run.runId, packetId);
671
- const promptArtifactRef = auditorPromptRef(run.runId, packetId);
672
- for (const [ref, label] of [[packetArtifactRef, "design auditor packet"], [promptArtifactRef, "auditor prompt"]]) {
673
- const absent = await ensureRefAbsent(projectRoot, ref, label);
674
- if (!absent.ok) return absent;
675
- }
676
- const built = buildPacketValue(inventory.value, ledger, run.runId, packetId, findingIds, options, timestamp);
677
- if (!built.ok) return inputError(built.error);
678
- await writeYamlRef(projectRoot, packetArtifactRef, built.packet);
679
- await writeYamlRef(projectRoot, promptArtifactRef, buildAuditorPromptValue(run.runId, packetId, packetArtifactRef, built.packet, timestamp));
680
- packetEntries.push({
681
- packet_id: packetId,
682
- packet_ref: packetArtifactRef,
683
- prompt_ref: promptArtifactRef,
684
- finding_ids: findingIds,
685
- source_finding_refs: built.packet.source_finding_refs,
686
- });
687
- }
688
- const manifest = {
689
- version: 2,
690
- kind: "sweep-design-batch-manifest",
691
- run_id: run.runId,
692
- manifest_id: manifestId,
693
- source_inventory_ref: inventory.ref,
694
- source_audit_sweep_id: inventory.value.source_audit_sweep_id,
695
- source_findings_ref: inventory.value.source_findings_ref,
696
- source_findings_sha256: inventory.value.source_findings_sha256,
697
- source_findings_mutation_policy: "read_only_never_update_from_sweep_design",
698
- batch_policy: "deterministic_inventory_order_chunking",
699
- batch_size: batchSize.value,
700
- packet_prefix: packetPrefix,
701
- selected_finding_count: ids.length,
702
- packet_count: packetEntries.length,
703
- packets: packetEntries,
704
- generated_artifact_policy: "packets_and_prompts_only_no_auditor_results",
705
- true_llm_closeout_policy: "requires_external_llm_session_or_llm_session_results_ingested_later",
706
- created_at: timestamp,
707
- };
708
- const ref = await writeYamlRef(projectRoot, manifestRef, manifest);
709
- return {
710
- ok: true,
711
- exitCode: 0,
712
- runId: run.runId,
713
- manifestRef: ref,
714
- packetCount: packetEntries.length,
715
- promptCount: packetEntries.length,
716
- findingCount: ids.length,
717
- sourceFindingsSha256: inventory.value.source_findings_sha256,
718
- };
719
- }
720
-
721
- export async function runAuditorPrompt(projectRoot, options) {
722
- const run = requireRunId(options);
723
- if (!run.ok) return run;
724
- const packetId = safeDesignId(options.packetId);
725
- if (!packetId) return inputError("nimicoding sweep design refused: --packet-id must be a stable id.\n");
726
- const packet = await assertDesignArtifact(projectRoot, packetRef(run.runId, packetId), "sweep-design-design-auditor-packet", "design auditor packet");
727
- if (!packet.ok) return packet;
728
- const packetErrors = validatePacket(packet.value);
729
- if (packetErrors.length > 0) return inputError(`nimicoding sweep design refused: ${packetErrors.join("; ")}.\n`);
730
- const prompt = buildAuditorPromptValue(run.runId, packetId, packet.ref, packet.value, options.verifiedAt ?? nowIso());
731
- const ref = await writeYamlRef(projectRoot, auditorPromptRef(run.runId, packetId), prompt);
732
- return { ok: true, exitCode: 0, runId: run.runId, packetId, promptRef: ref, findingCount: packet.value.included_finding_ids.length };
733
- }