audit-tools 0.55.4 → 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.
- package/dist/audit/cli/auditReviewBindings.d.ts +4 -4
- package/dist/audit/cli/auditStep.d.ts +15 -1
- package/dist/audit/cli/auditStep.d.ts.map +1 -1
- package/dist/audit/cli/auditStep.js +24 -11
- package/dist/audit/cli/auditStep.js.map +1 -1
- package/dist/audit/cli/charterExtractionPrompt.d.ts.map +1 -1
- package/dist/audit/cli/charterExtractionPrompt.js +3 -1
- package/dist/audit/cli/charterExtractionPrompt.js.map +1 -1
- package/dist/audit/cli/cleanup.d.ts.map +1 -1
- package/dist/audit/cli/cleanup.js +26 -2
- package/dist/audit/cli/cleanup.js.map +1 -1
- package/dist/audit/cli/conceptualDispatch.d.ts +2 -0
- package/dist/audit/cli/conceptualDispatch.d.ts.map +1 -1
- package/dist/audit/cli/conceptualDispatch.js +29 -8
- package/dist/audit/cli/conceptualDispatch.js.map +1 -1
- package/dist/audit/cli/dispatch/hostHandoff.d.ts +37 -3
- package/dist/audit/cli/dispatch/hostHandoff.d.ts.map +1 -1
- package/dist/audit/cli/dispatch/hostHandoff.js +185 -16
- package/dist/audit/cli/dispatch/hostHandoff.js.map +1 -1
- package/dist/audit/cli/dispatch/packetFilter.d.ts +1 -1
- package/dist/audit/cli/envelope.d.ts +1 -1
- package/dist/audit/cli/envelope.d.ts.map +1 -1
- package/dist/audit/cli/envelope.js +4 -1
- package/dist/audit/cli/envelope.js.map +1 -1
- package/dist/audit/cli/fanoutLanes.d.ts +30 -0
- package/dist/audit/cli/fanoutLanes.d.ts.map +1 -1
- package/dist/audit/cli/fanoutLanes.js +76 -8
- package/dist/audit/cli/fanoutLanes.js.map +1 -1
- package/dist/audit/cli/laneValidators.d.ts +9 -6
- package/dist/audit/cli/laneValidators.d.ts.map +1 -1
- package/dist/audit/cli/laneValidators.js +22 -7
- package/dist/audit/cli/laneValidators.js.map +1 -1
- package/dist/audit/cli/nextStepCommand.d.ts +3 -0
- package/dist/audit/cli/nextStepCommand.d.ts.map +1 -1
- package/dist/audit/cli/nextStepCommand.js +104 -66
- package/dist/audit/cli/nextStepCommand.js.map +1 -1
- package/dist/audit/cli/nextStepHelpers.d.ts +49 -14
- package/dist/audit/cli/nextStepHelpers.d.ts.map +1 -1
- package/dist/audit/cli/nextStepHelpers.js +169 -68
- package/dist/audit/cli/nextStepHelpers.js.map +1 -1
- package/dist/audit/cli/reviewRun.d.ts +10 -0
- package/dist/audit/cli/reviewRun.d.ts.map +1 -1
- package/dist/audit/cli/reviewRun.js +4 -3
- package/dist/audit/cli/reviewRun.js.map +1 -1
- package/dist/audit/cli/sampleRunCommand.d.ts +1 -1
- package/dist/audit/cli/semanticReviewStep.d.ts +2 -0
- package/dist/audit/cli/semanticReviewStep.d.ts.map +1 -1
- package/dist/audit/cli/semanticReviewStep.js +5 -50
- package/dist/audit/cli/semanticReviewStep.js.map +1 -1
- package/dist/audit/cli/validateResultsCommand.d.ts.map +1 -1
- package/dist/audit/cli/validateResultsCommand.js +3 -1
- package/dist/audit/cli/validateResultsCommand.js.map +1 -1
- package/dist/audit/contracts/workerSchemas.d.ts +14 -14
- package/dist/audit/extractors/fsIntake.d.ts +13 -0
- package/dist/audit/extractors/fsIntake.d.ts.map +1 -1
- package/dist/audit/extractors/fsIntake.js +11 -1
- package/dist/audit/extractors/fsIntake.js.map +1 -1
- package/dist/audit/io/artifacts.d.ts +35 -9
- package/dist/audit/io/artifacts.d.ts.map +1 -1
- package/dist/audit/io/artifacts.js +84 -67
- package/dist/audit/io/artifacts.js.map +1 -1
- package/dist/audit/io/rollover.d.ts +18 -0
- package/dist/audit/io/rollover.d.ts.map +1 -0
- package/dist/audit/io/rollover.js +152 -0
- package/dist/audit/io/rollover.js.map +1 -0
- package/dist/audit/io/runSnapshot.d.ts +149 -0
- package/dist/audit/io/runSnapshot.d.ts.map +1 -0
- package/dist/audit/io/runSnapshot.js +710 -0
- package/dist/audit/io/runSnapshot.js.map +1 -0
- package/dist/audit/orchestrator/advanceTypes.d.ts +11 -0
- package/dist/audit/orchestrator/advanceTypes.d.ts.map +1 -1
- package/dist/audit/orchestrator/autoFixExecutor.d.ts +9 -0
- package/dist/audit/orchestrator/autoFixExecutor.d.ts.map +1 -1
- package/dist/audit/orchestrator/autoFixExecutor.js +22 -2
- package/dist/audit/orchestrator/autoFixExecutor.js.map +1 -1
- package/dist/audit/orchestrator/charterExtractionExecutor.d.ts.map +1 -1
- package/dist/audit/orchestrator/charterExtractionExecutor.js +18 -3
- package/dist/audit/orchestrator/charterExtractionExecutor.js.map +1 -1
- package/dist/audit/orchestrator/charterPackets.d.ts +11 -1
- package/dist/audit/orchestrator/charterPackets.d.ts.map +1 -1
- package/dist/audit/orchestrator/charterPackets.js +13 -0
- package/dist/audit/orchestrator/charterPackets.js.map +1 -1
- package/dist/audit/orchestrator/dependencyMap.d.ts.map +1 -1
- package/dist/audit/orchestrator/dependencyMap.js +6 -0
- package/dist/audit/orchestrator/dependencyMap.js.map +1 -1
- package/dist/audit/orchestrator/dependencySlices.d.ts.map +1 -1
- package/dist/audit/orchestrator/dependencySlices.js +35 -11
- package/dist/audit/orchestrator/dependencySlices.js.map +1 -1
- package/dist/audit/orchestrator/designReviewPrompt.d.ts +9 -0
- package/dist/audit/orchestrator/designReviewPrompt.d.ts.map +1 -1
- package/dist/audit/orchestrator/designReviewPrompt.js +69 -31
- package/dist/audit/orchestrator/designReviewPrompt.js.map +1 -1
- package/dist/audit/orchestrator/designReviewSnapshot.d.ts +1 -0
- package/dist/audit/orchestrator/designReviewSnapshot.d.ts.map +1 -1
- package/dist/audit/orchestrator/designReviewSnapshot.js +2 -1
- package/dist/audit/orchestrator/designReviewSnapshot.js.map +1 -1
- package/dist/audit/orchestrator/executorRunners.d.ts.map +1 -1
- package/dist/audit/orchestrator/executorRunners.js +13 -4
- package/dist/audit/orchestrator/executorRunners.js.map +1 -1
- package/dist/audit/orchestrator/hostInputPause.js +1 -1
- package/dist/audit/orchestrator/hostInputPause.js.map +1 -1
- package/dist/audit/orchestrator/intakeExecutors.d.ts +8 -1
- package/dist/audit/orchestrator/intakeExecutors.d.ts.map +1 -1
- package/dist/audit/orchestrator/intakeExecutors.js +13 -4
- package/dist/audit/orchestrator/intakeExecutors.js.map +1 -1
- package/dist/audit/orchestrator/obligationPolicy.d.ts.map +1 -1
- package/dist/audit/orchestrator/obligationPolicy.js +4 -1
- package/dist/audit/orchestrator/obligationPolicy.js.map +1 -1
- package/dist/audit/orchestrator/planningExecutors.d.ts +1 -1
- package/dist/audit/orchestrator/planningExecutors.d.ts.map +1 -1
- package/dist/audit/orchestrator/planningExecutors.js +40 -6
- package/dist/audit/orchestrator/planningExecutors.js.map +1 -1
- package/dist/audit/orchestrator/requeueCommand.d.ts +1 -1
- package/dist/audit/orchestrator/systemicChallengeExecutor.d.ts.map +1 -1
- package/dist/audit/orchestrator/systemicChallengeExecutor.js +4 -1
- package/dist/audit/orchestrator/systemicChallengeExecutor.js.map +1 -1
- package/dist/audit/orchestrator/taskBuilder.d.ts +20 -0
- package/dist/audit/orchestrator/taskBuilder.d.ts.map +1 -1
- package/dist/audit/orchestrator/taskBuilder.js +80 -18
- package/dist/audit/orchestrator/taskBuilder.js.map +1 -1
- package/dist/audit/systemic/reviewFileMap.d.ts +72 -21
- package/dist/audit/systemic/reviewFileMap.d.ts.map +1 -1
- package/dist/audit/systemic/reviewFileMap.js +96 -45
- package/dist/audit/systemic/reviewFileMap.js.map +1 -1
- package/dist/audit/systemic/secondOrderAdversaryPrompt.d.ts +7 -0
- package/dist/audit/systemic/secondOrderAdversaryPrompt.d.ts.map +1 -1
- package/dist/audit/systemic/secondOrderAdversaryPrompt.js +39 -8
- package/dist/audit/systemic/secondOrderAdversaryPrompt.js.map +1 -1
- package/dist/audit/types.d.ts +12 -12
- package/dist/audit/validation/auditResults.d.ts +1 -0
- package/dist/audit/validation/auditResults.d.ts.map +1 -1
- package/dist/audit/validation/auditResults.js +1 -0
- package/dist/audit/validation/auditResults.js.map +1 -1
- package/dist/remediate/findingFilter.js +1 -1
- package/dist/remediate/findingFilter.js.map +1 -1
- package/dist/remediate/phases/close.d.ts +1 -0
- package/dist/remediate/phases/close.d.ts.map +1 -1
- package/dist/remediate/phases/close.js +29 -5
- package/dist/remediate/phases/close.js.map +1 -1
- package/dist/remediate/phases/closeVerifyAnalyzerLeads.d.ts +1 -1
- package/dist/remediate/phases/triage.d.ts +2 -1
- package/dist/remediate/phases/triage.d.ts.map +1 -1
- package/dist/remediate/phases/triage.js +46 -25
- package/dist/remediate/phases/triage.js.map +1 -1
- package/dist/remediate/phases/triageConformance.d.ts +14 -0
- package/dist/remediate/phases/triageConformance.d.ts.map +1 -0
- package/dist/remediate/phases/triageConformance.js +189 -0
- package/dist/remediate/phases/triageConformance.js.map +1 -0
- package/dist/remediate/state/decisionConsumption.d.ts +110 -0
- package/dist/remediate/state/decisionConsumption.d.ts.map +1 -0
- package/dist/remediate/state/decisionConsumption.js +122 -0
- package/dist/remediate/state/decisionConsumption.js.map +1 -0
- package/dist/remediate/state/store.d.ts +4 -0
- package/dist/remediate/state/store.d.ts.map +1 -1
- package/dist/remediate/state/store.js +16 -0
- package/dist/remediate/state/store.js.map +1 -1
- package/dist/remediate/steps/contractPipeline.d.ts +0 -6
- package/dist/remediate/steps/contractPipeline.d.ts.map +1 -1
- package/dist/remediate/steps/contractPipeline.js +3 -32
- package/dist/remediate/steps/contractPipeline.js.map +1 -1
- package/dist/remediate/steps/dispatch/contractConformanceReview.d.ts +9 -0
- package/dist/remediate/steps/dispatch/contractConformanceReview.d.ts.map +1 -1
- package/dist/remediate/steps/dispatch/contractConformanceReview.js +32 -14
- package/dist/remediate/steps/dispatch/contractConformanceReview.js.map +1 -1
- package/dist/remediate/steps/dispatch/hostContracts.js +1 -1
- package/dist/remediate/steps/dispatch/hostContracts.js.map +1 -1
- package/dist/remediate/steps/dispatch/hostHandoff.d.ts.map +1 -1
- package/dist/remediate/steps/dispatch/hostHandoff.js +6 -2
- package/dist/remediate/steps/dispatch/hostHandoff.js.map +1 -1
- package/dist/remediate/steps/dispatch/requiredTests.js +1 -1
- package/dist/remediate/steps/dispatch/requiredTests.js.map +1 -1
- package/dist/remediate/steps/gateCommands.d.ts +1 -0
- package/dist/remediate/steps/gateCommands.d.ts.map +1 -1
- package/dist/remediate/steps/gateCommands.js +8 -52
- package/dist/remediate/steps/gateCommands.js.map +1 -1
- package/dist/remediate/steps/nextStep.d.ts +7 -0
- package/dist/remediate/steps/nextStep.d.ts.map +1 -1
- package/dist/remediate/steps/nextStep.js +69 -75
- package/dist/remediate/steps/nextStep.js.map +1 -1
- package/dist/remediate/steps/prompts.d.ts.map +1 -1
- package/dist/remediate/steps/prompts.js +6 -9
- package/dist/remediate/steps/prompts.js.map +1 -1
- package/dist/remediate/steps/recoverIngest.js +1 -1
- package/dist/remediate/steps/recoverIngest.js.map +1 -1
- package/dist/shared/analyzers/provenance.d.ts +1 -1
- package/dist/shared/analyzers/provenance.js +1 -1
- package/dist/shared/contentKey.d.ts +3 -2
- package/dist/shared/contentKey.d.ts.map +1 -1
- package/dist/shared/contentKey.js +3 -2
- package/dist/shared/contentKey.js.map +1 -1
- package/dist/shared/decompose/charterExtraction.d.ts +200 -13
- package/dist/shared/decompose/charterExtraction.d.ts.map +1 -1
- package/dist/shared/decompose/charterExtraction.js +34 -6
- package/dist/shared/decompose/charterExtraction.js.map +1 -1
- package/dist/shared/decompose/systemicChallenge.js +1 -1
- package/dist/shared/decompose/systemicChallenge.js.map +1 -1
- package/dist/shared/engine/obligationEngine.d.ts +1 -1
- package/dist/shared/engine/obligationEngine.js +1 -1
- package/dist/shared/findings/dedupe.js +1 -1
- package/dist/shared/findings/dedupe.js.map +1 -1
- package/dist/shared/git.d.ts +30 -1
- package/dist/shared/git.d.ts.map +1 -1
- package/dist/shared/git.js +65 -6
- package/dist/shared/git.js.map +1 -1
- package/dist/shared/index.d.ts +1 -0
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js +1 -0
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/intent/clauseBoundaries.d.ts +1 -0
- package/dist/shared/intent/clauseBoundaries.d.ts.map +1 -1
- package/dist/shared/intent/clauseBoundaries.js +1 -0
- package/dist/shared/intent/clauseBoundaries.js.map +1 -1
- package/dist/shared/intent/pathScope.d.ts +1 -0
- package/dist/shared/intent/pathScope.d.ts.map +1 -1
- package/dist/shared/intent/pathScope.js +1 -0
- package/dist/shared/intent/pathScope.js.map +1 -1
- package/dist/shared/io/nodeWorktreeGuard.d.ts +1 -1
- package/dist/shared/io/nodeWorktreeGuard.js +1 -1
- package/dist/shared/io/pathIdentity.d.ts.map +1 -1
- package/dist/shared/io/pathIdentity.js +1 -0
- package/dist/shared/io/pathIdentity.js.map +1 -1
- package/dist/shared/io/stepContractWriter.d.ts +1 -0
- package/dist/shared/io/stepContractWriter.d.ts.map +1 -1
- package/dist/shared/io/stepContractWriter.js +1 -0
- package/dist/shared/io/stepContractWriter.js.map +1 -1
- package/dist/shared/loopCorePaths.d.ts.map +1 -1
- package/dist/shared/loopCorePaths.js +11 -0
- package/dist/shared/loopCorePaths.js.map +1 -1
- package/dist/shared/prompts.d.ts +2 -0
- package/dist/shared/prompts.d.ts.map +1 -1
- package/dist/shared/prompts.js +8 -2
- package/dist/shared/prompts.js.map +1 -1
- package/dist/shared/submission/ingestReport.d.ts.map +1 -1
- package/dist/shared/submission/ingestReport.js +19 -1
- package/dist/shared/submission/ingestReport.js.map +1 -1
- package/dist/shared/submission/submissionLedger.js +2 -2
- package/dist/shared/submission/submissionLedger.js.map +1 -1
- package/dist/shared/submission/submissionScan.js +1 -1
- package/dist/shared/submission/submissionScan.js.map +1 -1
- package/dist/shared/tooling/exec.js +2 -2
- package/dist/shared/tooling/exec.js.map +1 -1
- package/dist/shared/types/charter.d.ts +9 -0
- package/dist/shared/types/charter.d.ts.map +1 -1
- package/dist/shared/types/charter.js +7 -0
- package/dist/shared/types/charter.js.map +1 -1
- package/dist/shared/types/closingActions.js +1 -1
- package/dist/shared/types/closingActions.js.map +1 -1
- package/dist/shared/types/finding.js +2 -2
- package/dist/shared/types/finding.js.map +1 -1
- package/dist/shared/types/stepContract.js +1 -1
- package/dist/shared/types/stepContract.js.map +1 -1
- package/dist/shared/validation/findingGrounding.d.ts +1 -0
- package/dist/shared/validation/findingGrounding.d.ts.map +1 -1
- package/dist/shared/validation/findingGrounding.js +1 -0
- package/dist/shared/validation/findingGrounding.js.map +1 -1
- package/dist/shared/validation/producerBoundary.d.ts +10 -0
- package/dist/shared/validation/producerBoundary.d.ts.map +1 -0
- package/dist/shared/validation/producerBoundary.js +26 -0
- package/dist/shared/validation/producerBoundary.js.map +1 -0
- package/docs/audit-pkg/contracts.md +6 -2
- package/docs/audit-pkg/operator-guide.md +13 -4
- package/package.json +5 -1
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { readDecisionSnapshot, decisionContextDigest } from "../state/decisionConsumption.js";
|
|
1
2
|
import { RemediationPlanAuthorityError } from "../contractPipeline/runtimePlanAuthority.js";
|
|
3
|
+
import { reopenStaleTriageSuccesses } from "../phases/triageConformance.js";
|
|
2
4
|
import { stateRunId, requireStateRunId, currentHostBoundaryState } from "../state/runIdentity.js";
|
|
3
5
|
import { presentReportStep } from "./frictionCloseout.js";
|
|
4
6
|
import { reviewFilterDispositionsPath, persistReviewFilterDispositions } from "../review/filterDispositions.js";
|
|
@@ -34,7 +36,7 @@ import { applyIntentOrdering } from "../intent/intentOrdering.js";
|
|
|
34
36
|
import { resolveIntakeStep } from "./intakeResolver.js";
|
|
35
37
|
import { RUNTIME_RESIDUAL_DECLARATION, finalGateDisabledReason, finalGateRecordPath, readFinalGateVerdict, runToolOwnedFinalGate, writeFinalGateRedRecord, recordFinalGateOutcome, writeFinalGateVerdict, } from "./finalGate.js";
|
|
36
38
|
import { renderGateAttribution, worktreeContentId, finalGateBinding, } from "./gateCommands.js";
|
|
37
|
-
import { buildNextContractPipelineStep, readApprovedExecutionPlan, writePathASeedFromFindings,
|
|
39
|
+
import { buildNextContractPipelineStep, readApprovedExecutionPlan, writePathASeedFromFindings, } from "./contractPipeline.js";
|
|
38
40
|
import { compareCodeUnits } from "../../shared/compareCodeUnits.js";
|
|
39
41
|
import { executionPlanPaths, readCanonicalPlan, readPlanSource, readPlanReviewHistory } from "../contractPipeline/executionPlan.js";
|
|
40
42
|
import { buildReviewRequest, applyReviewResolution, parseReviewResolution, REVIEW_REQUEST_SCHEMA_VERSION, } from "../review/reviewGate.js";
|
|
@@ -472,6 +474,15 @@ function remediationIngestReportLines(ingested) {
|
|
|
472
474
|
.sort(compareCodeUnits),
|
|
473
475
|
});
|
|
474
476
|
}
|
|
477
|
+
/**
|
|
478
|
+
* Whether the ingest report names a result file the host must write: only the
|
|
479
|
+
* repair and landed-without-result sections do. Pending results render as a
|
|
480
|
+
* count, listed in the workload, so a report holding only those names no file.
|
|
481
|
+
*/
|
|
482
|
+
export function reportNamesResultFiles(ingested) {
|
|
483
|
+
return (ingested.issues.some((issue) => remediationIssueRemedy(issue) === "repair") ||
|
|
484
|
+
[...ingested.work_item_outcomes].some(([, outcome]) => outcome === "missing_result_with_commit"));
|
|
485
|
+
}
|
|
475
486
|
async function buildImplementDispatchStep(ctx) {
|
|
476
487
|
const { root, artifactsDir, state, store, runLogger } = ctx;
|
|
477
488
|
const runId = requireStateRunId(state);
|
|
@@ -618,7 +629,7 @@ async function buildImplementDispatchStep(ctx) {
|
|
|
618
629
|
"The file lists every work item that is ready now. Give each item's prompt to a worker. You choose the order, the groups, and how many run at the same time.",
|
|
619
630
|
"",
|
|
620
631
|
...report,
|
|
621
|
-
...(
|
|
632
|
+
...(reportNamesResultFiles(ingested) ? ["Change only the result files named above.", ""] : []),
|
|
622
633
|
"Do not edit the workload file.",
|
|
623
634
|
"",
|
|
624
635
|
"When each item has its commit on HEAD and its result file, run:",
|
|
@@ -720,7 +731,10 @@ async function activateApprovedPlan(root, artifactsDir, existing, _input, _runLo
|
|
|
720
731
|
if (!existing.run_start_dirty)
|
|
721
732
|
existing = { ...existing, run_start_dirty: [...await stagedAndUntracked(root)].sort() };
|
|
722
733
|
const filter = await readOptionalJsonFile(reviewFilterDispositionsPath(artifactsDir));
|
|
723
|
-
|
|
734
|
+
// Through the schema-checked reader: with zero survivors the review gate never
|
|
735
|
+
// rewrites a stale-schema record, so a raw read let its declines into the
|
|
736
|
+
// ledger as declined-by-review although the current run never decided them.
|
|
737
|
+
const decision = await readReviewDecision(artifactsDir);
|
|
724
738
|
const coverage = buildCoverageLedger({
|
|
725
739
|
planId: plan.plan_id, sourceFindings: filter?.originals ?? source.findings,
|
|
726
740
|
droppedNoEvidence: filter?.droppedNoEvidence ?? [], droppedByCheckpoint: filter?.droppedByCheckpoint ?? [],
|
|
@@ -1276,22 +1290,16 @@ const PLAN_CLARIFICATION_ACTIONS = ["clarified", "reject_finding", "defer"];
|
|
|
1276
1290
|
* - `rationale` is REQUIRED and non-empty on `clarified`: it becomes the item's
|
|
1277
1291
|
* `clarification_context`, the answer the next worker reads. A `clarified`
|
|
1278
1292
|
* entry without it re-opened the item with no answer attached.
|
|
1279
|
-
* -
|
|
1280
|
-
*
|
|
1281
|
-
*
|
|
1282
|
-
*
|
|
1283
|
-
* ONLY on `clarified`, the one action that re-opens the item; on
|
|
1284
|
-
* `reject_finding` or `defer` it used to be ignored without a word. Each path
|
|
1285
|
-
* is validated whole-file fail-closed BEFORE anything is applied
|
|
1286
|
-
* (`validateClarificationScopeAdditions`), so the host never edits the plan
|
|
1287
|
-
* by hand.
|
|
1293
|
+
* - There is no write-scope field: new write scope needs a revised, freshly
|
|
1294
|
+
* reviewed plan, so an answer cannot widen a unit (owner decision 2026-10-01;
|
|
1295
|
+
* the ignored `scope_additions` field was removed in two releases, and is now
|
|
1296
|
+
* refused as an unknown field).
|
|
1288
1297
|
*/
|
|
1289
1298
|
const PlanClarificationResolutionSchema = z
|
|
1290
1299
|
.object({
|
|
1291
1300
|
unit_id: z.string().min(1, "must be a non-empty finding id"),
|
|
1292
1301
|
action: z.enum(PLAN_CLARIFICATION_ACTIONS),
|
|
1293
1302
|
rationale: z.string().optional(),
|
|
1294
|
-
scope_additions: z.array(z.string()).optional(),
|
|
1295
1303
|
})
|
|
1296
1304
|
.strict()
|
|
1297
1305
|
.superRefine((entry, ctx) => {
|
|
@@ -1302,13 +1310,6 @@ const PlanClarificationResolutionSchema = z
|
|
|
1302
1310
|
message: 'is required and must be non-empty when action is "clarified" — it carries the answer to the next worker',
|
|
1303
1311
|
});
|
|
1304
1312
|
}
|
|
1305
|
-
if (entry.action !== "clarified" && entry.scope_additions !== undefined) {
|
|
1306
|
-
ctx.addIssue({
|
|
1307
|
-
code: z.ZodIssueCode.custom,
|
|
1308
|
-
path: ["scope_additions"],
|
|
1309
|
-
message: `is allowed only with action "clarified" — a ${entry.action} entry widens no write scope`,
|
|
1310
|
-
});
|
|
1311
|
-
}
|
|
1312
1313
|
});
|
|
1313
1314
|
/**
|
|
1314
1315
|
* Read and validate the mid-run `clarification_resolution.json` file.
|
|
@@ -1321,10 +1322,10 @@ const PlanClarificationResolutionSchema = z
|
|
|
1321
1322
|
* user's answer, and the item then waited forever for a question the round no
|
|
1322
1323
|
* longer showed.
|
|
1323
1324
|
*/
|
|
1324
|
-
async function readPlanClarificationResolutions(path) {
|
|
1325
|
+
async function readPlanClarificationResolutions(path, snapshotBytes) {
|
|
1325
1326
|
let value;
|
|
1326
1327
|
try {
|
|
1327
|
-
value = JSON.parse(await readFile(path, "utf8"));
|
|
1328
|
+
value = JSON.parse(snapshotBytes ?? await readFile(path, "utf8"));
|
|
1328
1329
|
}
|
|
1329
1330
|
catch (error) {
|
|
1330
1331
|
return {
|
|
@@ -1365,10 +1366,9 @@ async function readPlanClarificationResolutions(path) {
|
|
|
1365
1366
|
}
|
|
1366
1367
|
/**
|
|
1367
1368
|
* Every whole-file refusal of a parsed resolution, in check order: the parse,
|
|
1368
|
-
* then the closed id set
|
|
1369
|
-
* applied.
|
|
1369
|
+
* then the closed id set. Null means the file may be applied.
|
|
1370
1370
|
*/
|
|
1371
|
-
|
|
1371
|
+
function planClarificationRefusal(parsed, validIds, outsideSetLabel) {
|
|
1372
1372
|
if (!parsed.ok)
|
|
1373
1373
|
return parsed.reason;
|
|
1374
1374
|
const unknownIds = parsed.resolutions
|
|
@@ -1377,40 +1377,8 @@ async function planClarificationRefusal(root, state, parsed, validIds, outsideSe
|
|
|
1377
1377
|
if (unknownIds.length > 0) {
|
|
1378
1378
|
return `finding id(s) ${outsideSetLabel}: ${unknownIds.map((i) => `\`${i}\``).join(", ")}`;
|
|
1379
1379
|
}
|
|
1380
|
-
const scopeRefusals = await validateClarificationScopeAdditions(root, state, parsed.resolutions);
|
|
1381
|
-
if (scopeRefusals.length > 0) {
|
|
1382
|
-
return `invalid scope_additions — fix and re-submit: ${scopeRefusals.join(" | ")}`;
|
|
1383
|
-
}
|
|
1384
1380
|
return null;
|
|
1385
1381
|
}
|
|
1386
|
-
/**
|
|
1387
|
-
* Validate every `clarified` resolution's `scope_additions` BEFORE anything is
|
|
1388
|
-
* applied: each entry must normalize beneath the repository root against the
|
|
1389
|
-
* finding's owning block (the one write-scope normalizer), must clear the SAME
|
|
1390
|
-
* tracked-tree rule the promotion gate enforced (the delta lane must not
|
|
1391
|
-
* bypass it), and a finding with no owning block has no scope to widen. ANY
|
|
1392
|
-
* refusal refuses the WHOLE resolution file — the uniform id-join contract's
|
|
1393
|
-
* shape: a half-applied decision record is worse than a re-ask.
|
|
1394
|
-
*/
|
|
1395
|
-
async function validateClarificationScopeAdditions(root, state, resolutions) {
|
|
1396
|
-
const refusals = [];
|
|
1397
|
-
for (const res of resolutions) {
|
|
1398
|
-
if (res.action !== "clarified" || !res.scope_additions?.length)
|
|
1399
|
-
continue;
|
|
1400
|
-
const block = state.plan?.units?.find((b) => b.id === res.unit_id);
|
|
1401
|
-
if (!block) {
|
|
1402
|
-
refusals.push(`scope_additions for \`${res.unit_id}\`: no plan block owns this finding, so ` +
|
|
1403
|
-
`there is no write scope to widen.`);
|
|
1404
|
-
continue;
|
|
1405
|
-
}
|
|
1406
|
-
const normalized = normalizeBlockTouchedFiles(root, res.scope_additions, block.id);
|
|
1407
|
-
if (normalized.touched_files.some(path => !block.allowed_files.includes(path)))
|
|
1408
|
-
refusals.push(`Unit ${block.id} needs a revised executable plan and fresh review before its write scope can expand.`);
|
|
1409
|
-
refusals.push(...normalized.refusals);
|
|
1410
|
-
refusals.push(...(await checkWriteScopePathsAgainstTrackedTree(root, normalized.touched_files, `scope_additions for \`${res.unit_id}\` (block "${block.id}")`)));
|
|
1411
|
-
}
|
|
1412
|
-
return refusals;
|
|
1413
|
-
}
|
|
1414
1382
|
/**
|
|
1415
1383
|
* Apply one mid-run clarification resolution to its execution unit:
|
|
1416
1384
|
* `clarified` re-opens it (pending) with the answer as context,
|
|
@@ -1449,14 +1417,15 @@ async function applyPlanClarificationResolution(root, artifactsDir, state, store
|
|
|
1449
1417
|
if (!state.plan || !state.items)
|
|
1450
1418
|
return { kind: "applied", state };
|
|
1451
1419
|
const resolutionPath = join(artifactsDir, "clarification_resolution.json");
|
|
1452
|
-
const
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
//
|
|
1456
|
-
//
|
|
1457
|
-
//
|
|
1458
|
-
//
|
|
1459
|
-
|
|
1420
|
+
const inputSnapshot = await readDecisionSnapshot(resolutionPath);
|
|
1421
|
+
const contextDigest = decisionContextDigest(state);
|
|
1422
|
+
const parsed = await readPlanClarificationResolutions(resolutionPath, inputSnapshot?.bytes);
|
|
1423
|
+
// Uniform whole-file fail-closed contract: a malformed entry or an id outside
|
|
1424
|
+
// the paused set refuses the WHOLE resolution (archived, nothing applied) and
|
|
1425
|
+
// re-halts with the reason named. The silent-continue alternative drops the
|
|
1426
|
+
// user's answer and leaves its item waiting on a question nobody is asked, so
|
|
1427
|
+
// a decision record never half-applies.
|
|
1428
|
+
const refusal = planClarificationRefusal(parsed, new Set(pausedClarifications(state).map((q) => q.unit_id)), "not waiting for a clarification");
|
|
1460
1429
|
if (refusal !== null || !parsed.ok) {
|
|
1461
1430
|
await withFsRetry(() => rename(resolutionPath, `${resolutionPath}.refused-${Date.now()}`));
|
|
1462
1431
|
return {
|
|
@@ -1471,9 +1440,8 @@ async function applyPlanClarificationResolution(root, artifactsDir, state, store
|
|
|
1471
1440
|
const item = state.items[res.unit_id];
|
|
1472
1441
|
if (!item || isTerminalStatus(item.status))
|
|
1473
1442
|
continue;
|
|
1474
|
-
//
|
|
1475
|
-
//
|
|
1476
|
-
// here, and its revision (which hashes author order) stays the approved one.
|
|
1443
|
+
// The reviewed plan is never rewritten here, and its revision (which hashes
|
|
1444
|
+
// author order) stays the approved one.
|
|
1477
1445
|
applyClarificationActionToItem(item, res, now);
|
|
1478
1446
|
appliedCount += 1;
|
|
1479
1447
|
}
|
|
@@ -1484,9 +1452,11 @@ async function applyPlanClarificationResolution(root, artifactsDir, state, store
|
|
|
1484
1452
|
// outright). Mirrors the saveStateForPlan strip.
|
|
1485
1453
|
if (appliedCount > 0)
|
|
1486
1454
|
delete state.host_handoff;
|
|
1487
|
-
if (
|
|
1488
|
-
|
|
1489
|
-
|
|
1455
|
+
if (!inputSnapshot)
|
|
1456
|
+
throw new Error("Clarification input changed during application; retry without accepting it.");
|
|
1457
|
+
(state.decision_applications ??= []).push({ input: "clarification_resolution.json", input_sha256: inputSnapshot.sha256, input_identity_sha256: inputSnapshot.identity_sha256,
|
|
1458
|
+
context_sha256: contextDigest, run_id: state.plan.plan_id, revision_sha256: state.plan.review_revision_sha256,
|
|
1459
|
+
applied_at: now, retry_results: [] });
|
|
1490
1460
|
const remainingPending = state.plan.units.some((f) => state.items?.[f.id]?.status === "pending");
|
|
1491
1461
|
// Undecided-remainder guard, mirroring triage's still-blocked guard: a
|
|
1492
1462
|
// resolution covering only SOME of the paused items must not fall through to
|
|
@@ -1595,12 +1565,24 @@ async function handlePlanning(root, artifactsDir, state, store) {
|
|
|
1595
1565
|
async function handleImplementing(root, artifactsDir, state, runLogger, store) {
|
|
1596
1566
|
const triageStart = Date.now();
|
|
1597
1567
|
runLogger.event({ phase: "next-step", kind: "executor_start", obligation: state.status, note: "triage" });
|
|
1598
|
-
|
|
1568
|
+
// sites-pinned: tests/remediate/host-handoff-corroboration-obligations.test.ts
|
|
1569
|
+
const conformanceIssues = [];
|
|
1570
|
+
const triaged = await runTriagePhase(state, { root, artifactsDir }, issue => conformanceIssues.push(issue));
|
|
1599
1571
|
runLogger.event({ phase: "next-step", kind: "executor_end", obligation: state.status, note: "triage", duration_ms: Date.now() - triageStart });
|
|
1572
|
+
if (conformanceIssues.length) {
|
|
1573
|
+
await store.saveState(triaged);
|
|
1574
|
+
return { kind: "emit", step: await writeCurrentStep({
|
|
1575
|
+
stepKind: "review_contract_conformance", status: conformanceIssues.some(issue => issue.code === "conformance_review_unavailable") ? "blocked" : "ready",
|
|
1576
|
+
runId: stateRunId(triaged), repoRoot: root, artifactsDir,
|
|
1577
|
+
prompt: ["Independent contract conformance review is required before triage can accept these tool-owned working-tree observations.", ...conformanceIssues.map(issue => `${issue.work_item_id}: ${issue.message}\nRequest: ${issue.review_request_path}`), "Read each request in an independent context and write its bound response. Self-review cannot satisfy this requirement. Resume next-step after the responses are ready."].join("\n\n"),
|
|
1578
|
+
stopCondition: "Obtain independent conformance review or remain paused.",
|
|
1579
|
+
allowedCommands: [loaderCommand("next-step")],
|
|
1580
|
+
}) };
|
|
1581
|
+
}
|
|
1600
1582
|
// Triage may enter closing directly: the close itself owns mandatory final
|
|
1601
1583
|
// acceptance, so a status transition cannot bypass it.
|
|
1602
1584
|
if (triaged.status === "closing")
|
|
1603
|
-
return handleAllTerminalTransition(triaged, store);
|
|
1585
|
+
return handleAllTerminalTransition(triaged, store, root, artifactsDir);
|
|
1604
1586
|
await store.saveState(triaged);
|
|
1605
1587
|
return { kind: "transition", state: triaged };
|
|
1606
1588
|
}
|
|
@@ -1889,7 +1871,12 @@ async function runPhaseBoundaryGate(ctx) {
|
|
|
1889
1871
|
runLogger,
|
|
1890
1872
|
});
|
|
1891
1873
|
}
|
|
1892
|
-
async function handleAllTerminalTransition(state, store) {
|
|
1874
|
+
async function handleAllTerminalTransition(state, store, root, artifactsDir) {
|
|
1875
|
+
// sites-pinned: tests/remediate/host-handoff-corroboration-obligations.test.ts
|
|
1876
|
+
if (await reopenStaleTriageSuccesses(root, artifactsDir, state)) {
|
|
1877
|
+
await store.saveState(state);
|
|
1878
|
+
return { kind: "transition", state };
|
|
1879
|
+
}
|
|
1893
1880
|
// Final acceptance belongs to the actual close execution, after preview
|
|
1894
1881
|
// pauses. A transition carries no executable verification verdict.
|
|
1895
1882
|
state.status = "closing";
|
|
@@ -1897,6 +1884,11 @@ async function handleAllTerminalTransition(state, store) {
|
|
|
1897
1884
|
return { kind: "transition", state };
|
|
1898
1885
|
}
|
|
1899
1886
|
async function handleClosing(root, artifactsDir, state, runLogger, store, options) {
|
|
1887
|
+
// sites-pinned: tests/remediate/host-handoff-corroboration-obligations.test.ts
|
|
1888
|
+
if (await reopenStaleTriageSuccesses(root, artifactsDir, state)) {
|
|
1889
|
+
await store.saveState(state);
|
|
1890
|
+
return { kind: "transition", state };
|
|
1891
|
+
}
|
|
1900
1892
|
const closeStart = Date.now();
|
|
1901
1893
|
runLogger.event({ phase: "next-step", kind: "executor_start", obligation: state.status, note: "close" });
|
|
1902
1894
|
// Target verification and closing are product obligations. Development
|
|
@@ -2885,7 +2877,7 @@ export function buildMainObligations(ctx) {
|
|
|
2885
2877
|
derive: (state) => state != null && allItemsTerminal(state) && state.status !== "closing"
|
|
2886
2878
|
? "missing"
|
|
2887
2879
|
: "satisfied",
|
|
2888
|
-
execute: async (state) => handleAllTerminalTransition(requireState(state), store),
|
|
2880
|
+
execute: async (state) => handleAllTerminalTransition(requireState(state), store, root, artifactsDir),
|
|
2889
2881
|
},
|
|
2890
2882
|
{
|
|
2891
2883
|
id: "closing",
|
|
@@ -2955,6 +2947,8 @@ async function advanceUnderPhaseLock(deps) {
|
|
|
2955
2947
|
// Loaded FRESH under the mutex: a peer may have advanced and persisted state
|
|
2956
2948
|
// between the entry read and this process winning the lock.
|
|
2957
2949
|
let state = await store.loadState();
|
|
2950
|
+
if (state)
|
|
2951
|
+
await store.reconcileDecisionApplications(state);
|
|
2958
2952
|
let control = await store.loadOperatorLifecycle();
|
|
2959
2953
|
if (control && control.mode !== "active") {
|
|
2960
2954
|
return buildOperatorControlStep(root, artifactsDir, state, control);
|