@nimiplatform/nimi-coding 0.2.8 → 0.3.1

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 (206) hide show
  1. package/CHANGELOG.md +10 -90
  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/commands/validate-spec-governance.mjs +20 -0
  8. package/cli/constants.mjs +9 -417
  9. package/cli/help.mjs +28 -145
  10. package/cli/index.mjs +5 -33
  11. package/cli/lib/blueprint-audit.mjs +5 -12
  12. package/cli/lib/bootstrap.mjs +0 -9
  13. package/cli/lib/contracts.mjs +0 -163
  14. package/cli/lib/doctor.mjs +155 -10
  15. package/cli/lib/entrypoints.mjs +63 -167
  16. package/cli/lib/internal/contracts-loaders.mjs +0 -85
  17. package/cli/lib/internal/contracts-parse.mjs +84 -520
  18. package/cli/lib/internal/governance/ai/check-agents-freshness.mjs +13 -8
  19. package/cli/lib/internal/surface-taxonomy-validators.mjs +316 -66
  20. package/cli/lib/internal/validators-shared.mjs +0 -16
  21. package/cli/lib/internal/validators-spec-helpers.mjs +7 -140
  22. package/cli/lib/internal/validators-spec.mjs +103 -342
  23. package/cli/lib/shared.mjs +1 -42
  24. package/cli/lib/validators.mjs +0 -48
  25. package/cli/seeds/seed-policy.yaml +0 -3
  26. package/config/bootstrap.yaml +4 -4
  27. package/config/spec-generation-inputs.yaml +6 -12
  28. package/contracts/domain-admission.schema.yaml +3 -3
  29. package/contracts/migration-inventory.schema.yaml +12 -75
  30. package/contracts/negative-fixtures.yaml +19 -99
  31. package/contracts/placement-contract.schema.yaml +49 -78
  32. package/contracts/projection-edge.schema.yaml +37 -121
  33. package/contracts/shared-enums.yaml +4 -8
  34. package/contracts/spec-generation-inputs.schema.yaml +15 -112
  35. package/contracts/spec-layout.schema.yaml +32 -0
  36. package/contracts/surface-taxonomy.schema.yaml +43 -94
  37. package/contracts/table-family.schema.yaml +1 -1
  38. package/contracts/tracked-output-admission.schema.yaml +13 -66
  39. package/methodology/core.yaml +33 -25
  40. package/methodology/four-closure-policy.yaml +18 -26
  41. package/methodology/role-separation-policy.yaml +21 -27
  42. package/methodology/spec-reconstruction.yaml +17 -34
  43. package/package.json +2 -4
  44. package/spec/_meta/spec-tree-model.yaml +5 -101
  45. package/spec/product-scope.yaml +25 -57
  46. package/adapters/README.md +0 -25
  47. package/adapters/claude/README.md +0 -89
  48. package/adapters/claude/profile.yaml +0 -70
  49. package/adapters/codex/README.md +0 -53
  50. package/adapters/codex/profile.yaml +0 -78
  51. package/adapters/oh-my-codex/README.md +0 -184
  52. package/adapters/oh-my-codex/profile.yaml +0 -46
  53. package/cli/commands/admit-high-risk-decision.mjs +0 -108
  54. package/cli/commands/audit-sweep.mjs +0 -364
  55. package/cli/commands/closeout.mjs +0 -186
  56. package/cli/commands/decide-high-risk-execution.mjs +0 -124
  57. package/cli/commands/handoff.mjs +0 -123
  58. package/cli/commands/ingest-high-risk-execution.mjs +0 -95
  59. package/cli/commands/review-high-risk-execution.mjs +0 -95
  60. package/cli/commands/sweep-design.mjs +0 -295
  61. package/cli/commands/sweep.mjs +0 -22
  62. package/cli/commands/topic-formatters.mjs +0 -382
  63. package/cli/commands/topic-goal.mjs +0 -33
  64. package/cli/commands/topic-options-shared.mjs +0 -27
  65. package/cli/commands/topic-options-workflow.mjs +0 -767
  66. package/cli/commands/topic-options.mjs +0 -626
  67. package/cli/commands/topic-runner.mjs +0 -169
  68. package/cli/commands/topic.mjs +0 -795
  69. package/cli/commands/validate-acceptance.mjs +0 -5
  70. package/cli/commands/validate-execution-packet.mjs +0 -5
  71. package/cli/commands/validate-orchestration-state.mjs +0 -5
  72. package/cli/commands/validate-prompt.mjs +0 -5
  73. package/cli/commands/validate-worker-output.mjs +0 -5
  74. package/cli/lib/adapter-profiles.mjs +0 -403
  75. package/cli/lib/audit-execution.mjs +0 -52
  76. package/cli/lib/audit-sweep-runtime/admissions.mjs +0 -508
  77. package/cli/lib/audit-sweep-runtime/audit-validity.mjs +0 -356
  78. package/cli/lib/audit-sweep-runtime/chunks.mjs +0 -697
  79. package/cli/lib/audit-sweep-runtime/claude-auditor.mjs +0 -658
  80. package/cli/lib/audit-sweep-runtime/closeout.mjs +0 -144
  81. package/cli/lib/audit-sweep-runtime/codex-auditor-evidence.mjs +0 -654
  82. package/cli/lib/audit-sweep-runtime/codex-auditor.mjs +0 -527
  83. package/cli/lib/audit-sweep-runtime/common.mjs +0 -341
  84. package/cli/lib/audit-sweep-runtime/coverage-quality.mjs +0 -172
  85. package/cli/lib/audit-sweep-runtime/evidence-assignment.mjs +0 -155
  86. package/cli/lib/audit-sweep-runtime/format.mjs +0 -57
  87. package/cli/lib/audit-sweep-runtime/ingest.mjs +0 -486
  88. package/cli/lib/audit-sweep-runtime/inventory-spec-chunks.mjs +0 -425
  89. package/cli/lib/audit-sweep-runtime/inventory.mjs +0 -798
  90. package/cli/lib/audit-sweep-runtime/ledger.mjs +0 -315
  91. package/cli/lib/audit-sweep-runtime/p0p1-profile.mjs +0 -101
  92. package/cli/lib/audit-sweep-runtime/remediation.mjs +0 -349
  93. package/cli/lib/audit-sweep-runtime/rerun.mjs +0 -129
  94. package/cli/lib/audit-sweep-runtime/risk-budget.mjs +0 -300
  95. package/cli/lib/audit-sweep-runtime/status.mjs +0 -62
  96. package/cli/lib/audit-sweep-runtime/validators-ledger.mjs +0 -215
  97. package/cli/lib/audit-sweep-runtime/validators.mjs +0 -797
  98. package/cli/lib/audit-sweep.mjs +0 -19
  99. package/cli/lib/authority-convergence.mjs +0 -720
  100. package/cli/lib/closeout.mjs +0 -732
  101. package/cli/lib/codex-sdk-runner.mjs +0 -76
  102. package/cli/lib/external-execution.mjs +0 -101
  103. package/cli/lib/handoff.mjs +0 -812
  104. package/cli/lib/high-risk-admission.mjs +0 -512
  105. package/cli/lib/high-risk-decision.mjs +0 -353
  106. package/cli/lib/high-risk-ingest.mjs +0 -321
  107. package/cli/lib/high-risk-review.mjs +0 -267
  108. package/cli/lib/internal/contracts-parse-high-risk.mjs +0 -131
  109. package/cli/lib/internal/contracts-validators.mjs +0 -399
  110. package/cli/lib/internal/doctor-bootstrap-surface.mjs +0 -406
  111. package/cli/lib/internal/doctor-delegated-surface.mjs +0 -256
  112. package/cli/lib/internal/doctor-finalize.mjs +0 -383
  113. package/cli/lib/internal/doctor-format.mjs +0 -286
  114. package/cli/lib/internal/doctor-inspectors.mjs +0 -327
  115. package/cli/lib/internal/doctor-state.mjs +0 -205
  116. package/cli/lib/internal/validators-artifacts.mjs +0 -515
  117. package/cli/lib/sweep-design-runtime/common.mjs +0 -246
  118. package/cli/lib/sweep-design-runtime/engine.mjs +0 -733
  119. package/cli/lib/sweep-design-runtime/fix-topic.mjs +0 -414
  120. package/cli/lib/sweep-design-runtime/lifecycle.mjs +0 -54
  121. package/cli/lib/sweep-design-runtime/results.mjs +0 -324
  122. package/cli/lib/sweep-design.mjs +0 -8
  123. package/cli/lib/topic-artifacts.mjs +0 -186
  124. package/cli/lib/topic-authority-coverage.mjs +0 -73
  125. package/cli/lib/topic-closeout.mjs +0 -560
  126. package/cli/lib/topic-common.mjs +0 -404
  127. package/cli/lib/topic-decisions.mjs +0 -332
  128. package/cli/lib/topic-draft-packets.mjs +0 -167
  129. package/cli/lib/topic-execution.mjs +0 -533
  130. package/cli/lib/topic-goal.mjs +0 -440
  131. package/cli/lib/topic-ledger.mjs +0 -281
  132. package/cli/lib/topic-lifecycle-artifacts.mjs +0 -173
  133. package/cli/lib/topic-root-validation.mjs +0 -288
  134. package/cli/lib/topic-runner-commands.mjs +0 -174
  135. package/cli/lib/topic-runner-deferral.mjs +0 -532
  136. package/cli/lib/topic-runner-stale-gates.mjs +0 -114
  137. package/cli/lib/topic-runner-validation.mjs +0 -138
  138. package/cli/lib/topic-runner.mjs +0 -727
  139. package/cli/lib/topic-scaffold.mjs +0 -252
  140. package/cli/lib/topic-waves.mjs +0 -403
  141. package/cli/lib/topic.mjs +0 -81
  142. package/config/audit-execution-artifacts.yaml +0 -20
  143. package/config/external-execution-artifacts.yaml +0 -16
  144. package/config/host-adapter.yaml +0 -30
  145. package/config/host-profile.yaml +0 -29
  146. package/config/installer-evidence.yaml +0 -31
  147. package/config/skill-installer.yaml +0 -23
  148. package/config/skill-manifest.yaml +0 -48
  149. package/config/skills.yaml +0 -30
  150. package/contracts/acceptance.schema.yaml +0 -16
  151. package/contracts/admission-checklist.schema.yaml +0 -15
  152. package/contracts/audit-chunk.schema.yaml +0 -123
  153. package/contracts/audit-closeout.schema.yaml +0 -51
  154. package/contracts/audit-finding.schema.yaml +0 -61
  155. package/contracts/audit-ledger.schema.yaml +0 -138
  156. package/contracts/audit-plan.schema.yaml +0 -138
  157. package/contracts/audit-remediation-map.schema.yaml +0 -52
  158. package/contracts/audit-rerun.schema.yaml +0 -31
  159. package/contracts/audit-sweep-result.yaml +0 -53
  160. package/contracts/authority-convergence-audit.schema.yaml +0 -19
  161. package/contracts/closeout.schema.yaml +0 -25
  162. package/contracts/decision-review.schema.yaml +0 -16
  163. package/contracts/doc-spec-audit-result.yaml +0 -19
  164. package/contracts/execution-packet.schema.yaml +0 -49
  165. package/contracts/external-host-compatibility.yaml +0 -22
  166. package/contracts/forbidden-shortcuts.catalog.yaml +0 -23
  167. package/contracts/high-risk-admission.schema.yaml +0 -23
  168. package/contracts/high-risk-execution-result.yaml +0 -20
  169. package/contracts/orchestration-state.schema.yaml +0 -41
  170. package/contracts/overflow-continuation.schema.yaml +0 -12
  171. package/contracts/packet.schema.yaml +0 -30
  172. package/contracts/pending-note.schema.yaml +0 -17
  173. package/contracts/prompt.schema.yaml +0 -12
  174. package/contracts/remediation.schema.yaml +0 -16
  175. package/contracts/result.schema.yaml +0 -24
  176. package/contracts/spec-reconstruction-result.yaml +0 -41
  177. package/contracts/sweep-design-result.yaml +0 -349
  178. package/contracts/topic-goal.schema.yaml +0 -87
  179. package/contracts/topic-run-ledger.schema.yaml +0 -72
  180. package/contracts/topic-step-decision.schema.yaml +0 -45
  181. package/contracts/topic.schema.yaml +0 -65
  182. package/contracts/true-close.schema.yaml +0 -15
  183. package/contracts/wave.schema.yaml +0 -29
  184. package/contracts/worker-output.schema.yaml +0 -15
  185. package/contracts/workflow-consumer.schema.yaml +0 -110
  186. package/methodology/audit-sweep-p0p1-recall.yaml +0 -45
  187. package/methodology/authority-convergence-policy.yaml +0 -42
  188. package/methodology/overflow-continuation-policy.yaml +0 -14
  189. package/methodology/skill-exchange-projection.yaml +0 -114
  190. package/methodology/skill-handoff.yaml +0 -34
  191. package/methodology/skill-installer-result.yaml +0 -27
  192. package/methodology/skill-installer-summary-projection.yaml +0 -181
  193. package/methodology/skill-runtime.yaml +0 -23
  194. package/methodology/spec-target-truth-profile.yaml +0 -46
  195. package/methodology/topic-lifecycle-report.yaml +0 -144
  196. package/methodology/topic-lifecycle.yaml +0 -37
  197. package/methodology/topic-naming-ontology.yaml +0 -21
  198. package/methodology/topic-ontology.yaml +0 -38
  199. package/methodology/topic-validation-policy.yaml +0 -9
  200. package/methodology/wave-dag-policy.yaml +0 -14
  201. package/spec/_meta/command-gating-matrix.yaml +0 -143
  202. package/spec/_meta/generate-drift-migration-checklist.yaml +0 -137
  203. package/spec/_meta/governance-routing-cutover-checklist.yaml +0 -35
  204. package/spec/_meta/phase2-impacted-surface-matrix.yaml +0 -44
  205. package/spec/_meta/spec-authority-cutover-readiness.yaml +0 -102
  206. 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
- }