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