auditor-lambda 0.3.20 → 0.3.21
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 +12 -2
- package/audit-code-wrapper-lib.mjs +86 -32
- package/dist/cli.js +576 -10
- package/dist/prompts/renderWorkerPrompt.js +1 -0
- package/dist/supervisor/operatorHandoff.js +3 -7
- package/docs/contracts.md +23 -1
- package/docs/operator-guide.md +11 -4
- package/docs/product.md +4 -3
- package/package.json +1 -1
- package/scripts/postinstall.mjs +33 -0
- package/skills/audit-code/audit-code.prompt.md +15 -170
package/README.md
CHANGED
|
@@ -51,11 +51,11 @@ The explicit repair and compatibility setup path remains:
|
|
|
51
51
|
audit-code install
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
That bootstraps repo-local
|
|
54
|
+
That bootstraps repo-local supporting surfaces for the hosts we can automate today, including:
|
|
55
55
|
|
|
56
56
|
- Codex `AGENTS.md` fallback guidance for the global skill surface
|
|
57
57
|
- Claude Desktop local MCP bundle artifacts and project template guidance
|
|
58
|
-
- OpenCode `opencode.json` with the `/audit-code`
|
|
58
|
+
- OpenCode `opencode.json` with auditor MCP server and permission wiring; the `/audit-code` command stays in the global npm-installed OpenCode config
|
|
59
59
|
- VS Code prompt, custom agent, Copilot instructions, and `.vscode/mcp.json`
|
|
60
60
|
- Antigravity planning-mode guidance plus the shared repo-local MCP launcher
|
|
61
61
|
|
|
@@ -130,6 +130,16 @@ For one bounded debug step instead of run-to-completion:
|
|
|
130
130
|
audit-code --single-step
|
|
131
131
|
```
|
|
132
132
|
|
|
133
|
+
For the conversation step engine used by `/audit-code`:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
audit-code next-step
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
This writes `.audit-artifacts/steps/current-step.json` and
|
|
140
|
+
`.audit-artifacts/steps/current-prompt.md`; hosts should follow only the
|
|
141
|
+
returned step prompt.
|
|
142
|
+
|
|
133
143
|
For an operator-side artifact consistency check:
|
|
134
144
|
|
|
135
145
|
```bash
|
|
@@ -258,6 +258,7 @@ function printHelp({ usageName, preferredEntrypoint }) {
|
|
|
258
258
|
'- verify-install smoke-tests the generated host assets and repo-local MCP launchers after install',
|
|
259
259
|
'- mcp starts the local stdio MCP server for repo-local IDE integrations',
|
|
260
260
|
'- install-host --host copilot keeps the narrower Copilot-focused install path available',
|
|
261
|
+
'- next-step advances deterministic audit state and writes .audit-artifacts/steps/current-step.json plus current-prompt.md',
|
|
261
262
|
'- validate checks the current artifact bundle plus session-config/provider readiness and exits non-zero when issues exist',
|
|
262
263
|
'- validate-results --results FILE validates AuditResult payloads against the active task manifest without ingesting them',
|
|
263
264
|
'- explain-task <task_id> prints the resolved file coverage and current status for a task id',
|
|
@@ -547,6 +548,11 @@ const OPENCODE_AUDIT_BASH_PERMISSION = {
|
|
|
547
548
|
'audit-code cleanup*': 'deny',
|
|
548
549
|
'audit-code requeue*': 'deny',
|
|
549
550
|
'audit-code ingest-results*': 'deny',
|
|
551
|
+
'*dist*index.js* run-to-completion*': 'deny',
|
|
552
|
+
'*dist*index.js* synthesize*': 'deny',
|
|
553
|
+
'*dist*index.js* cleanup*': 'deny',
|
|
554
|
+
'*dist*index.js* requeue*': 'deny',
|
|
555
|
+
'*dist*index.js* ingest-results*': 'deny',
|
|
550
556
|
'*audit-code.mjs* run-to-completion*': 'deny',
|
|
551
557
|
'*audit-code.mjs* synthesize*': 'deny',
|
|
552
558
|
'*audit-code.mjs* cleanup*': 'deny',
|
|
@@ -554,48 +560,56 @@ const OPENCODE_AUDIT_BASH_PERMISSION = {
|
|
|
554
560
|
'*audit-code.mjs* ingest-results*': 'deny',
|
|
555
561
|
'audit-code': 'allow',
|
|
556
562
|
'audit-code ensure*': 'allow',
|
|
563
|
+
'audit-code next-step*': 'allow',
|
|
557
564
|
'audit-code prepare-dispatch*': 'allow',
|
|
558
565
|
'audit-code submit-packet*': 'allow',
|
|
559
566
|
'audit-code merge-and-ingest*': 'allow',
|
|
560
567
|
'audit-code validate*': 'allow',
|
|
561
568
|
'*audit-code.mjs': 'allow',
|
|
562
569
|
'*audit-code.mjs* ensure*': 'allow',
|
|
570
|
+
'*audit-code.mjs* next-step*': 'allow',
|
|
563
571
|
'*audit-code.mjs* prepare-dispatch*': 'allow',
|
|
564
572
|
'*audit-code.mjs* submit-packet*': 'allow',
|
|
565
573
|
'*audit-code.mjs* merge-and-ingest*': 'allow',
|
|
566
574
|
'*audit-code.mjs* worker-run*': 'allow',
|
|
567
575
|
'*audit-code.mjs* validate*': 'allow',
|
|
576
|
+
'*node* *auditor-lambda*dist*index.js* worker-run*': 'allow',
|
|
568
577
|
'node* .audit-code/install/run-mcp-server.mjs*': 'allow',
|
|
569
578
|
'node* ./.audit-code/install/run-mcp-server.mjs*': 'allow',
|
|
570
579
|
'git status*': 'allow',
|
|
571
580
|
'git diff*': 'allow',
|
|
572
581
|
'grep *': 'allow',
|
|
582
|
+
'Select-String *': 'allow',
|
|
573
583
|
'rm *': 'deny',
|
|
574
584
|
};
|
|
575
585
|
|
|
586
|
+
function externalDirectoryPattern(path) {
|
|
587
|
+
return `${replaceBackslashes(path).replace(/\/+$/u, '')}/**`;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
function renderOpenCodeExternalDirectoryPermission() {
|
|
591
|
+
return {
|
|
592
|
+
[externalDirectoryPattern(repoRoot)]: 'allow',
|
|
593
|
+
[externalDirectoryPattern(dirname(process.execPath))]: 'allow',
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
|
|
576
597
|
function renderOpenCodePermissionConfig() {
|
|
577
598
|
return {
|
|
578
599
|
read: 'allow',
|
|
579
600
|
glob: 'allow',
|
|
580
601
|
grep: 'allow',
|
|
602
|
+
external_directory: renderOpenCodeExternalDirectoryPermission(),
|
|
581
603
|
edit: { ...OPENCODE_AUDIT_EDIT_PERMISSION },
|
|
582
604
|
bash: { ...OPENCODE_AUDIT_BASH_PERMISSION },
|
|
583
605
|
};
|
|
584
606
|
}
|
|
585
607
|
|
|
586
|
-
function renderOpenCodeProjectConfig(root
|
|
608
|
+
function renderOpenCodeProjectConfig(root) {
|
|
587
609
|
const launcher = replaceBackslashes(toRepoRelativePath(root, join(root, '.audit-code', 'install', MCP_LAUNCHER_FILENAME)));
|
|
588
610
|
const auditPermission = renderOpenCodePermissionConfig();
|
|
589
611
|
return {
|
|
590
612
|
$schema: 'https://opencode.ai/config.json',
|
|
591
|
-
command: {
|
|
592
|
-
'audit-code': {
|
|
593
|
-
template: promptBody.trimStart(),
|
|
594
|
-
description: 'Autonomous local loop code auditing',
|
|
595
|
-
agent: 'auditor',
|
|
596
|
-
subtask: false,
|
|
597
|
-
},
|
|
598
|
-
},
|
|
599
613
|
mcp: {
|
|
600
614
|
auditor: {
|
|
601
615
|
type: 'local',
|
|
@@ -613,8 +627,7 @@ function renderOpenCodeProjectConfig(root, promptBody) {
|
|
|
613
627
|
'auditor*': true,
|
|
614
628
|
},
|
|
615
629
|
permission: {
|
|
616
|
-
|
|
617
|
-
bash: { ...OPENCODE_AUDIT_BASH_PERMISSION },
|
|
630
|
+
...auditPermission,
|
|
618
631
|
question: 'allow',
|
|
619
632
|
},
|
|
620
633
|
},
|
|
@@ -679,6 +692,14 @@ function mergeOpenCodePermissionConfig(existingPermission, generatedPermission)
|
|
|
679
692
|
return {
|
|
680
693
|
...generatedPermission,
|
|
681
694
|
...existingPermission,
|
|
695
|
+
read: generatedPermission.read,
|
|
696
|
+
glob: generatedPermission.glob,
|
|
697
|
+
grep: generatedPermission.grep,
|
|
698
|
+
external_directory: mergeOpenCodePermissionRule(
|
|
699
|
+
existingPermission.external_directory,
|
|
700
|
+
generatedPermission.external_directory,
|
|
701
|
+
generatedPermission.external_directory,
|
|
702
|
+
),
|
|
682
703
|
edit: mergeOpenCodePermissionRule(
|
|
683
704
|
existingPermission.edit,
|
|
684
705
|
generatedPermission.edit,
|
|
@@ -692,7 +713,27 @@ function mergeOpenCodePermissionConfig(existingPermission, generatedPermission)
|
|
|
692
713
|
};
|
|
693
714
|
}
|
|
694
715
|
|
|
716
|
+
function removeManagedOpenCodeCommand(commandConfig) {
|
|
717
|
+
const command = objectValue(commandConfig);
|
|
718
|
+
const { 'audit-code': _managedAuditCodeCommand, ...remaining } = command;
|
|
719
|
+
return remaining;
|
|
720
|
+
}
|
|
721
|
+
|
|
695
722
|
function assertOpenCodeAuditPermissionConfig(permissionConfig, label) {
|
|
723
|
+
for (const tool of ['read', 'glob', 'grep']) {
|
|
724
|
+
if (permissionConfig?.[tool] !== 'allow') {
|
|
725
|
+
throw new Error(`OpenCode ${label}.${tool} must be allow. Run "audit-code install --host opencode".`);
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
const externalDirectory = permissionConfig?.external_directory;
|
|
729
|
+
if (!externalDirectory || typeof externalDirectory !== 'object' || Array.isArray(externalDirectory)) {
|
|
730
|
+
throw new Error(`OpenCode ${label}.external_directory must allow audit package paths. Run "audit-code install --host opencode".`);
|
|
731
|
+
}
|
|
732
|
+
for (const pattern of Object.keys(renderOpenCodeExternalDirectoryPermission())) {
|
|
733
|
+
if (externalDirectory[pattern] !== 'allow') {
|
|
734
|
+
throw new Error(`OpenCode ${label}.external_directory must allow ${pattern}. Run "audit-code install --host opencode".`);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
696
737
|
const edit = permissionConfig?.edit;
|
|
697
738
|
const bash = permissionConfig?.bash;
|
|
698
739
|
if (!edit || typeof edit !== 'object' || Array.isArray(edit)) {
|
|
@@ -709,13 +750,18 @@ function assertOpenCodeAuditPermissionConfig(permissionConfig, label) {
|
|
|
709
750
|
for (const pattern of [
|
|
710
751
|
'audit-code',
|
|
711
752
|
'audit-code ensure*',
|
|
753
|
+
'audit-code next-step*',
|
|
712
754
|
'audit-code prepare-dispatch*',
|
|
713
755
|
'audit-code submit-packet*',
|
|
714
756
|
'audit-code merge-and-ingest*',
|
|
715
757
|
'*audit-code.mjs',
|
|
758
|
+
'*audit-code.mjs* next-step*',
|
|
716
759
|
'*audit-code.mjs* submit-packet*',
|
|
717
760
|
'*audit-code.mjs* merge-and-ingest*',
|
|
761
|
+
'*audit-code.mjs* worker-run*',
|
|
762
|
+
'*node* *auditor-lambda*dist*index.js* worker-run*',
|
|
718
763
|
'node* .audit-code/install/run-mcp-server.mjs*',
|
|
764
|
+
'Select-String *',
|
|
719
765
|
]) {
|
|
720
766
|
if (bash[pattern] !== 'allow') {
|
|
721
767
|
throw new Error(`OpenCode ${label}.bash must allow ${pattern}. Run "audit-code install --host opencode".`);
|
|
@@ -724,8 +770,19 @@ function assertOpenCodeAuditPermissionConfig(permissionConfig, label) {
|
|
|
724
770
|
for (const pattern of [
|
|
725
771
|
'audit-code run-to-completion*',
|
|
726
772
|
'audit-code synthesize*',
|
|
773
|
+
'audit-code cleanup*',
|
|
774
|
+
'audit-code requeue*',
|
|
775
|
+
'audit-code ingest-results*',
|
|
776
|
+
'*dist*index.js* run-to-completion*',
|
|
777
|
+
'*dist*index.js* synthesize*',
|
|
778
|
+
'*dist*index.js* cleanup*',
|
|
779
|
+
'*dist*index.js* requeue*',
|
|
780
|
+
'*dist*index.js* ingest-results*',
|
|
727
781
|
'*audit-code.mjs* run-to-completion*',
|
|
728
782
|
'*audit-code.mjs* synthesize*',
|
|
783
|
+
'*audit-code.mjs* cleanup*',
|
|
784
|
+
'*audit-code.mjs* requeue*',
|
|
785
|
+
'*audit-code.mjs* ingest-results*',
|
|
729
786
|
]) {
|
|
730
787
|
if (bash[pattern] !== 'deny') {
|
|
731
788
|
throw new Error(`OpenCode ${label}.bash must deny ${pattern}. Run "audit-code install --host opencode".`);
|
|
@@ -733,15 +790,12 @@ function assertOpenCodeAuditPermissionConfig(permissionConfig, label) {
|
|
|
733
790
|
}
|
|
734
791
|
}
|
|
735
792
|
|
|
736
|
-
function buildMergedOpenCodeProjectConfig(existing, root
|
|
737
|
-
const generated = renderOpenCodeProjectConfig(root
|
|
793
|
+
function buildMergedOpenCodeProjectConfig(existing, root) {
|
|
794
|
+
const generated = renderOpenCodeProjectConfig(root);
|
|
738
795
|
return {
|
|
739
796
|
...existing,
|
|
740
797
|
$schema: existing.$schema ?? generated.$schema,
|
|
741
|
-
command:
|
|
742
|
-
...objectValue(existing.command),
|
|
743
|
-
'audit-code': generated.command['audit-code'],
|
|
744
|
-
},
|
|
798
|
+
command: removeManagedOpenCodeCommand(existing.command),
|
|
745
799
|
mcp: {
|
|
746
800
|
...objectValue(existing.mcp),
|
|
747
801
|
auditor: generated.mcp.auditor,
|
|
@@ -1224,9 +1278,9 @@ const INSTALL_HOST_DEFINITIONS = {
|
|
|
1224
1278
|
host: 'opencode',
|
|
1225
1279
|
label: 'OpenCode',
|
|
1226
1280
|
support_level: 'supported',
|
|
1227
|
-
setup_kind: 'command+
|
|
1281
|
+
setup_kind: 'global-command+project-mcp',
|
|
1228
1282
|
summary:
|
|
1229
|
-
'Use the
|
|
1283
|
+
'Use the global OpenCode `/audit-code` command installed by npm plus generated project MCP and permission wiring.',
|
|
1230
1284
|
primary_path_key: 'opencodeConfigPath',
|
|
1231
1285
|
supporting_path_keys: [
|
|
1232
1286
|
'agentsInstructionsPath',
|
|
@@ -1234,8 +1288,8 @@ const INSTALL_HOST_DEFINITIONS = {
|
|
|
1234
1288
|
],
|
|
1235
1289
|
steps: [
|
|
1236
1290
|
'Open this repository in OpenCode.',
|
|
1237
|
-
'
|
|
1238
|
-
'
|
|
1291
|
+
'Use the global `/audit-code` command installed by `npm install -g auditor-lambda`.',
|
|
1292
|
+
'Let OpenCode load the generated `opencode.json` for the auditor MCP server and project permissions only.',
|
|
1239
1293
|
],
|
|
1240
1294
|
profile: {
|
|
1241
1295
|
writeOpenCode: true,
|
|
@@ -1944,18 +1998,13 @@ async function verifyInstalledBootstrap(argv) {
|
|
|
1944
1998
|
if (config?.mcp?.auditor?.type !== 'local') {
|
|
1945
1999
|
throw new Error(`OpenCode config must set mcp.auditor.type to "local", got ${config?.mcp?.auditor?.type ?? 'missing'}.`);
|
|
1946
2000
|
}
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
throw new Error('OpenCode config is missing command["audit-code"].template — the /audit-code slash command will not surface. Run "audit-code install".');
|
|
1950
|
-
}
|
|
1951
|
-
const { body: sourceBody } = splitFrontmatter(await readFile(promptAssetPath, 'utf8'));
|
|
1952
|
-
if (commandConfig.template !== sourceBody.trimStart()) {
|
|
1953
|
-
throw new Error('OpenCode config command["audit-code"].template is out of sync with the source prompt. Run "audit-code install".');
|
|
2001
|
+
if (config?.command?.['audit-code']) {
|
|
2002
|
+
throw new Error('OpenCode project config must not define command["audit-code"]; the slash command is global npm-installed state. Run "audit-code install --host opencode" to remove the stale local command.');
|
|
1954
2003
|
}
|
|
1955
2004
|
assertOpenCodeAuditPermissionConfig(config?.permission, 'permission');
|
|
1956
2005
|
assertOpenCodeAuditPermissionConfig(config?.agent?.auditor?.permission, 'agent.auditor.permission');
|
|
1957
2006
|
return {
|
|
1958
|
-
summary: 'OpenCode project config has MCP server
|
|
2007
|
+
summary: 'OpenCode project config has MCP server and audit permissions; /audit-code is supplied by the global npm-installed OpenCode command.',
|
|
1959
2008
|
path: assetPaths.opencodeConfigPath,
|
|
1960
2009
|
};
|
|
1961
2010
|
});
|
|
@@ -2130,8 +2179,8 @@ async function detectBootstrapRefreshReason(root, host) {
|
|
|
2130
2179
|
}
|
|
2131
2180
|
case 'opencode': {
|
|
2132
2181
|
const opencodeConfig = await readJson(assetPaths.opencodeConfigPath, 'OpenCode config').catch(() => null);
|
|
2133
|
-
if (opencodeConfig?.command?.['audit-code']
|
|
2134
|
-
return 'stale_host_asset:opencode:
|
|
2182
|
+
if (opencodeConfig?.command?.['audit-code']) {
|
|
2183
|
+
return 'stale_host_asset:opencode:local_command';
|
|
2135
2184
|
}
|
|
2136
2185
|
try {
|
|
2137
2186
|
assertOpenCodeAuditPermissionConfig(opencodeConfig?.permission, 'permission');
|
|
@@ -2398,7 +2447,7 @@ async function installBootstrap(argv, options = {}) {
|
|
|
2398
2447
|
await writeMergedGeneratedJson(
|
|
2399
2448
|
assetPaths.opencodeConfigPath,
|
|
2400
2449
|
'OpenCode project config',
|
|
2401
|
-
(existing) => buildMergedOpenCodeProjectConfig(existing, root
|
|
2450
|
+
(existing) => buildMergedOpenCodeProjectConfig(existing, root),
|
|
2402
2451
|
),
|
|
2403
2452
|
);
|
|
2404
2453
|
}
|
|
@@ -2621,6 +2670,11 @@ export async function runAuditCodeWrapper({
|
|
|
2621
2670
|
return;
|
|
2622
2671
|
}
|
|
2623
2672
|
|
|
2673
|
+
if (argv[0] === 'next-step') {
|
|
2674
|
+
await runDistCommand('next-step', argv.slice(1), { ensureArtifactsDir: true });
|
|
2675
|
+
return;
|
|
2676
|
+
}
|
|
2677
|
+
|
|
2624
2678
|
if (argv[0] === 'prepare-dispatch') {
|
|
2625
2679
|
await runDistCommand('prepare-dispatch', argv.slice(1));
|
|
2626
2680
|
return;
|