audit-tools 0.55.6 → 0.55.8

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 (153) hide show
  1. package/dist/audit/cli/lineIndex.d.ts.map +1 -1
  2. package/dist/audit/cli/lineIndex.js +19 -41
  3. package/dist/audit/cli/lineIndex.js.map +1 -1
  4. package/dist/audit/cli/nextStepCommand.d.ts.map +1 -1
  5. package/dist/audit/cli/nextStepCommand.js +5 -2
  6. package/dist/audit/cli/nextStepCommand.js.map +1 -1
  7. package/dist/audit/cli/nextStepHelpers.d.ts +6 -6
  8. package/dist/audit/cli/nextStepHelpers.d.ts.map +1 -1
  9. package/dist/audit/cli/nextStepHelpers.js +52 -129
  10. package/dist/audit/cli/nextStepHelpers.js.map +1 -1
  11. package/dist/audit/extractors/disposition.d.ts.map +1 -1
  12. package/dist/audit/extractors/disposition.js +14 -38
  13. package/dist/audit/extractors/disposition.js.map +1 -1
  14. package/dist/audit/extractors/graphManifestEdges/go.d.ts.map +1 -1
  15. package/dist/audit/extractors/graphManifestEdges/go.js +4 -10
  16. package/dist/audit/extractors/graphManifestEdges/go.js.map +1 -1
  17. package/dist/audit/extractors/graphManifestEdges/maven.d.ts.map +1 -1
  18. package/dist/audit/extractors/graphManifestEdges/maven.js +4 -10
  19. package/dist/audit/extractors/graphManifestEdges/maven.js.map +1 -1
  20. package/dist/audit/extractors/graphManifestEdges/packageJson.d.ts.map +1 -1
  21. package/dist/audit/extractors/graphManifestEdges/packageJson.js +4 -12
  22. package/dist/audit/extractors/graphManifestEdges/packageJson.js.map +1 -1
  23. package/dist/audit/extractors/graphManifestEdges/typescript.d.ts.map +1 -1
  24. package/dist/audit/extractors/graphManifestEdges/typescript.js +4 -10
  25. package/dist/audit/extractors/graphManifestEdges/typescript.js.map +1 -1
  26. package/dist/audit/extractors/graphPathUtils.d.ts +2 -0
  27. package/dist/audit/extractors/graphPathUtils.d.ts.map +1 -1
  28. package/dist/audit/extractors/graphPathUtils.js +14 -0
  29. package/dist/audit/extractors/graphPathUtils.js.map +1 -1
  30. package/dist/audit/extractors/readFileText.d.ts.map +1 -1
  31. package/dist/audit/extractors/readFileText.js +34 -5
  32. package/dist/audit/extractors/readFileText.js.map +1 -1
  33. package/dist/audit/orchestrator/acquisitionExecutor.d.ts +5 -2
  34. package/dist/audit/orchestrator/acquisitionExecutor.d.ts.map +1 -1
  35. package/dist/audit/orchestrator/acquisitionExecutor.js +28 -22
  36. package/dist/audit/orchestrator/acquisitionExecutor.js.map +1 -1
  37. package/dist/audit/orchestrator/reviewPacketGraphContext.d.ts +17 -0
  38. package/dist/audit/orchestrator/reviewPacketGraphContext.d.ts.map +1 -1
  39. package/dist/audit/orchestrator/reviewPacketGraphContext.js +51 -14
  40. package/dist/audit/orchestrator/reviewPacketGraphContext.js.map +1 -1
  41. package/dist/audit/orchestrator/reviewPacketSizing.d.ts +4 -4
  42. package/dist/audit/orchestrator/reviewPacketSizing.d.ts.map +1 -1
  43. package/dist/audit/orchestrator/reviewPacketSizing.js +5 -5
  44. package/dist/audit/orchestrator/reviewPacketSizing.js.map +1 -1
  45. package/dist/audit/orchestrator/reviewPackets.d.ts +2 -1
  46. package/dist/audit/orchestrator/reviewPackets.d.ts.map +1 -1
  47. package/dist/audit/orchestrator/reviewPackets.js +19 -11
  48. package/dist/audit/orchestrator/reviewPackets.js.map +1 -1
  49. package/dist/audit/orchestrator/runtimeCommand.d.ts +9 -2
  50. package/dist/audit/orchestrator/runtimeCommand.d.ts.map +1 -1
  51. package/dist/audit/orchestrator/runtimeCommand.js +14 -22
  52. package/dist/audit/orchestrator/runtimeCommand.js.map +1 -1
  53. package/dist/audit/orchestrator/scope.d.ts.map +1 -1
  54. package/dist/audit/orchestrator/scope.js +7 -2
  55. package/dist/audit/orchestrator/scope.js.map +1 -1
  56. package/dist/audit/orchestrator/scopeIndexBaseline.d.ts.map +1 -1
  57. package/dist/audit/orchestrator/scopeIndexBaseline.js +7 -29
  58. package/dist/audit/orchestrator/scopeIndexBaseline.js.map +1 -1
  59. package/dist/audit/orchestrator/selectiveDeepening/conflict.d.ts +6 -2
  60. package/dist/audit/orchestrator/selectiveDeepening/conflict.d.ts.map +1 -1
  61. package/dist/audit/orchestrator/selectiveDeepening/conflict.js +45 -4
  62. package/dist/audit/orchestrator/selectiveDeepening/conflict.js.map +1 -1
  63. package/dist/audit/orchestrator/selectiveDeepening/index.d.ts.map +1 -1
  64. package/dist/audit/orchestrator/selectiveDeepening/index.js +4 -4
  65. package/dist/audit/orchestrator/selectiveDeepening/index.js.map +1 -1
  66. package/dist/remediate/phases/close.d.ts.map +1 -1
  67. package/dist/remediate/phases/close.js +10 -7
  68. package/dist/remediate/phases/close.js.map +1 -1
  69. package/dist/remediate/phases/closeAcceptance.d.ts.map +1 -1
  70. package/dist/remediate/phases/closeAcceptance.js +2 -0
  71. package/dist/remediate/phases/closeAcceptance.js.map +1 -1
  72. package/dist/remediate/phases/closeVerifyAnalyzerLeads.d.ts +2 -1
  73. package/dist/remediate/phases/closeVerifyAnalyzerLeads.d.ts.map +1 -1
  74. package/dist/remediate/phases/closeVerifyAnalyzerLeads.js +10 -9
  75. package/dist/remediate/phases/closeVerifyAnalyzerLeads.js.map +1 -1
  76. package/dist/remediate/state/dirtyBaseline.d.ts +10 -0
  77. package/dist/remediate/state/dirtyBaseline.d.ts.map +1 -0
  78. package/dist/remediate/state/dirtyBaseline.js +18 -0
  79. package/dist/remediate/state/dirtyBaseline.js.map +1 -0
  80. package/dist/remediate/state/store.d.ts +4 -4
  81. package/dist/remediate/state/store.d.ts.map +1 -1
  82. package/dist/remediate/state/store.js +8 -0
  83. package/dist/remediate/state/store.js.map +1 -1
  84. package/dist/remediate/steps/dispatch/hostCorroboration.d.ts.map +1 -1
  85. package/dist/remediate/steps/dispatch/hostCorroboration.js +34 -82
  86. package/dist/remediate/steps/dispatch/hostCorroboration.js.map +1 -1
  87. package/dist/remediate/steps/dispatch/hostHandoff.d.ts.map +1 -1
  88. package/dist/remediate/steps/dispatch/hostHandoff.js +6 -1
  89. package/dist/remediate/steps/dispatch/hostHandoff.js.map +1 -1
  90. package/dist/remediate/steps/finalGate.d.ts.map +1 -1
  91. package/dist/remediate/steps/finalGate.js +11 -5
  92. package/dist/remediate/steps/finalGate.js.map +1 -1
  93. package/dist/remediate/steps/gateCommands.d.ts +1 -0
  94. package/dist/remediate/steps/gateCommands.d.ts.map +1 -1
  95. package/dist/remediate/steps/gateCommands.js +7 -11
  96. package/dist/remediate/steps/gateCommands.js.map +1 -1
  97. package/dist/remediate/steps/nextStep.d.ts +0 -10
  98. package/dist/remediate/steps/nextStep.d.ts.map +1 -1
  99. package/dist/remediate/steps/nextStep.js +55 -59
  100. package/dist/remediate/steps/nextStep.js.map +1 -1
  101. package/dist/shared/analyzers/acquisitionEngine.d.ts +12 -5
  102. package/dist/shared/analyzers/acquisitionEngine.d.ts.map +1 -1
  103. package/dist/shared/analyzers/acquisitionEngine.js +86 -38
  104. package/dist/shared/analyzers/acquisitionEngine.js.map +1 -1
  105. package/dist/shared/analyzers/binaryAcquisition.d.ts +17 -41
  106. package/dist/shared/analyzers/binaryAcquisition.d.ts.map +1 -1
  107. package/dist/shared/analyzers/binaryAcquisition.js +260 -227
  108. package/dist/shared/analyzers/binaryAcquisition.js.map +1 -1
  109. package/dist/shared/analyzers/binaryFetcher.d.ts +4 -0
  110. package/dist/shared/analyzers/binaryFetcher.d.ts.map +1 -0
  111. package/dist/shared/analyzers/binaryFetcher.js +79 -0
  112. package/dist/shared/analyzers/binaryFetcher.js.map +1 -0
  113. package/dist/shared/analyzers/binaryVersions.d.ts +5 -0
  114. package/dist/shared/analyzers/binaryVersions.d.ts.map +1 -0
  115. package/dist/shared/analyzers/binaryVersions.js +31 -0
  116. package/dist/shared/analyzers/binaryVersions.js.map +1 -0
  117. package/dist/shared/analyzers/candidates.d.ts +3 -3
  118. package/dist/shared/analyzers/candidates.d.ts.map +1 -1
  119. package/dist/shared/analyzers/candidates.js +35 -12
  120. package/dist/shared/analyzers/candidates.js.map +1 -1
  121. package/dist/shared/git.d.ts +38 -3
  122. package/dist/shared/git.d.ts.map +1 -1
  123. package/dist/shared/git.js +169 -55
  124. package/dist/shared/git.js.map +1 -1
  125. package/dist/shared/gitTrackedPaths.d.ts +39 -0
  126. package/dist/shared/gitTrackedPaths.d.ts.map +1 -0
  127. package/dist/shared/gitTrackedPaths.js +29 -0
  128. package/dist/shared/gitTrackedPaths.js.map +1 -0
  129. package/dist/shared/index.d.ts +4 -2
  130. package/dist/shared/index.d.ts.map +1 -1
  131. package/dist/shared/index.js +5 -2
  132. package/dist/shared/index.js.map +1 -1
  133. package/dist/shared/io/sourcePath.d.ts +8 -0
  134. package/dist/shared/io/sourcePath.d.ts.map +1 -0
  135. package/dist/shared/io/sourcePath.js +38 -0
  136. package/dist/shared/io/sourcePath.js.map +1 -0
  137. package/dist/shared/tooling/exec.d.ts +1 -0
  138. package/dist/shared/tooling/exec.d.ts.map +1 -1
  139. package/dist/shared/tooling/exec.js +20 -4
  140. package/dist/shared/tooling/exec.js.map +1 -1
  141. package/dist/shared/tooling/resolveExecutable.d.ts +10 -0
  142. package/dist/shared/tooling/resolveExecutable.d.ts.map +1 -0
  143. package/dist/shared/tooling/resolveExecutable.js +46 -0
  144. package/dist/shared/tooling/resolveExecutable.js.map +1 -0
  145. package/dist/shared/validation/citationGrounding.d.ts +1 -1
  146. package/dist/shared/validation/citationGrounding.d.ts.map +1 -1
  147. package/dist/shared/validation/citationGrounding.js +24 -11
  148. package/dist/shared/validation/citationGrounding.js.map +1 -1
  149. package/dist/shared/validation/findingGrounding.d.ts +1 -1
  150. package/dist/shared/validation/findingGrounding.d.ts.map +1 -1
  151. package/dist/shared/validation/findingGrounding.js +11 -23
  152. package/dist/shared/validation/findingGrounding.js.map +1 -1
  153. package/package.json +2 -2
