auditor-lambda 0.10.2 → 0.10.7
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/audit-code-wrapper-build.mjs +198 -0
- package/audit-code-wrapper-install-hosts.mjs +1140 -0
- package/audit-code-wrapper-io.mjs +155 -0
- package/audit-code-wrapper-legacy.mjs +125 -0
- package/audit-code-wrapper-lib.mjs +17 -1801
- package/audit-code-wrapper-opencode.mjs +256 -0
- package/dispatch/merge-results.mjs +5 -3
- package/dispatch/validate-result.mjs +2 -2
- package/dist/adapters/coverageSummary.js +6 -2
- package/dist/adapters/normalizeExternal.js +16 -1
- package/dist/adapters/npmAudit.js +20 -9
- package/dist/adapters/semgrep.js +26 -1
- package/dist/cli/advanceAuditCommand.d.ts +1 -0
- package/dist/cli/advanceAuditCommand.js +95 -0
- package/dist/cli/args.js +1 -2
- package/dist/cli/auditStep.js +2 -2
- package/dist/cli/cleanup.d.ts +11 -1
- package/dist/cli/cleanup.js +25 -5
- package/dist/cli/cleanupCommand.d.ts +1 -0
- package/dist/cli/cleanupCommand.js +24 -0
- package/dist/cli/dispatch.d.ts +55 -31
- package/dist/cli/dispatch.js +298 -241
- package/dist/cli/dispatchStatusCommand.d.ts +1 -0
- package/dist/cli/dispatchStatusCommand.js +68 -0
- package/dist/cli/explainTaskCommand.d.ts +1 -0
- package/dist/cli/explainTaskCommand.js +33 -0
- package/dist/cli/importExternalAnalyzerCommand.d.ts +1 -0
- package/dist/cli/importExternalAnalyzerCommand.js +20 -0
- package/dist/cli/ingestResultsCommand.d.ts +1 -0
- package/dist/cli/ingestResultsCommand.js +34 -0
- package/dist/cli/intakeCommand.d.ts +1 -0
- package/dist/cli/intakeCommand.js +17 -0
- package/dist/cli/lineIndex.js +19 -12
- package/dist/cli/mergeAndIngestCommand.js +68 -26
- package/dist/cli/nextStepCommand.d.ts +139 -0
- package/dist/cli/nextStepCommand.js +281 -232
- package/dist/cli/planCommand.d.ts +1 -0
- package/dist/cli/planCommand.js +16 -0
- package/dist/cli/prepareDispatchCommand.d.ts +1 -0
- package/dist/cli/prepareDispatchCommand.js +25 -0
- package/dist/cli/quotaCommand.d.ts +1 -0
- package/dist/cli/quotaCommand.js +56 -0
- package/dist/cli/requeueCommand.d.ts +1 -0
- package/dist/cli/requeueCommand.js +10 -0
- package/dist/cli/runToCompletion.js +451 -412
- package/dist/cli/sampleRunCommand.d.ts +1 -0
- package/dist/cli/sampleRunCommand.js +93 -0
- package/dist/cli/statusCommand.js +1 -1
- package/dist/cli/steps.js +4 -1
- package/dist/cli/submitPacketCommand.js +16 -15
- package/dist/cli/synthesizeCommand.d.ts +1 -0
- package/dist/cli/synthesizeCommand.js +15 -0
- package/dist/cli/updateRuntimeValidationCommand.d.ts +1 -0
- package/dist/cli/updateRuntimeValidationCommand.js +16 -0
- package/dist/cli/validateCommand.d.ts +1 -0
- package/dist/cli/validateCommand.js +41 -0
- package/dist/cli/validateResultCommand.d.ts +1 -0
- package/dist/cli/validateResultCommand.js +63 -0
- package/dist/cli/validateResultsCommand.d.ts +1 -0
- package/dist/cli/validateResultsCommand.js +31 -0
- package/dist/cli/workerRunCommand.d.ts +15 -1
- package/dist/cli/workerRunCommand.js +40 -4
- package/dist/cli.d.ts +3 -2
- package/dist/cli.js +21 -628
- package/dist/coverage.js +7 -3
- package/dist/extractors/analyzers/css.js +2 -2
- package/dist/extractors/analyzers/html.js +2 -2
- package/dist/extractors/analyzers/python.js +2 -2
- package/dist/extractors/analyzers/registry.js +17 -36
- package/dist/extractors/analyzers/treeSitter.d.ts +10 -1
- package/dist/extractors/analyzers/treeSitter.js +28 -6
- package/dist/extractors/analyzers/typescript.js +104 -85
- package/dist/extractors/browserExtension.js +4 -1
- package/dist/extractors/designAssessment.js +21 -21
- package/dist/extractors/fsIntake.js +34 -10
- package/dist/extractors/graph.js +17 -7
- package/dist/extractors/graphManifestEdges/cargo.d.ts +4 -0
- package/dist/extractors/graphManifestEdges/cargo.js +107 -0
- package/dist/extractors/graphManifestEdges/go.d.ts +5 -0
- package/dist/extractors/graphManifestEdges/go.js +151 -0
- package/dist/extractors/graphManifestEdges/index.d.ts +8 -0
- package/dist/extractors/graphManifestEdges/index.js +11 -0
- package/dist/extractors/graphManifestEdges/jsonc.d.ts +3 -0
- package/dist/extractors/graphManifestEdges/jsonc.js +97 -0
- package/dist/extractors/graphManifestEdges/maven.d.ts +3 -0
- package/dist/extractors/graphManifestEdges/maven.js +73 -0
- package/dist/extractors/graphManifestEdges/packageJson.d.ts +19 -0
- package/dist/extractors/graphManifestEdges/packageJson.js +204 -0
- package/dist/extractors/graphManifestEdges/pnpm.d.ts +2 -0
- package/dist/extractors/graphManifestEdges/pnpm.js +42 -0
- package/dist/extractors/graphManifestEdges/pyproject.d.ts +3 -0
- package/dist/extractors/graphManifestEdges/pyproject.js +83 -0
- package/dist/extractors/graphManifestEdges/toml.d.ts +4 -0
- package/dist/extractors/graphManifestEdges/toml.js +68 -0
- package/dist/extractors/graphManifestEdges/typescript.d.ts +3 -0
- package/dist/extractors/graphManifestEdges/typescript.js +56 -0
- package/dist/extractors/graphManifestEdges/workspace.d.ts +10 -0
- package/dist/extractors/graphManifestEdges/workspace.js +72 -0
- package/dist/extractors/graphManifestEdges/yaml.d.ts +3 -0
- package/dist/extractors/graphManifestEdges/yaml.js +59 -0
- package/dist/extractors/graphManifestEdges/yamlPaths.d.ts +4 -0
- package/dist/extractors/graphManifestEdges/yamlPaths.js +89 -0
- package/dist/extractors/graphPythonImports.js +4 -20
- package/dist/extractors/pathPatterns.js +3 -13
- package/dist/io/artifacts.d.ts +1 -1
- package/dist/io/artifacts.js +4 -1
- package/dist/io/runArtifacts.d.ts +8 -2
- package/dist/io/runArtifacts.js +103 -69
- package/dist/io/toolingManifest.js +2 -1
- package/dist/orchestrator/advance.js +36 -0
- package/dist/orchestrator/artifactFreshness.d.ts +1 -1
- package/dist/orchestrator/artifactFreshness.js +1 -1
- package/dist/orchestrator/artifactMetadata.js +5 -5
- package/dist/orchestrator/auditTaskUtils.d.ts +4 -0
- package/dist/orchestrator/auditTaskUtils.js +8 -12
- package/dist/orchestrator/autoFixExecutor.js +40 -26
- package/dist/orchestrator/dependencyMap.js +1 -1
- package/dist/orchestrator/executorResult.d.ts +33 -0
- package/dist/orchestrator/executors.d.ts +7 -0
- package/dist/orchestrator/executors.js +24 -0
- package/dist/orchestrator/fileAnchors.js +42 -29
- package/dist/orchestrator/fileIntegrity.js +6 -1
- package/dist/orchestrator/flowCoverage.js +1 -2
- package/dist/orchestrator/flowPlanning.js +8 -4
- package/dist/orchestrator/graphEnrichmentExecutor.js +67 -45
- package/dist/orchestrator/ingestionExecutors.js +9 -1
- package/dist/orchestrator/intakeExecutors.d.ts +0 -4
- package/dist/orchestrator/intakeExecutors.js +24 -14
- package/dist/orchestrator/localCommands.d.ts +1 -0
- package/dist/orchestrator/localCommands.js +10 -17
- package/dist/orchestrator/nextStep.js +3 -1
- package/dist/orchestrator/requeueCommand.js +4 -0
- package/dist/orchestrator/reviewPacketGraph.js +50 -18
- package/dist/orchestrator/reviewPackets.js +10 -8
- package/dist/orchestrator/runtimeCommand.js +35 -7
- package/dist/orchestrator/runtimeValidationUpdate.js +6 -0
- package/dist/orchestrator/selectiveDeepening/highRiskClean.js +3 -2
- package/dist/orchestrator/selectiveDeepening/lensVerification.js +44 -18
- package/dist/orchestrator/staleness.js +3 -3
- package/dist/orchestrator/state.js +1 -1
- package/dist/orchestrator/syntaxResolutionExecutor.js +17 -24
- package/dist/orchestrator/synthesisExecutors.js +1 -0
- package/dist/orchestrator/taskBuilder.js +5 -4
- package/dist/providers/claudeCodeProvider.js +4 -1
- package/dist/providers/opencodeProvider.js +4 -1
- package/dist/quota/discoveredLimits.js +3 -3
- package/dist/quota/headerExtraction.js +5 -2
- package/dist/quota/headerExtractors/claudeCodeHeaderExtractor.js +3 -0
- package/dist/quota/headerExtractors/index.js +3 -3
- package/dist/quota/index.d.ts +3 -1
- package/dist/quota/index.js +3 -0
- package/dist/reporting/findingIdentity.d.ts +21 -0
- package/dist/reporting/findingIdentity.js +72 -0
- package/dist/reporting/findingRanks.d.ts +3 -0
- package/dist/reporting/findingRanks.js +24 -0
- package/dist/reporting/mergeFindings.js +1 -24
- package/dist/reporting/synthesis.d.ts +3 -1
- package/dist/reporting/synthesis.js +36 -7
- package/dist/reporting/synthesisNarrativePrompt.js +3 -0
- package/dist/reporting/workBlocks.js +1 -14
- package/dist/supervisor/operatorHandoff.js +2 -6
- package/dist/supervisor/runLedger.js +30 -41
- package/dist/types/activeDispatch.d.ts +31 -0
- package/dist/types/activeDispatch.js +2 -0
- package/dist/types.d.ts +21 -4
- package/dist/types.js +24 -16
- package/dist/validation/artifacts.js +3 -0
- package/dist/validation/auditResults.js +8 -2
- package/package.json +2 -2
- package/schemas/audit_findings.schema.json +5 -1
- package/schemas/audit_plan_metrics.schema.json +1 -1
- package/schemas/audit_result.schema.json +5 -6
- package/schemas/audit_task.schema.json +1 -4
- package/schemas/blind_spot_register.schema.json +1 -1
- package/schemas/coverage_matrix.schema.json +2 -8
- package/schemas/finding.schema.json +3 -17
- package/schemas/flow_coverage.schema.json +2 -8
- package/schemas/graph_bundle.schema.json +31 -0
- package/schemas/lens.schema.json +7 -0
- package/schemas/review_packets.schema.json +6 -17
- package/schemas/step_contract.schema.json +8 -2
- package/schemas/unit_manifest.schema.json +1 -4
- package/scripts/postinstall.mjs +3 -1
- package/skills/audit-code/audit-code.prompt.md +2 -3
- package/dist/extractors/graphManifestEdges.d.ts +0 -12
- package/dist/extractors/graphManifestEdges.js +0 -1135
|
@@ -4,7 +4,11 @@ import { isAuditExcludedStatus } from "../extractors/disposition.js";
|
|
|
4
4
|
import { resolveNodeTool, runFirstAvailableCommand, } from "./localCommands.js";
|
|
5
5
|
function tryRunConfiguredFormatter(root, candidates) {
|
|
6
6
|
const result = runFirstAvailableCommand(root, candidates);
|
|
7
|
-
|
|
7
|
+
if (result === null)
|
|
8
|
+
return "not_found";
|
|
9
|
+
if (!result.error && result.exitCode === 0)
|
|
10
|
+
return "success";
|
|
11
|
+
return "failed";
|
|
8
12
|
}
|
|
9
13
|
const PRETTIER_CONFIG_FILES = [
|
|
10
14
|
".prettierrc",
|
|
@@ -43,6 +47,17 @@ async function hasPrettierConfig(root) {
|
|
|
43
47
|
return false;
|
|
44
48
|
}
|
|
45
49
|
}
|
|
50
|
+
function runFormatter(root, toolName, candidates, executedTools, failedTools, toolTimings) {
|
|
51
|
+
const start = Date.now();
|
|
52
|
+
const outcome = tryRunConfiguredFormatter(root, candidates);
|
|
53
|
+
if (outcome === "success") {
|
|
54
|
+
executedTools.push(toolName);
|
|
55
|
+
toolTimings.push({ tool: toolName, duration_ms: Date.now() - start });
|
|
56
|
+
}
|
|
57
|
+
else if (outcome === "failed") {
|
|
58
|
+
failedTools.push(toolName);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
46
61
|
export async function runAutoFixExecutor(bundle, root) {
|
|
47
62
|
if (!bundle.file_disposition) {
|
|
48
63
|
throw new Error("Cannot run auto fix executor without file_disposition");
|
|
@@ -57,6 +72,7 @@ export async function runAutoFixExecutor(bundle, root) {
|
|
|
57
72
|
}
|
|
58
73
|
}
|
|
59
74
|
const executedTools = [];
|
|
75
|
+
const failedTools = [];
|
|
60
76
|
const toolTimings = [];
|
|
61
77
|
// JS, TS, HTML, CSS, JSON, YAML, MD
|
|
62
78
|
if ((await hasPrettierConfig(root)) &&
|
|
@@ -70,62 +86,60 @@ export async function runAutoFixExecutor(bundle, root) {
|
|
|
70
86
|
extensions.has("yml") ||
|
|
71
87
|
extensions.has("yaml") ||
|
|
72
88
|
extensions.has("md"))) {
|
|
73
|
-
|
|
74
|
-
if (tryRunConfiguredFormatter(root, [
|
|
89
|
+
runFormatter(root, "prettier", [
|
|
75
90
|
...resolveNodeTool(root, join("node_modules", "prettier", "bin", "prettier.cjs"), ["--write", "."], "prettier --write ."),
|
|
76
91
|
{ command: "prettier", args: ["--write", "."], display: "prettier --write ." },
|
|
77
92
|
{ command: "npx", args: ["--yes", "prettier", "--write", "."], display: "npx --yes prettier --write ." },
|
|
78
|
-
])
|
|
79
|
-
executedTools.push("prettier");
|
|
80
|
-
toolTimings.push({ tool: "prettier", duration_ms: Date.now() - prettierStart });
|
|
81
|
-
}
|
|
93
|
+
], executedTools, failedTools, toolTimings);
|
|
82
94
|
}
|
|
83
95
|
// Python
|
|
84
96
|
if (extensions.has("py")) {
|
|
85
|
-
|
|
86
|
-
if (tryRunConfiguredFormatter(root, [
|
|
97
|
+
runFormatter(root, "black", [
|
|
87
98
|
{ command: "black", args: ["."], display: "black ." },
|
|
88
99
|
{ command: "python", args: ["-m", "black", "."], display: "python -m black ." },
|
|
89
100
|
{ command: "uvx", args: ["black", "."], display: "uvx black ." },
|
|
90
101
|
{ command: "pipx", args: ["run", "black", "."], display: "pipx run black ." },
|
|
91
|
-
])
|
|
92
|
-
executedTools.push("black");
|
|
93
|
-
toolTimings.push({ tool: "black", duration_ms: Date.now() - blackStart });
|
|
94
|
-
}
|
|
102
|
+
], executedTools, failedTools, toolTimings);
|
|
95
103
|
}
|
|
96
104
|
// SQL
|
|
97
105
|
if (extensions.has("sql")) {
|
|
98
|
-
|
|
99
|
-
if (tryRunConfiguredFormatter(root, [
|
|
106
|
+
runFormatter(root, "sqlfluff", [
|
|
100
107
|
{ command: "sqlfluff", args: ["fix", "--force", "."], display: "sqlfluff fix --force ." },
|
|
101
108
|
{ command: "uvx", args: ["sqlfluff", "fix", "--force", "."], display: "uvx sqlfluff fix --force ." },
|
|
102
109
|
{ command: "pipx", args: ["run", "sqlfluff", "fix", "--force", "."], display: "pipx run sqlfluff fix --force ." },
|
|
103
|
-
])
|
|
104
|
-
executedTools.push("sqlfluff");
|
|
105
|
-
toolTimings.push({ tool: "sqlfluff", duration_ms: Date.now() - sqlfluffStart });
|
|
106
|
-
}
|
|
110
|
+
], executedTools, failedTools, toolTimings);
|
|
107
111
|
}
|
|
108
112
|
// Go
|
|
109
113
|
if (extensions.has("go")) {
|
|
110
|
-
|
|
111
|
-
if (tryRunConfiguredFormatter(root, [
|
|
114
|
+
runFormatter(root, "gofmt", [
|
|
112
115
|
{ command: "gofmt", args: ["-w", "."], display: "gofmt -w ." },
|
|
113
|
-
])
|
|
114
|
-
executedTools.push("gofmt");
|
|
115
|
-
toolTimings.push({ tool: "gofmt", duration_ms: Date.now() - gofmtStart });
|
|
116
|
-
}
|
|
116
|
+
], executedTools, failedTools, toolTimings);
|
|
117
117
|
}
|
|
118
118
|
const resultsArtifact = {
|
|
119
119
|
executed_tools: executedTools,
|
|
120
|
+
failed_tools: failedTools,
|
|
120
121
|
tool_timings: toolTimings,
|
|
121
122
|
timestamp: new Date().toISOString(),
|
|
122
123
|
};
|
|
124
|
+
let progressDetail;
|
|
125
|
+
if (executedTools.length === 0 && failedTools.length === 0) {
|
|
126
|
+
progressDetail = "Formatters executed: None.";
|
|
127
|
+
}
|
|
128
|
+
else if (failedTools.length === 0) {
|
|
129
|
+
progressDetail = `Formatters executed: ${executedTools.join(", ")}.`;
|
|
130
|
+
}
|
|
131
|
+
else if (executedTools.length === 0) {
|
|
132
|
+
progressDetail = `Formatters executed: None. Formatters failed: ${failedTools.join(", ")}.`;
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
progressDetail = `Formatters executed: ${executedTools.join(", ")}. Formatters failed: ${failedTools.join(", ")}.`;
|
|
136
|
+
}
|
|
123
137
|
return {
|
|
124
138
|
updated: {
|
|
125
139
|
...bundle,
|
|
126
140
|
auto_fixes_applied: resultsArtifact,
|
|
127
141
|
},
|
|
128
142
|
artifacts_written: ["auto_fixes_applied.json"],
|
|
129
|
-
progress_summary: `Phase 1 Deterministic Auto-Fix complete.
|
|
143
|
+
progress_summary: `Phase 1 Deterministic Auto-Fix complete. ${progressDetail}`,
|
|
130
144
|
};
|
|
131
145
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Invalidation map keyed by UPSTREAM artifact → the list of DOWNSTREAM
|
|
2
2
|
// artifacts that depend on it (and so become stale when it changes). The name
|
|
3
3
|
// reflects the actual direction: each entry's value is that key's *dependents*.
|
|
4
|
-
// `
|
|
4
|
+
// `buildArtifactDependenciesMap` flips this to the "X depends on Y" view used by
|
|
5
5
|
// computeArtifactMetadata. (Renamed from the misleading ARTIFACT_DEPENDENCY_MAP,
|
|
6
6
|
// which read as "X's dependencies" — the opposite of what it stores.)
|
|
7
7
|
export const ARTIFACT_DEPENDENTS_MAP = {
|
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
import type { ArtifactBundle } from "../io/artifacts.js";
|
|
2
|
+
/**
|
|
3
|
+
* Structured log event emitted during an executor step. Machine consumers should
|
|
4
|
+
* read `log_entries` and `degraded` on `ExecutorRunResult` rather than parsing
|
|
5
|
+
* `progress_summary`.
|
|
6
|
+
*/
|
|
7
|
+
export interface LogEntry {
|
|
8
|
+
severity: "debug" | "info" | "warn" | "error";
|
|
9
|
+
message: string;
|
|
10
|
+
timestamp_ms: number;
|
|
11
|
+
/** Contextual key/value pairs such as task_id, run_id, analyzer name, file path. */
|
|
12
|
+
context?: Record<string, unknown>;
|
|
13
|
+
}
|
|
2
14
|
/**
|
|
3
15
|
* Resolved audit scope, emitted by the intake executor so the conversation-first
|
|
4
16
|
* loader can echo what is about to be audited (and gate on confirmation when a
|
|
@@ -23,6 +35,9 @@ export interface ScopeSummary {
|
|
|
23
35
|
* artifact filenames it wrote (which drive metadata/staleness bookkeeping in
|
|
24
36
|
* advanceAudit), and a one-line human progress summary. Shared by every executor
|
|
25
37
|
* module so they need not depend on the internalExecutors barrel.
|
|
38
|
+
*
|
|
39
|
+
* `progress_summary` is a human-readable one-liner for UI display only. Machine
|
|
40
|
+
* consumers should read `log_entries` and `degraded` instead of parsing it.
|
|
26
41
|
*/
|
|
27
42
|
export interface ExecutorRunResult {
|
|
28
43
|
updated: ArtifactBundle;
|
|
@@ -34,4 +49,22 @@ export interface ExecutorRunResult {
|
|
|
34
49
|
* `mis_scope_smells` is non-empty.
|
|
35
50
|
*/
|
|
36
51
|
scope_summary?: ScopeSummary;
|
|
52
|
+
/**
|
|
53
|
+
* Structured log events emitted during the step (errors, warnings, partial
|
|
54
|
+
* failures, analyzer skips). Machine consumers should read this instead of
|
|
55
|
+
* parsing `progress_summary`.
|
|
56
|
+
*/
|
|
57
|
+
log_entries?: LogEntry[];
|
|
58
|
+
/**
|
|
59
|
+
* Wall-clock milliseconds from executor entry to return, enabling step-latency
|
|
60
|
+
* tracking without string-parsing.
|
|
61
|
+
*/
|
|
62
|
+
step_duration_ms?: number;
|
|
63
|
+
/**
|
|
64
|
+
* Set to `true` when the step completed but encountered at least one non-fatal
|
|
65
|
+
* error (e.g. a language-analyzer failure, a line-count error, a missing task
|
|
66
|
+
* artifact). Lets callers detect partial failure without scanning
|
|
67
|
+
* `progress_summary`.
|
|
68
|
+
*/
|
|
69
|
+
degraded?: boolean;
|
|
37
70
|
}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
export interface ExecutorDefinition {
|
|
2
2
|
id: string;
|
|
3
|
+
kind: "deterministic" | "host_delegation";
|
|
3
4
|
obligation_ids: string[];
|
|
4
5
|
description: string;
|
|
5
6
|
}
|
|
7
|
+
/**
|
|
8
|
+
* Returns true when the executor identified by `id` is a host-delegation point
|
|
9
|
+
* (i.e. it pauses the deterministic pipeline and asks the active LLM agent to
|
|
10
|
+
* perform work) rather than a deterministic executor.
|
|
11
|
+
*/
|
|
12
|
+
export declare function isHostDelegationExecutor(id: string): boolean;
|
|
6
13
|
export declare const EXECUTOR_REGISTRY: ExecutorDefinition[];
|
|
@@ -1,76 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns true when the executor identified by `id` is a host-delegation point
|
|
3
|
+
* (i.e. it pauses the deterministic pipeline and asks the active LLM agent to
|
|
4
|
+
* perform work) rather than a deterministic executor.
|
|
5
|
+
*/
|
|
6
|
+
export function isHostDelegationExecutor(id) {
|
|
7
|
+
const entry = EXECUTOR_REGISTRY.find((e) => e.id === id);
|
|
8
|
+
return entry?.kind === "host_delegation";
|
|
9
|
+
}
|
|
1
10
|
export const EXECUTOR_REGISTRY = [
|
|
2
11
|
{
|
|
3
12
|
id: "intake_executor",
|
|
13
|
+
kind: "deterministic",
|
|
4
14
|
obligation_ids: ["repo_manifest", "file_disposition"],
|
|
5
15
|
description: "Create intake artifacts for repository discovery and disposition.",
|
|
6
16
|
},
|
|
7
17
|
{
|
|
8
18
|
id: "structure_executor",
|
|
19
|
+
kind: "deterministic",
|
|
9
20
|
obligation_ids: ["structure_artifacts"],
|
|
10
21
|
description: "Build structure artifacts such as units, surfaces, graphs, flows, and risk.",
|
|
11
22
|
},
|
|
12
23
|
{
|
|
13
24
|
id: "graph_enrichment_executor",
|
|
25
|
+
kind: "deterministic",
|
|
14
26
|
obligation_ids: ["graph_enrichment_current"],
|
|
15
27
|
description: "Layer optional language-analyzer edges onto the deterministic graph (regex floor preserved); record analyzer provenance.",
|
|
16
28
|
},
|
|
17
29
|
{
|
|
18
30
|
id: "design_assessment_executor",
|
|
31
|
+
kind: "deterministic",
|
|
19
32
|
obligation_ids: ["design_assessment_current"],
|
|
20
33
|
description: "Run deterministic structural analysis to assess overall project design.",
|
|
21
34
|
},
|
|
22
35
|
{
|
|
23
36
|
id: "design_review",
|
|
37
|
+
kind: "host_delegation",
|
|
24
38
|
obligation_ids: ["design_review_completed"],
|
|
25
39
|
description: "Pause the pipeline and delegate a holistic project design review to the active LLM agent.",
|
|
26
40
|
},
|
|
27
41
|
{
|
|
28
42
|
id: "planning_executor",
|
|
43
|
+
kind: "deterministic",
|
|
29
44
|
obligation_ids: ["planning_artifacts"],
|
|
30
45
|
description: "Build coverage, tasks, runtime validation planning artifacts, and related planning outputs.",
|
|
31
46
|
},
|
|
32
47
|
{
|
|
33
48
|
id: "result_ingestion_executor",
|
|
49
|
+
kind: "deterministic",
|
|
34
50
|
obligation_ids: ["audit_results_ingested"],
|
|
35
51
|
description: "Ingest available audit result artifacts and refresh dependent coverage artifacts.",
|
|
36
52
|
},
|
|
37
53
|
{
|
|
38
54
|
id: "runtime_validation_executor",
|
|
55
|
+
kind: "deterministic",
|
|
39
56
|
obligation_ids: ["runtime_validation_current"],
|
|
40
57
|
description: "Merge runtime validation evidence updates when provided.",
|
|
41
58
|
},
|
|
42
59
|
{
|
|
43
60
|
id: "runtime_validation_update_executor",
|
|
61
|
+
kind: "deterministic",
|
|
44
62
|
obligation_ids: [],
|
|
45
63
|
description: "Merge imported runtime validation evidence updates.",
|
|
46
64
|
},
|
|
47
65
|
{
|
|
48
66
|
id: "synthesis_executor",
|
|
67
|
+
kind: "deterministic",
|
|
49
68
|
obligation_ids: ["synthesis_current"],
|
|
50
69
|
description: "Emit the canonical audit-findings.json and render the deterministic Markdown audit report.",
|
|
51
70
|
},
|
|
52
71
|
{
|
|
53
72
|
id: "synthesis_narrative_executor",
|
|
73
|
+
kind: "deterministic",
|
|
54
74
|
obligation_ids: ["synthesis_narrative_current"],
|
|
55
75
|
description: "Resolve the optional synthesis narrative (themes, executive summary, top risks); omit deterministically without a provider.",
|
|
56
76
|
},
|
|
57
77
|
{
|
|
58
78
|
id: "external_analyzer_import_executor",
|
|
79
|
+
kind: "deterministic",
|
|
59
80
|
obligation_ids: [],
|
|
60
81
|
description: "Import normalized external analyzer results into the artifact set.",
|
|
61
82
|
},
|
|
62
83
|
{
|
|
63
84
|
id: "auto_fix_executor",
|
|
85
|
+
kind: "deterministic",
|
|
64
86
|
obligation_ids: ["auto_fixes_applied"],
|
|
65
87
|
description: "Run configured deterministic code formatters to apply surface-level fixes automatically.",
|
|
66
88
|
},
|
|
67
89
|
{
|
|
68
90
|
id: "syntax_resolution_executor",
|
|
91
|
+
kind: "deterministic",
|
|
69
92
|
obligation_ids: ["syntax_resolved"],
|
|
70
93
|
description: "Run deterministic static analysis/compilers and extract any remaining unfixable syntactical errors into external signals.",
|
|
71
94
|
},
|
|
72
95
|
{
|
|
73
96
|
id: "agent",
|
|
97
|
+
kind: "host_delegation",
|
|
74
98
|
obligation_ids: ["audit_tasks_completed"],
|
|
75
99
|
description: "Pause the pipeline and delegate pending codebase review tasks or syntax resolutions to the active LLM agent.",
|
|
76
100
|
},
|
|
@@ -7,7 +7,13 @@
|
|
|
7
7
|
*/
|
|
8
8
|
const GRAPH_EDGE_BUCKETS = ["imports", "calls", "references"];
|
|
9
9
|
const MAX_ANCHORS = 160;
|
|
10
|
-
|
|
10
|
+
// Keywords that signal elevated-risk or review-worthy lines, grouped by concern:
|
|
11
|
+
// auth/access: auth, password, permission, role, secret, token
|
|
12
|
+
// injection/execution: deserialize, eval, exec, query, spawn, sql
|
|
13
|
+
// crypto: decrypt, encrypt
|
|
14
|
+
// concurrency/reliability: cache, lock, race, retry, timeout, transaction
|
|
15
|
+
// debt markers: FIXME, TODO
|
|
16
|
+
const KEYWORD_PATTERN = /\b(auth|password|permission|role|secret|token|deserialize|eval|exec|query|spawn|sql|decrypt|encrypt|cache|lock|race|retry|timeout|transaction|FIXME|TODO)\b/i;
|
|
11
17
|
const SYMBOL_PATTERNS = [
|
|
12
18
|
{
|
|
13
19
|
kind: "import",
|
|
@@ -124,6 +130,35 @@ function collectGraphEdges(graphBundle, path) {
|
|
|
124
130
|
a.from.localeCompare(b.from) ||
|
|
125
131
|
a.to.localeCompare(b.to));
|
|
126
132
|
}
|
|
133
|
+
function scanSymbol(line, lineNumber, anchors, seen) {
|
|
134
|
+
for (const { kind, pattern, label } of SYMBOL_PATTERNS) {
|
|
135
|
+
const match = line.match(pattern);
|
|
136
|
+
if (!match) {
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
const name = match.slice(1).find((value) => value && value.trim().length > 0) ?? label;
|
|
140
|
+
addAnchor(anchors, seen, {
|
|
141
|
+
kind,
|
|
142
|
+
name: truncate(name, 80),
|
|
143
|
+
line: lineNumber,
|
|
144
|
+
detail: truncate(`${label}: ${line}`, 180),
|
|
145
|
+
});
|
|
146
|
+
return kind;
|
|
147
|
+
}
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
function scanKeyword(line, lineNumber, anchors, seen) {
|
|
151
|
+
if (!KEYWORD_PATTERN.test(line)) {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
addAnchor(anchors, seen, {
|
|
155
|
+
kind: "keyword",
|
|
156
|
+
name: truncate(line.match(KEYWORD_PATTERN)?.[1] ?? "keyword", 80),
|
|
157
|
+
line: lineNumber,
|
|
158
|
+
detail: truncate(line, 180),
|
|
159
|
+
});
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
127
162
|
export function buildFileAnchorSummary(params) {
|
|
128
163
|
const anchors = [];
|
|
129
164
|
const seen = new Set();
|
|
@@ -148,35 +183,13 @@ export function buildFileAnchorSummary(params) {
|
|
|
148
183
|
}
|
|
149
184
|
lines.forEach((line, index) => {
|
|
150
185
|
const lineNumber = index + 1;
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
if (kind === "route") {
|
|
158
|
-
routeCount += 1;
|
|
159
|
-
}
|
|
160
|
-
else if (kind === "symbol") {
|
|
161
|
-
symbolCount += 1;
|
|
162
|
-
}
|
|
163
|
-
addAnchor(anchors, seen, {
|
|
164
|
-
kind,
|
|
165
|
-
name: truncate(name, 80),
|
|
166
|
-
line: lineNumber,
|
|
167
|
-
detail: truncate(`${label}: ${line}`, 180),
|
|
168
|
-
});
|
|
169
|
-
break;
|
|
170
|
-
}
|
|
171
|
-
if (KEYWORD_PATTERN.test(line)) {
|
|
186
|
+
const symbolKind = scanSymbol(line, lineNumber, anchors, seen);
|
|
187
|
+
if (symbolKind === "route")
|
|
188
|
+
routeCount += 1;
|
|
189
|
+
else if (symbolKind === "symbol")
|
|
190
|
+
symbolCount += 1;
|
|
191
|
+
if (scanKeyword(line, lineNumber, anchors, seen))
|
|
172
192
|
keywordCount += 1;
|
|
173
|
-
addAnchor(anchors, seen, {
|
|
174
|
-
kind: "keyword",
|
|
175
|
-
name: truncate(line.match(KEYWORD_PATTERN)?.[1] ?? "keyword", 80),
|
|
176
|
-
line: lineNumber,
|
|
177
|
-
detail: truncate(line, 180),
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
193
|
});
|
|
181
194
|
const graphEdges = collectGraphEdges(params.graphBundle, path);
|
|
182
195
|
for (const edge of graphEdges) {
|
|
@@ -36,7 +36,12 @@ export async function checkFileIntegrity(root, manifest, scope) {
|
|
|
36
36
|
missing.push(record.path);
|
|
37
37
|
}
|
|
38
38
|
else {
|
|
39
|
-
console.warn(
|
|
39
|
+
console.warn('fileIntegrity: I/O error', {
|
|
40
|
+
root,
|
|
41
|
+
scope_size: files.length,
|
|
42
|
+
file: record.path,
|
|
43
|
+
code: code ?? String(err),
|
|
44
|
+
});
|
|
40
45
|
ioErrors.push(record.path);
|
|
41
46
|
}
|
|
42
47
|
}
|
|
@@ -32,8 +32,7 @@ export function buildFlowCoverage(criticalFlows, coverageMatrix) {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
const completed_lenses = [...completed];
|
|
35
|
-
const status = required.
|
|
36
|
-
required.every((lens) => completed_lenses.includes(lens))
|
|
35
|
+
const status = required.every((lens) => completed_lenses.includes(lens))
|
|
37
36
|
? "complete"
|
|
38
37
|
: completed_lenses.length > 0
|
|
39
38
|
? "partial"
|
|
@@ -1,21 +1,25 @@
|
|
|
1
|
-
const
|
|
1
|
+
const FLOW_REVIEW_LENSES = [
|
|
2
2
|
"security",
|
|
3
3
|
"reliability",
|
|
4
4
|
"correctness",
|
|
5
|
+
"data_integrity",
|
|
6
|
+
"operability",
|
|
7
|
+
"performance",
|
|
8
|
+
"observability",
|
|
5
9
|
];
|
|
6
10
|
function lensPathKey(lens, path) {
|
|
7
11
|
return `${lens}:${path}`;
|
|
8
12
|
}
|
|
9
13
|
function flowLensPriority(lens) {
|
|
10
|
-
const index =
|
|
11
|
-
return index >= 0 ? index :
|
|
14
|
+
const index = FLOW_REVIEW_LENSES.indexOf(lens);
|
|
15
|
+
return index >= 0 ? index : FLOW_REVIEW_LENSES.length;
|
|
12
16
|
}
|
|
13
17
|
export function claimFlowReviewBlocks(criticalFlows, pendingByLens, assigned) {
|
|
14
18
|
const candidates = [];
|
|
15
19
|
for (const flow of criticalFlows.flows) {
|
|
16
20
|
const flowPaths = [...new Set(flow.paths)].sort((a, b) => a.localeCompare(b));
|
|
17
21
|
const desiredLenses = flow.concerns
|
|
18
|
-
.filter((concern) =>
|
|
22
|
+
.filter((concern) => FLOW_REVIEW_LENSES.includes(concern))
|
|
19
23
|
.sort((a, b) => flowLensPriority(a) - flowLensPriority(b));
|
|
20
24
|
for (const lens of desiredLenses) {
|
|
21
25
|
const pendingPaths = pendingByLens.get(lens);
|
|
@@ -39,6 +39,58 @@ function mergeRoutes(floor, analyzer) {
|
|
|
39
39
|
a.handler.localeCompare(b.handler) ||
|
|
40
40
|
(a.method ?? "").localeCompare(b.method ?? ""));
|
|
41
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Run one analyzer: resolve its dependency, invoke analyze(), and return a
|
|
44
|
+
* discriminated result. Early-exit guards (not_applicable / skip / absent-root)
|
|
45
|
+
* are handled by the caller; this helper starts from a confirmed runnable state.
|
|
46
|
+
*/
|
|
47
|
+
async function runSingleAnalyzer(analyzer, root, setting, bundle, pathLookup, includedFiles, disposition, cacheRoot) {
|
|
48
|
+
const run = resolveForRun(analyzer, root, setting, cacheRoot);
|
|
49
|
+
if (run.resolution === "absent") {
|
|
50
|
+
return { ok: false, note: run.note ?? "Dependency absent.", resolution: "absent" };
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
const output = await analyzer.analyze(includedFiles.filter((f) => analyzer.supports(f)), {
|
|
54
|
+
root,
|
|
55
|
+
repoManifest: bundle.repo_manifest,
|
|
56
|
+
disposition,
|
|
57
|
+
includedFiles,
|
|
58
|
+
pathLookup,
|
|
59
|
+
dependencyPath: run.path,
|
|
60
|
+
});
|
|
61
|
+
return {
|
|
62
|
+
ok: true,
|
|
63
|
+
edges: output.edges ?? [],
|
|
64
|
+
routes: output.routes ?? [],
|
|
65
|
+
resolution: run.resolution,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
const note = error instanceof Error
|
|
70
|
+
? `Analyzer failed [${error.name}]: ${error.message}${error.stack ? ` — stack: ${error.stack.split("\n").slice(0, 4).join(" | ")}` : ""}`
|
|
71
|
+
: `Analyzer failed: ${String(error)}.`;
|
|
72
|
+
return { ok: false, note, resolution: run.resolution };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Assemble the enriched GraphBundle from the regex floor plus per-bucket
|
|
77
|
+
* analyzer edges and merged route edges.
|
|
78
|
+
*/
|
|
79
|
+
function buildEnrichedGraph(floor, bucketEdges, routeEdges, analyzersUsed) {
|
|
80
|
+
return {
|
|
81
|
+
...floor,
|
|
82
|
+
graphs: {
|
|
83
|
+
...floor.graphs,
|
|
84
|
+
imports: mergeAnalyzerEdges(floor.graphs.imports ?? [], bucketEdges.imports),
|
|
85
|
+
calls: mergeAnalyzerEdges(floor.graphs.calls ?? [], bucketEdges.calls),
|
|
86
|
+
references: mergeAnalyzerEdges(floor.graphs.references ?? [], bucketEdges.references),
|
|
87
|
+
...(routeEdges.length > 0
|
|
88
|
+
? { routes: mergeRoutes(floor.graphs.routes ?? [], routeEdges) }
|
|
89
|
+
: {}),
|
|
90
|
+
},
|
|
91
|
+
analyzers_used: [...new Set(analyzersUsed)].sort(),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
42
94
|
/**
|
|
43
95
|
* Resolve a dependency for actual execution (may install for ephemeral/permanent).
|
|
44
96
|
* `auto`/`repo` with an absent dependency falls back to the regex floor.
|
|
@@ -107,38 +159,16 @@ export async function runGraphEnrichmentExecutor(bundle, options = {}) {
|
|
|
107
159
|
entries.push({ id: analyzer.id, resolution: "absent", setting, edges_added: 0, routes_added: 0, note: "No repository root available for analysis." });
|
|
108
160
|
continue;
|
|
109
161
|
}
|
|
110
|
-
const
|
|
111
|
-
if (
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
try {
|
|
118
|
-
const output = await analyzer.analyze(supportedFiles, {
|
|
119
|
-
root,
|
|
120
|
-
repoManifest: bundle.repo_manifest,
|
|
121
|
-
disposition,
|
|
122
|
-
includedFiles,
|
|
123
|
-
pathLookup,
|
|
124
|
-
dependencyPath: run.path,
|
|
125
|
-
});
|
|
126
|
-
edges = output.edges ?? [];
|
|
127
|
-
routes = output.routes ?? [];
|
|
128
|
-
}
|
|
129
|
-
catch (error) {
|
|
130
|
-
entries.push({
|
|
131
|
-
id: analyzer.id,
|
|
132
|
-
resolution: run.resolution,
|
|
133
|
-
setting,
|
|
134
|
-
edges_added: 0,
|
|
135
|
-
routes_added: 0,
|
|
136
|
-
note: error instanceof Error
|
|
137
|
-
? `Analyzer failed [${error.name}]: ${error.message}${error.stack ? ` — stack: ${error.stack.split("\n").slice(0, 4).join(" | ")}` : ""}`
|
|
138
|
-
: `Analyzer failed: ${String(error)}.`,
|
|
139
|
-
});
|
|
162
|
+
const result = await runSingleAnalyzer(analyzer, root, setting, bundle, pathLookup, includedFiles, disposition, options.cacheRoot);
|
|
163
|
+
if (!result.ok) {
|
|
164
|
+
const entry = { id: analyzer.id, resolution: result.resolution, setting, edges_added: 0, routes_added: 0, note: result.note };
|
|
165
|
+
entries.push(entry);
|
|
166
|
+
if (entry.note?.startsWith("Analyzer failed")) {
|
|
167
|
+
console.warn(`[graph-enrichment] Analyzer '${analyzer.id}' failed: ${entry.note}`);
|
|
168
|
+
}
|
|
140
169
|
continue;
|
|
141
170
|
}
|
|
171
|
+
const { edges, routes, resolution } = result;
|
|
142
172
|
for (const edge of edges) {
|
|
143
173
|
bucketEdges[bucketForKind(edge.kind)].push(edge);
|
|
144
174
|
}
|
|
@@ -146,7 +176,7 @@ export async function runGraphEnrichmentExecutor(bundle, options = {}) {
|
|
|
146
176
|
if (edges.length + routes.length > 0) {
|
|
147
177
|
analyzersUsed.push(analyzer.id);
|
|
148
178
|
}
|
|
149
|
-
entries.push({ id: analyzer.id, resolution
|
|
179
|
+
entries.push({ id: analyzer.id, resolution, setting, edges_added: edges.length, routes_added: routes.length });
|
|
150
180
|
}
|
|
151
181
|
const applied = analyzersUsed.length > 0;
|
|
152
182
|
const record = {
|
|
@@ -158,19 +188,7 @@ export async function runGraphEnrichmentExecutor(bundle, options = {}) {
|
|
|
158
188
|
// reasons of low-confidence edges on whichever graph stands — the floor's
|
|
159
189
|
// heuristic edges exist regardless of analyzers.
|
|
160
190
|
const graphBundle = applied
|
|
161
|
-
?
|
|
162
|
-
...floor,
|
|
163
|
-
graphs: {
|
|
164
|
-
...floor.graphs,
|
|
165
|
-
imports: mergeAnalyzerEdges(floor.graphs.imports ?? [], bucketEdges.imports),
|
|
166
|
-
calls: mergeAnalyzerEdges(floor.graphs.calls ?? [], bucketEdges.calls),
|
|
167
|
-
references: mergeAnalyzerEdges(floor.graphs.references ?? [], bucketEdges.references),
|
|
168
|
-
...(routeEdges.length > 0
|
|
169
|
-
? { routes: mergeRoutes(floor.graphs.routes ?? [], routeEdges) }
|
|
170
|
-
: {}),
|
|
171
|
-
},
|
|
172
|
-
analyzers_used: [...new Set(analyzersUsed)].sort(),
|
|
173
|
-
}
|
|
191
|
+
? buildEnrichedGraph(floor, bucketEdges, routeEdges, analyzersUsed)
|
|
174
192
|
: floor;
|
|
175
193
|
let reasoned = { rewritten: 0, candidates: 0 };
|
|
176
194
|
if (options.llmEdgeReasoning === true && options.edgeReasoning) {
|
|
@@ -181,10 +199,14 @@ export async function runGraphEnrichmentExecutor(bundle, options = {}) {
|
|
|
181
199
|
? ` Edge reasoning rewrote ${reasoned.rewritten} reason(s).`
|
|
182
200
|
: "";
|
|
183
201
|
if (!graphChanged) {
|
|
202
|
+
const failedEntries = entries.filter((e) => e.note?.startsWith("Analyzer failed"));
|
|
203
|
+
const failureSuffix = failedEntries.length > 0
|
|
204
|
+
? `; ${failedEntries.length} analyzer(s) failed: ${failedEntries.map((e) => e.id).join(", ")} (see analyzer_capability.json)`
|
|
205
|
+
: "";
|
|
184
206
|
return {
|
|
185
207
|
updated: { ...bundle, analyzer_capability: record },
|
|
186
208
|
artifacts_written: ["analyzer_capability.json"],
|
|
187
|
-
progress_summary:
|
|
209
|
+
progress_summary: `Graph enrichment omitted; deterministic regex graph retained.${failureSuffix}`,
|
|
188
210
|
};
|
|
189
211
|
}
|
|
190
212
|
const totalEdges = entries.reduce((sum, entry) => sum + entry.edges_added, 0);
|
|
@@ -139,6 +139,8 @@ export async function runRuntimeValidationExecutor(bundle, root, options = {}) {
|
|
|
139
139
|
const existing = bundle.runtime_validation_report ?? { results: [] };
|
|
140
140
|
const byTaskId = new Map(existing.results.map((result) => [result.task_id, result]));
|
|
141
141
|
const byCommand = new Map();
|
|
142
|
+
let uniqueCommandsRun = 0;
|
|
143
|
+
let deduplicatedHits = 0;
|
|
142
144
|
for (const task of bundle.runtime_validation_tasks.tasks) {
|
|
143
145
|
const prior = byTaskId.get(task.id);
|
|
144
146
|
if (prior &&
|
|
@@ -156,6 +158,12 @@ export async function runRuntimeValidationExecutor(bundle, root, options = {}) {
|
|
|
156
158
|
continue;
|
|
157
159
|
}
|
|
158
160
|
const signature = task.command.join("\0");
|
|
161
|
+
if (byCommand.has(signature)) {
|
|
162
|
+
deduplicatedHits++;
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
uniqueCommandsRun++;
|
|
166
|
+
}
|
|
159
167
|
const outcome = byCommand.get(signature) ?? (await runCommand(task.command, root, { opentoken: options.opentoken }));
|
|
160
168
|
byCommand.set(signature, outcome);
|
|
161
169
|
byTaskId.set(task.id, {
|
|
@@ -185,7 +193,7 @@ export async function runRuntimeValidationExecutor(bundle, root, options = {}) {
|
|
|
185
193
|
"runtime_validation_report.json",
|
|
186
194
|
...selectiveDeepening.artifacts,
|
|
187
195
|
],
|
|
188
|
-
progress_summary: `Executed deterministic runtime validation for ${bundle.runtime_validation_tasks.tasks.length} task(s).` +
|
|
196
|
+
progress_summary: `Executed deterministic runtime validation for ${bundle.runtime_validation_tasks.tasks.length} task(s) (${uniqueCommandsRun} unique command(s) run, ${deduplicatedHits} served from deduplication cache).` +
|
|
189
197
|
selectiveDeepening.summarySuffix,
|
|
190
198
|
};
|
|
191
199
|
}
|
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import type { ArtifactBundle } from "../io/artifacts.js";
|
|
2
2
|
import type { ExecutorRunResult } from "./executorResult.js";
|
|
3
|
-
/** Prefix used to carry the scope summary inside `progress_summary` for hosts
|
|
4
|
-
* that read the step's progress text rather than the `scope_summary.json`
|
|
5
|
-
* artifact. The loader extracts everything after this marker as JSON. */
|
|
6
|
-
export declare const SCOPE_SUMMARY_PREFIX = "SCOPE_SUMMARY:";
|
|
7
3
|
/**
|
|
8
4
|
* Detect signals that the resolved audit root may be the *wrong* directory.
|
|
9
5
|
* Two heuristics, returned as zero or more human-readable warnings:
|