auditor-lambda 0.3.20 → 0.3.22

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 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 `/audit-code` surfaces for the hosts we can automate today, including:
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` slash command and auditor MCP server
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, promptBody) {
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
- edit: { ...OPENCODE_AUDIT_EDIT_PERMISSION },
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, promptBody) {
737
- const generated = renderOpenCodeProjectConfig(root, promptBody);
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+agent+mcp',
1281
+ setup_kind: 'global-command+project-mcp',
1228
1282
  summary:
1229
- 'Use the generated `opencode.json` so the `/audit-code` slash command and the local auditor MCP server are both available.',
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
- 'Let OpenCode load the generated `opencode.json` — it registers the `/audit-code` slash command and the auditor MCP server.',
1238
- 'Invoke `/audit-code` and keep the audit loop on the auditor MCP tools.',
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
- const commandConfig = config?.command?.['audit-code'];
1948
- if (!commandConfig?.template) {
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, /audit-code slash command, and audit permissions.',
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']?.template !== sourcePromptBody.trimStart()) {
2134
- return 'stale_host_asset:opencode:config_command';
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, promptBody),
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;
@@ -2631,6 +2685,11 @@ export async function runAuditCodeWrapper({
2631
2685
  return;
2632
2686
  }
2633
2687
 
2688
+ if (argv[0] === 'quota') {
2689
+ await runDistCommand('quota', argv.slice(1), { ensureArtifactsDir: true });
2690
+ return;
2691
+ }
2692
+
2634
2693
  if (argv[0] === 'submit-packet') {
2635
2694
  await runDistCommand('submit-packet', argv.slice(1));
2636
2695
  return;