audit-tools 0.55.5 → 0.55.6

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 (166) hide show
  1. package/dist/audit/cli/auditStep.d.ts +15 -1
  2. package/dist/audit/cli/auditStep.d.ts.map +1 -1
  3. package/dist/audit/cli/auditStep.js +24 -11
  4. package/dist/audit/cli/auditStep.js.map +1 -1
  5. package/dist/audit/cli/cleanup.d.ts.map +1 -1
  6. package/dist/audit/cli/cleanup.js +26 -2
  7. package/dist/audit/cli/cleanup.js.map +1 -1
  8. package/dist/audit/cli/conceptualDispatch.d.ts +2 -0
  9. package/dist/audit/cli/conceptualDispatch.d.ts.map +1 -1
  10. package/dist/audit/cli/conceptualDispatch.js +29 -8
  11. package/dist/audit/cli/conceptualDispatch.js.map +1 -1
  12. package/dist/audit/cli/dispatch/hostHandoff.d.ts +37 -3
  13. package/dist/audit/cli/dispatch/hostHandoff.d.ts.map +1 -1
  14. package/dist/audit/cli/dispatch/hostHandoff.js +185 -16
  15. package/dist/audit/cli/dispatch/hostHandoff.js.map +1 -1
  16. package/dist/audit/cli/fanoutLanes.d.ts +30 -0
  17. package/dist/audit/cli/fanoutLanes.d.ts.map +1 -1
  18. package/dist/audit/cli/fanoutLanes.js +76 -8
  19. package/dist/audit/cli/fanoutLanes.js.map +1 -1
  20. package/dist/audit/cli/nextStepCommand.d.ts +3 -0
  21. package/dist/audit/cli/nextStepCommand.d.ts.map +1 -1
  22. package/dist/audit/cli/nextStepCommand.js +104 -66
  23. package/dist/audit/cli/nextStepCommand.js.map +1 -1
  24. package/dist/audit/cli/nextStepHelpers.d.ts +49 -14
  25. package/dist/audit/cli/nextStepHelpers.d.ts.map +1 -1
  26. package/dist/audit/cli/nextStepHelpers.js +164 -68
  27. package/dist/audit/cli/nextStepHelpers.js.map +1 -1
  28. package/dist/audit/cli/reviewRun.d.ts +4 -0
  29. package/dist/audit/cli/reviewRun.d.ts.map +1 -1
  30. package/dist/audit/cli/reviewRun.js +1 -1
  31. package/dist/audit/cli/reviewRun.js.map +1 -1
  32. package/dist/audit/cli/semanticReviewStep.d.ts +2 -0
  33. package/dist/audit/cli/semanticReviewStep.d.ts.map +1 -1
  34. package/dist/audit/cli/semanticReviewStep.js +5 -50
  35. package/dist/audit/cli/semanticReviewStep.js.map +1 -1
  36. package/dist/audit/cli/validateResultsCommand.d.ts.map +1 -1
  37. package/dist/audit/cli/validateResultsCommand.js +3 -1
  38. package/dist/audit/cli/validateResultsCommand.js.map +1 -1
  39. package/dist/audit/extractors/fsIntake.d.ts +13 -0
  40. package/dist/audit/extractors/fsIntake.d.ts.map +1 -1
  41. package/dist/audit/extractors/fsIntake.js +11 -1
  42. package/dist/audit/extractors/fsIntake.js.map +1 -1
  43. package/dist/audit/io/artifacts.d.ts +35 -9
  44. package/dist/audit/io/artifacts.d.ts.map +1 -1
  45. package/dist/audit/io/artifacts.js +84 -67
  46. package/dist/audit/io/artifacts.js.map +1 -1
  47. package/dist/audit/io/rollover.d.ts +18 -0
  48. package/dist/audit/io/rollover.d.ts.map +1 -0
  49. package/dist/audit/io/rollover.js +152 -0
  50. package/dist/audit/io/rollover.js.map +1 -0
  51. package/dist/audit/io/runSnapshot.d.ts +149 -0
  52. package/dist/audit/io/runSnapshot.d.ts.map +1 -0
  53. package/dist/audit/io/runSnapshot.js +710 -0
  54. package/dist/audit/io/runSnapshot.js.map +1 -0
  55. package/dist/audit/orchestrator/advanceTypes.d.ts +11 -0
  56. package/dist/audit/orchestrator/advanceTypes.d.ts.map +1 -1
  57. package/dist/audit/orchestrator/autoFixExecutor.d.ts +9 -0
  58. package/dist/audit/orchestrator/autoFixExecutor.d.ts.map +1 -1
  59. package/dist/audit/orchestrator/autoFixExecutor.js +22 -2
  60. package/dist/audit/orchestrator/autoFixExecutor.js.map +1 -1
  61. package/dist/audit/orchestrator/charterExtractionExecutor.d.ts.map +1 -1
  62. package/dist/audit/orchestrator/charterExtractionExecutor.js +18 -3
  63. package/dist/audit/orchestrator/charterExtractionExecutor.js.map +1 -1
  64. package/dist/audit/orchestrator/charterPackets.d.ts +11 -1
  65. package/dist/audit/orchestrator/charterPackets.d.ts.map +1 -1
  66. package/dist/audit/orchestrator/charterPackets.js +13 -0
  67. package/dist/audit/orchestrator/charterPackets.js.map +1 -1
  68. package/dist/audit/orchestrator/designReviewPrompt.d.ts +9 -0
  69. package/dist/audit/orchestrator/designReviewPrompt.d.ts.map +1 -1
  70. package/dist/audit/orchestrator/designReviewPrompt.js +69 -31
  71. package/dist/audit/orchestrator/designReviewPrompt.js.map +1 -1
  72. package/dist/audit/orchestrator/designReviewSnapshot.d.ts +1 -0
  73. package/dist/audit/orchestrator/designReviewSnapshot.d.ts.map +1 -1
  74. package/dist/audit/orchestrator/designReviewSnapshot.js +2 -1
  75. package/dist/audit/orchestrator/designReviewSnapshot.js.map +1 -1
  76. package/dist/audit/orchestrator/executorRunners.d.ts.map +1 -1
  77. package/dist/audit/orchestrator/executorRunners.js +13 -4
  78. package/dist/audit/orchestrator/executorRunners.js.map +1 -1
  79. package/dist/audit/orchestrator/intakeExecutors.d.ts +8 -1
  80. package/dist/audit/orchestrator/intakeExecutors.d.ts.map +1 -1
  81. package/dist/audit/orchestrator/intakeExecutors.js +13 -4
  82. package/dist/audit/orchestrator/intakeExecutors.js.map +1 -1
  83. package/dist/audit/orchestrator/obligationPolicy.d.ts.map +1 -1
  84. package/dist/audit/orchestrator/obligationPolicy.js +4 -1
  85. package/dist/audit/orchestrator/obligationPolicy.js.map +1 -1
  86. package/dist/audit/orchestrator/planningExecutors.d.ts +1 -1
  87. package/dist/audit/orchestrator/planningExecutors.d.ts.map +1 -1
  88. package/dist/audit/orchestrator/planningExecutors.js +40 -6
  89. package/dist/audit/orchestrator/planningExecutors.js.map +1 -1
  90. package/dist/audit/orchestrator/systemicChallengeExecutor.d.ts.map +1 -1
  91. package/dist/audit/orchestrator/systemicChallengeExecutor.js +4 -1
  92. package/dist/audit/orchestrator/systemicChallengeExecutor.js.map +1 -1
  93. package/dist/audit/orchestrator/taskBuilder.d.ts +20 -0
  94. package/dist/audit/orchestrator/taskBuilder.d.ts.map +1 -1
  95. package/dist/audit/orchestrator/taskBuilder.js +80 -18
  96. package/dist/audit/orchestrator/taskBuilder.js.map +1 -1
  97. package/dist/audit/systemic/reviewFileMap.d.ts +72 -21
  98. package/dist/audit/systemic/reviewFileMap.d.ts.map +1 -1
  99. package/dist/audit/systemic/reviewFileMap.js +96 -45
  100. package/dist/audit/systemic/reviewFileMap.js.map +1 -1
  101. package/dist/audit/systemic/secondOrderAdversaryPrompt.d.ts +7 -0
  102. package/dist/audit/systemic/secondOrderAdversaryPrompt.d.ts.map +1 -1
  103. package/dist/audit/systemic/secondOrderAdversaryPrompt.js +39 -8
  104. package/dist/audit/systemic/secondOrderAdversaryPrompt.js.map +1 -1
  105. package/dist/remediate/phases/close.d.ts.map +1 -1
  106. package/dist/remediate/phases/close.js +19 -4
  107. package/dist/remediate/phases/close.js.map +1 -1
  108. package/dist/remediate/phases/triage.d.ts +2 -1
  109. package/dist/remediate/phases/triage.d.ts.map +1 -1
  110. package/dist/remediate/phases/triage.js +46 -25
  111. package/dist/remediate/phases/triage.js.map +1 -1
  112. package/dist/remediate/phases/triageConformance.d.ts +14 -0
  113. package/dist/remediate/phases/triageConformance.d.ts.map +1 -0
  114. package/dist/remediate/phases/triageConformance.js +189 -0
  115. package/dist/remediate/phases/triageConformance.js.map +1 -0
  116. package/dist/remediate/state/decisionConsumption.d.ts +110 -0
  117. package/dist/remediate/state/decisionConsumption.d.ts.map +1 -0
  118. package/dist/remediate/state/decisionConsumption.js +122 -0
  119. package/dist/remediate/state/decisionConsumption.js.map +1 -0
  120. package/dist/remediate/state/store.d.ts +4 -0
  121. package/dist/remediate/state/store.d.ts.map +1 -1
  122. package/dist/remediate/state/store.js +16 -0
  123. package/dist/remediate/state/store.js.map +1 -1
  124. package/dist/remediate/steps/dispatch/contractConformanceReview.d.ts +9 -0
  125. package/dist/remediate/steps/dispatch/contractConformanceReview.d.ts.map +1 -1
  126. package/dist/remediate/steps/dispatch/contractConformanceReview.js +32 -14
  127. package/dist/remediate/steps/dispatch/contractConformanceReview.js.map +1 -1
  128. package/dist/remediate/steps/dispatch/hostHandoff.d.ts.map +1 -1
  129. package/dist/remediate/steps/dispatch/hostHandoff.js +4 -0
  130. package/dist/remediate/steps/dispatch/hostHandoff.js.map +1 -1
  131. package/dist/remediate/steps/gateCommands.d.ts.map +1 -1
  132. package/dist/remediate/steps/gateCommands.js +6 -52
  133. package/dist/remediate/steps/gateCommands.js.map +1 -1
  134. package/dist/remediate/steps/nextStep.d.ts +7 -0
  135. package/dist/remediate/steps/nextStep.d.ts.map +1 -1
  136. package/dist/remediate/steps/nextStep.js +56 -19
  137. package/dist/remediate/steps/nextStep.js.map +1 -1
  138. package/dist/shared/contentKey.d.ts +3 -2
  139. package/dist/shared/contentKey.d.ts.map +1 -1
  140. package/dist/shared/contentKey.js +3 -2
  141. package/dist/shared/contentKey.js.map +1 -1
  142. package/dist/shared/decompose/charterExtraction.d.ts +189 -1
  143. package/dist/shared/decompose/charterExtraction.d.ts.map +1 -1
  144. package/dist/shared/decompose/charterExtraction.js +17 -2
  145. package/dist/shared/decompose/charterExtraction.js.map +1 -1
  146. package/dist/shared/git.d.ts +30 -1
  147. package/dist/shared/git.d.ts.map +1 -1
  148. package/dist/shared/git.js +65 -6
  149. package/dist/shared/git.js.map +1 -1
  150. package/dist/shared/loopCorePaths.d.ts.map +1 -1
  151. package/dist/shared/loopCorePaths.js +2 -0
  152. package/dist/shared/loopCorePaths.js.map +1 -1
  153. package/dist/shared/prompts.d.ts +2 -0
  154. package/dist/shared/prompts.d.ts.map +1 -1
  155. package/dist/shared/prompts.js +8 -2
  156. package/dist/shared/prompts.js.map +1 -1
  157. package/dist/shared/submission/ingestReport.d.ts.map +1 -1
  158. package/dist/shared/submission/ingestReport.js +19 -1
  159. package/dist/shared/submission/ingestReport.js.map +1 -1
  160. package/dist/shared/types/charter.d.ts +9 -0
  161. package/dist/shared/types/charter.d.ts.map +1 -1
  162. package/dist/shared/types/charter.js +7 -0
  163. package/dist/shared/types/charter.js.map +1 -1
  164. package/docs/audit-pkg/contracts.md +6 -2
  165. package/docs/audit-pkg/operator-guide.md +13 -4
  166. package/package.json +2 -1