@@ -1,3 +1,4 @@
1
+ import { admitRemediationDirtyBaseline, RemediationDirtyBaselineError } from "../state/dirtyBaseline.js";
1
2
  import { readDecisionSnapshot, decisionContextDigest } from "../state/decisionConsumption.js";
2
3
  import { RemediationPlanAuthorityError } from "../contractPipeline/runtimePlanAuthority.js";
3
4
  import { reopenStaleTriageSuccesses } from "../phases/triageConformance.js";
@@ -441,13 +442,14 @@ async function saveStateForPlan(artifactsDir, existing, plan, planCoverage) {
441
442
  return state;
442
443
  }
443
444
  async function forceReplanFromExistingIntake(root, artifactsDir, previous, runLogger) {
445
+ admitRemediationDirtyBaseline(previous);
444
446
  const step = await buildNextContractPipelineStep({ root, artifactsDir, runId: requireStateRunId(previous), forceRevision: false });
445
447
  if (step)
446
448
  return { kind: "planning_step", step };
447
449
  const approved = await readApprovedExecutionPlan(artifactsDir);
448
450
  if (!approved)
449
451
  return { kind: "blocked", reason: "Revise and independently approve the current executable plan before replanning. Accepted execution history is preserved." };
450
- const activated = await activateApprovedPlan(root, artifactsDir, previous, approved, runLogger);
452
+ const activated = await activateApprovedPlan(root, artifactsDir, previous, approved, runLogger, "existing_run");
451
453
  if (activated.kind === "blocked")
452
454
  return activated;
453
455
  // Activation already carries unchanged history and applies CURRENT owner
@@ -708,7 +710,11 @@ async function emitPlanRevisionBlockedStep(root, artifactsDir, blocked) {
708
710
  prompt: `# Executable plan requires attention\n\n${blocked.reason}\nThe current plan and accepted execution history are preserved. Revise the plan through its tool-issued submission and obtain fresh review before continuing.`,
709
711
  allowedCommands: [loaderCommand("next-step")], stopCondition: "Resolve the named plan/review issue before implementation.", artifactPaths: { execution_plan: executionPlanPaths(artifactsDir).canonical } });
