auditor-lambda 0.3.5 → 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -407,6 +407,42 @@ async function writeGeneratedJson(targetPath, value) {
407
407
  };
408
408
  }
409
409
 
410
+ async function readJsonObjectIfExists(targetPath, description) {
411
+ if (!(await fileExists(targetPath))) {
412
+ return {};
413
+ }
414
+
415
+ let parsed;
416
+ try {
417
+ parsed = JSON.parse(await readFile(targetPath, 'utf8'));
418
+ } catch (error) {
419
+ throw new Error(
420
+ `${description} exists but is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
421
+ );
422
+ }
423
+
424
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
425
+ throw new Error(`${description} must be a JSON object when it already exists.`);
426
+ }
427
+
428
+ return parsed;
429
+ }
430
+
431
+ async function writeMergedGeneratedJson(targetPath, description, buildValue) {
432
+ const existed = await fileExists(targetPath);
433
+ const existing = await readJsonObjectIfExists(targetPath, description);
434
+ await mkdir(dirname(targetPath), { recursive: true });
435
+ await writeFile(
436
+ targetPath,
437
+ JSON.stringify(buildValue(existing), null, 2) + '\n',
438
+ 'utf8',
439
+ );
440
+ return {
441
+ path: targetPath,
442
+ mode: existed ? 'updated' : 'created',
443
+ };
444
+ }
445
+
410
446
  async function writeGeneratedBinary(targetPath, content) {
411
447
  const existed = await fileExists(targetPath);
412
448
  await mkdir(dirname(targetPath), { recursive: true });
@@ -481,70 +517,99 @@ function renderCodexAutomationRecipe() {
481
517
 
482
518
  function renderOpenCodeProjectConfig(root) {
483
519
  const launcher = replaceBackslashes(toRepoRelativePath(root, join(root, '.audit-code', 'install', MCP_LAUNCHER_FILENAME)));
484
- return JSON.stringify(
485
- {
486
- $schema: 'https://opencode.ai/config.json',
487
- mcp: {
488
- auditor: {
489
- type: 'local',
490
- command: ['node', launcher],
491
- enabled: true,
492
- timeout: 10000,
493
- },
520
+ return {
521
+ $schema: 'https://opencode.ai/config.json',
522
+ mcp: {
523
+ auditor: {
524
+ type: 'local',
525
+ command: ['node', launcher],
526
+ enabled: true,
527
+ timeout: 10000,
494
528
  },
495
- permission: {
496
- read: 'allow',
497
- glob: 'allow',
498
- grep: 'allow',
499
- edit: 'ask',
500
- bash: {
501
- '*': 'ask',
502
- 'git status*': 'allow',
503
- 'git diff*': 'allow',
504
- 'grep *': 'allow',
505
- 'rm *': 'deny',
506
- },
529
+ },
530
+ permission: {
531
+ read: 'allow',
532
+ glob: 'allow',
533
+ grep: 'allow',
534
+ edit: 'ask',
535
+ bash: {
536
+ '*': 'ask',
537
+ 'git status*': 'allow',
538
+ 'git diff*': 'allow',
539
+ 'grep *': 'allow',
540
+ 'rm *': 'deny',
507
541
  },
508
- agent: {
509
- auditor: {
510
- description:
511
- 'Read-heavy audit orchestration agent for the /audit-code workflow.',
512
- tools: {
513
- 'auditor*': true,
514
- },
515
- permission: {
516
- edit: 'ask',
517
- bash: {
518
- '*': 'ask',
519
- 'git status*': 'allow',
520
- 'git diff*': 'allow',
521
- 'grep *': 'allow',
522
- 'rm *': 'deny',
523
- },
524
- question: 'allow',
542
+ },
543
+ agent: {
544
+ auditor: {
545
+ description:
546
+ 'Read-heavy audit orchestration agent for the /audit-code workflow.',
547
+ tools: {
548
+ 'auditor*': true,
549
+ },
550
+ permission: {
551
+ edit: 'ask',
552
+ bash: {
553
+ '*': 'ask',
554
+ 'git status*': 'allow',
555
+ 'git diff*': 'allow',
556
+ 'grep *': 'allow',
557
+ 'rm *': 'deny',
525
558
  },
559
+ question: 'allow',
526
560
  },
527
561
  },
528
562
  },
529
- null,
530
- 2,
531
- ) + '\n';
563
+ };
532
564
  }
533
565
 
534
566
  function renderVSCodeMcpConfig() {
535
- return JSON.stringify(
536
- {
537
- servers: {
538
- auditor: {
539
- type: 'stdio',
540
- command: 'node',
541
- args: ['${workspaceFolder}/.audit-code/install/run-mcp-server.mjs'],
542
- },
567
+ return {
568
+ servers: {
569
+ auditor: {
570
+ type: 'stdio',
571
+ command: 'node',
572
+ args: ['${workspaceFolder}/.audit-code/install/run-mcp-server.mjs'],
543
573
  },
544
574
  },
545
- null,
546
- 2,
547
- ) + '\n';
575
+ };
576
+ }
577
+
578
+ function objectValue(value) {
579
+ return value && typeof value === 'object' && !Array.isArray(value)
580
+ ? value
581
+ : {};
582
+ }
583
+
584
+ function buildMergedOpenCodeProjectConfig(existing, root) {
585
+ const generated = renderOpenCodeProjectConfig(root);
586
+ return {
587
+ ...existing,
588
+ $schema: existing.$schema ?? generated.$schema,
589
+ mcp: {
590
+ ...objectValue(existing.mcp),
591
+ auditor: generated.mcp.auditor,
592
+ },
593
+ permission:
594
+ existing.permission && typeof existing.permission === 'object' && !Array.isArray(existing.permission)
595
+ ? existing.permission
596
+ : generated.permission,
597
+ agent: {
598
+ ...objectValue(existing.agent),
599
+ auditor: generated.agent.auditor,
600
+ },
601
+ };
602
+ }
603
+
604
+ function buildMergedVSCodeMcpConfig(existing) {
605
+ const generated = renderVSCodeMcpConfig();
606
+ return {
607
+ ...existing,
608
+ servers: {
609
+ ...objectValue(existing.servers),
610
+ auditor: generated.servers.auditor,
611
+ },
612
+ };
548
613
  }
549
614
 
550
615
  function renderClaudeDesktopProjectTemplate() {
@@ -932,116 +997,203 @@ async function buildClaudeDesktopBundle(root, results) {
932
997
  };
933
998
  }
934
999
 
935
- function buildHostCatalog({ root, host, assets }) {
936
- const entries = {
937
- codex: {
938
- host: 'codex',
939
- label: 'Codex',
940
- support_level: 'supported',
941
- setup_kind: 'skills+mcp+instructions',
942
- summary:
943
- 'Use the generated Codex skill bundle, AGENTS instructions, and shared MCP launcher so Codex can drive the backend through native tools instead of raw shell commands.',
944
- primary_path: assets.codexSkillPath,
945
- supporting_paths: [
946
- assets.agentsInstructionsPath,
947
- assets.codexMcpSetupPath,
948
- assets.codexAutomationRecipePath,
949
- ].filter(Boolean),
950
- steps: [
951
- 'Open this repository in Codex.',
952
- 'Ensure Codex can access the repo-local auditor MCP server using the generated setup guide.',
953
- 'Ask Codex to use the auditor MCP tools to start or continue `/audit-code`.',
954
- ],
1000
+ const INSTALL_PROFILE_FLAGS = [
1001
+ 'writeVSCode',
1002
+ 'writeCopilotInstructions',
1003
+ 'writeOpenCode',
1004
+ 'writeCodex',
1005
+ 'writeClaudeDesktop',
1006
+ 'writeAntigravity',
1007
+ 'writeAgents',
1008
+ ];
1009
+
1010
+ const INSTALL_HOST_ORDER = [
1011
+ 'codex',
1012
+ 'claude-desktop',
1013
+ 'opencode',
1014
+ 'vscode',
1015
+ 'antigravity',
1016
+ ];
1017
+
1018
+ const INSTALL_HOST_DEFINITIONS = {
1019
+ codex: {
1020
+ host: 'codex',
1021
+ label: 'Codex',
1022
+ support_level: 'supported',
1023
+ setup_kind: 'skills+mcp+instructions',
1024
+ summary:
1025
+ 'Use the generated Codex skill bundle, AGENTS instructions, and shared MCP launcher so Codex can drive the backend through native tools instead of raw shell commands.',
1026
+ primary_path_key: 'codexSkillPath',
1027
+ supporting_path_keys: [
1028
+ 'agentsInstructionsPath',
1029
+ 'codexMcpSetupPath',
1030
+ 'codexAutomationRecipePath',
1031
+ ],
1032
+ steps: [
1033
+ 'Open this repository in Codex.',
1034
+ 'Ensure Codex can access the repo-local auditor MCP server using the generated setup guide.',
1035
+ 'Ask Codex to use the auditor MCP tools to start or continue `/audit-code`.',
1036
+ ],
1037
+ profile: {
1038
+ writeCodex: true,
1039
+ writeAgents: true,
955
1040
  },
956
- 'claude-desktop': {
957
- host: 'claude-desktop',
958
- label: 'Claude Desktop',
959
- support_level: 'supported',
960
- setup_kind: 'local-mcp-bundle',
961
- summary:
962
- 'Install the generated local MCP bundle in Claude Desktop, then use the project template and prompt asset as supporting context.',
963
- primary_path: assets.claudeDesktopDxtPath,
964
- supporting_paths: [
965
- assets.claudeDesktopMcpbPath,
966
- assets.claudeDesktopProjectTemplatePath,
967
- assets.claudeDesktopRemoteConnectorPath,
968
- assets.installedPromptPath,
969
- ].filter(Boolean),
970
- steps: [
971
- 'Open Claude Desktop Settings and install the generated `.dxt` bundle.',
972
- 'Configure the repository root when prompted so the bundle can launch the local auditor MCP server.',
973
- 'Use the project template and prompt asset to kick off `/audit-code` in conversation.',
974
- ],
1041
+ },
1042
+ 'claude-desktop': {
1043
+ host: 'claude-desktop',
1044
+ label: 'Claude Desktop',
1045
+ support_level: 'supported',
1046
+ setup_kind: 'local-mcp-bundle',
1047
+ summary:
1048
+ 'Install the generated local MCP bundle in Claude Desktop, then use the project template and prompt asset as supporting context.',
1049
+ primary_path_key: 'claudeDesktopDxtPath',
1050
+ supporting_path_keys: [
1051
+ 'claudeDesktopMcpbPath',
1052
+ 'claudeDesktopProjectTemplatePath',
1053
+ 'claudeDesktopRemoteConnectorPath',
1054
+ 'installedPromptPath',
1055
+ ],
1056
+ steps: [
1057
+ 'Open Claude Desktop Settings and install the generated `.dxt` bundle.',
1058
+ 'Configure the repository root when prompted so the bundle can launch the local auditor MCP server.',
1059
+ 'Use the project template and prompt asset to kick off `/audit-code` in conversation.',
1060
+ ],
1061
+ profile: {
1062
+ writeClaudeDesktop: true,
975
1063
  },
976
- opencode: {
977
- host: 'opencode',
978
- label: 'OpenCode',
979
- support_level: 'supported',
980
- setup_kind: 'command+agent+mcp',
981
- summary:
982
- 'Use the generated OpenCode command and project config so `/audit-code` and the local auditor MCP server are available together.',
983
- primary_path: assets.opencodeCommandPath,
984
- supporting_paths: [
985
- assets.opencodeConfigPath,
986
- assets.opencodeSkillPath,
987
- assets.agentsInstructionsPath,
988
- assets.mcpLauncherPath,
989
- ].filter(Boolean),
990
- steps: [
991
- 'Open this repository in OpenCode.',
992
- 'Let OpenCode load the generated `opencode.json` so the auditor MCP server is available.',
993
- 'Invoke `/audit-code` and keep the audit loop on the auditor MCP tools.',
994
- ],
1064
+ },
1065
+ opencode: {
1066
+ host: 'opencode',
1067
+ label: 'OpenCode',
1068
+ support_level: 'supported',
1069
+ setup_kind: 'command+agent+mcp',
1070
+ summary:
1071
+ 'Use the generated OpenCode command and project config so `/audit-code` and the local auditor MCP server are available together.',
1072
+ primary_path_key: 'opencodeCommandPath',
1073
+ supporting_path_keys: [
1074
+ 'opencodeConfigPath',
1075
+ 'opencodeSkillPath',
1076
+ 'agentsInstructionsPath',
1077
+ 'mcpLauncherPath',
1078
+ ],
1079
+ steps: [
1080
+ 'Open this repository in OpenCode.',
1081
+ 'Let OpenCode load the generated `opencode.json` so the auditor MCP server is available.',
1082
+ 'Invoke `/audit-code` and keep the audit loop on the auditor MCP tools.',
1083
+ ],
1084
+ profile: {
1085
+ writeOpenCode: true,
1086
+ writeAgents: true,
995
1087
  },
996
- vscode: {
997
- host: 'vscode',
998
- label: 'VS Code',
999
- support_level: 'supported',
1000
- setup_kind: 'prompt+agent+mcp',
1001
- summary:
1002
- 'Use the generated prompt file, custom agent, and workspace MCP configuration for the cleanest VS Code integration.',
1003
- primary_path: assets.vscodePromptPath,
1004
- supporting_paths: [
1005
- assets.vscodeAgentPath,
1006
- assets.vscodeMcpConfigPath,
1007
- assets.copilotInstructionsPath,
1008
- ].filter(Boolean),
1009
- steps: [
1010
- 'Open this repository in VS Code with Copilot.',
1011
- 'Allow VS Code to discover the workspace MCP server from `.vscode/mcp.json`.',
1012
- 'Invoke `/audit-code` in chat and use the custom auditor agent when you want the dedicated orchestration persona.',
1013
- ],
1088
+ },
1089
+ vscode: {
1090
+ host: 'vscode',
1091
+ label: 'VS Code',
1092
+ support_level: 'supported',
1093
+ setup_kind: 'prompt+agent+mcp',
1094
+ summary:
1095
+ 'Use the generated prompt file, custom agent, and workspace MCP configuration for the cleanest VS Code integration.',
1096
+ primary_path_key: 'vscodePromptPath',
1097
+ supporting_path_keys: [
1098
+ 'vscodeAgentPath',
1099
+ 'vscodeMcpConfigPath',
1100
+ 'copilotInstructionsPath',
1101
+ ],
1102
+ steps: [
1103
+ 'Open this repository in VS Code with Copilot.',
1104
+ 'Allow VS Code to discover the workspace MCP server from `.vscode/mcp.json`.',
1105
+ 'Invoke `/audit-code` in chat and use the custom auditor agent when you want the dedicated orchestration persona.',
1106
+ ],
1107
+ profile: {
1108
+ writeVSCode: true,
1109
+ writeCopilotInstructions: true,
1014
1110
  },
1015
- antigravity: {
1016
- host: 'antigravity',
1017
- label: 'Antigravity',
1018
- support_level: 'guided',
1019
- setup_kind: 'planning-guide+mcp-ready',
1020
- summary:
1021
- 'Start in Planning mode with the generated guide and AGENTS instructions, then use the shared MCP launcher once Antigravity is ready to call structured tools.',
1022
- primary_path: assets.antigravityPlanningGuidePath,
1023
- supporting_paths: [
1024
- assets.agentsInstructionsPath,
1025
- assets.mcpLauncherPath,
1026
- assets.installedPromptPath,
1027
- ].filter(Boolean),
1028
- steps: [
1029
- 'Open this repository in Antigravity Planning mode.',
1030
- 'Load the generated planning guide and AGENTS instructions before starting the audit.',
1031
- 'Use the shared auditor MCP server when Antigravity needs structured audit state instead of free-form shell guesses.',
1032
- ],
1111
+ },
1112
+ antigravity: {
1113
+ host: 'antigravity',
1114
+ label: 'Antigravity',
1115
+ support_level: 'guided',
1116
+ setup_kind: 'planning-guide+mcp-ready',
1117
+ summary:
1118
+ 'Start in Planning mode with the generated guide and AGENTS instructions, then use the shared MCP launcher once Antigravity is ready to call structured tools.',
1119
+ primary_path_key: 'antigravityPlanningGuidePath',
1120
+ supporting_path_keys: [
1121
+ 'agentsInstructionsPath',
1122
+ 'mcpLauncherPath',
1123
+ 'installedPromptPath',
1124
+ ],
1125
+ steps: [
1126
+ 'Open this repository in Antigravity Planning mode.',
1127
+ 'Load the generated planning guide and AGENTS instructions before starting the audit.',
1128
+ 'Use the shared auditor MCP server when Antigravity needs structured audit state instead of free-form shell guesses.',
1129
+ ],
1130
+ profile: {
1131
+ writeAntigravity: true,
1132
+ writeAgents: true,
1033
1133
  },
1034
- };
1134
+ },
1135
+ };
1136
+
1137
+ function supportedInstallHostsMessage() {
1138
+ return ['all', 'copilot', ...INSTALL_HOST_ORDER].join(', ');
1139
+ }
1140
+
1141
+ function getInstallHostKeys(host) {
1142
+ if (host === 'all') {
1143
+ return INSTALL_HOST_ORDER;
1144
+ }
1145
+
1146
+ if (host === 'copilot') {
1147
+ return ['vscode'];
1148
+ }
1149
+
1150
+ if (INSTALL_HOST_DEFINITIONS[host]) {
1151
+ return [host];
1152
+ }
1153
+
1154
+ throw new Error(
1155
+ `Unsupported host "${host}". Supported hosts: ${supportedInstallHostsMessage()}.`,
1156
+ );
1157
+ }
1158
+
1159
+ function getInstallProfile(host) {
1160
+ const profile = Object.fromEntries(
1161
+ INSTALL_PROFILE_FLAGS.map((flag) => [flag, false]),
1162
+ );
1163
+
1164
+ for (const hostKey of getInstallHostKeys(host)) {
1165
+ const hostProfile = INSTALL_HOST_DEFINITIONS[hostKey].profile;
1166
+ for (const flag of INSTALL_PROFILE_FLAGS) {
1167
+ profile[flag] = profile[flag] || Boolean(hostProfile[flag]);
1168
+ }
1169
+ }
1170
+
1171
+ return profile;
1172
+ }
1035
1173
 
1036
- const hostOrder = host === 'all'
1037
- ? ['codex', 'claude-desktop', 'opencode', 'vscode', 'antigravity']
1038
- : host === 'copilot'
1039
- ? ['vscode']
1040
- : [host];
1174
+ function buildHostCatalog({ root, host, assets }) {
1175
+ return getInstallHostKeys(host)
1176
+ .map((hostKey) => {
1177
+ const definition = INSTALL_HOST_DEFINITIONS[hostKey];
1178
+ const primaryPath = assets[definition.primary_path_key];
1179
+ if (!primaryPath) {
1180
+ return null;
1181
+ }
1041
1182
 
1042
- return hostOrder
1043
- .map((hostKey) => entries[hostKey])
1044
- .filter((entry) => entry?.primary_path)
1183
+ return {
1184
+ host: definition.host,
1185
+ label: definition.label,
1186
+ support_level: definition.support_level,
1187
+ setup_kind: definition.setup_kind,
1188
+ summary: definition.summary,
1189
+ primary_path: primaryPath,
1190
+ supporting_paths: definition.supporting_path_keys
1191
+ .map((key) => assets[key])
1192
+ .filter(Boolean),
1193
+ steps: definition.steps,
1194
+ };
1195
+ })
1196
+ .filter(Boolean)
1045
1197
  .map((entry) => ({
1046
1198
  ...entry,
1047
1199
  primary_path: entry.primary_path,
@@ -1102,6 +1254,7 @@ function renderInstallGuide({
1102
1254
  lines.push('', 'Backend fallback:');
1103
1255
  lines.push('- from the repository root, run `audit-code` only when you intentionally need the repo-local backend wrapper');
1104
1256
  lines.push('- run `audit-code verify-install` after bootstrap when you want to smoke-test the generated launchers and host configs');
1257
+ lines.push('- rerun `audit-code install` to refresh every generated host surface from the shared prompt, skill, and MCP launcher assets together');
1105
1258
 
1106
1259
  if (host !== 'all') {
1107
1260
  lines.push('');
@@ -1112,85 +1265,6 @@ function renderInstallGuide({
1112
1265
  return lines.join('\n');
1113
1266
  }
1114
1267
 
1115
- function getInstallProfile(host) {
1116
- switch (host) {
1117
- case 'all':
1118
- return {
1119
- writeVSCode: true,
1120
- writeCopilotInstructions: true,
1121
- writeOpenCode: true,
1122
- writeCodex: true,
1123
- writeClaudeDesktop: true,
1124
- writeAntigravity: true,
1125
- writeAgents: true,
1126
- };
1127
- case 'copilot':
1128
- return {
1129
- writeVSCode: true,
1130
- writeCopilotInstructions: true,
1131
- writeAgents: false,
1132
- writeOpenCode: false,
1133
- writeCodex: false,
1134
- writeClaudeDesktop: false,
1135
- writeAntigravity: false,
1136
- };
1137
- case 'vscode':
1138
- return {
1139
- writeVSCode: true,
1140
- writeCopilotInstructions: true,
1141
- writeAgents: false,
1142
- writeOpenCode: false,
1143
- writeCodex: false,
1144
- writeClaudeDesktop: false,
1145
- writeAntigravity: false,
1146
- };
1147
- case 'opencode':
1148
- return {
1149
- writeVSCode: false,
1150
- writeCopilotInstructions: false,
1151
- writeAgents: true,
1152
- writeOpenCode: true,
1153
- writeCodex: false,
1154
- writeClaudeDesktop: false,
1155
- writeAntigravity: false,
1156
- };
1157
- case 'codex':
1158
- return {
1159
- writeVSCode: false,
1160
- writeCopilotInstructions: false,
1161
- writeAgents: true,
1162
- writeOpenCode: false,
1163
- writeCodex: true,
1164
- writeClaudeDesktop: false,
1165
- writeAntigravity: false,
1166
- };
1167
- case 'claude-desktop':
1168
- return {
1169
- writeVSCode: false,
1170
- writeCopilotInstructions: false,
1171
- writeAgents: false,
1172
- writeOpenCode: false,
1173
- writeCodex: false,
1174
- writeClaudeDesktop: true,
1175
- writeAntigravity: false,
1176
- };
1177
- case 'antigravity':
1178
- return {
1179
- writeVSCode: false,
1180
- writeCopilotInstructions: false,
1181
- writeAgents: true,
1182
- writeOpenCode: false,
1183
- writeCodex: false,
1184
- writeClaudeDesktop: false,
1185
- writeAntigravity: true,
1186
- };
1187
- default:
1188
- throw new Error(
1189
- `Unsupported host "${host}". Supported hosts: all, copilot, vscode, opencode, codex, claude-desktop, antigravity.`,
1190
- );
1191
- }
1192
- }
1193
-
1194
1268
  async function assertDirectoryExists(path, description) {
1195
1269
  let stats;
1196
1270
  try {
@@ -1512,7 +1586,7 @@ async function verifyInstalledBootstrap(argv) {
1512
1586
  (installManifest.hosts ?? []).map((entry) => [entry.host, entry]),
1513
1587
  );
1514
1588
  const selectedHosts = requestedHost && requestedHost !== 'all'
1515
- ? [requestedHost]
1589
+ ? getInstallHostKeys(requestedHost)
1516
1590
  : [...hostCatalog.keys()];
1517
1591
 
1518
1592
  await collectVerifyCheck(generalChecks, 'install_guide', async () => {
@@ -2056,9 +2130,10 @@ async function installBootstrap(argv) {
2056
2130
  ),
2057
2131
  );
2058
2132
  results.push(
2059
- await writeGeneratedMarkdown(
2133
+ await writeMergedGeneratedJson(
2060
2134
  assetPaths.opencodeConfigPath,
2061
- renderOpenCodeProjectConfig(root),
2135
+ 'OpenCode project config',
2136
+ (existing) => buildMergedOpenCodeProjectConfig(existing, root),
2062
2137
  ),
2063
2138
  );
2064
2139
  }
@@ -2084,9 +2159,10 @@ async function installBootstrap(argv) {
2084
2159
  ),
2085
2160
  );
2086
2161
  results.push(
2087
- await writeGeneratedMarkdown(
2162
+ await writeMergedGeneratedJson(
2088
2163
  assetPaths.vscodeMcpConfigPath,
2089
- renderVSCodeMcpConfig(),
2164
+ 'VS Code MCP config',
2165
+ buildMergedVSCodeMcpConfig,
2090
2166
  ),
2091
2167
  );
2092
2168
  }
@@ -2116,6 +2192,7 @@ async function installBootstrap(argv) {
2116
2192
  install_manifest_path: installManifestPath,
2117
2193
  mcp_server_launcher_path: mcpLauncherPath,
2118
2194
  source_prompt_path: resolve(promptAssetPath),
2195
+ source_skill_path: resolve(skillAssetPath),
2119
2196
  asset_paths: assetPaths,
2120
2197
  hosts: hostGuidance,
2121
2198
  };
@@ -2155,6 +2232,7 @@ async function installBootstrap(argv) {
2155
2232
  install_manifest_path: installManifestPath,
2156
2233
  mcp_server_launcher_path: mcpLauncherPath,
2157
2234
  source_prompt_path: resolve(promptAssetPath),
2235
+ source_skill_path: resolve(skillAssetPath),
2158
2236
  files: results,
2159
2237
  slash_command_surfaces: {
2160
2238
  vscode_prompt: assetPaths.vscodePromptPath,
package/dist/cli.js CHANGED
@@ -36,6 +36,9 @@ const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
36
36
  const ADVANCE_AUDIT_CONTRACT_VERSION = "audit-code/v1alpha1";
37
37
  const WORKER_RESULT_CONTRACT_VERSION = "audit-code-worker-result/v1alpha1";
38
38
  const LARGE_FILE_PACKET_TARGET_LINES = 2500;
39
+ const SMALL_MODEL_HINT_MAX_LINES = 500;
40
+ const SMALL_MODEL_HINT_MAX_ESTIMATED_TOKENS = 3000;
41
+ const DEEP_MODEL_HINT_MIN_ESTIMATED_TOKENS = 9000;
39
42
  const DIRECT_CLI_DEFAULTS = {
40
43
  rootDir: ".",
41
44
  artifactsDir: ".artifacts",
@@ -1474,6 +1477,58 @@ function isIsolatedLargeFilePacket(packet) {
1474
1477
  return (packet.file_paths.length === 1 &&
1475
1478
  packet.total_lines > LARGE_FILE_PACKET_TARGET_LINES);
1476
1479
  }
1480
+ function buildDispatchComplexity(packet, largeFileMode) {
1481
+ return {
1482
+ priority: packet.priority,
1483
+ task_count: packet.task_ids.length,
1484
+ file_count: packet.file_paths.length,
1485
+ total_lines: packet.total_lines,
1486
+ estimated_tokens: packet.estimated_tokens,
1487
+ lenses: packet.lenses,
1488
+ tags: packet.tags ?? [],
1489
+ large_file_mode: largeFileMode,
1490
+ };
1491
+ }
1492
+ function buildDispatchModelHint(complexity) {
1493
+ const deepReasons = [];
1494
+ if (complexity.priority === "high")
1495
+ deepReasons.push("high_priority");
1496
+ if (complexity.large_file_mode)
1497
+ deepReasons.push("isolated_large_file");
1498
+ if (complexity.estimated_tokens >= DEEP_MODEL_HINT_MIN_ESTIMATED_TOKENS) {
1499
+ deepReasons.push("high_estimated_tokens");
1500
+ }
1501
+ if (complexity.tags.some((tag) => tag === "critical_flow" || tag.startsWith("critical_flow:"))) {
1502
+ deepReasons.push("critical_flow");
1503
+ }
1504
+ if (complexity.tags.some((tag) => tag === "external_analyzer_signal" || tag.startsWith("external_tool:"))) {
1505
+ deepReasons.push("external_analyzer_signal");
1506
+ }
1507
+ if (deepReasons.length > 0) {
1508
+ return { tier: "deep", reasons: deepReasons };
1509
+ }
1510
+ const sensitiveLenses = new Set(["security", "data_integrity", "reliability"]);
1511
+ const hasSensitiveLens = complexity.lenses.some((lens) => sensitiveLenses.has(lens));
1512
+ if (complexity.priority === "low" &&
1513
+ complexity.total_lines <= SMALL_MODEL_HINT_MAX_LINES &&
1514
+ complexity.estimated_tokens <= SMALL_MODEL_HINT_MAX_ESTIMATED_TOKENS &&
1515
+ !hasSensitiveLens &&
1516
+ complexity.tags.length === 0) {
1517
+ return { tier: "small", reasons: ["small_low_priority_packet"] };
1518
+ }
1519
+ const reasons = [];
1520
+ if (complexity.priority === "medium")
1521
+ reasons.push("medium_priority");
1522
+ if (hasSensitiveLens)
1523
+ reasons.push("sensitive_lens");
1524
+ if (complexity.total_lines > SMALL_MODEL_HINT_MAX_LINES) {
1525
+ reasons.push("moderate_size");
1526
+ }
1527
+ return {
1528
+ tier: "standard",
1529
+ reasons: reasons.length > 0 ? reasons : ["default_review_packet"],
1530
+ };
1531
+ }
1477
1532
  function withinRoot(root, path) {
1478
1533
  const rootPath = resolve(root);
1479
1534
  const absolutePath = resolve(rootPath, path);
@@ -1641,6 +1696,7 @@ async function cmdPrepareDispatch(argv) {
1641
1696
  `--run-id-b64 ${toBase64Url(runId)} ` +
1642
1697
  `--packet-id-b64 ${toBase64Url(packet.packet_id)} ` +
1643
1698
  `--artifacts-dir-b64 ${toBase64Url(artifactsDir)}`;
1699
+ const complexity = buildDispatchComplexity(packet, largeFileMode);
1644
1700
  for (const task of packetTasks) {
1645
1701
  resultMapEntries.push({
1646
1702
  packet_id: packet.packet_id,
@@ -1712,6 +1768,8 @@ async function cmdPrepareDispatch(argv) {
1712
1768
  description: `Audit ${packet.file_paths.length} file(s), ${packet.task_ids.length} task(s), ${packet.lenses.length} lens(es) (~${packet.total_lines} lines)` +
1713
1769
  (largeFileMode ? " [isolated large-file mode]" : ""),
1714
1770
  prompt_path: promptPath,
1771
+ complexity,
1772
+ model_hint: buildDispatchModelHint(complexity),
1715
1773
  });
1716
1774
  }
1717
1775
  await writeJsonFile(dispatchPlanPath, plan);
@@ -2170,7 +2228,7 @@ async function cmdValidate(argv) {
2170
2228
  ...providerIssues,
2171
2229
  ];
2172
2230
  const resolvedProvider = rawSessionConfig === undefined
2173
- ? "auto"
2231
+ ? "local-subprocess"
2174
2232
  : sessionConfigIssues.length > 0
2175
2233
  ? null
2176
2234
  : resolveFreshSessionProviderName(undefined, rawSessionConfig);
@@ -254,7 +254,7 @@ The current implementation shipped the shared installer and MCP substrate. The r
254
254
 
255
255
  Highest-value follow-through:
256
256
 
257
- 1. validate the generated Codex, Claude Desktop, OpenCode, and VS Code assets inside the real products they target
257
+ 1. validate the generated Codex, Claude Desktop, OpenCode, VS Code, and Antigravity assets inside the real products they target
258
258
  2. tighten generated quick-start guidance anywhere those host smoke tests expose ambiguity
259
259
  3. document exactly how Antigravity artifacts should map into `import_results` and `import_runtime_updates`
260
260
  4. keep host claims conservative until those end-to-end product checks are complete
@@ -10,6 +10,9 @@ That command installs the repo-local `/audit-code` surfaces we can automate toda
10
10
  It is also the single refresh path: rerun `audit-code install` after prompt or
11
11
  skill updates to rewrite the shared install assets and every generated
12
12
  host-specific surface from the same source files.
13
+ The generated manifest records the canonical prompt and skill source paths so
14
+ host surfaces can be checked against one shared source of truth instead of
15
+ drifting independently.
13
16
 
14
17
  After bootstrap, run:
15
18
 
@@ -28,6 +31,7 @@ Installed shared surfaces:
28
31
  - `.audit-code/install/GETTING-STARTED.md`
29
32
  - `.audit-code/install/manifest.json`
30
33
  - `.audit-code/install/run-mcp-server.mjs`
34
+ - `.audit-artifacts/session-config.json` when no backend fallback config exists yet
31
35
 
32
36
  Installed host-specific surfaces:
33
37
 
@@ -76,6 +80,7 @@ without supplying extra root paths, provider flags, or model-selection arguments
76
80
  ## What is fully automated today
77
81
 
78
82
  - shared installer output, manifest generation, and repo-local MCP launcher generation
83
+ - default backend fallback session-config creation when no config exists yet
79
84
  - Codex skill-bundle and AGENTS-oriented install output
80
85
  - OpenCode command, skill, prompt, and config generation
81
86
  - VS Code prompt, custom-agent, instruction, and MCP config generation
@@ -84,7 +89,7 @@ without supplying extra root paths, provider flags, or model-selection arguments
84
89
 
85
90
  ## What is not fully automated today
86
91
 
87
- - product-level smoke validation for the generated Codex, Claude Desktop, OpenCode, and VS Code assets
92
+ - product-level smoke validation for the generated Codex, Claude Desktop, OpenCode, VS Code, and Antigravity assets
88
93
  - one-click proof that the generated Claude Desktop bundle installs cleanly in a real Desktop environment
89
94
  - documented Antigravity artifact round-tripping back through `import_results` and `import_runtime_updates`
90
95
 
@@ -121,13 +121,31 @@ The command prints a compact JSON envelope:
121
121
  {
122
122
  "packet_id": "src-auth:security-correctness:packet-1-...",
123
123
  "description": "Audit 2 file(s), 2 task(s), 2 lens(es) (~70 lines)",
124
- "prompt_path": ".audit-artifacts/runs/run-1/task-results/src-auth_security-correctness_packet-1_ab12cd34ef56.prompt.md"
124
+ "prompt_path": ".audit-artifacts/runs/run-1/task-results/src-auth_security-correctness_packet-1_ab12cd34ef56.prompt.md",
125
+ "complexity": {
126
+ "priority": "high",
127
+ "task_count": 2,
128
+ "file_count": 2,
129
+ "total_lines": 70,
130
+ "estimated_tokens": 1180,
131
+ "lenses": ["security", "correctness"],
132
+ "tags": ["critical_flow"],
133
+ "large_file_mode": false
134
+ },
135
+ "model_hint": {
136
+ "tier": "deep",
137
+ "reasons": ["high_priority", "critical_flow"]
138
+ }
125
139
  }
126
140
  ```
127
141
 
128
142
  The orchestrator should launch one subagent per entry with the entry
129
143
  description and a prompt that tells the subagent to read and follow
130
144
  `entry.prompt_path`.
145
+ If the host supports per-subagent model selection, it may map
146
+ `entry.model_hint.tier` (`small`, `standard`, or `deep`) to local model names.
147
+ These hints are provider-neutral; the backend does not hardcode model names or
148
+ require model selection during normal use.
131
149
 
132
150
  ## Large File Mode
133
151
 
@@ -30,7 +30,7 @@ audit-code install --host vscode
30
30
  ## Behavior
31
31
 
32
32
  - the command copies the canonical prompt payload from `skills/audit-code/audit-code.prompt.md`
33
- - the generated prompt file explicitly sets `agent: agent` so Copilot Chat runs `/audit-code` with tool-capable agent mode
33
+ - the generated prompt file explicitly sets `agent: auditor` so Copilot Chat uses the generated auditor custom agent
34
34
  - the installer upserts its managed compatibility block into `.github/copilot-instructions.md` instead of clobbering unrelated instructions
35
35
  - it prints machine-readable JSON describing the installed targets
36
36
 
@@ -13,6 +13,17 @@ For that surface, the default model rule is:
13
13
 
14
14
  That is the intended product contract.
15
15
 
16
+ When packet dispatch is prepared, `dispatch-plan.json` includes
17
+ provider-neutral complexity metadata and a `model_hint.tier` value:
18
+
19
+ - `small` for tiny, low-priority packets without sensitive lenses or risk tags
20
+ - `standard` for ordinary bounded review packets
21
+ - `deep` for high-priority, large, critical-flow, or external-signal packets
22
+
23
+ Hosts that support per-subagent model choice may map those tiers to their own
24
+ available models. Hosts that do not support model choice can ignore the fields.
25
+ The backend still does not prescribe concrete model names.
26
+
16
27
  ## 2. Backend provider rule
17
28
 
18
29
  When the local backend delegates bounded worker runs into an external provider, model selection becomes provider-specific.
@@ -3,7 +3,7 @@
3
3
  This document tracks the next meaningful implementation work after the packet
4
4
  review-dispatch refactor and the current skill-first productionization pass.
5
5
 
6
- As of April 22, 2026, the shared MCP substrate and the first host-native installer pass have landed, but this repository is not yet ready for a public production launch.
6
+ As of April 30, 2026, the shared MCP substrate and the host-native installer pass have landed, but this repository is not yet ready for a public production launch.
7
7
 
8
8
  See:
9
9
 
@@ -144,7 +144,7 @@ Status:
144
144
 
145
145
  Most likely shape:
146
146
 
147
- - run fresh-repo smoke checks inside Codex, Claude Desktop, OpenCode, and VS Code
147
+ - run fresh-repo smoke checks inside Codex, Claude Desktop, OpenCode, and VS Code, with Antigravity validated against its planning-mode path
148
148
  - confirm that the generated files are both syntactically valid and actually discovered by each host
149
149
  - tighten generated docs wherever operator confusion appears during those checks
150
150
  - keep Antigravity as a documented planning-mode path unless a stable project config contract is published
package/docs/packaging.md CHANGED
@@ -17,6 +17,8 @@ The primary product surface is `/audit-code` in conversation.
17
17
  That means the package needs to ship:
18
18
 
19
19
  - the canonical prompt asset at `skills/audit-code/audit-code.prompt.md`
20
+ - the companion Codex/OpenCode skill asset at `skills/audit-code/SKILL.md`
21
+ - packet-dispatch support data such as `dispatch/lens-definitions.json`
20
22
  - the backend fallback wrapper exposed as `audit-code`
21
23
 
22
24
  A linked-command smoke test proves the installed wrapper and prompt lookup work from the working tree.
@@ -76,11 +78,11 @@ The repository now includes packaging metadata and lifecycle hooks intended for
76
78
 
77
79
  - `package.json` is no longer marked private
78
80
  - `publishConfig.access` defaults publication to the public npm access level
79
- - package contents are curated with a `files` allowlist that includes the canonical prompt asset
81
+ - package contents are curated with a `files` allowlist that includes the canonical prompt, skill, dispatch, schema, and runtime assets
80
82
  - `prepack` and `prepare` build the runtime artifact
81
83
  - `verify:release` codifies the minimum in-repo release gate
82
84
  - `prepublishOnly` now runs that full release gate, including both linked-install and packaged-install smoke validation
83
- - packaged smoke now verifies the tarball includes `audit-code-wrapper-lib.mjs`, the prompt asset, the response schema, and `dist/` entrypoints before install-time smoke runs
85
+ - packaged smoke now verifies the tarball includes `audit-code-wrapper-lib.mjs`, the prompt and skill assets, dispatch lens definitions, the response schema, and `dist/` entrypoints before install-time smoke runs
84
86
  - the GitHub publish workflow uses the same release gate before `npm publish`
85
87
  - the GitHub publish workflow uses npm Trusted Publishing with GitHub OIDC instead of a long-lived publish token
86
88
  - prerelease versions now default to the `next` dist-tag in the publish workflow unless an explicit tag override is chosen on manual dispatch
@@ -25,6 +25,8 @@ Anything below `dist/index.js` remains a backend or development interface rather
25
25
  - packaged installs must include:
26
26
  - `audit-code`
27
27
  - `audit-code-wrapper-lib.mjs`
28
+ - `dispatch/lens-definitions.json`
29
+ - `skills/audit-code/SKILL.md`
28
30
  - `skills/audit-code/audit-code.prompt.md`
29
31
  - `schemas/audit-code-v1alpha1.schema.json`
30
32
  - the checked-in `dist/` output is part of the shipped runtime contract for installed usage
@@ -38,7 +40,7 @@ Anything below `dist/index.js` remains a backend or development interface rather
38
40
  ### Host surfaces
39
41
 
40
42
  - ChatGPT-style project conversations are the intended `/audit-code` product surface
41
- - VS Code / GitHub Copilot, OpenCode, and Claude Code repositories are supported through `audit-code install`
43
+ - Codex, Claude Desktop, OpenCode, VS Code / GitHub Copilot, and Antigravity repository surfaces are generated through `audit-code install`
42
44
  - editor integrations that import `skills/audit-code/audit-code.prompt.md` are supported as prompt-based integrations
43
45
  - no editor-specific native install surface should be called production-ready until it has explicit documentation and a repeatable verification path
44
46
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Verdict
4
4
 
5
- As of April 22, 2026, the package release path is ready for a public npm release candidate, but the broader host experience still has follow-through work before it should be described as a frictionless production launch.
5
+ As of April 30, 2026, the package release path has a strong in-repo release gate, but the broader host experience still has follow-through work before it should be described as a frictionless production launch.
6
6
 
7
7
  What is already true:
8
8
 
@@ -11,9 +11,9 @@ What is already true:
11
11
  - linked-install smoke coverage passes
12
12
  - packaged-install smoke coverage passes
13
13
  - packaged tarball contract verification passes
14
- - `npm run verify:release` passes for the current `0.2.8` worktree
15
- - local `npm publish --dry-run` passes for `auditor-lambda@0.2.8`
16
- - npm currently reports `auditor-lambda@0.2.6` as `latest`, so the checked-in release version is still unpublished
14
+ - `npm run verify:release` is the authoritative local release gate for the current worktree
15
+ - local `npm publish --dry-run` should be run before any release candidate publish
16
+ - npm registry state should be verified at release time rather than inferred from checked-in docs
17
17
  - malformed config and corrupted artifact handling are explicit
18
18
  - blocked fallback runs now emit structured operator handoff guidance
19
19
  - supported repo-local hosts now share a bootstrap install path via `audit-code install`
@@ -27,7 +27,7 @@ The biggest remaining gaps are product and release-operational, not core wrapper
27
27
  1. npm publication is not fully proven end to end.
28
28
  The repo now has a Trusted Publishing workflow and a passing local dry run, but npm-side trusted publisher setup plus the first GitHub Actions dry run still need to be completed outside the codebase.
29
29
  2. The primary conversation-first product still has setup friction on hosts without a verified repo-local slash-command surface.
30
- VS Code / Copilot, OpenCode, and Claude Code now share a bootstrap path, but Claude Desktop, Antigravity, and other hosts still need more work.
30
+ Codex, Claude Desktop, OpenCode, VS Code / Copilot, and Antigravity now share the same bootstrap command, but each generated host surface still needs real-product verification before it can be called frictionless.
31
31
  3. Provider-assisted continuation still needs polish outside the happy path.
32
32
  Configured interactive bridges can now continue through audit-task review, but operator guidance and host-specific ergonomics still need refinement when a provider cannot produce results cleanly.
33
33
 
@@ -38,7 +38,7 @@ The explicit launch bar is now documented in `docs/production-launch-bar.md`, an
38
38
  1. Confirm release operations externally.
39
39
  Validate npm package-name ownership for `auditor-lambda`, configure npm Trusted Publishing for `.github/workflows/publish-package.yml`, and run a real GitHub Actions dry run or prerelease publish from that workflow path.
40
40
  2. Extend bootstrap coverage beyond the currently automated hosts.
41
- Keep `audit-code install` stable for VS Code / Copilot, OpenCode, and Claude Code, and close the remaining friction gap for hosts that still lack a verified repo-local install surface.
41
+ Keep `audit-code install` stable for Codex, Claude Desktop, OpenCode, VS Code / Copilot, and Antigravity, and close the remaining friction gap for hosts that still lack a verified repo-local install surface.
42
42
  3. Polish provider-assisted UX.
43
43
  Keep the new continuation path explicit and inspectable while improving failure hints, host guidance, and operator recovery when a provider bridge misbehaves.
44
44
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "auditor-lambda",
3
- "version": "0.3.5",
3
+ "version": "0.3.6",
4
4
  "private": false,
5
5
  "description": "Portable hybrid code-auditing framework for arbitrary repositories.",
6
6
  "type": "module",
@@ -28,6 +28,10 @@ command, then stop so the user can rerun `/audit-code` from fresh context.
28
28
  Subagent fan-out belongs to the host agent runtime rather than to repo-local
29
29
  backend provider settings.
30
30
 
31
+ When dispatch-plan entries include provider-neutral complexity and
32
+ `model_hint.tier` metadata, a capable host may map those tiers to its own
33
+ subagent models. The backend should not prescribe concrete model names.
34
+
31
35
  Bounded steps are a backend implementation detail, not the intended user experience.
32
36
 
33
37
  ## Embedded Prompt Payload
@@ -81,6 +81,11 @@ In a single message, launch one Agent/subagent call per dispatch-plan entry:
81
81
  Agent({ description: entry.description, prompt: "Read and follow the audit instructions in: " + entry.prompt_path })
82
82
  ```
83
83
 
84
+ If the host supports per-subagent model selection, use `entry.model_hint.tier`
85
+ as a provider-neutral routing hint (`small`, `standard`, or `deep`). Map it to
86
+ available host models without asking the user to choose model names. If model
87
+ selection is unavailable, ignore the hint and dispatch normally.
88
+
84
89
  If the host supports per-subagent tool restrictions, give review subagents no
85
90
  Write tool and allow shell access only for the `audit-code submit-packet`
86
91
  command printed in their prompt.