@@ -7,19 +7,20 @@ import { validateAuditArguments, NEXT_STEP_ARGUMENTS } from "./argumentContract.
7
7
  import { functionalPreflightStep } from "./functionalPreflight.js";
8
8
  import { SEMANTIC_REVIEW_DEMAND } from "../../shared/types/stepContract.js";
9
9
  import { INDEPENDENT_CONTEXT, SEPARATE_CONTEXT_OR_SELF } from "../../shared/prompts.js";
10
- // sites-pinned: tests/audit/next-step-helpers.test.ts, tests/audit/charter-emit-order.test.ts, tests/audit/executor-registry-sync.test.ts, tests/audit/pipeline-integration.test.ts
10
+ // sites-pinned: tests/audit/next-step-helpers.test.ts, tests/audit/charter-emit-order.test.ts, tests/audit/executor-registry-sync.test.ts, tests/audit/pipeline-integration.test.ts, tests/audit/review-file-map-context.test.ts, tests/audit/artifacts-dir-rollover.test.ts
11
11
  import { mkdir, readFile, writeFile } from "node:fs/promises";
12
12
  import { join, resolve } from "node:path";
13
- import { loadAnalyzerPolicy, loadSessionIntent, applyGuidanceFile, applyGuidanceText, runWithBlockedStepBackstop, writeBlockedStepContract, laneAssetsDir, hostScratchDir, renderFanoutExecutionLines, writeTextFile, writeJsonFile, toPromptPathToken, AUDIT_FINDINGS_FILENAME, } from "audit-tools/shared";
13
+ import { loadAnalyzerPolicy, loadSessionIntent, applyGuidanceFile, applyGuidanceText, runWithBlockedStepBackstop, writeBlockedStepContract, laneAssetsDir, hostScratchDir, renderFanoutExecutionLines, writeJsonFile, toPromptPathToken, AUDIT_FINDINGS_FILENAME, } from "audit-tools/shared";
14
14
  // The ONE shared table-driven step-emission scaffold. Imported by relative path