710
712
  }
711
- async function activateApprovedPlan(root, artifactsDir, existing, _input, _runLogger) {
713
+ async function activateApprovedPlan(root, artifactsDir, existing, _input, _runLogger, origin) {
714
+ if (origin === "existing_run")
715
+ admitRemediationDirtyBaseline(existing);
716
+ else if ("run_start_dirty" in existing || "run_start_dirty_encoding" in existing)
717
+ throw new RemediationDirtyBaselineError();
712
718
  const approved = await readApprovedExecutionPlan(artifactsDir);
713
719
  if (!approved)
714
720
  return { kind: "blocked", reason: "No current independently approved executable plan exists. Re-run planning; unreviewed projections cannot dispatch." };
@@ -728,8 +734,9 @@ async function activateApprovedPlan(root, artifactsDir, existing, _input, _runLo
728
734
  ...(facts.commands.e2e ? { e2e_command: renderPromptCommand(facts.commands.e2e), e2e_command_source: "project_facts" } : {}),
729
735
  };
730
736
  plan = await applyCheckpointIntentOrdering(artifactsDir, plan);
731
- if (!existing.run_start_dirty)
732
- existing = { ...existing, run_start_dirty: [...await stagedAndUntracked(root)].sort() };
737
+ if (origin === "new_pre_edit_run") {
738
+ existing = { ...existing, run_start_dirty: [...await stagedAndUntracked(root)], run_start_dirty_encoding: "git-z/v1" };
739
+ }
733
740
  const filter = await readOptionalJsonFile(reviewFilterDispositionsPath(artifactsDir));
734
741
  // Through the schema-checked reader: with zero survivors the review gate never
735
742
  // rewrites a stale-schema record, so a raw read let its declines into the
@@ -1004,11 +1011,11 @@ sourceAuditRead) {
1004
1011
  `path=${findingsPath}`,
1005
1012
  });
