auditor-lambda 0.10.7 → 0.11.0
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/README.md +5 -0
- package/audit-code-wrapper-install-hosts.mjs +1 -1
- package/audit-code-wrapper-lib.mjs +5 -5
- package/audit-code-wrapper-opencode.mjs +2 -3
- package/dist/cli/advanceAuditCommand.js +2 -2
- package/dist/cli/args.d.ts +3 -3
- package/dist/cli/args.js +5 -8
- package/dist/cli/dispatch.d.ts +1 -0
- package/dist/cli/dispatch.js +24 -5
- package/dist/cli/nextStepCommand.js +2 -4
- package/dist/cli/prompts.js +7 -6
- package/dist/cli/resynthesizeCommand.d.ts +1 -0
- package/dist/cli/resynthesizeCommand.js +50 -0
- package/dist/cli/runToCompletion.js +2 -2
- package/dist/cli.js +5 -1
- package/dist/extractors/fsIntake.js +1 -1
- package/dist/extractors/pathPatterns.js +1 -1
- package/dist/io/artifacts.d.ts +3 -2
- package/dist/io/artifacts.js +6 -4
- package/dist/io/runArtifacts.js +1 -1
- package/dist/orchestrator/advance.js +6 -0
- package/dist/orchestrator/dependencyMap.js +7 -0
- package/dist/orchestrator/designReviewPrompt.js +31 -10
- package/dist/orchestrator/executors.js +6 -0
- package/dist/orchestrator/ingestionExecutors.js +29 -1
- package/dist/orchestrator/intentCheckpointExecutor.d.ts +3 -0
- package/dist/orchestrator/intentCheckpointExecutor.js +29 -0
- package/dist/orchestrator/lensSelection.d.ts +32 -0
- package/dist/orchestrator/lensSelection.js +69 -0
- package/dist/orchestrator/planningExecutors.js +18 -3
- package/dist/orchestrator.d.ts +1 -1
- package/dist/orchestrator.js +3 -4
- package/dist/prompts/renderWorkerPrompt.js +6 -0
- package/dist/providers/claudeCodeProvider.js +1 -1
- package/dist/quota/index.d.ts +5 -3
- package/dist/quota/index.js +1 -1
- package/dist/reporting/synthesis.d.ts +10 -0
- package/dist/reporting/synthesis.js +23 -0
- package/dist/reporting/synthesisNarrativePrompt.js +3 -1
- package/docs/development.md +6 -0
- package/package.json +2 -1
- package/schemas/audit_findings.schema.json +14 -1
- package/schemas/dispatch_quota.schema.json +86 -2
- package/schemas/finding.schema.json +14 -1
- package/scripts/postinstall.mjs +1 -2
- package/skills/audit-code/audit-code.prompt.md +1 -1
package/README.md
CHANGED
|
@@ -212,11 +212,16 @@ Optional backend config:
|
|
|
212
212
|
|
|
213
213
|
```bash
|
|
214
214
|
npm install
|
|
215
|
+
npm run test:single -- tests/next-step.test.mjs
|
|
215
216
|
npm run verify:release
|
|
216
217
|
npm run release:patch
|
|
217
218
|
npm run release:patch:publish
|
|
218
219
|
```
|
|
219
220
|
|
|
221
|
+
When developing from a fresh clone or git worktree, run repo-root `npm install`
|
|
222
|
+
before package checks. Missing workspace links can look like stale
|
|
223
|
+
`@audit-tools/shared` export or type errors.
|
|
224
|
+
|
|
220
225
|
For GitHub Actions publication and npm Trusted Publishing setup, see `docs/release.md`.
|
|
221
226
|
|
|
222
227
|
## Key Docs
|
|
@@ -720,7 +720,7 @@ export async function installBootstrap(argv, options = {}) {
|
|
|
720
720
|
);
|
|
721
721
|
results.push(await writeGeneratedJson(installManifestPath, installManifest));
|
|
722
722
|
|
|
723
|
-
const sessionConfigPath = join(root, '.audit-
|
|
723
|
+
const sessionConfigPath = join(root, '.audit-tools', 'audit', 'session-config.json');
|
|
724
724
|
if (!(await fileExists(sessionConfigPath))) {
|
|
725
725
|
const defaultConfig = { provider: 'local-subprocess' };
|
|
726
726
|
await mkdir(dirname(sessionConfigPath), { recursive: true });
|
|
@@ -123,7 +123,7 @@ function printHelp({ usageName, preferredEntrypoint }) {
|
|
|
123
123
|
'- verify-install smoke-tests the generated host assets after install',
|
|
124
124
|
'- mcp starts the local stdio MCP server for repo-local IDE integrations',
|
|
125
125
|
'- install-host --host copilot keeps the narrower Copilot-focused install path available',
|
|
126
|
-
'- next-step advances deterministic audit state and writes .audit-
|
|
126
|
+
'- next-step advances deterministic audit state and writes .audit-tools/audit/steps/current-step.json plus current-prompt.md',
|
|
127
127
|
'- validate checks the current artifact bundle plus session-config/provider readiness and exits non-zero when issues exist',
|
|
128
128
|
'- validate-results --results FILE validates AuditResult payloads against the active task manifest without ingesting them',
|
|
129
129
|
'- explain-task <task_id> prints the resolved file coverage and current status for a task id',
|
|
@@ -141,7 +141,7 @@ function printHelp({ usageName, preferredEntrypoint }) {
|
|
|
141
141
|
'',
|
|
142
142
|
'Defaults:',
|
|
143
143
|
'- --root .',
|
|
144
|
-
'- --artifacts-dir <root>/.audit-
|
|
144
|
+
'- --artifacts-dir <root>/.audit-tools/audit',
|
|
145
145
|
'',
|
|
146
146
|
'Completion signals:',
|
|
147
147
|
'- done: audit_state.status is complete',
|
|
@@ -166,7 +166,7 @@ async function printPromptPath() {
|
|
|
166
166
|
async function runDistCommand(commandName, argv, { ensureArtifactsDir = false } = {}) {
|
|
167
167
|
const commandArgs = [...argv];
|
|
168
168
|
const rootValue = resolve(getFlag(commandArgs, '--root') ?? '.');
|
|
169
|
-
const artifactsDir = resolve(getFlag(commandArgs, '--artifacts-dir') ?? join(rootValue, '.audit-
|
|
169
|
+
const artifactsDir = resolve(getFlag(commandArgs, '--artifacts-dir') ?? join(rootValue, '.audit-tools', 'audit'));
|
|
170
170
|
|
|
171
171
|
setDefaultFlag(commandArgs, '--root', rootValue);
|
|
172
172
|
setDefaultFlag(commandArgs, '--artifacts-dir', artifactsDir);
|
|
@@ -184,7 +184,7 @@ async function runDistCommand(commandName, argv, { ensureArtifactsDir = false }
|
|
|
184
184
|
async function runDistCommandInline(commandName, argv) {
|
|
185
185
|
const commandArgs = [...argv];
|
|
186
186
|
const rootValue = resolve(getFlag(commandArgs, '--root') ?? '.');
|
|
187
|
-
const artifactsDir = resolve(getFlag(commandArgs, '--artifacts-dir') ?? join(rootValue, '.audit-
|
|
187
|
+
const artifactsDir = resolve(getFlag(commandArgs, '--artifacts-dir') ?? join(rootValue, '.audit-tools', 'audit'));
|
|
188
188
|
|
|
189
189
|
setDefaultFlag(commandArgs, '--root', rootValue);
|
|
190
190
|
setDefaultFlag(commandArgs, '--artifacts-dir', artifactsDir);
|
|
@@ -305,7 +305,7 @@ export async function runAuditCodeWrapper({
|
|
|
305
305
|
wrapperArgs.push('--single-step');
|
|
306
306
|
}
|
|
307
307
|
const rootValue = resolve(getFlag(wrapperArgs, '--root') ?? '.');
|
|
308
|
-
const artifactsDir = resolve(getFlag(wrapperArgs, '--artifacts-dir') ?? join(rootValue, '.audit-
|
|
308
|
+
const artifactsDir = resolve(getFlag(wrapperArgs, '--artifacts-dir') ?? join(rootValue, '.audit-tools', 'audit'));
|
|
309
309
|
|
|
310
310
|
setDefaultFlag(wrapperArgs, '--root', rootValue);
|
|
311
311
|
setDefaultFlag(wrapperArgs, '--artifacts-dir', artifactsDir);
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
export const OPENCODE_AUDIT_EDIT_PERMISSION = {
|
|
2
2
|
'*': 'ask',
|
|
3
3
|
'.audit-code/**': 'allow',
|
|
4
|
-
'.audit-
|
|
5
|
-
'audit-report.md': 'allow',
|
|
4
|
+
'.audit-tools/**': 'allow',
|
|
6
5
|
};
|
|
7
6
|
|
|
8
7
|
export const OPENCODE_AUDIT_EXTERNAL_DIRECTORY_PERMISSION = { '*': 'allow' };
|
|
@@ -176,7 +175,7 @@ export function assertOpenCodeAuditPermissionConfig(permissionConfig, label) {
|
|
|
176
175
|
if (!edit || typeof edit !== 'object' || Array.isArray(edit)) {
|
|
177
176
|
throw new Error(`OpenCode ${label}.edit must allow audit-owned file paths. Run "audit-code install --host opencode".`);
|
|
178
177
|
}
|
|
179
|
-
for (const pattern of ['.audit-code/**', '.audit-
|
|
178
|
+
for (const pattern of ['.audit-code/**', '.audit-tools/**']) {
|
|
180
179
|
if (edit[pattern] !== 'allow') {
|
|
181
180
|
throw new Error(`OpenCode ${label}.edit must allow ${pattern}. Run "audit-code install --host opencode".`);
|
|
182
181
|
}
|
|
@@ -54,7 +54,7 @@ export async function cmdAdvanceAudit(argv) {
|
|
|
54
54
|
providerName,
|
|
55
55
|
});
|
|
56
56
|
if (result.audit_state.status === "complete") {
|
|
57
|
-
await promoteFinalAuditReport({ artifactsDir
|
|
57
|
+
await promoteFinalAuditReport({ artifactsDir });
|
|
58
58
|
}
|
|
59
59
|
return;
|
|
60
60
|
}
|
|
@@ -90,6 +90,6 @@ export async function cmdAdvanceAudit(argv) {
|
|
|
90
90
|
providerName,
|
|
91
91
|
});
|
|
92
92
|
if (result.audit_state.status === "complete") {
|
|
93
|
-
await promoteFinalAuditReport({ artifactsDir
|
|
93
|
+
await promoteFinalAuditReport({ artifactsDir });
|
|
94
94
|
}
|
|
95
95
|
}
|
package/dist/cli/args.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { toPromptPathToken, quotePromptCommandArg, type SessionConfig } from "@audit-tools/shared";
|
|
2
2
|
export type UiMode = "visible" | "headless";
|
|
3
3
|
export declare const DIRECT_CLI_DEFAULTS: {
|
|
4
4
|
rootDir: string;
|
|
@@ -23,7 +23,7 @@ export declare function fromBase64Url(value: string): string;
|
|
|
23
23
|
export declare function digestId(value: string): string;
|
|
24
24
|
export declare function safeArtifactStem(value: string): string;
|
|
25
25
|
export declare function artifactNameForId(value: string, extension: string): string;
|
|
26
|
-
export declare
|
|
26
|
+
export declare const quoteCommandArg: typeof quotePromptCommandArg;
|
|
27
27
|
/**
|
|
28
28
|
* Normalize a generated command token to POSIX path separators. These command
|
|
29
29
|
* strings are embedded in step prompts and `allowed_commands` and run by the
|
|
@@ -34,7 +34,7 @@ export declare function quoteCommandArg(value: string): string;
|
|
|
34
34
|
* are touched, and no non-path argument in this CLI contains one, so this is a
|
|
35
35
|
* targeted normalization rather than a blanket rewrite.
|
|
36
36
|
*/
|
|
37
|
-
export declare
|
|
37
|
+
export declare const toPosixCommandToken: typeof toPromptPathToken;
|
|
38
38
|
export declare function renderCommand(argv: string[]): string;
|
|
39
39
|
export declare function summarizeLaunchExit(result: {
|
|
40
40
|
accepted?: boolean;
|
package/dist/cli/args.js
CHANGED
|
@@ -3,10 +3,11 @@ import { readdir } from "node:fs/promises";
|
|
|
3
3
|
import { Buffer } from "node:buffer";
|
|
4
4
|
import { createHash } from "node:crypto";
|
|
5
5
|
import { join, resolve } from "node:path";
|
|
6
|
+
import { renderPromptCommand, toPromptPathToken, quotePromptCommandArg, } from "@audit-tools/shared";
|
|
6
7
|
import { resolveFreshSessionProviderName } from "../providers/index.js";
|
|
7
8
|
export const DIRECT_CLI_DEFAULTS = {
|
|
8
9
|
rootDir: ".",
|
|
9
|
-
artifactsDir: ".
|
|
10
|
+
artifactsDir: ".audit-tools/audit",
|
|
10
11
|
maxRuns: 1000,
|
|
11
12
|
agentBatchSize: 6,
|
|
12
13
|
parallelWorkers: 1,
|
|
@@ -76,9 +77,7 @@ export function safeArtifactStem(value) {
|
|
|
76
77
|
export function artifactNameForId(value, extension) {
|
|
77
78
|
return `${safeArtifactStem(value)}_${digestId(value)}.${extension}`;
|
|
78
79
|
}
|
|
79
|
-
export
|
|
80
|
-
return /[\s"]/u.test(value) ? `"${value.replace(/"/g, '\\"')}"` : value;
|
|
81
|
-
}
|
|
80
|
+
export const quoteCommandArg = quotePromptCommandArg;
|
|
82
81
|
/**
|
|
83
82
|
* Normalize a generated command token to POSIX path separators. These command
|
|
84
83
|
* strings are embedded in step prompts and `allowed_commands` and run by the
|
|
@@ -89,11 +88,9 @@ export function quoteCommandArg(value) {
|
|
|
89
88
|
* are touched, and no non-path argument in this CLI contains one, so this is a
|
|
90
89
|
* targeted normalization rather than a blanket rewrite.
|
|
91
90
|
*/
|
|
92
|
-
export
|
|
93
|
-
return value.includes("\\") ? value.replace(/\\/g, "/") : value;
|
|
94
|
-
}
|
|
91
|
+
export const toPosixCommandToken = toPromptPathToken;
|
|
95
92
|
export function renderCommand(argv) {
|
|
96
|
-
return argv
|
|
93
|
+
return renderPromptCommand(argv);
|
|
97
94
|
}
|
|
98
95
|
export function summarizeLaunchExit(result) {
|
|
99
96
|
if (result.accepted !== false && !result.error) {
|
package/dist/cli/dispatch.d.ts
CHANGED
package/dist/cli/dispatch.js
CHANGED
|
@@ -10,7 +10,7 @@ import { orderTasksForPacketReview, buildReviewPackets, sizeIndexFromManifest, }
|
|
|
10
10
|
import { buildFileAnchorSummary } from "../orchestrator/fileAnchors.js";
|
|
11
11
|
import { resolveFreshSessionProviderName } from "../providers/index.js";
|
|
12
12
|
import { loadSessionConfig } from "../supervisor/sessionConfig.js";
|
|
13
|
-
import { computeDispatchCapacity, buildProviderModelKey, resolveHostModel, readQuotaState, resolveHostActiveSubagentLimit, lookupDiscoveredLimits, mergeDiscoveredLimits, } from "../quota/index.js";
|
|
13
|
+
import { computeDispatchCapacity, buildProviderModelKey, resolveHostModel, readQuotaState, resolveHostActiveSubagentLimit, lookupDiscoveredLimits, mergeDiscoveredLimits, summarizeDispatchCapacityPools, } from "../quota/index.js";
|
|
14
14
|
import { taskResultPath, packetPromptPath, artifactNameForId, toBase64Url, fromBase64Url, getFlag, } from "./args.js";
|
|
15
15
|
export const LARGE_FILE_PACKET_TARGET_LINES = 2500;
|
|
16
16
|
export const SMALL_MODEL_HINT_MAX_LINES = 500;
|
|
@@ -303,10 +303,12 @@ export function buildTaskSections(packetTasks, lensDefs, lineIndex) {
|
|
|
303
303
|
* Wraps the 75-line array-join block and returns the assembled prompt string.
|
|
304
304
|
*/
|
|
305
305
|
export function buildPacketPrompt(params) {
|
|
306
|
-
const { packet, fileList, largeFileSection, taskSections, submitCommand } = params;
|
|
306
|
+
const { packet, fileList, largeFileSection, taskSections, submitCommand, repoRoot } = params;
|
|
307
307
|
const largeFileMode = isIsolatedLargeFilePacket(packet);
|
|
308
308
|
return [
|
|
309
309
|
"You are a code auditor. Review this packet once, then submit exactly one result per listed task.",
|
|
310
|
+
repoRoot ? `Repository root: ${repoRoot}` : "Repository root: use the root from the step contract.",
|
|
311
|
+
"Set the shell/tool workdir to the repository root when running backend commands.",
|
|
310
312
|
"",
|
|
311
313
|
"## Packet",
|
|
312
314
|
`packet_id: ${packet.packet_id}`,
|
|
@@ -316,8 +318,8 @@ export function buildPacketPrompt(params) {
|
|
|
316
318
|
"",
|
|
317
319
|
"## Files to read",
|
|
318
320
|
largeFileMode
|
|
319
|
-
? "Use targeted Read/Grep calls. Paths are repo-relative
|
|
320
|
-
: "Use your Read tool. Paths are repo-relative
|
|
321
|
+
? "Use targeted Read/Grep calls. Paths are repo-relative to the repository root above."
|
|
322
|
+
: "Use your Read tool. Paths are repo-relative to the repository root above.",
|
|
321
323
|
"Use host Read and Grep tools for source inspection. Do not use shell search commands.",
|
|
322
324
|
fileList,
|
|
323
325
|
"",
|
|
@@ -331,6 +333,8 @@ export function buildPacketPrompt(params) {
|
|
|
331
333
|
"packet-*-result.json / audit_result_*.json) — the submit-packet command below is the only",
|
|
332
334
|
"way to record results, and it writes them inside the artifacts directory for you.",
|
|
333
335
|
"Produce one JSON array containing exactly one AuditResult object for each listed task.",
|
|
336
|
+
"Windows PowerShell: do not pipe an inline foreach statement directly into ConvertTo-Json.",
|
|
337
|
+
"Assign the foreach output to a variable first, then pipe that variable to ConvertTo-Json.",
|
|
334
338
|
"",
|
|
335
339
|
"Schema file (resolve relative to this prompt's directory): audit_result.schema.json",
|
|
336
340
|
" $refs resolved from the same directory: finding.schema.json, audit_task.schema.json",
|
|
@@ -437,6 +441,8 @@ async function computeDispatchQuota(params) {
|
|
|
437
441
|
wave_size: dispatchCapacity.total_slots,
|
|
438
442
|
estimated_wave_tokens: dispatchCapacity.estimated_wave_tokens,
|
|
439
443
|
cooldown_until: dispatchCapacity.cooldown_until,
|
|
444
|
+
binding_cap: dispatchCapacity.binding_cap,
|
|
445
|
+
capacity_pools: summarizeDispatchCapacityPools(dispatchCapacity),
|
|
440
446
|
quota_source_snapshot: waveSchedule.quota_source_snapshot ?? null,
|
|
441
447
|
backoff_state: null,
|
|
442
448
|
};
|
|
@@ -633,8 +639,11 @@ export async function prepareDispatchArtifacts(params) {
|
|
|
633
639
|
result_path: resultPathByTaskId.get(task.task_id),
|
|
634
640
|
});
|
|
635
641
|
}
|
|
636
|
-
const prompt = buildPacketPrompt({ packet, packetTasks, fileList, largeFileSection, taskSections, submitCommand });
|
|
642
|
+
const prompt = buildPacketPrompt({ packet, packetTasks, fileList, largeFileSection, taskSections, submitCommand, repoRoot: reviewRoot });
|
|
637
643
|
await writeFile(promptPath, prompt, "utf8");
|
|
644
|
+
const packetWritePaths = packetTasks
|
|
645
|
+
.map((task) => resultPathByTaskId.get(task.task_id))
|
|
646
|
+
.filter((p) => p !== undefined);
|
|
638
647
|
plan.push({
|
|
639
648
|
packet_id: packet.packet_id,
|
|
640
649
|
description: `Audit ${packet.file_paths.length} file(s), ${packet.task_ids.length} task(s), ${packet.lenses.length} lens(es) (~${packet.total_lines} lines)` +
|
|
@@ -642,6 +651,16 @@ export async function prepareDispatchArtifacts(params) {
|
|
|
642
651
|
prompt_path: promptPath,
|
|
643
652
|
complexity,
|
|
644
653
|
model_hint: buildDispatchModelHint(complexity),
|
|
654
|
+
access: {
|
|
655
|
+
read_paths: [
|
|
656
|
+
promptPath,
|
|
657
|
+
...(reviewRoot
|
|
658
|
+
? packet.file_paths.map((p) => join(reviewRoot, p))
|
|
659
|
+
: packet.file_paths),
|
|
660
|
+
],
|
|
661
|
+
write_paths: packetWritePaths,
|
|
662
|
+
forbidden_patterns: ["packet-*-result.json", "audit_result_*.json"],
|
|
663
|
+
},
|
|
645
664
|
});
|
|
646
665
|
}
|
|
647
666
|
await writeJsonFile(dispatchPlanPath, plan);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { mkdir, unlink, writeFile } from "node:fs/promises";
|
|
2
|
-
import { join, resolve } from "node:path";
|
|
2
|
+
import { dirname, join, resolve } from "node:path";
|
|
3
3
|
import { isFileMissingError, readJsonFile, writeJsonFile, } from "@audit-tools/shared";
|
|
4
4
|
import { loadArtifactBundle, promoteFinalAuditReport, writeCoreArtifacts, AUDIT_REPORT_FILENAME, } from "../io/artifacts.js";
|
|
5
5
|
import { advanceAudit } from "../orchestrator/advance.js";
|
|
@@ -71,14 +71,13 @@ export async function buildTerminalStep(params, bundle, state, blockedReason) {
|
|
|
71
71
|
}
|
|
72
72
|
const promoted = await promoteFinalAuditReport({
|
|
73
73
|
artifactsDir: params.artifactsDir,
|
|
74
|
-
repoRoot: params.root,
|
|
75
74
|
});
|
|
76
75
|
return {
|
|
77
76
|
kind: "complete",
|
|
78
77
|
state,
|
|
79
78
|
bundle,
|
|
80
79
|
finalReportPath: promoted.promoted
|
|
81
|
-
? join(params.
|
|
80
|
+
? join(dirname(params.artifactsDir), AUDIT_REPORT_FILENAME)
|
|
82
81
|
: join(params.artifactsDir, AUDIT_REPORT_FILENAME),
|
|
83
82
|
};
|
|
84
83
|
}
|
|
@@ -293,7 +292,6 @@ async function runDeterministicForNextStep(params) {
|
|
|
293
292
|
});
|
|
294
293
|
const promoted = await promoteFinalAuditReport({
|
|
295
294
|
artifactsDir: params.artifactsDir,
|
|
296
|
-
repoRoot: params.root,
|
|
297
295
|
});
|
|
298
296
|
return {
|
|
299
297
|
kind: "complete",
|
package/dist/cli/prompts.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DO_NOT_TOKEN_WRAP_NOTE } from "@audit-tools/shared";
|
|
1
|
+
import { DO_NOT_TOKEN_WRAP_NOTE, DISPATCH_PROMPT_HANDOFF_NOTE } from "@audit-tools/shared";
|
|
2
2
|
import { renderCommand } from "./args.js";
|
|
3
3
|
/**
|
|
4
4
|
* Token prefix the host should use to re-invoke the backend in generated
|
|
@@ -93,7 +93,7 @@ export function renderDispatchReviewPrompt(params) {
|
|
|
93
93
|
...dispatchDataLines,
|
|
94
94
|
...canaryLines,
|
|
95
95
|
"",
|
|
96
|
-
|
|
96
|
+
DISPATCH_PROMPT_HANDOFF_NOTE,
|
|
97
97
|
"",
|
|
98
98
|
"Subagent prompt shape:",
|
|
99
99
|
"",
|
|
@@ -104,7 +104,7 @@ export function renderDispatchReviewPrompt(params) {
|
|
|
104
104
|
"",
|
|
105
105
|
"Each subagent must submit its packet through the submit command printed in its packet prompt and stop after successful submission.",
|
|
106
106
|
"",
|
|
107
|
-
"**File access pre-approval:** Each dispatch plan entry includes an `access` object with `read_paths` and `
|
|
107
|
+
"**File access pre-approval:** Each dispatch plan entry includes an `access` object with `read_paths`, `write_paths`, and `forbidden_patterns`. If your host supports per-subagent file access restrictions, pre-approve exactly `entry.access.read_paths` and `entry.access.write_paths` for each subagent. Do not grant broad workspace or task-results directory write access. Workers should not access files outside their declared paths.",
|
|
108
108
|
"",
|
|
109
109
|
"**After all waves complete:**",
|
|
110
110
|
"",
|
|
@@ -172,10 +172,11 @@ export function renderEdgeReasoningDispatchPrompt(params) {
|
|
|
172
172
|
"optional pass: it only rewrites the `reason` string of those edges — it never",
|
|
173
173
|
"adds, removes, re-targets, or re-weights an edge.",
|
|
174
174
|
"",
|
|
175
|
-
"Dispatch exactly ONE subagent (via the `task` tool or equivalent).
|
|
176
|
-
"prompt file path; do not load the file into this orchestrator context:",
|
|
175
|
+
"Dispatch exactly ONE subagent (via the `task` tool or equivalent).",
|
|
177
176
|
"",
|
|
178
|
-
|
|
177
|
+
DISPATCH_PROMPT_HANDOFF_NOTE,
|
|
178
|
+
"",
|
|
179
|
+
` Prompt path: ${params.promptPath}`,
|
|
179
180
|
"",
|
|
180
181
|
"Subagent prompt shape:",
|
|
181
182
|
"",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function cmdResynthesize(argv: string[]): Promise<void>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
4
|
+
import { getRootDir } from "./args.js";
|
|
5
|
+
import { normalizeExistingFindingsReport, renderAuditReportMarkdown, } from "../reporting/synthesis.js";
|
|
6
|
+
const AUDIT_TOOLS_DIR = ".audit-tools";
|
|
7
|
+
const FINDINGS_FILENAME = "audit-findings.json";
|
|
8
|
+
const REPORT_FILENAME = "audit-report.md";
|
|
9
|
+
function getFlagValue(argv, flag) {
|
|
10
|
+
const idx = argv.indexOf(flag);
|
|
11
|
+
return idx >= 0 && idx + 1 < argv.length ? argv[idx + 1] : undefined;
|
|
12
|
+
}
|
|
13
|
+
export async function cmdResynthesize(argv) {
|
|
14
|
+
const root = getRootDir(argv);
|
|
15
|
+
const auditToolsDir = join(root, AUDIT_TOOLS_DIR);
|
|
16
|
+
const defaultInput = join(auditToolsDir, FINDINGS_FILENAME);
|
|
17
|
+
const inputPath = getFlagValue(argv, "--input") ?? defaultInput;
|
|
18
|
+
if (!existsSync(inputPath)) {
|
|
19
|
+
console.error(`resynthesize: ${FINDINGS_FILENAME} not found at ${inputPath}. ` +
|
|
20
|
+
`Run the full audit first, or supply --input <path>.`);
|
|
21
|
+
process.exitCode = 1;
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const raw = await readFile(inputPath, "utf8");
|
|
25
|
+
let report;
|
|
26
|
+
try {
|
|
27
|
+
report = JSON.parse(raw);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
31
|
+
console.error(`resynthesize: could not parse ${inputPath}: ${msg}`);
|
|
32
|
+
process.exitCode = 1;
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const normalized = normalizeExistingFindingsReport(report);
|
|
36
|
+
const markdown = renderAuditReportMarkdown(normalized);
|
|
37
|
+
await mkdir(auditToolsDir, { recursive: true });
|
|
38
|
+
const outputFindingsPath = join(auditToolsDir, FINDINGS_FILENAME);
|
|
39
|
+
const outputReportPath = join(auditToolsDir, REPORT_FILENAME);
|
|
40
|
+
await writeFile(outputFindingsPath, JSON.stringify(normalized, null, 2), "utf8");
|
|
41
|
+
await writeFile(outputReportPath, markdown, "utf8");
|
|
42
|
+
console.log(JSON.stringify({
|
|
43
|
+
source: inputPath,
|
|
44
|
+
findings_output: outputFindingsPath,
|
|
45
|
+
report_output: outputReportPath,
|
|
46
|
+
finding_count: normalized.summary.finding_count,
|
|
47
|
+
work_block_count: normalized.summary.work_block_count,
|
|
48
|
+
contract_version: normalized.contract_version,
|
|
49
|
+
}, null, 2));
|
|
50
|
+
}
|
|
@@ -671,7 +671,7 @@ async function handleNoExecutor(params) {
|
|
|
671
671
|
providerName,
|
|
672
672
|
});
|
|
673
673
|
if (state.status === "complete") {
|
|
674
|
-
await promoteFinalAuditReport({ artifactsDir
|
|
674
|
+
await promoteFinalAuditReport({ artifactsDir });
|
|
675
675
|
}
|
|
676
676
|
}
|
|
677
677
|
async function runParallelWaveStep(params) {
|
|
@@ -869,7 +869,7 @@ async function handleMaxRunsReached(params) {
|
|
|
869
869
|
providerName,
|
|
870
870
|
});
|
|
871
871
|
if (reportRendered) {
|
|
872
|
-
await promoteFinalAuditReport({ artifactsDir
|
|
872
|
+
await promoteFinalAuditReport({ artifactsDir });
|
|
873
873
|
}
|
|
874
874
|
}
|
|
875
875
|
export async function cmdRunToCompletion(argv) {
|
package/dist/cli.js
CHANGED
|
@@ -23,6 +23,7 @@ import { cmdValidate } from "./cli/validateCommand.js";
|
|
|
23
23
|
import { cmdValidateResults } from "./cli/validateResultsCommand.js";
|
|
24
24
|
import { cmdRequeue } from "./cli/requeueCommand.js";
|
|
25
25
|
import { cmdSynthesize } from "./cli/synthesizeCommand.js";
|
|
26
|
+
import { cmdResynthesize } from "./cli/resynthesizeCommand.js";
|
|
26
27
|
import { cmdCleanup } from "./cli/cleanupCommand.js";
|
|
27
28
|
import { cmdQuota } from "./cli/quotaCommand.js";
|
|
28
29
|
import { cmdDispatchStatus } from "./cli/dispatchStatusCommand.js";
|
|
@@ -93,6 +94,9 @@ async function main(argv) {
|
|
|
93
94
|
case "synthesize":
|
|
94
95
|
await cmdSynthesize(argv);
|
|
95
96
|
return;
|
|
97
|
+
case "resynthesize":
|
|
98
|
+
await cmdResynthesize(argv);
|
|
99
|
+
return;
|
|
96
100
|
case "cleanup":
|
|
97
101
|
await cmdCleanup(argv);
|
|
98
102
|
return;
|
|
@@ -119,7 +123,7 @@ async function main(argv) {
|
|
|
119
123
|
return;
|
|
120
124
|
default:
|
|
121
125
|
console.error(`Unknown command: ${command}`);
|
|
122
|
-
console.error("Available commands: sample-run, advance-audit, next-step, run-to-completion, worker-run, import-external-analyzer, intake, plan, ingest-results, explain-task, update-runtime-validation, validate, validate-results, requeue, synthesize, cleanup, prepare-dispatch, merge-and-ingest, submit-packet, validate-result, quota, status, dispatch-status");
|
|
126
|
+
console.error("Available commands: sample-run, advance-audit, next-step, run-to-completion, worker-run, import-external-analyzer, intake, plan, ingest-results, explain-task, update-runtime-validation, validate, validate-results, requeue, synthesize, resynthesize, cleanup, prepare-dispatch, merge-and-ingest, submit-packet, validate-result, quota, status, dispatch-status");
|
|
123
127
|
process.exitCode = 1;
|
|
124
128
|
}
|
|
125
129
|
}
|
|
@@ -204,7 +204,7 @@ export function isGeneratedTestArtifactPath(normalized) {
|
|
|
204
204
|
return splitSegments(normalized).some((segment) => segment.startsWith(".test-") && segment.endsWith("-artifacts"));
|
|
205
205
|
}
|
|
206
206
|
export function isAuditArtifactPath(normalized) {
|
|
207
|
-
return hasSegment(normalized, ".audit-
|
|
207
|
+
return hasSegment(normalized, ".audit-tools");
|
|
208
208
|
}
|
|
209
209
|
export function isTestPath(normalized) {
|
|
210
210
|
const segments = splitSegments(normalized);
|
package/dist/io/artifacts.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { cp, rm } from "node:fs/promises";
|
|
|
2
2
|
import type { AuditResult, AuditTask, CoverageMatrix, RepoManifest, UnitManifest } from "../types.js";
|
|
3
3
|
import type { AuditState } from "../types/auditState.js";
|
|
4
4
|
import type { ArtifactMetadataManifest } from "../types/artifactMetadata.js";
|
|
5
|
-
import type { AuditFindingsReport, FileDisposition, CriticalFlowManifest, GraphBundle, RiskRegister, SurfaceManifest } from "@audit-tools/shared";
|
|
5
|
+
import type { AuditFindingsReport, FileDisposition, CriticalFlowManifest, GraphBundle, RiskRegister, SurfaceManifest, IntentCheckpoint } from "@audit-tools/shared";
|
|
6
6
|
import type { SynthesisNarrativeRecord } from "../types/synthesisNarrative.js";
|
|
7
7
|
import type { ExternalAnalyzerResults } from "../types/externalAnalyzer.js";
|
|
8
8
|
import type { FlowCoverageManifest } from "../types/flowCoverage.js";
|
|
@@ -17,6 +17,7 @@ type ArtifactPayloadMap = {
|
|
|
17
17
|
repo_manifest: RepoManifest;
|
|
18
18
|
file_disposition: FileDisposition;
|
|
19
19
|
auto_fixes_applied: unknown;
|
|
20
|
+
intent_checkpoint: IntentCheckpoint;
|
|
20
21
|
unit_manifest: UnitManifest;
|
|
21
22
|
graph_bundle: GraphBundle;
|
|
22
23
|
surface_manifest: SurfaceManifest;
|
|
@@ -68,6 +69,7 @@ export declare const ARTIFACT_DEFINITIONS: {
|
|
|
68
69
|
readonly repo_manifest: ArtifactDefinition<"repo_manifest">;
|
|
69
70
|
readonly file_disposition: ArtifactDefinition<"file_disposition">;
|
|
70
71
|
readonly auto_fixes_applied: ArtifactDefinition<"auto_fixes_applied">;
|
|
72
|
+
readonly intent_checkpoint: ArtifactDefinition<"intent_checkpoint">;
|
|
71
73
|
readonly unit_manifest: ArtifactDefinition<"unit_manifest">;
|
|
72
74
|
readonly graph_bundle: ArtifactDefinition<"graph_bundle">;
|
|
73
75
|
readonly surface_manifest: ArtifactDefinition<"surface_manifest">;
|
|
@@ -103,7 +105,6 @@ export declare function writeCoreArtifacts(root: string, bundle: ArtifactBundle,
|
|
|
103
105
|
export declare function cleanupIntermediateArtifacts(root: string): Promise<string[]>;
|
|
104
106
|
export declare function promoteFinalAuditReport(params: {
|
|
105
107
|
artifactsDir: string;
|
|
106
|
-
repoRoot: string;
|
|
107
108
|
}, options?: {
|
|
108
109
|
copy?: typeof cp;
|
|
109
110
|
remove?: typeof rm;
|
package/dist/io/artifacts.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cp, rm, unlink } from "node:fs/promises";
|
|
2
|
-
import { join } from "node:path";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
3
|
import { isFileMissingError, readOptionalJsonFile, readOptionalNdjsonFile, readOptionalTextFile, writeJsonFile, writeNdjsonFile, writeTextFile, } from "@audit-tools/shared";
|
|
4
4
|
import { buildToolingManifest } from "./toolingManifest.js";
|
|
5
5
|
// Canonical filename for the rendered findings report. Single source of truth
|
|
@@ -34,6 +34,7 @@ export const ARTIFACT_DEFINITIONS = {
|
|
|
34
34
|
repo_manifest: jsonArtifact("repo_manifest.json", "intake"),
|
|
35
35
|
file_disposition: jsonArtifact("file_disposition.json", "intake"),
|
|
36
36
|
auto_fixes_applied: jsonArtifact("auto_fixes_applied.json", "intake"),
|
|
37
|
+
intent_checkpoint: jsonArtifact("intent_checkpoint.json", "intake"),
|
|
37
38
|
unit_manifest: jsonArtifact("unit_manifest.json", "analysis"),
|
|
38
39
|
graph_bundle: jsonArtifact("graph_bundle.json", "analysis"),
|
|
39
40
|
surface_manifest: jsonArtifact("surface_manifest.json", "analysis"),
|
|
@@ -130,8 +131,9 @@ export async function cleanupIntermediateArtifacts(root) {
|
|
|
130
131
|
return deleted;
|
|
131
132
|
}
|
|
132
133
|
export async function promoteFinalAuditReport(params, options = {}) {
|
|
134
|
+
const outputDir = dirname(params.artifactsDir);
|
|
133
135
|
const source = join(params.artifactsDir, AUDIT_REPORT_FILENAME);
|
|
134
|
-
const destination = join(
|
|
136
|
+
const destination = join(outputDir, AUDIT_REPORT_FILENAME);
|
|
135
137
|
const copy = options.copy ?? cp;
|
|
136
138
|
const remove = options.remove ?? rm;
|
|
137
139
|
const warn = options.warn ?? ((message) => process.stderr.write(`${message}\n`));
|
|
@@ -147,12 +149,12 @@ export async function promoteFinalAuditReport(params, options = {}) {
|
|
|
147
149
|
// Promote the canonical machine contract alongside the human report. Missing
|
|
148
150
|
// (e.g. legacy bundle) or unreadable: best-effort, never blocks completion.
|
|
149
151
|
try {
|
|
150
|
-
await copy(join(params.artifactsDir, "audit-findings.json"), join(
|
|
152
|
+
await copy(join(params.artifactsDir, "audit-findings.json"), join(outputDir, "audit-findings.json"), { force: true });
|
|
151
153
|
}
|
|
152
154
|
catch (error) {
|
|
153
155
|
// audit-findings.json is optional output; absence must not fail promotion.
|
|
154
156
|
// Log so operators can distinguish a partial promotion from a clean one.
|
|
155
|
-
warn(`audit-code: could not promote audit-findings.json to ${join(
|
|
157
|
+
warn(`audit-code: could not promote audit-findings.json to ${join(outputDir, "audit-findings.json")}: ` +
|
|
156
158
|
(error instanceof Error ? error.message : String(error)));
|
|
157
159
|
}
|
|
158
160
|
try {
|
package/dist/io/runArtifacts.js
CHANGED
|
@@ -187,7 +187,7 @@ export async function writeDispatchBatchFiles(artifactsDir, runs, currentTasks,
|
|
|
187
187
|
"# audit-code parallel dispatch",
|
|
188
188
|
"",
|
|
189
189
|
`This batch launched ${runs.length} deferred review run(s).`,
|
|
190
|
-
"Each run keeps its own task.json, prompt.md, result.json, and status.json under .audit-
|
|
190
|
+
"Each run keeps its own task.json, prompt.md, result.json, and status.json under .audit-tools/audit/runs/<run_id>/.",
|
|
191
191
|
"Use current-tasks.json for the combined task list. The per-run files below are operational references for launched workers; do not read per-run prompt or schema files unless debugging a failed dispatch.",
|
|
192
192
|
"",
|
|
193
193
|
"Runs:",
|
|
@@ -3,6 +3,7 @@ import { decideNextStep, findObligation } from "./nextStep.js";
|
|
|
3
3
|
import { deriveAuditState } from "./state.js";
|
|
4
4
|
import { computeArtifactMetadata } from "./artifactMetadata.js";
|
|
5
5
|
import { runIntakeExecutor } from "./intakeExecutors.js";
|
|
6
|
+
import { runIntentCheckpointExecutor } from "./intentCheckpointExecutor.js";
|
|
6
7
|
import { runStructureExecutor, runDesignAssessmentExecutor, runDesignReviewAutoComplete, } from "./structureExecutors.js";
|
|
7
8
|
import { runPlanningExecutor } from "./planningExecutors.js";
|
|
8
9
|
import { runResultIngestionExecutor, runRuntimeValidationExecutor, runRuntimeValidationUpdateExecutor, runExternalAnalyzerImportExecutor, } from "./ingestionExecutors.js";
|
|
@@ -91,6 +92,11 @@ export async function advanceAudit(bundle, options = {}) {
|
|
|
91
92
|
run = await runIntakeExecutor(bundle, root);
|
|
92
93
|
break;
|
|
93
94
|
}
|
|
95
|
+
case "intent_checkpoint_executor": {
|
|
96
|
+
const root = requireRoot(options.root, "intent_checkpoint_executor");
|
|
97
|
+
run = await runIntentCheckpointExecutor(bundle, root, options.since);
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
94
100
|
case "structure_executor":
|
|
95
101
|
// root is intentionally optional: present → buildGraphBundleFromFs, absent → manifest-only buildGraphBundle
|
|
96
102
|
run = await runStructureExecutor(bundle, options.root);
|
|
@@ -8,6 +8,13 @@ export const ARTIFACT_DEPENDENTS_MAP = {
|
|
|
8
8
|
"tooling_manifest.json": [
|
|
9
9
|
"repo_manifest.json",
|
|
10
10
|
],
|
|
11
|
+
"intent_checkpoint.json": [
|
|
12
|
+
"coverage_matrix.json",
|
|
13
|
+
"audit_tasks.json",
|
|
14
|
+
"audit_plan_metrics.json",
|
|
15
|
+
"review_packets.json",
|
|
16
|
+
"requeue_tasks.json",
|
|
17
|
+
],
|
|
11
18
|
"repo_manifest.json": [
|
|
12
19
|
"file_disposition.json",
|
|
13
20
|
"unit_manifest.json",
|