15
15
  // like every other cross-area shared module this area reaches for.
16
16
  import { createStepEmissionScaffold } from "../../shared/steps/stepEmissionScaffold.js";
17
17
  import { cleanupStaleArtifactsDir } from "./cleanup.js";
18
+ import { rollOverFinishedRun } from "../io/rollover.js";
18
19
  import { materializeFanoutLanes } from "./fanoutLanes.js";
19
- import { AUDIT_GATE_SUBMISSION_SCOPE, GATE_LANES, charterExtractionCoverageFilename, charterExtractionLane, charterExtractionPacketFilename, laneSubmissionPath, mergeLaneShortfalls, recordExpectedLanes, renderLaneShortfallLines, systemicChallengeLane, } from "./laneSubmissions.js";
20
- import { buildCharterPacketManifest, materializeCharterPacket, } from "../orchestrator/charterPackets.js";
20
+ import { AUDIT_GATE_SUBMISSION_SCOPE, GATE_LANES, charterExtractionLane, laneSubmissionPath, mergeLaneShortfalls, recordExpectedLanes, renderLaneShortfallLines, systemicChallengeLane, } from "./laneSubmissions.js";
21
+ import { carriedCharterLane } from "../orchestrator/charterPackets.js";
21
22
  import { buildEdgeReasoningPrompt, edgeReasoningContentHash, } from "../orchestrator/edgeReasoning.js";
22
- import { renderContractReviewPrompt, } from "../orchestrator/designReviewPrompt.js";
23
+ import { designReviewFileMapContext, renderContractReviewPrompt, } from "../orchestrator/designReviewPrompt.js";
23
24
  import { resolveIntentLensSelection } from "../orchestrator/lensSelection.js";
24
25
  import { prepareConceptualDispatch, resolveConceptualReviewSettings, } from "./conceptualDispatch.js";
25
26
  import { buildDesignReReviewSection } from "../orchestrator/designReviewSnapshot.js";
@@ -33,12 +34,13 @@ import { renderCharterComparisonPrompt } from "./charterComparisonPrompt.js";
33
34
  import { renderCharterFidelityPrompt } from "./charterFidelityPrompt.js";
34
35
  import { buildCharterFidelityPacket } from "../orchestrator/charterFidelityPacket.js";
35
36
  import { renderCharterClarificationPrompt } from "./charterClarificationPrompt.js";
36
- import { renderSecondOrderAdversaryPrompt } from "../systemic/secondOrderAdversaryPrompt.js";
37
+ import { adversaryFileMapContext, renderSecondOrderAdversaryPrompt, } from "../systemic/secondOrderAdversaryPrompt.js";
37
38
  import { aggregateMetricsDigest } from "../systemic/aggregateMetricsDigest.js";