1006
1013
  }
1007
- async function handleReadyIntakeContractPipeline(root, artifactsDir, options, runLogger) {
1014
+ async function handleReadyIntakeContractPipeline(root, artifactsDir, options, runLogger, origin) {
1008
1015
  // Resume the tool-owned plan without reconstructing completed intake.
1009
1016
  const earlyExtractedPlan = await readApprovedExecutionPlan(artifactsDir);
1010
1017
  if (earlyExtractedPlan && !existsSync(executionPlanPaths(artifactsDir).submission)) {
1011
- const outcome = await activateApprovedPlan(root, artifactsDir, { status: "pending" }, earlyExtractedPlan, runLogger);
1018
+ const outcome = await activateApprovedPlan(root, artifactsDir, { status: "pending" }, earlyExtractedPlan, runLogger, origin);
1012
1019
  return outcome.kind === "blocked"
1013
1020
  ? emitPlanRevisionBlockedStep(root, artifactsDir, outcome)
1014
1021
  : outcome.state;
@@ -1022,7 +1029,7 @@ async function handleReadyIntakeContractPipeline(root, artifactsDir, options, ru
1022
1029
  const approved = await readApprovedExecutionPlan(artifactsDir);
1023
1030
  if (!approved)
1024
1031
  return null;
1025
- const outcome = await activateApprovedPlan(root, artifactsDir, { status: "pending" }, approved, runLogger);
1032
+ const outcome = await activateApprovedPlan(root, artifactsDir, { status: "pending" }, approved, runLogger, origin);
1026
1033
  return outcome.kind === "blocked"
1027
1034
  ? emitPlanRevisionBlockedStep(root, artifactsDir, outcome)
1028
1035
  : outcome.state;
@@ -1177,16 +1184,16 @@ async function handleReadyIntakeContractPipeline(root, artifactsDir, options, ru
1177
1184
  if (!extractedPlan) {
1178
1185
  return null;
1179
1186
  }
1180
- const outcome = await activateApprovedPlan(root, artifactsDir, { status: "pending" }, extractedPlan, runLogger);
1187
+ const outcome = await activateApprovedPlan(root, artifactsDir, { status: "pending" }, extractedPlan, runLogger, origin);
1181
1188
  return outcome.kind === "blocked"
1182
1189
  ? emitPlanRevisionBlockedStep(root, artifactsDir, outcome)
1183
1190
  : outcome.state;
1184
1191
  }
1185
- async function handlePendingIntake(root, artifactsDir, options, runLogger) {
1192
+ async function handlePendingIntake(root, artifactsDir, options, runLogger, origin) {
1186
1193
  // Existing source ownership survives pending review and approval invalidation.
1187
1194
  // The earlier confirm_intent obligation still guards this continuation.
1188
1195
  if (await readPlanSource(artifactsDir)) {
1189
- return handleReadyIntakeContractPipeline(root, artifactsDir, options, runLogger);
1196
+ return handleReadyIntakeContractPipeline(root, artifactsDir, options, runLogger, origin);
1190
1197
  }
1191
1198
  const inputResolution = resolveInputPaths(root, options.input);
1192
1199
  const intakeResult = await resolveIntakeStep({
@@ -1205,7 +1212,7 @@ async function handlePendingIntake(root, artifactsDir, options, runLogger) {
1205
1212
  return intakeResult.step;
1206
1213
  }
1207
1214
  // Intake is complete — route both paths through the contract pipeline.
1208
- return handleReadyIntakeContractPipeline(root, artifactsDir, options, runLogger);
1215
+ return handleReadyIntakeContractPipeline(root, artifactsDir, options, runLogger, origin);
1209
1216
  }
1210
1217
  async function handleNoState(root, artifactsDir) {
1211
1218
  const paths = intakePaths(artifactsDir);
@@ -1614,6 +1621,7 @@ async function handleImplementing(root, artifactsDir, state, runLogger, store) {
1614
1621
  */
1615
1622
  async function emitFinalGateRedStep(ctx) {
1616
1623
  const { root, artifactsDir, state, scope, gate, runLogger } = ctx;
1624
+ admitRemediationDirtyBaseline(state);
1617
1625
  const failed = gate.results.find((r) => !r.passed);
1618
1626
  const recordPath = ctx.recordedPath ?? await writeFinalGateRedRecord(artifactsDir, scope, failed, {
1619
1627
  root,
@@ -1736,6 +1744,7 @@ function explicitFinalGateTestCommand(state) {
1736
1744
  }
1737
1745
  async function runPhaseBoundaryGate(ctx) {
1738
1746
  const { root, artifactsDir, state, options, runLogger } = ctx;
1747
+ admitRemediationDirtyBaseline(state);
1739
1748
  // Whether a gate is DUE is decided BEFORE whether it is suppressed. The old
1740
1749
  // order asked the suppression first and returned, so a disabled run could not
1741
1750
  // tell "no gate was due this pass" from "a gate was due and skipped" — and the
@@ -2404,19 +2413,7 @@ function requireState(state) {
2404
2413
  }
2405
2414
  return state;
2406
2415
  }
2407
- /**
2408
- * Priority order for the pre-intake obligations — mirrors the original cascade's
2409
- * top-down guard order exactly so selection cannot drift.
2410
- */
2411
- export const PRE_INTAKE_PRIORITY = [
2412
- "input_conflict",
2413
- "confirm_resume",
2414
- "confirm_intent",
2415
- "interpret_intent",
2416
- "complete_redelivery",
2417
- "complete",
2418
- "pending_intake",
2419
- ];
2416
+ // sites-pinned: tests/remediate/obligation-priority-coverage.test.ts
2420
2417
  /**
2421
2418
  * The linear pre-intake gates as declarative obligations (A3 slice 1). Built per
2422
2419
  * call so each `derive` can close over `ctx` paths + the pre-read `snapshot` and
@@ -2668,7 +2665,7 @@ Then run:
2668
2665
  id: "pending_intake",
2669
2666
  derive: (state) => (state == null ? "missing" : "satisfied"),
2670
2667
  execute: async (_state, c) => {
2671
- const outcome = await handlePendingIntake(c.root, c.artifactsDir, c.options, c.runLogger);
2668
+ const outcome = await handlePendingIntake(c.root, c.artifactsDir, c.options, c.runLogger, "new_pre_edit_run");
2672
2669
  if (outcome && "step_kind" in outcome) {
2673
2670
  return { kind: "emit", step: outcome };
2674
2671
  }
@@ -2680,23 +2677,6 @@ Then run:
2680
2677
  },
2681
2678
  ];
2682
2679
  }
2683
- /**
2684
- * Priority order for the main (post-intake) obligations — mirrors the original
2685
- * cascade tail's guard order exactly so selection cannot drift.
2686
- */
2687
- export const MAIN_PRIORITY = [
2688
- "operator_plan_only",
2689
- "waiting_for_clarification",
2690
- "waiting_for_triage",
2691
- "planning_documentable",
2692
- "deferred_clarification",
2693
- "implementing",
2694
- "triage",
2695
- "planning_zero",
2696
- "all_terminal",
2697
- "closing",
2698
- "unhandled",
2699
- ];
2700
2680
  /**
2701
2681
  * The post-intake cascade tail as declarative obligations (A3 slice 2). Runs on a
2702
2682
  * non-null state (pre-intake resolved it). Every phase handler returns a
@@ -2947,6 +2927,21 @@ async function advanceUnderPhaseLock(deps) {
2947
2927
  // Loaded FRESH under the mutex: a peer may have advanced and persisted state
2948
2928
  // between the entry read and this process winning the lock.
2949
2929
  let state = await store.loadState();
2930
+ const reportOnlyRequest = state?.status === "complete" &&
2931
+ options.input === undefined && options.severity === undefined && options.findingIds === undefined &&
2932
+ options.guidanceFile === undefined && options.guidanceText === undefined && options.verificationCommand === undefined &&
2933
+ options.guidanceFileSupplied !== true && options.forceReplan !== true && options.planOnly !== true && options.finalizeClosing !== true;
2934
+ // Only a potential complete/report-only request may inspect plan freshness
2935
+ // before baseline admission. No authority write can precede this fence.
2936
+ if (state && !reportOnlyRequest)
2937
+ admitRemediationDirtyBaseline(state);
2938
+ const currentCanonical = state?.plan ? await readCanonicalPlan(artifactsDir) : undefined;
2939
+ const pendingPlanSubmission = existsSync(executionPlanPaths(artifactsDir).submission);
2940
+ const revisionMismatch = Boolean(currentCanonical && currentCanonical.revision_sha256 !== state?.plan?.review_revision_sha256);
2941
+ if (reportOnlyRequest && !pendingPlanSubmission && !revisionMismatch)
2942
+ return handleComplete(root, artifactsDir, state);
2943
+ if (state && reportOnlyRequest)
2944
+ admitRemediationDirtyBaseline(state);
2950
2945
  if (state)
2951
2946
  await store.reconcileDecisionApplications(state);
2952
2947
  let control = await store.loadOperatorLifecycle();
@@ -3001,8 +2996,7 @@ async function advanceUnderPhaseLock(deps) {
3001
2996
  // Preamble — forceReplan re-grounds from existing intake. The whole decide loop
3002
2997
  // runs once per host call (the engine folds planning → implementing → … through
3003
2998
  // transitions, never a recursive decideNextStepLoop), so this fires at most once.
3004
- const currentCanonical = state?.plan ? await readCanonicalPlan(artifactsDir) : undefined;
3005
- if (state != null && (options.forceReplan || existsSync(executionPlanPaths(artifactsDir).submission) || (currentCanonical && currentCanonical.revision_sha256 !== state.plan?.review_revision_sha256))) {
2999
+ if (state != null && (options.forceReplan || pendingPlanSubmission || revisionMismatch)) {
3006
3000
  await countStep(state);
3007
3001
  const replanOutcome = await forceReplanFromExistingIntake(root, artifactsDir, state, runLogger);
3008
3002
  // A discarded plan is REPORTED here, not collapsed into `state = null`. Once
@@ -3062,7 +3056,7 @@ async function advanceUnderPhaseLock(deps) {
3062
3056
  // The linear pre-intake gates run as obligations through the shared advance
3063
3057
  // loop. An emit returns to the host; a transition re-scans within this call;
3064
3058
  // exhausting them (step === null) means the run is past intake and falls
3065
- // through to the post-intake `advance` (MAIN_PRIORITY) below.
3059
+ // through to the post-intake `advance` below.
3066
3060
  const ctx = {
3067
3061
  root,
3068
3062
  artifactsDir,
@@ -3072,20 +3066,21 @@ async function advanceUnderPhaseLock(deps) {
3072
3066
  inputResolution,
3073
3067
  countStep,
3074
3068
  };
3069
+ const preIntakeObligations = buildPreIntakeObligations(ctx, {
3070
+ existingCheckpoint,
3071
+ rejectedCheckpointFields: checkpointRead?.rejected ?? [],
3072
+ resumeAck,
3073
+ entryState: state,
3074
+ suppliedInputUnchanged,
3075
+ sourceAlreadyBound: boundSource !== undefined,
3076
+ inputSelectionChanged,
3077
+ selectionAlreadyBound: recordedSelection !== undefined,
3078
+ selectedSourceChanged,
3079
+ guidanceFileSupplied: Boolean(options.guidanceFileSupplied || options.guidanceFile || options.guidanceText !== undefined),
3080
+ });
3075
3081
  const preIntake = await advance({
3076
- priority: PRE_INTAKE_PRIORITY,
3077
- obligations: buildPreIntakeObligations(ctx, {
3078
- existingCheckpoint,
3079
- rejectedCheckpointFields: checkpointRead?.rejected ?? [],
3080
- resumeAck,
3081
- entryState: state,
3082
- suppliedInputUnchanged,
3083
- sourceAlreadyBound: boundSource !== undefined,
3084
- inputSelectionChanged,
3085
- selectionAlreadyBound: recordedSelection !== undefined,
3086
- selectedSourceChanged,
3087
- guidanceFileSupplied: Boolean(options.guidanceFileSupplied || options.guidanceFile || options.guidanceText !== undefined),
3088
- }),
3082
+ priority: preIntakeObligations.map(def => def.id),
3083
+ obligations: preIntakeObligations,
3089
3084
  }, state, ctx);
3090
3085
  if (preIntake.step)
3091
3086
  return preIntake.step;
@@ -3113,7 +3108,8 @@ async function advanceUnderPhaseLock(deps) {
3113
3108
  // store without returning the persisted value, so the main fold reads from disk
3114
3109
  // exactly as it did when it owned its own lock acquisition.
3115
3110
  const advanceState = (await store.loadState()) ?? state;
3116
- const main = await advance({ priority: MAIN_PRIORITY, obligations: buildMainObligations(ctx) }, advanceState, ctx);
3111
+ const mainObligations = buildMainObligations(ctx);
3112
+ const main = await advance({ priority: mainObligations.map(def => def.id), obligations: mainObligations }, advanceState, ctx);
3117
3113
  if (main.step)
3118
3114
  return main.step;
3119
3115
  // Same contract as the pre-intake fold above: a non-convergent stop must not