@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,527 +0,0 @@
1
- import { spawn } from "node:child_process";
2
- import { mkdir } from "node:fs/promises";
3
- import path from "node:path";
4
-
5
- import {
6
- appendRunEvent,
7
- artifactPath,
8
- artifactRef,
9
- chunkRef,
10
- ensureIsoTimestamp,
11
- inputError,
12
- loadChunk,
13
- loadPlan,
14
- packetRef,
15
- resolveInsideProject,
16
- safeSweepId,
17
- withAuditSweepMutationLock,
18
- writeYamlRef,
19
- } from "./common.mjs";
20
- import { buildAuditorPacket, reviewAuditSweepChunk, updatePlanChunk } from "./chunks.mjs";
21
- import { extractCodexAuditorEvidenceFile, P0P1_RULE_CHECK_IDS } from "./codex-auditor-evidence.mjs";
22
- import { ingestAuditSweepChunk } from "./ingest.mjs";
23
- import { budgetBlockForChunk } from "./risk-budget.mjs";
24
- import { validateAuditSweepArtifacts } from "./validators.mjs";
25
-
26
- const CODEX_AUDITOR_DEFAULT = "codex_semantic_auditor";
27
- const DEFAULT_CODEX_TIMEOUT_MS = 10 * 60 * 1000;
28
- const CODEX_TIMEOUT_KILL_GRACE_MS = 3000;
29
- const CODEX_RAW_SUFFIX = ".codex-raw.json";
30
- const CODEX_EVIDENCE_SUFFIX = ".codex-evidence.json";
31
-
32
- function codexOutputRef(sweepId, chunkId, suffix) {
33
- return artifactRef("evidence_refs", sweepId, "codex-output", `${chunkId}${suffix}`);
34
- }
35
-
36
- function codexRunToken(timestamp) {
37
- return timestamp.replace(/[^0-9A-Za-z]+/g, "-").replace(/^-+|-+$/g, "");
38
- }
39
-
40
- function projectRefForPath(projectRoot, absolutePath) {
41
- return path.relative(projectRoot, absolutePath).replace(/\\/g, "/");
42
- }
43
- function codexPrompt({ packet, auditorPacketRef, rawRef, sessionRef }) {
44
- return [
45
- "You are the Codex semantic auditor for a nimicoding sweep audit chunk.",
46
- "Run in read-only, audit-only mode. Do not edit files. Do not implement product fixes.",
47
- `Read the auditor packet from ${auditorPacketRef} and inspect the chunk authority refs and implementation evidence semantically.`,
48
- "Do not rely on this prompt as the chunk inventory; the packet file is the source for files, authority_refs, selected_implementation_refs, audit_depth, retrieval_prepass, and the raw semantic output contract.",
49
- "Scripts may not generate findings or no-findings; your conclusions must come from your own inspection.",
50
- "The packet is compact: evidence_inventory/selected_implementation_refs is the manager-selected implementation slice, not the full manager-owned inventory.",
51
- "Do not ask for, reconstruct, or echo the omitted full evidence_inventory. audit-codex will mechanically fill coverage.files, coverage.authority_refs, and full coverage.evidence_files from manager-owned chunk state.",
52
- "You only author semantic audit content: authority_outcomes reasoning/status, inspected_implementation_refs, P0/P1 rule checks, p0p1_negative_reasoning when applicable, and findings.",
53
- "For each authority outcome, set authority_ref to the packet authority_ref and put inspected implementation refs in inspected_implementation_refs or implementation_evidence_refs.",
54
- "Every implementation ref you cite must be an exact file ref from packet.selected_implementation_refs / packet.evidence_inventory.",
55
- "Never put AGENTS.md, README.md, spec files, authority refs, methodology docs, or governance docs in inspected_implementation_refs, implementation_evidence_refs, coverage.p0p1_evidence_refs, findings[].implementation_refs, or coverage.p0p1_rule_checks[].implementation_refs; even if packet.selected_implementation_refs includes them, treat them as context only.",
56
- "If only context/governance/authority documents are available after that exclusion, use status=\"not_applicable\" for P0/P1 rule checks and explain the lack of implementation surface in negative_reasoning.",
57
- "If a governance or authority document influenced reasoning, mention it only in negative_reasoning/description text, not in any implementation_refs array.",
58
- "Use packet.audit_depth to size your inspection: deep means inspect the selected slice thoroughly, normal means focused semantic inspection, shallow means audit generated/table/index invariants from the selected slice without expanding the omitted inventory.",
59
- "Return exactly one JSON object and nothing else. Do not wrap it in markdown.",
60
- "The JSON object must have exactly these top-level fields: chunk_id, auditor, coverage, findings.",
61
- `Set auditor.id to ${JSON.stringify(packet.auditor)}.`,
62
- `Set auditor.mode to "codex_semantic_audit".`,
63
- `Set auditor.methodology_ref to "package://@nimiplatform/nimi-coding/methodology/audit-sweep-p0p1-recall.yaml".`,
64
- "Put P0/P1 rule checks only at coverage.p0p1_rule_checks.",
65
- `Set auditor.provenance.kind to "semantic_audit".`,
66
- `Set auditor.provenance.packet_ref to ${JSON.stringify(packetRef(packet.sweep_id, packet.chunk_id))}.`,
67
- `Set auditor.provenance.session_ref to ${JSON.stringify(sessionRef)}.`,
68
- `Set auditor.provenance.transcript_ref to ${JSON.stringify(rawRef)}.`,
69
- "coverage.authority_outcomes must contain one outcome per authority_ref.",
70
- `coverage.p0p1_rule_checks must contain exactly these ids and no aliases: ${P0P1_RULE_CHECK_IDS.join(", ")}.`,
71
- "Each coverage.authority_outcomes[] object must include negative_reasoning when no critical/high finding is emitted for the chunk.",
72
- "Each coverage.p0p1_rule_checks[] object must include id, status, implementation_refs, and negative_reasoning.",
73
- "Use status=\"checked\" when implementation evidence was inspected; checked rules must cite at least one in-scope implementation ref.",
74
- "Use status=\"not_applicable\" only when the rule truly has no implementation surface, and explain that in negative_reasoning.",
75
- "When the packet evidence_inventory is empty and no critical/high finding is emitted, include coverage.p0p1_implementation_not_applicable_reason with the chunk-specific reason implementation refs are not applicable.",
76
- "Do not use priority defect class aliases such as authority_boundary_bypass, security_or_permission_bypass, destructive_action_without_gate, package_boundary_violation, or unadmitted_truth_or_evidence_source as rule check ids.",
77
- "Do not emit coverage.files, coverage.authority_refs, or coverage.evidence_files; those fields are manager-owned and will be populated from the packet.",
78
- "Do not emit authority_outcomes[].evidence_refs; it is manager-owned and will be built from authority_ref plus inspected implementation refs.",
79
- "Every finding must include severity, category, impact, title, description, and location.file. Set severity to critical or high for P0/P1 findings. Set finding.category to one of the exact P0/P1 rule ids when the finding maps to a P0/P1 rule; do not use rule_id as the primary finding category field.",
80
- "Set findings[].location.file to an exact packet.selected_implementation_refs file for implementation findings. For authority-only findings with no implementation surface, set findings[].location.file to the in-scope authority_ref that contains the defect.",
81
- "authority_outcomes[].status is an audit-process enum only: audited, blocked, or not_applicable.",
82
- "Use status=audited when the authority/evidence was inspected, even if you discovered violations.",
83
- "When an authority outcome uses status=blocked or status=not_applicable, include reason with the chunk-specific blocker or not-applicable explanation.",
84
- "Do not use compliance verdicts such as violated, pass, fail, compliant, or non_compliant in authority_outcomes[].status; put violations in findings.",
85
- "For no-finding chunks, include chunk-specific inspected implementation refs, P0/P1 rule checks, and negative reasoning.",
86
- ].join("\n");
87
- }
88
-
89
- function terminateProcess(child, signal) {
90
- try {
91
- if (process.platform !== "win32" && child.pid) {
92
- process.kill(-child.pid, signal);
93
- return;
94
- }
95
- } catch {
96
- // Fall through to direct child termination.
97
- }
98
- try {
99
- child.kill(signal);
100
- } catch {
101
- // Process may already have exited.
102
- }
103
- }
104
-
105
- function executableInvocation(executable, args) {
106
- if (
107
- process.platform === "win32" &&
108
- [".cjs", ".js", ".mjs"].includes(path.extname(executable).toLowerCase())
109
- ) {
110
- return { command: process.execPath, args: [executable, ...args] };
111
- }
112
- return { command: executable, args };
113
- }
114
-
115
- function runCodexExec({ projectRoot, codexBin, rawOutputPath, prompt, timeoutMs }) {
116
- return new Promise((resolve) => {
117
- const boundedTimeoutMs = Number.isInteger(timeoutMs) && timeoutMs > 0 ? timeoutMs : DEFAULT_CODEX_TIMEOUT_MS;
118
- let timedOut = false;
119
- let settled = false;
120
- let killTimer = null;
121
- const invocation = executableInvocation(codexBin, [
122
- "exec",
123
- "-C",
124
- projectRoot,
125
- "-s",
126
- "read-only",
127
- "--output-last-message",
128
- rawOutputPath,
129
- "-",
130
- ]);
131
- const child = spawn(invocation.command, invocation.args, {
132
- cwd: projectRoot,
133
- stdio: ["pipe", "pipe", "pipe"],
134
- detached: process.platform !== "win32",
135
- });
136
-
137
- const timeoutTimer = setTimeout(() => {
138
- timedOut = true;
139
- terminateProcess(child, "SIGTERM");
140
- killTimer = setTimeout(() => terminateProcess(child, "SIGKILL"), CODEX_TIMEOUT_KILL_GRACE_MS);
141
- }, boundedTimeoutMs);
142
-
143
- let stdout = "";
144
- let stderr = "";
145
- child.stdout.on("data", (chunk) => {
146
- stdout += chunk.toString();
147
- });
148
- child.stderr.on("data", (chunk) => {
149
- stderr += chunk.toString();
150
- });
151
- child.on("error", (error) => {
152
- if (settled) {
153
- return;
154
- }
155
- settled = true;
156
- clearTimeout(timeoutTimer);
157
- if (killTimer) {
158
- clearTimeout(killTimer);
159
- }
160
- resolve({ ok: false, exitCode: 1, timedOut, timeoutMs: boundedTimeoutMs, stdout, stderr: `${stderr}${error.message}` });
161
- });
162
- child.on("close", (exitCode, signal) => {
163
- if (settled) {
164
- return;
165
- }
166
- settled = true;
167
- clearTimeout(timeoutTimer);
168
- if (killTimer) {
169
- clearTimeout(killTimer);
170
- }
171
- resolve({ ok: exitCode === 0 && !timedOut, exitCode, signal, timedOut, timeoutMs: boundedTimeoutMs, stdout, stderr });
172
- });
173
- child.stdin.end(prompt);
174
- });
175
- }
176
-
177
- async function prepareCodexAuditPacket(projectRoot, options) {
178
- return withAuditSweepMutationLock(projectRoot, options.sweepId, "chunk codex audit prepare", async () => {
179
- const planResult = await loadPlan(projectRoot, options.sweepId);
180
- if (!planResult.ok) {
181
- return inputError(planResult.error);
182
- }
183
- const chunkResult = await loadChunk(projectRoot, options.sweepId, options.chunkId);
184
- if (!chunkResult.ok) {
185
- return inputError(chunkResult.error);
186
- }
187
- if (chunkResult.chunk.state === "skipped") {
188
- return inputError("nimicoding sweep audit refused: skipped chunks cannot be audited through Codex.\n");
189
- }
190
- const budgetBlock = budgetBlockForChunk(planResult.plan, chunkResult.chunk);
191
- if (budgetBlock && chunkResult.chunk.state !== "frozen") {
192
- return inputError(`nimicoding sweep audit refused: ${budgetBlock}; build or admit remediation bundles before continuing discovery.\n`);
193
- }
194
-
195
- const dispatch = {
196
- auditor: options.auditor ?? CODEX_AUDITOR_DEFAULT,
197
- criteria: chunkResult.chunk.criteria,
198
- files: chunkResult.chunk.files,
199
- authority_refs: chunkResult.chunk.authority_refs ?? chunkResult.chunk.files,
200
- host_authority_projection_refs: chunkResult.chunk.host_authority_projection_refs ?? [],
201
- evidence_roots: chunkResult.chunk.evidence_roots ?? [],
202
- admitted_evidence_roots: chunkResult.chunk.admitted_evidence_roots ?? [],
203
- evidence_inventory: chunkResult.chunk.evidence_inventory ?? [],
204
- evidence_inventory_status: chunkResult.chunk.evidence_inventory_status ?? null,
205
- evidence_inventory_empty_reason: chunkResult.chunk.evidence_inventory_empty_reason ?? null,
206
- execution_owner: "nimicoding_codex_auditor_path",
207
- };
208
- const packet = buildAuditorPacket(options.sweepId, chunkResult.chunk, dispatch.auditor, options.dispatchedAt, planResult.plan, { projectRoot });
209
- packet.execution_owner = "nimicoding_codex_auditor_path";
210
- packet.raw_output_contract = {
211
- raw_output_is_transcript_ref: true,
212
- raw_output_must_be_exact_json: true,
213
- schema_drift_rejected_fail_closed: true,
214
- scripts_may_only_extract_schema_conformant_evidence: true,
215
- };
216
-
217
- const auditorPacketRef = packetRef(options.sweepId, options.chunkId);
218
- const updatedChunk = {
219
- ...chunkResult.chunk,
220
- state: "dispatched",
221
- lifecycle: {
222
- ...chunkResult.chunk.lifecycle,
223
- dispatched_at: options.dispatchedAt,
224
- ingested_at: null,
225
- reviewed_at: null,
226
- frozen_at: null,
227
- failed_at: null,
228
- skipped_at: null,
229
- },
230
- dispatch,
231
- evidence_ref: null,
232
- finding_count: 0,
233
- audit_validity: null,
234
- review: null,
235
- failure: null,
236
- updated_at: options.dispatchedAt,
237
- };
238
-
239
- await writeYamlRef(projectRoot, auditorPacketRef, packet);
240
- await writeYamlRef(projectRoot, chunkResult.chunkRef, updatedChunk);
241
- await writeYamlRef(projectRoot, planResult.planRef, {
242
- ...updatePlanChunk(planResult.plan, options.chunkId, {
243
- state: "dispatched",
244
- evidence_ref: null,
245
- finding_count: 0,
246
- audit_validity: null,
247
- failure: null,
248
- }),
249
- updated_at: options.dispatchedAt,
250
- });
251
- const runLedgerRef = await appendRunEvent(projectRoot, options.sweepId, {
252
- event_type: "chunk_codex_audit_prepared",
253
- chunk_id: options.chunkId,
254
- chunk_ref: chunkRef(options.sweepId, options.chunkId),
255
- packet_ref: auditorPacketRef,
256
- auditor: dispatch.auditor,
257
- });
258
- return {
259
- ok: true,
260
- chunk: updatedChunk,
261
- packet,
262
- packetRef: auditorPacketRef,
263
- chunkRef: chunkResult.chunkRef,
264
- runLedgerRef,
265
- };
266
- });
267
- }
268
-
269
- async function markCodexAuditFailed(projectRoot, options) {
270
- return withAuditSweepMutationLock(projectRoot, options.sweepId, "chunk codex audit fail", async () => {
271
- const planResult = await loadPlan(projectRoot, options.sweepId);
272
- if (!planResult.ok) {
273
- return inputError(planResult.error);
274
- }
275
- const chunkResult = await loadChunk(projectRoot, options.sweepId, options.chunkId);
276
- if (!chunkResult.ok) {
277
- return inputError(chunkResult.error);
278
- }
279
- const failure = {
280
- reason: options.reason,
281
- failed_at: options.failedAt,
282
- packet_ref: options.packetRef,
283
- transcript_ref: options.transcriptRef,
284
- phase: options.phase,
285
- };
286
- const updatedChunk = {
287
- ...chunkResult.chunk,
288
- state: "failed",
289
- lifecycle: {
290
- ...chunkResult.chunk.lifecycle,
291
- failed_at: options.failedAt,
292
- skipped_at: null,
293
- },
294
- failure,
295
- updated_at: options.failedAt,
296
- };
297
- await writeYamlRef(projectRoot, chunkResult.chunkRef, updatedChunk);
298
- await writeYamlRef(projectRoot, planResult.planRef, {
299
- ...updatePlanChunk(planResult.plan, options.chunkId, {
300
- state: "failed",
301
- failure,
302
- }),
303
- updated_at: options.failedAt,
304
- });
305
- const runLedgerRef = await appendRunEvent(projectRoot, options.sweepId, {
306
- event_type: "chunk_failed",
307
- chunk_id: options.chunkId,
308
- chunk_ref: chunkResult.chunkRef,
309
- packet_ref: options.packetRef,
310
- transcript_ref: options.transcriptRef,
311
- summary: options.reason,
312
- phase: options.phase,
313
- });
314
- return {
315
- ok: true,
316
- state: "failed",
317
- chunkRef: chunkResult.chunkRef,
318
- runLedgerRef,
319
- };
320
- });
321
- }
322
-
323
- export async function runCodexAuditSweepChunk(projectRoot, options) {
324
- const sweepId = safeSweepId(options.sweepId);
325
- if (!sweepId || typeof options.chunkId !== "string") {
326
- return inputError("nimicoding sweep audit refused: --sweep-id and --chunk-id are required.\n");
327
- }
328
- const dispatchedAtError = ensureIsoTimestamp(options.dispatchedAt, "--dispatched-at");
329
- if (dispatchedAtError) {
330
- return dispatchedAtError;
331
- }
332
- const verifiedAtError = ensureIsoTimestamp(options.verifiedAt, "--verified-at");
333
- if (verifiedAtError) {
334
- return verifiedAtError;
335
- }
336
- const reviewedAtError = ensureIsoTimestamp(options.reviewedAt, "--reviewed-at");
337
- if (reviewedAtError) {
338
- return reviewedAtError;
339
- }
340
-
341
- const prepare = await prepareCodexAuditPacket(projectRoot, {
342
- ...options,
343
- sweepId,
344
- });
345
- if (!prepare.ok) {
346
- return prepare;
347
- }
348
-
349
- const outputSuffix = `.${codexRunToken(options.dispatchedAt)}`;
350
- let rawRef = codexOutputRef(sweepId, options.chunkId, `${outputSuffix}${CODEX_RAW_SUFFIX}`);
351
- const evidenceCandidateRef = codexOutputRef(sweepId, options.chunkId, `${outputSuffix}${CODEX_EVIDENCE_SUFFIX}`);
352
- let rawOutputPath = artifactPath(projectRoot, rawRef);
353
- let sessionRef = `codex-exec:${sweepId}:${options.chunkId}:${options.dispatchedAt}`;
354
- if (options.fromRawOutput) {
355
- const replaySource = resolveInsideProject(projectRoot, options.fromRawOutput, "--from-raw-output");
356
- if (!replaySource.ok) {
357
- await markCodexAuditFailed(projectRoot, {
358
- sweepId,
359
- chunkId: options.chunkId,
360
- failedAt: options.verifiedAt,
361
- packetRef: prepare.packetRef,
362
- transcriptRef: rawRef,
363
- phase: "raw_output_replay",
364
- reason: replaySource.error.trim(),
365
- });
366
- return inputError(replaySource.error);
367
- }
368
- rawOutputPath = replaySource.absolutePath;
369
- rawRef = projectRefForPath(projectRoot, rawOutputPath);
370
- sessionRef = `codex-replay:${sweepId}:${options.chunkId}:${options.dispatchedAt}`;
371
- } else {
372
- await mkdir(path.dirname(rawOutputPath), { recursive: true });
373
- const runResult = await runCodexExec({
374
- projectRoot,
375
- codexBin: options.codexBin ?? "codex",
376
- rawOutputPath,
377
- prompt: codexPrompt({
378
- packet: prepare.packet,
379
- auditorPacketRef: prepare.packetRef,
380
- rawRef,
381
- sessionRef,
382
- }),
383
- timeoutMs: options.timeoutMs,
384
- });
385
- if (!runResult.ok) {
386
- const failureReason = runResult.timedOut
387
- ? `Codex auditor execution timed out after ${runResult.timeoutMs}ms.`
388
- : `Codex auditor execution failed with exit code ${runResult.exitCode ?? "unknown"}.`;
389
- await markCodexAuditFailed(projectRoot, {
390
- sweepId,
391
- chunkId: options.chunkId,
392
- failedAt: options.verifiedAt,
393
- packetRef: prepare.packetRef,
394
- transcriptRef: rawRef,
395
- phase: "codex_execution",
396
- reason: failureReason,
397
- });
398
- await appendRunEvent(projectRoot, sweepId, {
399
- event_type: "chunk_codex_audit_failed",
400
- chunk_id: options.chunkId,
401
- chunk_ref: prepare.chunkRef,
402
- packet_ref: prepare.packetRef,
403
- transcript_ref: rawRef,
404
- exit_code: runResult.exitCode,
405
- timed_out: runResult.timedOut,
406
- timeout_ms: runResult.timeoutMs,
407
- stderr_tail: runResult.stderr.slice(-2000),
408
- });
409
- return inputError(`nimicoding sweep audit refused: ${failureReason}\n`);
410
- }
411
- }
412
-
413
- const extracted = await extractCodexAuditorEvidenceFile(projectRoot, {
414
- rawOutputPath,
415
- evidenceRef: evidenceCandidateRef,
416
- chunk: prepare.chunk,
417
- packetRef: prepare.packetRef,
418
- sessionRef,
419
- transcriptRef: rawRef,
420
- auditorId: options.auditor ?? CODEX_AUDITOR_DEFAULT,
421
- });
422
- if (!extracted.ok) {
423
- await markCodexAuditFailed(projectRoot, {
424
- sweepId,
425
- chunkId: options.chunkId,
426
- failedAt: options.verifiedAt,
427
- packetRef: prepare.packetRef,
428
- transcriptRef: rawRef,
429
- phase: "auditor_output_validation",
430
- reason: `Codex auditor output rejected: ${extracted.error}.`,
431
- });
432
- await appendRunEvent(projectRoot, sweepId, {
433
- event_type: "chunk_codex_auditor_output_rejected",
434
- chunk_id: options.chunkId,
435
- chunk_ref: prepare.chunkRef,
436
- packet_ref: prepare.packetRef,
437
- transcript_ref: rawRef,
438
- reason: extracted.error,
439
- });
440
- return inputError(`nimicoding sweep audit refused: Codex auditor output rejected for ${options.chunkId}: ${extracted.error}.\n`);
441
- }
442
-
443
- await appendRunEvent(projectRoot, sweepId, {
444
- event_type: "chunk_codex_auditor_output_accepted",
445
- chunk_id: options.chunkId,
446
- chunk_ref: prepare.chunkRef,
447
- packet_ref: prepare.packetRef,
448
- transcript_ref: rawRef,
449
- evidence_candidate_ref: evidenceCandidateRef,
450
- audit_validity: extracted.auditValidity,
451
- });
452
-
453
- const ingest = await ingestAuditSweepChunk(projectRoot, {
454
- sweepId,
455
- chunkId: options.chunkId,
456
- fromPath: evidenceCandidateRef,
457
- verifiedAt: options.verifiedAt,
458
- });
459
- if (!ingest.ok) {
460
- await markCodexAuditFailed(projectRoot, {
461
- sweepId,
462
- chunkId: options.chunkId,
463
- failedAt: options.verifiedAt,
464
- packetRef: prepare.packetRef,
465
- transcriptRef: rawRef,
466
- phase: "chunk_ingest",
467
- reason: `Codex auditor evidence ingest rejected: ${ingest.error ?? "unknown ingest failure"}.`,
468
- });
469
- return inputError(`nimicoding sweep audit refused: Codex auditor evidence ingest rejected for ${options.chunkId}: ${ingest.error ?? "unknown ingest failure"}.\n`);
470
- }
471
-
472
- const review = await reviewAuditSweepChunk(projectRoot, {
473
- sweepId,
474
- chunkId: options.chunkId,
475
- verdict: "pass",
476
- reviewedAt: options.reviewedAt,
477
- reviewer: options.reviewer ?? "nimicoding_codex_auditor_path",
478
- summary: options.summary ?? `Codex semantic audit accepted from ${rawRef}.`,
479
- });
480
- if (!review.ok) {
481
- await markCodexAuditFailed(projectRoot, {
482
- sweepId,
483
- chunkId: options.chunkId,
484
- failedAt: options.reviewedAt,
485
- packetRef: prepare.packetRef,
486
- transcriptRef: rawRef,
487
- phase: "chunk_review",
488
- reason: `Codex auditor evidence review rejected: ${review.error ?? "unknown review failure"}.`,
489
- });
490
- return inputError(`nimicoding sweep audit refused: Codex auditor evidence review rejected for ${options.chunkId}: ${review.error ?? "unknown review failure"}.\n`);
491
- }
492
-
493
- const validation = await validateAuditSweepArtifacts(projectRoot, {
494
- sweepId,
495
- scope: "chunks",
496
- });
497
- if (!validation.ok) {
498
- await markCodexAuditFailed(projectRoot, {
499
- sweepId,
500
- chunkId: options.chunkId,
501
- failedAt: options.reviewedAt,
502
- packetRef: prepare.packetRef,
503
- transcriptRef: rawRef,
504
- phase: "post_chunk_validation",
505
- reason: "Post-Codex chunk validation failed.",
506
- });
507
- return inputError(`nimicoding sweep audit refused: post-Codex chunk validation failed for ${options.chunkId}.\n`);
508
- }
509
-
510
- return {
511
- ok: true,
512
- exitCode: 0,
513
- sweepId,
514
- chunkId: options.chunkId,
515
- state: "frozen",
516
- packetRef: prepare.packetRef,
517
- transcriptRef: rawRef,
518
- extractedEvidenceRef: evidenceCandidateRef,
519
- evidenceRef: ingest.evidenceRef,
520
- findingsRef: ingest.findingsRef,
521
- findingCount: ingest.findingCount,
522
- addedCount: ingest.addedCount,
523
- duplicateCount: ingest.duplicateCount,
524
- reviewRef: review.runLedgerRef,
525
- validationScope: "chunks",
526
- };
527
- }