38
39
  import { resolveCharterCeiling } from "../orchestrator/charterExtractionExecutor.js";
39
40
  import { ensureSupervisorDirs } from "../io/runArtifacts.js";
40
41
  import { persistConfigErrorHandoff, } from "./reviewRun.js";
41
42
  import { renderSemanticReviewStep, prepareSemanticReviewWorkload } from "./semanticReviewStep.js";
43
+ import { lookupRunSince } from "../io/runSnapshot.js";
42
44
  import { renderConfirmIntentPrompt } from "./confirmIntentStep.js";
43
45
  import { writeCurrentStep, STEP_CONTRACT_VERSION } from "./steps.js";
44
46
  import { nextStepCommand, renderAnalyzerConsentPrompt, renderAnalyzerInstallPrompt, renderEdgeReasoningDispatchPrompt, renderPresentReportPrompt, } from "./prompts.js";
@@ -46,7 +48,7 @@ import { getArtifactsDir, getFlag, hasFlag, getRootDir, getTimeoutMs, warnIfNotG
46
48
  // Import the helpers used locally, then re-export the full helper surface so
47
49
  // existing imports remain valid (an `export … from` clause creates no local
48
50
  // bindings, so the locally-used names must be imported explicitly).
49
- import { runDeterministicForNextStep, renderDesignReviewRejectionNotice, renderEdgeReasoningRejectionNotice, } from "./nextStepHelpers.js";
51
+ import { runDeterministicForNextStep, renderDesignReviewRejectionNotice, renderEdgeReasoningRejectionNotice, writeCharterLaneAssets, } from "./nextStepHelpers.js";
50
52
  export { tryConsumeSubmission, consumeArraySubmission, consumeObjectSubmission, renderDesignReviewRejectionNotice, renderEdgeReasoningRejectionNotice, buildTerminalStep, handleGraphEnrichmentBranch, handleDesignReviewBranch, handleSynthesisNarrativeBranch, executeAndRecord, checkFinalizationCycle, checkNoProgressBeforeDispatch, runDeterministicForNextStep, } from "./nextStepHelpers.js";
51
53
  /**
52
54
  * The two host-facing notices every design-review pass prepends to its prompt:
@@ -76,10 +78,11 @@ async function designReviewNotesSection(artifactsDir, bundle, pass) {
76
78
  * packet it prepares first. Settings therefore stay an INPUT here rather than
77
79
  * being resolved inside, which keeps each branch's write ordering unchanged.
78
80
  */
79
- async function prepareConceptualPass(artifactsDir, bundle, settings) {
81
+ async function prepareConceptualPass(artifactsDir, sourceRoot, bundle, settings) {
80
82
  const notesSection = await designReviewNotesSection(artifactsDir, bundle, "conceptual");
81
83
  return prepareConceptualDispatch({
82
84
  artifactsDir,
85
+ sourceRoot,
83
86
  bundle,
84
87
  settings,
85
88
  ...notesSection,
@@ -109,8 +112,13 @@ async function prepareContractDispatch(opts) {
109
112
  // it is told which lenses the operator selected, from the ONE resolution every
110
113
  // draw reads.
111
114
  const lenses = resolveIntentLensSelection(opts.bundle.intent_checkpoint?.lens_selection);
115
+ const reviewOptions = {
116
+ max_units: opts.maxUnits,
117
+ ...(lenses === undefined ? {} : { lenses }),
118
+ };
112
119
  const fanout = await materializeFanoutLanes({
113
120
  artifactsDir: opts.artifactsDir,
121
+ sourceRoot: opts.sourceRoot,
114
122
  runId: AUDIT_GATE_SUBMISSION_SCOPE,
115
123
  lanes: [
116
124
  {
@@ -120,14 +128,14 @@ async function prepareContractDispatch(opts) {
120
128
  ...SEMANTIC_REVIEW_DEMAND,
121
129
  label: "Contract review (adversarial)",
122
130
  promptFilename: "design-review-contract-prompt.md",
131
+ // The prompt carries the call-site map's summary; the complete map is
132
+ // this read-only, bound file.
133
+ generatedContext: [designReviewFileMapContext(opts.bundle, reviewOptions).contextFile],
123
134
  // No results-path section here: `materializeFanoutLanes` appends the one
124
135
  // canonical footer (bound path + the read-only-executor alternative) to
125
136
  // every lane prompt it writes.
126
137
  promptText: [
127
- renderContractReviewPrompt(opts.bundle, {
128
- max_units: opts.maxUnits,
129
- ...(lenses === undefined ? {} : { lenses }),
130
- }),
138
+ renderContractReviewPrompt(opts.bundle, reviewOptions),
131
139
  ...[notesSection.reReviewSection, notesSection.rejectionNotice]
132
140
  .filter((section) => Boolean(section))
133
141
  .flatMap((section) => ["", section]),
@@ -142,7 +150,7 @@ async function prepareContractDispatch(opts) {
142
150
  contract_prompt: promptPath,
143
151
  contract_results: resultsPath,
144
152
  },
145
- readPaths: [promptPath],
153
+ readPaths: [promptPath, ...fanout.lanes[0].generatedContextPaths],
146
154
  writePaths: [resultsPath],
147
155
  shortfall: fanout.shortfall,
148
156
  };
@@ -188,16 +196,20 @@ export async function cmdNextStep(argv) {
188
196
  }));
189
197
  }
190
198
  async function cmdNextStepBody(argv, root, artifactsDir) {
199
+ // Rollover (owner decision 2026-10-08, "keep the artifacts dir"): a run that
200
+ // ENDED — its terminal step presented a promoted report — becomes this run's
201
+ // starting point: its derived work stays for the staleness DAG to judge, and
202
+ // everything that belonged to it goes. A run whose report was never promoted
203
+ // has no run-ended marker; the fold's terminal step presents and promotes it,
204
+ // so it is not rolled over. Must run BEFORE the sweep, the mkdir and applyGuidanceFile
205
+ // below (fresh guidance must never be swept), and before the fold loads the
206
+ // bundle (a retained `complete` state would short-circuit every derivation).
207
+ await rollOverFinishedRun(artifactsDir);
191
208
  // Pre-run sweep (docs-14; one rule, 74c89b226ab9b9cd): clear a stale working
192
209
  // dir so the fresh run starts clean — one whose run is `not_started` (junk
193
- // from a run that never got going) or `complete` with its promotion already
194
- // finished (a leftover from an rm that failed). The rule is the same one the
195
- // `cleanup` verb applies; a `complete` dir with work left is a live
196
- // continuation the fold's terminal step presents and promotes, so it survives
197
- // entry. Must run BEFORE the mkdir below and BEFORE applyGuidanceFile (fresh
198
- // guidance must never be swept). Inside the backstop, a malformed
199
- // audit_state.json re-throw becomes a blocked-step contract rather than a raw
200
- // crash.
210
+ // from a run that never got going). The rule is the same one the `cleanup`
211
+ // verb applies. Inside the backstop, a malformed audit_state.json re-throw
212
+ // becomes a blocked-step contract rather than a raw crash.
201
213
  await cleanupStaleArtifactsDir(artifactsDir);
202
214
  // Inside the backstop (AGY review catch): a supervisor-dir IO failure must
203
215
  // yield a blocked step too. The backstop's own writer needs no pre-created
@@ -274,6 +286,7 @@ async function cmdNextStepBody(argv, root, artifactsDir) {
274
286
  advisoryNotice: result.advisoryNotice,
275
287
  argv,
276
288
  root,
289
+ sourceRoot: result.sourceRoot,
277
290
  artifactsDir,
278
291
  analyzerPolicy,
279
292
  result,
@@ -355,7 +368,7 @@ async function withReadyInspection(plan, ctx) {
355
368
  if (plan.via !== "current" || !ctx || !inspectionRun)
356
369
  return plan;
357
370
  const { handoff, resultPaths } = await prepareSemanticReviewWorkload({
358
- root: ctx.root, artifactsDir: ctx.artifactsDir,
371
+ root: ctx.root, sourceRoot: ctx.sourceRoot, artifactsDir: ctx.artifactsDir,
359
372
  bundle: ctx.result.bundle, activeReviewRun: inspectionRun,
360
373
  });
361
374
  return {
@@ -396,27 +409,23 @@ async function writeAuditStep(plan) {
396
409
  }
397
410
  }
398
411
  /**
399
- * Insert the fold's drained advisory lines just under a prompt's first line —
400
- * its `# <title>` heading — where session-scoped advisories belong: before the
401
- * instructions they qualify.
412
+ * The task above can end with "run next-step and follow only the new prompt",
413
+ * and the carry is stated on one step only, so the lead tells the reader to act
414
+ * on the report first.
415
+ */
416
+ const CARRIED_REPORT_LEAD = "Before you run next-step, read the report below on results from earlier work.";
417
+ /**
418
+ * Append the fold's drained advisory lines AFTER a prompt's own instructions.
402
419
  *
403
- * A prompt that does not start with a heading (or has no second line) is
404
- * returned unchanged rather than spliced somewhere meaningless. Every audit
405
- * plan's prompt opens with its heading — each row is a literal template
406
- * starting with `# ` — so this is the degenerate-input arm, not the norm.
420
+ * The lines report on OTHER work — the results of an earlier review step — so
421
+ * they do not qualify this step's instructions, and the step states its own
422
+ * task first (owner, 2026-10-06, after the 2026-10-05 dogfood run put hundreds
423
+ * of carried lines between a design-review heading and its instructions).
407
424
  */
408
425
  function withAdvisoryNoticeInPrompt(prompt, advisoryNotice) {
409
426
  if (advisoryNotice === undefined || advisoryNotice.length === 0)
410
427
  return prompt;
411
- const headingEnd = prompt.indexOf("\n");
412
- if (!prompt.startsWith("# ") || headingEnd < 0)
413
- return prompt;
414
- return [
415
- prompt.slice(0, headingEnd),
416
- "",
417
- ...advisoryNotice,
418
- prompt.slice(headingEnd + 1),
419
- ].join("\n");
428
+ return [prompt.trimEnd(), "", CARRIED_REPORT_LEAD, "", ...advisoryNotice].join("\n");
420
429
  }
421
430
  /**
422
431
  * Apply the fold's drained advisory lines to a step plan.
@@ -523,7 +532,7 @@ function renderIgnoredReviewNoticeLines(settings) {
523
532
  ? [settings.ignored_review_notice, ""]
524
533
  : [];
525
534
  }
526
- const emitDesignReviewParallel = emissionRow(async ({ root, artifactsDir }, result) => {
535
+ const emitDesignReviewParallel = emissionRow(async ({ root, sourceRoot, artifactsDir }, result) => {
527
536
  // Both passes are unsatisfied — dispatch the contract pass and the
528
537
  // conceptual pass simultaneously. The conceptual pass is shallow (one agent)
529
538
  // or deep (N independent perspective lanes + an independent judge),
@@ -532,10 +541,11 @@ const emitDesignReviewParallel = emissionRow(async ({ root, artifactsDir }, resu
532
541
  const conceptualSettings = resolveConceptualReviewSettings(result.bundle);
533
542
  const contract = await prepareContractDispatch({
534
543
  artifactsDir,
544
+ sourceRoot,
535
545
  bundle: result.bundle,
536
546
  maxUnits: conceptualSettings.max_units,
537
547
  });
538
- const conceptual = await prepareConceptualPass(artifactsDir, result.bundle, conceptualSettings);
548
+ const conceptual = await prepareConceptualPass(artifactsDir, sourceRoot, result.bundle, conceptualSettings);
539
549
  const shortfall = mergeLaneShortfalls([
540
550
  contract.shortfall,
541
551
  conceptual.shortfall,
@@ -574,7 +584,7 @@ const emitDesignReviewParallel = emissionRow(async ({ root, artifactsDir }, resu
574
584
  submissionShortfall: shortfall,
575
585
  });
576
586
  });
577
- const emitDesignReviewContract = emissionRow(async ({ root, artifactsDir }, result) => {
587
+ const emitDesignReviewContract = emissionRow(async ({ root, sourceRoot, artifactsDir }, result) => {
578
588
  // Only the contract pass remains — dispatched exactly as in the parallel
579
589
  // branch. This branch is reached whenever the conceptual pass is already
580
590
  // done, i.e. late in a run the host itself drove, which is precisely when
@@ -584,6 +594,7 @@ const emitDesignReviewContract = emissionRow(async ({ root, artifactsDir }, resu
584
594
  const conceptualSettings = resolveConceptualReviewSettings(result.bundle);
585
595
  const contract = await prepareContractDispatch({
586
596
  artifactsDir,
597
+ sourceRoot,
587
598
  bundle: result.bundle,
588
599
  maxUnits: conceptualSettings.max_units,
589
600
  });
@@ -616,13 +627,13 @@ const emitDesignReviewContract = emissionRow(async ({ root, artifactsDir }, resu
616
627
  submissionShortfall: contract.shortfall,
617
628
  });
618
629
  });
619
- const emitDesignReviewConceptual = emissionRow(async ({ root, artifactsDir }, result) => {
630
+ const emitDesignReviewConceptual = emissionRow(async ({ root, sourceRoot, artifactsDir }, result) => {
620
631
  // Only the conceptual pass remains — shallow (one agent) or deep (N
621
632
  // independent perspective lanes + an independent judge), resolved JIT
622
633
  // from the user-confirmed checkpoint / session config.
623
634
  const continueCommand = nextStepCommand(root, artifactsDir);
624
635
  const conceptualSettings = resolveConceptualReviewSettings(result.bundle);
625
- const conceptual = await prepareConceptualPass(artifactsDir, result.bundle, conceptualSettings);
636
+ const conceptual = await prepareConceptualPass(artifactsDir, sourceRoot, result.bundle, conceptualSettings);
626
637
  const prompt = [
627
638
  "# Design review — conceptual pass",
628
639
  "",
@@ -656,7 +667,7 @@ const emitDesignReviewConceptual = emissionRow(async ({ root, artifactsDir }, re
656
667
  submissionShortfall: conceptual.shortfall,
657
668
  });
658
669
  });
659
- const emitCharterExtraction = emissionRow(async ({ root, artifactsDir }, result) => {
670
+ const emitCharterExtraction = emissionRow(async ({ root, sourceRoot, artifactsDir }, result) => {
660
671
  // Phase C charter layer (conceptual, teleological): one blind, materialized
661
672
  // LANE per charter kind (design resolution 2 — independence is the shape of
662
673
  // the artifacts, not a merge instruction); the tool merges the per-kind
@@ -672,23 +683,28 @@ const emitCharterExtraction = emissionRow(async ({ root, artifactsDir }, result)
672
683
  // lane's evidence current.
673
684
  // Promise.all retains `kinds` order. The materializer derives the packet
674
685
  // read paths from that ordered lane list, never from IO completion order.
675
- const laneSpecs = await Promise.all(kinds.map(async (kind) => {
686
+ // A kind whose packet is unchanged since the previous register's lane was
687
+ // written is CARRIED by the merge (`carriedCharterLane`): no lane is asked
688
+ // to re-author it. Its packet and coverage are still written — the merge
689
+ // checks the carried lane's citations against them.
690
+ const laneResults = (await Promise.all(kinds.map(async (kind) => {
676
691
  const lane = charterExtractionLane(kind);
677
692
  const submissionPath = laneSubmissionPath(artifactsDir, lane);
678
- const packetPath = join(laneAssetsDir(artifactsDir), charterExtractionPacketFilename(kind));
679
- const packet = await materializeCharterPacket({
680
- root,
681
- bundle: result.bundle,
682
- kind,
683
- });
684
- await writeTextFile(packetPath, packet.markdown);
685
693
  // The manifest the lane reads, persisted for the ingest pass: coverage
686
694
  // folds into the register and the delivered line runs are what a
687
695
  // citation is checked against.
688
- await writeJsonFile(join(laneAssetsDir(artifactsDir), charterExtractionCoverageFilename(kind)), buildCharterPacketManifest(kind, packet.excerpts, packet.coverage));
696
+ const { packetPath, packet, digest } = await writeCharterLaneAssets({
697
+ sourceRoot,
698
+ artifactsDir,
699
+ bundle: result.bundle,
700
+ kind,
701
+ });
702
+ if (carriedCharterLane(result.bundle, kind, digest) !== undefined) {
703
+ return undefined;
704
+ }
689
705
  return {
690
706
  id: lane,
691
- semanticInputRevision: hashContent(packet.markdown),
707
+ semanticInputRevision: digest,
692
708
  fileCount: new Set(packet.excerpts.map(excerpt => excerpt.source_path)).size,
693
709
  ...SEMANTIC_REVIEW_DEMAND,
694
710
  contextPaths: [packetPath],
@@ -700,9 +716,12 @@ const emitCharterExtraction = emissionRow(async ({ root, artifactsDir }, result)
700
716
  packetPath,
701
717
  }),
702
718
  };
703
- }));
719
+ })));
720
+ const carriedKinds = kinds.filter((_, index) => laneResults[index] === undefined);
721
+ const laneSpecs = laneResults.filter((spec) => spec !== undefined);
704
722
  const fanout = await materializeFanoutLanes({
705
723
  artifactsDir,
724
+ sourceRoot,
706
725
  runId: AUDIT_GATE_SUBMISSION_SCOPE,
707
726
  lanes: laneSpecs,
708
727
  });
@@ -732,6 +751,12 @@ const emitCharterExtraction = emissionRow(async ({ root, artifactsDir }, result)
732
751
  })),
733
752
  }),
734
753
  "",
754
+ ...(carriedKinds.length > 0
755
+ ? [
756
+ `Carried from the previous extraction (their evidence packet is unchanged — no lane is asked to re-author them): ${carriedKinds.join(", ")}.`,
757
+ "",
758
+ ]
759
+ : []),
735
760
  ...(completedLanes.length > 0
736
761
  ? [
737
762
  `Already complete (results on disk — do NOT redo these lanes): ${completedLanes
@@ -756,7 +781,7 @@ const emitCharterExtraction = emissionRow(async ({ root, artifactsDir }, result)
756
781
  submissionShortfall: fanout.shortfall,
757
782
  });
758
783
  });
759
- const emitCharterComparison = emissionRow(async ({ root, artifactsDir }, result) => {
784
+ const emitCharterComparison = emissionRow(async ({ root, sourceRoot, artifactsDir }, result) => {
760
785
  // Steps 2–3 of the charter layer: the comparison reader (it authored none of
761
786
  // the three lane DAGs) confirms the tool's correspondence candidates and
762
787
  // records the typed differences; the tool assembles, routes and pre-checks at
@@ -778,6 +803,7 @@ const emitCharterComparison = emissionRow(async ({ root, artifactsDir }, result)
778
803
  const lanePrompt = renderCharterComparisonPrompt(result.bundle, { submissionPath, laneGraphPaths });
779
804
  const fanout = await materializeFanoutLanes({
780
805
  artifactsDir,
806
+ sourceRoot,
781
807
  runId: AUDIT_GATE_SUBMISSION_SCOPE,
782
808
  lanes: [
783
809
  {
@@ -829,7 +855,7 @@ const emitCharterComparison = emissionRow(async ({ root, artifactsDir }, result)
829
855
  submissionShortfall: fanout.shortfall,
830
856
  });
831
857
  });
832
- const emitCharterFidelity = emissionRow(async ({ root, artifactsDir }, result) => {
858
+ const emitCharterFidelity = emissionRow(async ({ root, sourceRoot, artifactsDir }, result) => {
833
859
  // Step 4 of the charter layer: a SEPARATE lane judges, per finding candidate,
834
860
  // whether the sources genuinely differ. Blind by input: the tool materializes
835
861
  // a packet holding the accounts, their citations and the source slices at
@@ -837,11 +863,12 @@ const emitCharterFidelity = emissionRow(async ({ root, artifactsDir }, result) =
837
863
  const continueCommand = nextStepCommand(root, artifactsDir);
838
864
  const submissionPath = laneSubmissionPath(artifactsDir, GATE_LANES.charter_fidelity);
839
865
  const packetPath = join(laneAssetsDir(artifactsDir), "charter-fidelity-packet.md");
840
- const fidelityPacket = await buildCharterFidelityPacket(result.bundle, root);
866
+ const fidelityPacket = await buildCharterFidelityPacket(result.bundle, sourceRoot);
841
867
  await writeFile(packetPath, fidelityPacket, "utf8");
842
868
  const lanePrompt = renderCharterFidelityPrompt({ submissionPath, packetPath });
843
869
  const fanout = await materializeFanoutLanes({
844
870
  artifactsDir,
871
+ sourceRoot,
845
872
  runId: AUDIT_GATE_SUBMISSION_SCOPE,
846
873
  lanes: [
847
874
  {
@@ -926,8 +953,8 @@ const emitCharterClarification = emissionRow(async ({ root, artifactsDir }, resu
926
953
  submissionShortfall: shortfall,
927
954
  });
928
955
  });
929
- // sites-pinned: tests/audit/systemic-round-identity.test.ts
930
- const emitSystemicChallenge = emissionRow(async ({ root, artifactsDir }, result) => {
956
+ // sites-pinned: tests/audit/systemic-round-identity.test.ts, tests/audit/review-file-map-context.test.ts
957
+ const emitSystemicChallenge = emissionRow(async ({ root, sourceRoot, artifactsDir }, result) => {
931
958
  // Phase E second-order adversary (loop-until-dry): the tool has opened the loop
932
959
  // and computed the language-neutral aggregate-metrics digest. The host dispatches
933
960
  // a SEPARATE adversary agent whose mandate is optimization/better-way; it writes
@@ -956,6 +983,7 @@ const emitSystemicChallenge = emissionRow(async ({ root, artifactsDir }, result)
956
983
  // FILE — the adversary is a SEPARATE agent by lane class, on every host.
957
984
  const fanout = await materializeFanoutLanes({
958
985
  artifactsDir,
986
+ sourceRoot,
959
987
  runId: AUDIT_GATE_SUBMISSION_SCOPE,
960
988
  roundId: lane,
961
989
  lanes: [
@@ -965,6 +993,7 @@ const emitSystemicChallenge = emissionRow(async ({ root, artifactsDir }, result)
965
993
  fileCount: result.bundle.repo_manifest?.files.length ?? 0,
966
994
  ...SEMANTIC_REVIEW_DEMAND,
967
995
  contextPaths: evidencePaths,
996
+ generatedContext: [adversaryFileMapContext(result.bundle).contextFile],
968
997
  label: "Second-order adversary (improvement-seeking challenge)",
969
998
  promptFilename: "systemic-challenge-prompt.md",
970
999
  promptText: adversaryPrompt,
@@ -1015,10 +1044,13 @@ const emitSystemicChallenge = emissionRow(async ({ root, artifactsDir }, result)
1015
1044
  submissionShortfall: fanout.shortfall,
1016
1045
  });
1017
1046
  });
1018
- const emitConfirmIntent = emissionRow(async ({ root, artifactsDir, argv }, result) => {
1047
+ const emitConfirmIntent = emissionRow(async ({ root, sourceRoot, artifactsDir, argv }, result) => {
1019
1048
  const intentCheckpointPath = join(artifactsDir, "intent_checkpoint.json");
1020
1049
  const continueCommand = nextStepCommand(root, artifactsDir);
1021
- const preDigest = await computeScopePreDigest(result.bundle, root, getFlag(argv, "--since"));
1050
+ // The `--since` commit the fold resolved and recorded for this run, so the
1051
+ // pre-digest names the same delta the planning draw uses.
1052
+ const sinceFlag = getFlag(argv, "--since");
1053
+ const preDigest = await computeScopePreDigest(result.bundle, sourceRoot, sinceFlag === undefined ? undefined : await lookupRunSince(artifactsDir, sinceFlag));
1022
1054
  let bootstrappedGuidance;
1023
1055
  if (!result.bundle.intent_checkpoint) {
1024
1056
  try {
@@ -1103,7 +1135,7 @@ const emitAnalyzerInstall = emissionRow(async ({ root, artifactsDir, analyzerPol
1103
1135
  submissionShortfall: shortfall,
1104
1136
  });
1105
1137
  });
1106
- const emitEdgeReasoning = emissionRow(async ({ root, artifactsDir }, result) => {
1138
+ const emitEdgeReasoning = emissionRow(async ({ root, sourceRoot, artifactsDir }, result) => {
1107
1139
  const edgeReasoningResultsPath = laneSubmissionPath(artifactsDir, GATE_LANES.edge_reasoning);
1108
1140
  const continueCommand = nextStepCommand(root, artifactsDir);
1109
1141
  const basePrompt = buildEdgeReasoningPrompt(result.candidates);
@@ -1130,6 +1162,7 @@ const emitEdgeReasoning = emissionRow(async ({ root, artifactsDir }, result) =>
1130
1162
  // step so the K-of-N/result-exists semantics stay single-sourced.
1131
1163
  const fanout = await materializeFanoutLanes({
1132
1164
  artifactsDir,
1165
+ sourceRoot,
1133
1166
  runId: AUDIT_GATE_SUBMISSION_SCOPE,
1134
1167
  lanes: [
1135
1168
  {
@@ -1260,7 +1293,7 @@ const emitIntentEquivalence = emissionRow(async ({ root, artifactsDir }, result)
1260
1293
  submissionShortfall: shortfall,
1261
1294
  });
1262
1295
  });
1263
- const emitCriticalFlowFallback = emissionRow(async ({ root, artifactsDir }, result) => {
1296
+ const emitCriticalFlowFallback = emissionRow(async ({ root, sourceRoot, artifactsDir }, result) => {
1264
1297
  const fallbackResultsPath = laneSubmissionPath(artifactsDir, GATE_LANES.critical_flow_fallback);
1265
1298
  const continueCommand = nextStepCommand(root, artifactsDir);
1266
1299
  const manifestPath = toPromptPathToken(join(artifactsDir, "critical_flows.json"));
@@ -1273,6 +1306,7 @@ const emitCriticalFlowFallback = emissionRow(async ({ root, artifactsDir }, resu
1273
1306
  const lanePrompt = basePrompt;
1274
1307
  const fanout = await materializeFanoutLanes({
1275
1308
  artifactsDir,
1309
+ sourceRoot,
1276
1310
  runId: AUDIT_GATE_SUBMISSION_SCOPE,
1277
1311
  lanes: [
1278
1312
  {
@@ -1320,7 +1354,7 @@ const emitCriticalFlowFallback = emissionRow(async ({ root, artifactsDir }, resu
1320
1354
  submissionShortfall: fanout.shortfall,
1321
1355
  });
1322
1356
  });
1323
- const emitSynthesisNarrative = emissionRow(async ({ root, artifactsDir }, result) => {
1357
+ const emitSynthesisNarrative = emissionRow(async ({ root, sourceRoot, artifactsDir }, result) => {
1324
1358
  const narrativeResultsPath = laneSubmissionPath(artifactsDir, GATE_LANES.synthesis_narrative);
1325
1359
  const continueCommand = nextStepCommand(root, artifactsDir);
1326
1360
  // The complete findings report, named in the prompt AND granted below. The
@@ -1339,6 +1373,7 @@ const emitSynthesisNarrative = emissionRow(async ({ root, artifactsDir }, result
1339
1373
  const lanePrompt = basePrompt;
1340
1374
  const fanout = await materializeFanoutLanes({
1341
1375
  artifactsDir,
1376
+ sourceRoot,
1342
1377
  runId: AUDIT_GATE_SUBMISSION_SCOPE,
1343
1378
  lanes: [
1344
1379
  {
@@ -1430,6 +1465,7 @@ const NEXT_STEP_EMISSION = createStepEmissionScaffold({
1430
1465
  const result = ctx.result;
1431
1466
  return semanticReviewPlan({
1432
1467
  root: ctx.root,
1468
+ sourceRoot: ctx.sourceRoot,
1433
1469
  artifactsDir: ctx.artifactsDir,
1434
1470
  activeReviewRun: result.activeReviewRun,
1435
1471
  bundle: result.bundle,
@@ -1441,7 +1477,9 @@ const NEXT_STEP_EMISSION = createStepEmissionScaffold({
1441
1477
  },
1442
1478
  // The drained advisory lines decorate the PLAN inside the one writer, so
1443
1479
  // they reach every row (and the fallback) without a second splice per row.
1444
- write: async (plan, ctx) => writeAuditStep(await withReadyInspection(withAdvisoryNotice(plan, ctx?.advisoryNotice), ctx)),
1480
+ // They decorate LAST: the ready-inspection section is part of this step's
1481
+ // own task, and the carried report follows the whole task.
1482
+ write: async (plan, ctx) => writeAuditStep(withAdvisoryNotice(await withReadyInspection(plan, ctx), ctx?.advisoryNotice)),
1445
1483
  // The tool's only externally-observable per-invocation contract.
1446
1484
  log: (step) => {
1447
1485
  console.log(JSON.stringify(step, null, 2));