auditor-lambda 0.9.2 → 0.10.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.
Files changed (40) hide show
  1. package/README.md +2 -9
  2. package/audit-code-wrapper-lib.mjs +19 -920
  3. package/dist/cli/auditStep.d.ts +1 -33
  4. package/dist/cli/dispatch.d.ts +47 -0
  5. package/dist/cli/dispatch.js +116 -1
  6. package/dist/cli/mergeAndIngestCommand.js +10 -0
  7. package/dist/cli/nextStepCommand.js +3 -1
  8. package/dist/cli/prompts.d.ts +2 -0
  9. package/dist/cli/prompts.js +9 -0
  10. package/dist/cli/semanticReviewStep.js +12 -1
  11. package/dist/cli/steps.d.ts +15 -0
  12. package/dist/cli.js +1 -8
  13. package/dist/io/artifacts.d.ts +9 -1
  14. package/dist/io/artifacts.js +7 -0
  15. package/dist/io/runArtifacts.d.ts +14 -0
  16. package/dist/io/runArtifacts.js +23 -0
  17. package/dist/orchestrator/designReviewPrompt.d.ts +4 -1
  18. package/dist/orchestrator/designReviewPrompt.js +43 -2
  19. package/dist/orchestrator/executorResult.d.ts +25 -0
  20. package/dist/orchestrator/intakeExecutors.d.ts +19 -1
  21. package/dist/orchestrator/intakeExecutors.js +89 -3
  22. package/dist/orchestrator/nextStep.d.ts +1 -0
  23. package/dist/orchestrator/nextStep.js +1 -1
  24. package/dist/orchestrator/state.js +8 -1
  25. package/dist/providers/constants.d.ts +1 -1
  26. package/dist/providers/constants.js +1 -1
  27. package/dist/reporting/synthesis.d.ts +8 -0
  28. package/dist/reporting/synthesis.js +16 -1
  29. package/dist/supervisor/operatorHandoff.js +2 -0
  30. package/dist/types/auditScope.d.ts +16 -2
  31. package/dist/validation/sessionConfig.js +35 -0
  32. package/docs/contracts.md +0 -16
  33. package/docs/operator-guide.md +6 -8
  34. package/package.json +1 -1
  35. package/schemas/audit_findings.schema.json +1 -0
  36. package/scripts/postinstall.mjs +0 -174
  37. package/skills/audit-code/SKILL.md +17 -1
  38. package/skills/audit-code/audit-code.prompt.md +25 -0
  39. package/dist/mcp/server.d.ts +0 -72
  40. package/dist/mcp/server.js +0 -765
@@ -22,10 +22,7 @@ const INSTALL_GUIDE_FILENAME = 'GETTING-STARTED.md';
22
22
  const INSTALL_MANIFEST_FILENAME = 'manifest.json';
23
23
  const DEFAULT_INSTALL_HOST = 'all';
24
24
  const INSTALLED_PROMPT_FILENAME = 'audit-code.import.md';
25
- const MCP_LAUNCHER_FILENAME = 'run-mcp-server.mjs';
26
25
  const packageVersion = JSON.parse(await readFile(packageJsonPath, 'utf8')).version;
27
- const MCP_PROTOCOL_VERSION = '2025-06-18';
28
- const INSTALL_VERIFY_TIMEOUT_MS = 10_000;
29
26
 
30
27
  function hasFlag(argv, name) {
31
28
  return argv.includes(name);
@@ -318,7 +315,7 @@ function printHelp({ usageName, preferredEntrypoint }) {
318
315
  '- prompt-path prints the absolute path to the canonical /audit-code prompt asset',
319
316
  '- ensure lazily bootstraps repo-local /audit-code assets when they are missing or stale',
320
317
  '- install bootstraps /audit-code into supported repo-local host surfaces',
321
- '- verify-install smoke-tests the generated host assets and repo-local MCP launchers after install',
318
+ '- verify-install smoke-tests the generated host assets after install',
322
319
  '- mcp starts the local stdio MCP server for repo-local IDE integrations',
323
320
  '- install-host --host copilot keeps the narrower Copilot-focused install path available',
324
321
  '- next-step advances deterministic audit state and writes .audit-artifacts/steps/current-step.json plus current-prompt.md',
@@ -661,29 +658,6 @@ function renderVSCodeAgentFile() {
661
658
  ].join('\n');
662
659
  }
663
660
 
664
- function renderCodexMcpSetupGuide(root) {
665
- return [
666
- '# Codex MCP setup',
667
- '',
668
- 'Codex shares MCP configuration between the app, CLI, and IDE extension. Register a local stdio MCP server named `auditor` that launches the repo-local wrapper below.',
669
- '',
670
- 'Recommended command:',
671
- `- command: \`node\``,
672
- `- args: \`${toRepoRelativePath(root, join(root, '.audit-code', 'install', MCP_LAUNCHER_FILENAME))}\``,
673
- '',
674
- 'Equivalent config shape:',
675
- '',
676
- '```toml',
677
- '[mcp_servers.auditor]',
678
- 'command = "node"',
679
- `args = ["${replaceBackslashes(toRepoRelativePath(root, join(root, '.audit-code', 'install', MCP_LAUNCHER_FILENAME)))}"]`,
680
- '```',
681
- '',
682
- 'Prefer `audit-code next-step` directly. Use the registered `auditor` MCP tools only when shell access is unavailable; they return the same one-step contract.',
683
- '',
684
- ].join('\n');
685
- }
686
-
687
661
  function renderCodexAutomationRecipe() {
688
662
  return [
689
663
  '# Codex re-audit automation recipe',
@@ -692,7 +666,7 @@ function renderCodexAutomationRecipe() {
692
666
  '',
693
667
  '- Prompt: Re-run the autonomous audit workflow for this repository with `audit-code next-step`, summarize only new or regressed findings, and stop once the deterministic report is current.',
694
668
  '- Cadence: daily on active branches or before release cut-offs',
695
- '- Inputs: repository root; the installed `auditor` MCP server is optional compatibility plumbing',
669
+ '- Inputs: repository root',
696
670
  '',
697
671
  'Use this recipe as a starting point for a Codex automation once the local workflow is stable in your environment.',
698
672
  '',
@@ -739,8 +713,6 @@ const OPENCODE_AUDIT_BASH_PERMISSION = {
739
713
  '*audit-code.mjs* worker-run*': 'allow',
740
714
  '*audit-code.mjs* validate*': 'allow',
741
715
  '*node* *auditor-lambda*dist*index.js* worker-run*': 'allow',
742
- 'node* .audit-code/install/run-mcp-server.mjs*': 'allow',
743
- 'node* ./.audit-code/install/run-mcp-server.mjs*': 'allow',
744
716
  'git status*': 'allow',
745
717
  'git diff*': 'allow',
746
718
  'grep *': 'allow',
@@ -787,18 +759,6 @@ function renderOpenCodeProjectConfig(_root) {
787
759
  };
788
760
  }
789
761
 
790
- function renderVSCodeMcpConfig() {
791
- return {
792
- servers: {
793
- auditor: {
794
- type: 'stdio',
795
- command: 'node',
796
- args: ['${workspaceFolder}/.audit-code/install/run-mcp-server.mjs'],
797
- },
798
- },
799
- };
800
- }
801
-
802
762
  function objectValue(value) {
803
763
  return value && typeof value === 'object' && !Array.isArray(value)
804
764
  ? value
@@ -910,7 +870,6 @@ function assertOpenCodeAuditPermissionConfig(permissionConfig, label) {
910
870
  '*audit-code.mjs* merge-and-ingest*',
911
871
  '*audit-code.mjs* worker-run*',
912
872
  '*node* *auditor-lambda*dist*index.js* worker-run*',
913
- 'node* .audit-code/install/run-mcp-server.mjs*',
914
873
  ]) {
915
874
  if (bash[pattern] !== 'allow') {
916
875
  throw new Error(`OpenCode ${label}.bash must allow ${pattern}. Run "audit-code install --host opencode".`);
@@ -969,58 +928,6 @@ function buildMergedOpenCodeProjectConfig(existing, root) {
969
928
  };
970
929
  }
971
930
 
972
- function buildMergedVSCodeMcpConfig(existing) {
973
- const generated = renderVSCodeMcpConfig();
974
- return {
975
- ...existing,
976
- servers: {
977
- ...objectValue(existing.servers),
978
- auditor: generated.servers.auditor,
979
- },
980
- };
981
- }
982
-
983
- function renderClaudeDesktopProjectTemplate() {
984
- return [
985
- '# Claude Desktop project template',
986
- '',
987
- 'Suggested project instructions:',
988
- '',
989
- '- Treat `/audit-code` as the canonical autonomous audit workflow for this repository.',
990
- '- Prefer `audit-code next-step`; use the installed auditor MCP tools only as a compatibility adapter over the same step contract.',
991
- '- Read the operator handoff and artifact resources before asking for more context.',
992
- '- Present the final deterministic audit report as work blocks first.',
993
- '',
994
- 'Suggested project knowledge uploads:',
995
- '',
996
- '- `.audit-code/install/audit-code.import.md`',
997
- '- `.audit-code/install/GETTING-STARTED.md`',
998
- '- `docs/operator-guide.md` when you want host-specific operator context',
999
- '',
1000
- 'Starter prompt:',
1001
- '',
1002
- '> Start `/audit-code` for this repository using `audit-code next-step`. Continue until the audit is complete or blocked for operator input, and summarize the current handoff status before you stop.',
1003
- '',
1004
- ].join('\n');
1005
- }
1006
-
1007
- function renderClaudeDesktopRemoteConnectorTemplate() {
1008
- return JSON.stringify(
1009
- {
1010
- name: 'auditor-lambda',
1011
- transport: 'remote-mcp',
1012
- url: 'https://example.com/auditor-lambda/mcp',
1013
- notes: [
1014
- 'Replace the URL with your hosted auditor MCP endpoint.',
1015
- 'Expose the same tool names as the local bundle: start_audit, get_status, continue_audit, explain_task, validate_artifacts, import_results, import_runtime_updates.',
1016
- 'Use OAuth or host-level auth when deploying this connector for Team or Enterprise rollouts.',
1017
- ],
1018
- },
1019
- null,
1020
- 2,
1021
- ) + '\n';
1022
- }
1023
-
1024
931
  function renderAntigravityPlanningGuide(root) {
1025
932
  return [
1026
933
  '# Antigravity planning-mode guide',
@@ -1029,12 +936,11 @@ function renderAntigravityPlanningGuide(root) {
1029
936
  '',
1030
937
  '1. Open Antigravity in Planning mode.',
1031
938
  '2. Load the repo-local prompt asset or the AGENTS instructions before starting the audit conversation.',
1032
- '3. Ask Antigravity to use `audit-code next-step` directly. The installed auditor MCP server is available only as compatibility plumbing when direct shell access is unavailable.',
939
+ '3. Ask Antigravity to use `audit-code next-step` directly.',
1033
940
  '4. Review Antigravity artifacts before accepting major code changes or imported evidence.',
1034
941
  '',
1035
942
  'Recommended repo-local paths:',
1036
943
  `- prompt asset: \`${toRepoRelativePath(root, join(root, '.audit-code', 'install', INSTALLED_PROMPT_FILENAME))}\``,
1037
- `- MCP launcher: \`${toRepoRelativePath(root, join(root, '.audit-code', 'install', MCP_LAUNCHER_FILENAME))}\``,
1038
944
  '',
1039
945
  'Artifact round-tripping policy:',
1040
946
  '',
@@ -1059,388 +965,17 @@ function renderGeminiCommandToml(promptBody) {
1059
965
  ].join('\n');
1060
966
  }
1061
967
 
1062
- function renderSharedMcpLauncher(sourcePackageRoot) {
1063
- return [
1064
- "import { access, readFile } from 'node:fs/promises';",
1065
- "import { constants } from 'node:fs';",
1066
- "import { spawn } from 'node:child_process';",
1067
- "import { dirname, join, resolve } from 'node:path';",
1068
- "import { fileURLToPath } from 'node:url';",
1069
- '',
1070
- 'const scriptDir = dirname(fileURLToPath(import.meta.url));',
1071
- "const repoRoot = resolve(scriptDir, '..', '..');",
1072
- "const artifactsDir = join(repoRoot, '.audit-artifacts');",
1073
- '// Absolute path to the auditor-lambda package that generated this launcher.',
1074
- '// Intentionally machine-specific: it is a load-bearing fallback candidate',
1075
- '// (tried after a repo-local dependency) that lets the launcher find the',
1076
- '// backend entrypoint when the target repo has no local auditor-lambda dep.',
1077
- '// This file is regenerated per-install by `audit-code ensure`/`install` and',
1078
- '// is gitignored, so the path is always re-derived for the current machine;',
1079
- '// if it ever goes stale the launcher degrades gracefully to PATH/npx below.',
1080
- `const sourcePackageRoot = ${JSON.stringify(sourcePackageRoot)};`,
1081
- '',
1082
- 'async function exists(path) {',
1083
- ' try {',
1084
- ' await access(path, constants.F_OK);',
1085
- ' return true;',
1086
- ' } catch {',
1087
- ' return false;',
1088
- ' }',
1089
- '}',
1090
- '',
1091
- 'function spawnForward(command, args) {',
1092
- ' return new Promise((resolvePromise, rejectPromise) => {',
1093
- ' const child = spawn(command, args, {',
1094
- ' cwd: repoRoot,',
1095
- ' env: process.env,',
1096
- " stdio: ['inherit', 'inherit', 'inherit'],",
1097
- ' });',
1098
- " child.on('error', rejectPromise);",
1099
- " child.on('exit', (code) => resolvePromise(code ?? 1));",
1100
- ' });',
1101
- '}',
1102
- '',
1103
- 'async function tryCandidates() {',
1104
- " const localPackageEntrypoint = join(repoRoot, 'node_modules', 'auditor-lambda', 'audit-code.mjs');",
1105
- " const localBin = process.platform === 'win32'",
1106
- " ? join(repoRoot, 'node_modules', '.bin', 'audit-code.cmd')",
1107
- " : join(repoRoot, 'node_modules', '.bin', 'audit-code');",
1108
- " const repoPackageJsonPath = join(repoRoot, 'package.json');",
1109
- " const sourcePackageEntrypoint = sourcePackageRoot",
1110
- " ? join(sourcePackageRoot, 'audit-code.mjs')",
1111
- " : null;",
1112
- " const sourcePackageJsonPath = sourcePackageRoot",
1113
- " ? join(sourcePackageRoot, 'package.json')",
1114
- " : null;",
1115
- ' const sharedArgs = [\'mcp\', \'--root\', repoRoot, \'--artifacts-dir\', artifactsDir];',
1116
- '',
1117
- ' if (await exists(localPackageEntrypoint)) {',
1118
- ' return await spawnForward(process.execPath, [localPackageEntrypoint, ...sharedArgs]);',
1119
- ' }',
1120
- '',
1121
- ' if (await exists(repoPackageJsonPath) && await exists(join(repoRoot, \'audit-code.mjs\'))) {',
1122
- ' try {',
1123
- " const packageJson = JSON.parse(await readFile(repoPackageJsonPath, 'utf8'));",
1124
- " if (packageJson?.name === 'auditor-lambda') {",
1125
- " return await spawnForward(process.execPath, [join(repoRoot, 'audit-code.mjs'), ...sharedArgs]);",
1126
- ' }',
1127
- ' } catch {',
1128
- ' // fall through to the next candidate',
1129
- ' }',
1130
- ' }',
1131
- '',
1132
- ' if (sourcePackageEntrypoint && sourcePackageJsonPath && await exists(sourcePackageEntrypoint) && await exists(sourcePackageJsonPath)) {',
1133
- ' try {',
1134
- " const packageJson = JSON.parse(await readFile(sourcePackageJsonPath, 'utf8'));",
1135
- " if (packageJson?.name === 'auditor-lambda') {",
1136
- ' return await spawnForward(process.execPath, [sourcePackageEntrypoint, ...sharedArgs]);',
1137
- ' }',
1138
- ' } catch {',
1139
- ' // fall through to the next candidate',
1140
- ' }',
1141
- ' }',
1142
- '',
1143
- ' if (await exists(localBin)) {',
1144
- ' return await spawnForward(localBin, sharedArgs);',
1145
- ' }',
1146
- '',
1147
- " const pathCandidate = process.platform === 'win32' ? 'audit-code.cmd' : 'audit-code';",
1148
- ' let exitCode = await spawnForward(pathCandidate, sharedArgs).catch(() => null);',
1149
- ' if (typeof exitCode === \'number\') {',
1150
- ' return exitCode;',
1151
- ' }',
1152
- '',
1153
- " exitCode = await spawnForward('npx', ['--no-install', 'audit-code', ...sharedArgs]).catch(() => null);",
1154
- " if (typeof exitCode === 'number') {",
1155
- ' return exitCode;',
1156
- ' }',
1157
- '',
1158
- ' throw new Error(',
1159
- " 'Unable to locate an audit-code executable. Install auditor-lambda as a dependency or make the audit-code binary available on PATH.',",
1160
- ' );',
1161
- '}',
1162
- '',
1163
- 'const code = await tryCandidates();',
1164
- 'process.exitCode = code;',
1165
- '',
1166
- ].join('\n');
1167
- }
1168
-
1169
- function createCrc32Table() {
1170
- const table = new Uint32Array(256);
1171
- for (let index = 0; index < 256; index += 1) {
1172
- let value = index;
1173
- for (let bit = 0; bit < 8; bit += 1) {
1174
- value = (value & 1) !== 0 ? (0xedb88320 ^ (value >>> 1)) : (value >>> 1);
1175
- }
1176
- table[index] = value >>> 0;
1177
- }
1178
- return table;
1179
- }
1180
-
1181
- const CRC32_TABLE = createCrc32Table();
1182
-
1183
- function crc32(buffer) {
1184
- let crc = 0xffffffff;
1185
- for (const byte of buffer) {
1186
- crc = CRC32_TABLE[(crc ^ byte) & 0xff] ^ (crc >>> 8);
1187
- }
1188
- return (crc ^ 0xffffffff) >>> 0;
1189
- }
1190
-
1191
- async function listFilesRecursive(root) {
1192
- const files = [];
1193
- const entries = await readdir(root, { withFileTypes: true });
1194
- for (const entry of entries) {
1195
- const absolutePath = join(root, entry.name);
1196
- if (entry.isDirectory()) {
1197
- files.push(...(await listFilesRecursive(absolutePath)));
1198
- continue;
1199
- }
1200
- if (entry.isFile()) {
1201
- files.push(absolutePath);
1202
- }
1203
- }
1204
- return files.sort((a, b) => a.localeCompare(b));
1205
- }
1206
-
1207
- async function createStoredZipBuffer(sourceDir) {
1208
- const absoluteFiles = await listFilesRecursive(sourceDir);
1209
- const localParts = [];
1210
- const centralParts = [];
1211
- let offset = 0;
1212
-
1213
- for (const absolutePath of absoluteFiles) {
1214
- const relativePath = replaceBackslashes(relative(sourceDir, absolutePath));
1215
- const fileName = Buffer.from(relativePath, 'utf8');
1216
- const content = await readFile(absolutePath);
1217
- const checksum = crc32(content);
1218
-
1219
- const localHeader = Buffer.alloc(30);
1220
- localHeader.writeUInt32LE(0x04034b50, 0);
1221
- localHeader.writeUInt16LE(20, 4);
1222
- localHeader.writeUInt16LE(0, 6);
1223
- localHeader.writeUInt16LE(0, 8);
1224
- localHeader.writeUInt16LE(0, 10);
1225
- localHeader.writeUInt16LE(0, 12);
1226
- localHeader.writeUInt32LE(checksum, 14);
1227
- localHeader.writeUInt32LE(content.length, 18);
1228
- localHeader.writeUInt32LE(content.length, 22);
1229
- localHeader.writeUInt16LE(fileName.length, 26);
1230
- localHeader.writeUInt16LE(0, 28);
1231
-
1232
- localParts.push(localHeader, fileName, content);
1233
-
1234
- const centralHeader = Buffer.alloc(46);
1235
- centralHeader.writeUInt32LE(0x02014b50, 0);
1236
- centralHeader.writeUInt16LE(20, 4);
1237
- centralHeader.writeUInt16LE(20, 6);
1238
- centralHeader.writeUInt16LE(0, 8);
1239
- centralHeader.writeUInt16LE(0, 10);
1240
- centralHeader.writeUInt16LE(0, 12);
1241
- centralHeader.writeUInt16LE(0, 14);
1242
- centralHeader.writeUInt32LE(checksum, 16);
1243
- centralHeader.writeUInt32LE(content.length, 20);
1244
- centralHeader.writeUInt32LE(content.length, 24);
1245
- centralHeader.writeUInt16LE(fileName.length, 28);
1246
- centralHeader.writeUInt16LE(0, 30);
1247
- centralHeader.writeUInt16LE(0, 32);
1248
- centralHeader.writeUInt16LE(0, 34);
1249
- centralHeader.writeUInt16LE(0, 36);
1250
- centralHeader.writeUInt32LE(0, 38);
1251
- centralHeader.writeUInt32LE(offset, 42);
1252
-
1253
- centralParts.push(centralHeader, fileName);
1254
- offset += localHeader.length + fileName.length + content.length;
1255
- }
1256
-
1257
- const centralDirectory = Buffer.concat(centralParts);
1258
- const endOfCentralDirectory = Buffer.alloc(22);
1259
- endOfCentralDirectory.writeUInt32LE(0x06054b50, 0);
1260
- endOfCentralDirectory.writeUInt16LE(0, 4);
1261
- endOfCentralDirectory.writeUInt16LE(0, 6);
1262
- endOfCentralDirectory.writeUInt16LE(absoluteFiles.length, 8);
1263
- endOfCentralDirectory.writeUInt16LE(absoluteFiles.length, 10);
1264
- endOfCentralDirectory.writeUInt32LE(centralDirectory.length, 12);
1265
- endOfCentralDirectory.writeUInt32LE(offset, 16);
1266
- endOfCentralDirectory.writeUInt16LE(0, 20);
1267
-
1268
- return Buffer.concat([...localParts, centralDirectory, endOfCentralDirectory]);
1269
- }
1270
-
1271
- // Copy the auditor's dist + schemas + skills + wrapper entrypoints (and, best
1272
- // effort, the resolved @audit-tools/shared dist) into the Claude Desktop bundle
1273
- // tree. Returns whether the bundle directory already existed (for the
1274
- // created/updated result marker).
1275
- async function copyClaudeDesktopBundleFiles(bundleRoot, serverRoot) {
1276
- const bundleExisted = await fileExists(bundleRoot);
1277
- await mkdir(serverRoot, { recursive: true });
1278
- await cp(distEntry.replace(/dist[\\/]index\.js$/, 'dist'), join(bundleRoot, 'dist'), { recursive: true, force: true });
1279
- await cp(join(repoRoot, 'schemas'), join(bundleRoot, 'schemas'), { recursive: true, force: true });
1280
- // dist/cli/dispatch.js reads dispatch/lens-definitions.json from the package
1281
- // root at runtime, so the bundle must ship the top-level dispatch/ data dir
1282
- // (lens-definitions.json + the standalone validate/merge helpers) the same way
1283
- // the npm `files` array does. Omitting it ENOENTs the first dispatch step.
1284
- await cp(join(repoRoot, 'dispatch'), join(bundleRoot, 'dispatch'), { recursive: true, force: true });
1285
- await cp(join(repoRoot, 'skills', 'audit-code'), join(bundleRoot, 'skills', 'audit-code'), { recursive: true, force: true });
1286
- await writeFile(join(bundleRoot, 'audit-code.mjs'), await readFile(join(repoRoot, 'audit-code.mjs')));
1287
- await writeFile(join(bundleRoot, 'audit-code-wrapper-lib.mjs'), await readFile(join(repoRoot, 'audit-code-wrapper-lib.mjs')));
1288
- await writeFile(join(bundleRoot, 'package.json'), await readFile(join(repoRoot, 'package.json')));
1289
-
1290
- try {
1291
- const req = createRequire(join(repoRoot, 'package.json'));
1292
- const sharedEntry = req.resolve('@audit-tools/shared');
1293
- let sharedRoot = dirname(sharedEntry);
1294
- while (sharedRoot !== dirname(sharedRoot) && !(await fileExists(join(sharedRoot, 'package.json')))) {
1295
- sharedRoot = dirname(sharedRoot);
1296
- }
1297
- const bundleSharedRoot = join(bundleRoot, 'node_modules', '@audit-tools', 'shared');
1298
- await mkdir(bundleSharedRoot, { recursive: true });
1299
- await cp(join(sharedRoot, 'dist'), join(bundleSharedRoot, 'dist'), { recursive: true, force: true });
1300
- await writeFile(join(bundleSharedRoot, 'package.json'), await readFile(join(sharedRoot, 'package.json')));
1301
- } catch {
1302
- // @audit-tools/shared not resolvable — bundle will use runtime resolution
1303
- }
1304
-
1305
- return { bundleExisted };
1306
- }
1307
-
1308
- // Source for the bundle's server/index.js shim: it spawns the bundled
1309
- // audit-code.mjs in MCP mode against the user-configured repo root.
1310
- function renderClaudeDesktopServerEntry() {
1311
- return [
1312
- "import { spawn } from 'node:child_process';",
1313
- "import { dirname, join } from 'node:path';",
1314
- "import { fileURLToPath } from 'node:url';",
1315
- '',
1316
- 'const serverDir = dirname(fileURLToPath(import.meta.url));',
1317
- "const bundleRoot = join(serverDir, '..');",
1318
- "const repoRoot = process.env.AUDIT_CODE_REPO_ROOT;",
1319
- "const artifactsDir = process.env.AUDIT_CODE_ARTIFACTS_DIR || (repoRoot ? join(repoRoot, '.audit-artifacts') : undefined);",
1320
- '',
1321
- 'if (!repoRoot) {',
1322
- " console.error('AUDIT_CODE_REPO_ROOT must be configured before launching the auditor MCP bundle.');",
1323
- ' process.exit(1);',
1324
- '}',
1325
- '',
1326
- "const child = spawn(process.execPath, [join(bundleRoot, 'audit-code.mjs'), 'mcp', '--root', repoRoot, '--artifacts-dir', artifactsDir], {",
1327
- " cwd: repoRoot,",
1328
- ' env: process.env,',
1329
- " stdio: ['inherit', 'inherit', 'inherit'],",
1330
- '});',
1331
- '',
1332
- "child.on('exit', (code) => {",
1333
- ' process.exitCode = code ?? 1;',
1334
- '});',
1335
- '',
1336
- ].join('\n');
1337
- }
1338
-
1339
- // The DXT/MCPB manifest.json describing the bundled node MCP server and its
1340
- // Claude Desktop user-config inputs.
1341
- function buildClaudeDesktopManifest() {
1342
- return {
1343
- manifest_version: '0.3',
1344
- name: 'auditor-lambda',
1345
- display_name: 'Auditor Lambda',
1346
- version: packageVersion,
1347
- description: 'Compatibility MCP bundle for the /audit-code autonomous audit workflow.',
1348
- long_description:
1349
- 'Runs a local compatibility MCP adapter whose start and continue tools return the same audit-code next-step contract as the direct CLI loop.',
1350
- author: {
1351
- name: 'auditor-lambda',
1352
- url: 'https://github.com/OhOkThisIsFine/auditor-lambda',
1353
- },
1354
- repository: {
1355
- type: 'git',
1356
- url: 'https://github.com/OhOkThisIsFine/auditor-lambda.git',
1357
- },
1358
- documentation: 'https://github.com/OhOkThisIsFine/auditor-lambda/tree/main/docs',
1359
- support: 'https://github.com/OhOkThisIsFine/auditor-lambda/issues',
1360
- license: 'MIT',
1361
- compatibility: {
1362
- claude_desktop: '>=1.0.0',
1363
- platforms: ['darwin', 'win32', 'linux'],
1364
- runtimes: {
1365
- node: '>=20.0.0',
1366
- },
1367
- },
1368
- tools_generated: true,
1369
- prompts_generated: true,
1370
- server: {
1371
- type: 'node',
1372
- entry_point: 'server/index.js',
1373
- mcp_config: {
1374
- command: 'node',
1375
- args: ['${__dirname}/server/index.js'],
1376
- env: {
1377
- AUDIT_CODE_REPO_ROOT: '${user_config.repo_root}',
1378
- AUDIT_CODE_ARTIFACTS_DIR: '${user_config.artifacts_dir}',
1379
- },
1380
- },
1381
- },
1382
- user_config: {
1383
- repo_root: {
1384
- type: 'directory',
1385
- title: 'Repository Root',
1386
- description: 'Repository to audit with auditor-lambda.',
1387
- required: true,
1388
- },
1389
- artifacts_dir: {
1390
- type: 'directory',
1391
- title: 'Artifacts Directory',
1392
- description: 'Optional override for the audit artifacts directory.',
1393
- required: false,
1394
- },
1395
- },
1396
- };
1397
- }
1398
-
1399
- // Orchestrates the Claude Desktop bundle: copy files, write the server shim and
1400
- // manifest, then zip into the .dxt / .mcpb archives. Pushes each generated file
1401
- // into `results`.
1402
- async function buildClaudeDesktopBundle(root, results) {
1403
- const bundleRoot = join(root, '.audit-code', 'install', 'claude-desktop', 'bundle');
1404
- const serverRoot = join(bundleRoot, 'server');
1405
- const manifestPath = join(bundleRoot, 'manifest.json');
1406
- const serverEntrypointPath = join(serverRoot, 'index.js');
1407
- const dxtPath = join(root, '.audit-code', 'install', 'claude-desktop', 'auditor-lambda.dxt');
1408
- const mcpbPath = join(root, '.audit-code', 'install', 'claude-desktop', 'auditor-lambda.mcpb');
1409
-
1410
- const { bundleExisted } = await copyClaudeDesktopBundleFiles(bundleRoot, serverRoot);
1411
- results.push({ path: bundleRoot, mode: bundleExisted ? 'updated' : 'created' });
1412
-
1413
- results.push(
1414
- await writeGeneratedMarkdown(serverEntrypointPath, renderClaudeDesktopServerEntry()),
1415
- );
1416
- results.push(await writeGeneratedJson(manifestPath, buildClaudeDesktopManifest()));
1417
-
1418
- const archive = await createStoredZipBuffer(bundleRoot);
1419
- results.push(await writeGeneratedBinary(dxtPath, archive));
1420
- results.push(await writeGeneratedBinary(mcpbPath, archive));
1421
-
1422
- return {
1423
- bundleRoot,
1424
- manifestPath,
1425
- dxtPath,
1426
- mcpbPath,
1427
- serverEntrypointPath,
1428
- };
1429
- }
1430
-
1431
968
  const INSTALL_PROFILE_FLAGS = [
1432
969
  'writeVSCode',
1433
970
  'writeCopilotInstructions',
1434
971
  'writeOpenCode',
1435
972
  'writeCodex',
1436
- 'writeClaudeDesktop',
1437
973
  'writeAntigravity',
1438
974
  'writeAgents',
1439
975
  ];
1440
976
 
1441
977
  const INSTALL_HOST_ORDER = [
1442
978
  'codex',
1443
- 'claude-desktop',
1444
979
  'opencode',
1445
980
  'vscode',
1446
981
  'antigravity',
@@ -1457,7 +992,6 @@ const INSTALL_HOST_DEFINITIONS = {
1457
992
  primary_path_key: 'agentsInstructionsPath',
1458
993
  supporting_path_keys: [
1459
994
  'installedPromptPath',
1460
- 'mcpLauncherPath',
1461
995
  ],
1462
996
  steps: [
1463
997
  'Open this repository in Codex.',
@@ -1480,119 +1014,16 @@ const INSTALL_HOST_DEFINITIONS = {
1480
1014
  });
1481
1015
  },
1482
1016
  },
1483
- 'claude-desktop': {
1484
- host: 'claude-desktop',
1485
- label: 'Claude Desktop',
1486
- support_level: 'supported',
1487
- setup_kind: 'local-mcp-bundle',
1488
- summary:
1489
- 'Install the generated local MCP compatibility bundle in Claude Desktop, then use the project template and prompt asset as supporting context.',
1490
- primary_path_key: 'claudeDesktopDxtPath',
1491
- supporting_path_keys: [
1492
- 'claudeDesktopMcpbPath',
1493
- 'claudeDesktopProjectTemplatePath',
1494
- 'claudeDesktopRemoteConnectorPath',
1495
- 'installedPromptPath',
1496
- ],
1497
- steps: [
1498
- 'Open Claude Desktop Settings and install the generated `.dxt` bundle.',
1499
- 'Configure the repository root when prompted so the bundle can launch the local auditor MCP adapter.',
1500
- 'Use the project template and prompt asset to kick off `/audit-code` in conversation.',
1501
- ],
1502
- profile: {
1503
- writeClaudeDesktop: true,
1504
- },
1505
- async verify({ checks, root, assetPaths, collectVerifyCheck: collect }) {
1506
- const bundleManifestPath = join(
1507
- root,
1508
- '.audit-code',
1509
- 'install',
1510
- 'claude-desktop',
1511
- 'bundle',
1512
- 'manifest.json',
1513
- );
1514
- const bundleServerPath = join(
1515
- root,
1516
- '.audit-code',
1517
- 'install',
1518
- 'claude-desktop',
1519
- 'bundle',
1520
- 'server',
1521
- 'index.js',
1522
- );
1523
-
1524
- await collect(checks, 'claude_bundle_manifest', async () => {
1525
- const manifest = await readJson(bundleManifestPath, 'Claude Desktop bundle manifest');
1526
- if (manifest?.server?.entry_point !== 'server/index.js') {
1527
- throw new Error(`Claude Desktop bundle manifest has an unexpected entry_point: ${manifest?.server?.entry_point ?? 'missing'}.`);
1528
- }
1529
- return {
1530
- summary: 'Claude Desktop bundle manifest parsed successfully.',
1531
- path: bundleManifestPath,
1532
- };
1533
- });
1534
- await collect(checks, 'claude_connector_template', async () => {
1535
- const connector = await readJson(
1536
- assetPaths.claudeDesktopRemoteConnectorPath,
1537
- 'Claude Desktop remote connector template',
1538
- );
1539
- if (connector?.transport !== 'remote-mcp') {
1540
- throw new Error(`Claude Desktop remote connector transport must be "remote-mcp", got ${connector?.transport ?? 'missing'}.`);
1541
- }
1542
- return {
1543
- summary: 'Claude Desktop remote connector template parsed successfully.',
1544
- path: assetPaths.claudeDesktopRemoteConnectorPath,
1545
- };
1546
- });
1547
- await collect(checks, 'claude_dxt_archive', async () => ({
1548
- summary: 'Claude Desktop .dxt bundle is present.',
1549
- path: assetPaths.claudeDesktopDxtPath,
1550
- size_bytes: await verifyZipFile(
1551
- assetPaths.claudeDesktopDxtPath,
1552
- 'Claude Desktop .dxt bundle',
1553
- ),
1554
- }));
1555
- await collect(checks, 'claude_mcpb_archive', async () => ({
1556
- summary: 'Claude Desktop .mcpb bundle is present.',
1557
- path: assetPaths.claudeDesktopMcpbPath,
1558
- size_bytes: await verifyZipFile(
1559
- assetPaths.claudeDesktopMcpbPath,
1560
- 'Claude Desktop .mcpb bundle',
1561
- ),
1562
- }));
1563
- await collect(checks, 'claude_bundle_mcp', async () => {
1564
- const probe = await probeMcpServer({
1565
- label: 'Claude Desktop bundle server',
1566
- command: process.execPath,
1567
- args: [bundleServerPath],
1568
- cwd: root,
1569
- env: {
1570
- AUDIT_CODE_REPO_ROOT: root,
1571
- AUDIT_CODE_ARTIFACTS_DIR: join(root, '.audit-artifacts'),
1572
- },
1573
- });
1574
- const toolNames = (probe.tools?.tools ?? []).map((tool) => tool.name);
1575
- if (!toolNames.includes('start_audit')) {
1576
- throw new Error('Claude Desktop bundle server did not expose the start_audit tool.');
1577
- }
1578
- return {
1579
- summary: 'Claude Desktop bundle completed an MCP handshake.',
1580
- tool_count: toolNames.length,
1581
- };
1582
- });
1583
- },
1584
- },
1585
1017
  opencode: {
1586
1018
  host: 'opencode',
1587
1019
  label: 'OpenCode',
1588
1020
  support_level: 'supported',
1589
- setup_kind: 'global-command+project-mcp',
1021
+ setup_kind: 'global-command+project-permissions',
1590
1022
  summary:
1591
- 'Use the global OpenCode `/audit-code` command installed by npm plus generated project permissions; MCP is compatibility-only.',
1023
+ 'Use the global OpenCode `/audit-code` command installed by npm plus generated project permissions.',
1592
1024
  primary_path_key: 'opencodeConfigPath',
1593
1025
  supporting_path_keys: [
1594
1026
  'agentsInstructionsPath',
1595
- 'mcpLauncherPath',
1596
1027
  ],
1597
1028
  steps: [
1598
1029
  'Open this repository in OpenCode.',
@@ -1625,19 +1056,17 @@ const INSTALL_HOST_DEFINITIONS = {
1625
1056
  host: 'vscode',
1626
1057
  label: 'VS Code',
1627
1058
  support_level: 'supported',
1628
- setup_kind: 'prompt+agent+mcp',
1059
+ setup_kind: 'prompt+agent',
1629
1060
  summary:
1630
- 'Use the generated prompt file and custom agent for next-step-first VS Code integration; workspace MCP is compatibility-only.',
1061
+ 'Use the generated prompt file and custom agent for next-step-first VS Code integration.',
1631
1062
  primary_path_key: 'vscodePromptPath',
1632
1063
  supporting_path_keys: [
1633
1064
  'vscodeAgentPath',
1634
- 'vscodeMcpConfigPath',
1635
1065
  'copilotInstructionsPath',
1636
1066
  ],
1637
1067
  steps: [
1638
1068
  'Open this repository in VS Code with Copilot.',
1639
1069
  'Invoke `/audit-code` from the generated prompt or chat so the workflow calls `audit-code next-step` directly.',
1640
- 'Use the workspace MCP adapter only when direct shell access is unavailable.',
1641
1070
  ],
1642
1071
  profile: {
1643
1072
  writeVSCode: true,
@@ -1661,42 +1090,27 @@ const INSTALL_HOST_DEFINITIONS = {
1661
1090
  path: assetPaths.vscodePromptPath,
1662
1091
  };
1663
1092
  });
1664
- await collect(checks, 'vscode_mcp_config', async () => {
1665
- const config = await readJson(assetPaths.vscodeMcpConfigPath, 'VS Code MCP config');
1666
- const args = config?.servers?.auditor?.args;
1667
- if (config?.servers?.auditor?.command !== 'node') {
1668
- throw new Error(`VS Code MCP config must use node as the command, got ${config?.servers?.auditor?.command ?? 'missing'}.`);
1669
- }
1670
- if (!Array.isArray(args) || args[0] !== '${workspaceFolder}/.audit-code/install/run-mcp-server.mjs') {
1671
- throw new Error(`VS Code MCP config must point at \${workspaceFolder}/.audit-code/install/${MCP_LAUNCHER_FILENAME}.`);
1672
- }
1673
- return {
1674
- summary: 'VS Code MCP config parsed successfully.',
1675
- path: assetPaths.vscodeMcpConfigPath,
1676
- };
1677
- });
1678
1093
  },
1679
1094
  },
1680
1095
  antigravity: {
1681
1096
  host: 'antigravity',
1682
1097
  label: 'Antigravity',
1683
1098
  support_level: 'supported',
1684
- setup_kind: 'agent-skill+gemini-command+planning-guide+mcp-ready',
1099
+ setup_kind: 'agent-skill+gemini-command+planning-guide',
1685
1100
  summary:
1686
- 'Uses the project-scoped .agent/skills/audit-code/SKILL.md skill, the .gemini/commands/audit-code.toml slash command, the planning guide, and AGENTS instructions. The shared MCP launcher is compatibility-only.',
1101
+ 'Uses the project-scoped .agent/skills/audit-code/SKILL.md skill, the .gemini/commands/audit-code.toml slash command, the planning guide, and AGENTS instructions.',
1687
1102
  primary_path_key: 'antigravitySkillPath',
1688
1103
  supporting_path_keys: [
1689
1104
  'geminiCommandPath',
1690
1105
  'antigravityPlanningGuidePath',
1691
1106
  'agentsInstructionsPath',
1692
- 'mcpLauncherPath',
1693
1107
  'installedPromptPath',
1694
1108
  ],
1695
1109
  steps: [
1696
1110
  'Open this repository in Antigravity.',
1697
1111
  'The audit-code skill is automatically discovered from .agent/skills/audit-code/SKILL.md.',
1698
1112
  'The /audit-code slash command is also available from .gemini/commands/audit-code.toml.',
1699
- 'Use `audit-code next-step` directly; use the shared auditor MCP launcher only when direct shell access is unavailable.',
1113
+ 'Use `audit-code next-step` directly.',
1700
1114
  ],
1701
1115
  profile: {
1702
1116
  writeAntigravity: true,
@@ -1715,11 +1129,11 @@ const INSTALL_HOST_DEFINITIONS = {
1715
1129
  });
1716
1130
  await collect(checks, 'antigravity_guide', async () => {
1717
1131
  const content = await readFile(assetPaths.antigravityPlanningGuidePath, 'utf8');
1718
- if (!content.includes(MCP_LAUNCHER_FILENAME) || !content.includes(INSTALLED_PROMPT_FILENAME)) {
1719
- throw new Error(`Antigravity guide must reference both ${MCP_LAUNCHER_FILENAME} and ${INSTALLED_PROMPT_FILENAME}.`);
1132
+ if (!content.includes(INSTALLED_PROMPT_FILENAME)) {
1133
+ throw new Error(`Antigravity guide must reference ${INSTALLED_PROMPT_FILENAME}.`);
1720
1134
  }
1721
1135
  return {
1722
- summary: 'Antigravity planning guide references the repo-local prompt asset and MCP launcher.',
1136
+ summary: 'Antigravity planning guide references the repo-local prompt asset.',
1723
1137
  path: assetPaths.antigravityPlanningGuidePath,
1724
1138
  };
1725
1139
  });
@@ -1809,7 +1223,6 @@ function renderInstallGuide({
1809
1223
  installedPromptPath,
1810
1224
  installedSkillPath,
1811
1225
  installManifestPath,
1812
- mcpLauncherPath,
1813
1226
  hostGuidance,
1814
1227
  }) {
1815
1228
  const lines = [
@@ -1821,7 +1234,6 @@ function renderInstallGuide({
1821
1234
  `- prompt asset: \`${toRepoRelativePath(root, installedPromptPath)}\``,
1822
1235
  `- skill asset: \`${toRepoRelativePath(root, installedSkillPath)}\``,
1823
1236
  `- host manifest: \`${toRepoRelativePath(root, installManifestPath)}\``,
1824
- `- shared MCP launcher: \`${toRepoRelativePath(root, mcpLauncherPath)}\``,
1825
1237
  '',
1826
1238
  'Host-specific quick starts:',
1827
1239
  ];
@@ -1854,7 +1266,7 @@ function renderInstallGuide({
1854
1266
  lines.push('', 'Backend fallback:');
1855
1267
  lines.push('- from the repository root, run `audit-code` only when you intentionally need the repo-local backend wrapper');
1856
1268
  lines.push('- run `audit-code verify-install` after bootstrap when you want to smoke-test the generated launchers and host configs');
1857
- lines.push('- rerun `audit-code install` to refresh every generated host surface from the shared prompt, skill, and MCP launcher assets together');
1269
+ lines.push('- rerun `audit-code install` to refresh every generated host surface from the shared prompt and skill assets together');
1858
1270
 
1859
1271
  if (host !== 'all') {
1860
1272
  lines.push('');
@@ -1878,207 +1290,6 @@ async function assertDirectoryExists(path, description) {
1878
1290
  }
1879
1291
  }
1880
1292
 
1881
- function encodeMcpMessage(payload) {
1882
- const body = Buffer.from(JSON.stringify(payload), 'utf8');
1883
- return Buffer.concat([
1884
- Buffer.from(`Content-Length: ${body.length}\r\n\r\n`, 'utf8'),
1885
- body,
1886
- ]);
1887
- }
1888
-
1889
- function createInstallMcpClient(command, args, options = {}) {
1890
- const child = spawn(command, args, {
1891
- cwd: options.cwd,
1892
- env: { ...process.env, ...(options.env ?? {}) },
1893
- stdio: ['pipe', 'pipe', 'pipe'],
1894
- });
1895
-
1896
- let buffer = Buffer.alloc(0);
1897
- let stderr = '';
1898
- let exitError = null;
1899
- const pending = new Map();
1900
-
1901
- function failPending(error) {
1902
- for (const { reject } of pending.values()) {
1903
- reject(error);
1904
- }
1905
- pending.clear();
1906
- }
1907
-
1908
- child.stdout.on('data', (chunk) => {
1909
- buffer = Buffer.concat([buffer, chunk]);
1910
-
1911
- while (true) {
1912
- const separator = buffer.indexOf('\r\n\r\n');
1913
- if (separator < 0) {
1914
- return;
1915
- }
1916
-
1917
- const headerBlock = buffer.slice(0, separator).toString('utf8');
1918
- const contentLengthHeader = headerBlock
1919
- .split('\r\n')
1920
- .find((header) => header.toLowerCase().startsWith('content-length:'));
1921
- if (!contentLengthHeader) {
1922
- return;
1923
- }
1924
-
1925
- const contentLength = Number(contentLengthHeader.split(':')[1]?.trim());
1926
- const frameLength = separator + 4 + contentLength;
1927
- if (buffer.length < frameLength) {
1928
- return;
1929
- }
1930
-
1931
- const payload = JSON.parse(
1932
- buffer.slice(separator + 4, frameLength).toString('utf8'),
1933
- );
1934
- buffer = buffer.slice(frameLength);
1935
-
1936
- if (pending.has(payload.id)) {
1937
- const { resolve, reject } = pending.get(payload.id);
1938
- pending.delete(payload.id);
1939
- if (payload.error) {
1940
- reject(
1941
- new Error(payload.error.message ?? JSON.stringify(payload.error)),
1942
- );
1943
- continue;
1944
- }
1945
- resolve(payload.result);
1946
- }
1947
- }
1948
- });
1949
-
1950
- child.stderr.on('data', (chunk) => {
1951
- stderr += String(chunk);
1952
- });
1953
-
1954
- child.on('error', (error) => {
1955
- exitError = error;
1956
- failPending(error);
1957
- });
1958
-
1959
- child.on('exit', (code, signal) => {
1960
- if (exitError) {
1961
- return;
1962
- }
1963
- exitError = new Error(
1964
- `MCP process exited early with code ${code ?? 'null'}${signal ? ` and signal ${signal}` : ''}.${stderr.trim().length > 0 ? ` ${stderr.trim()}` : ''}`,
1965
- );
1966
- failPending(exitError);
1967
- });
1968
-
1969
- function request(id, method, params = {}) {
1970
- return new Promise((resolve, reject) => {
1971
- if (exitError) {
1972
- reject(exitError);
1973
- return;
1974
- }
1975
- pending.set(id, { resolve, reject });
1976
- child.stdin.write(
1977
- encodeMcpMessage({
1978
- jsonrpc: '2.0',
1979
- id,
1980
- method,
1981
- params,
1982
- }),
1983
- );
1984
- });
1985
- }
1986
-
1987
- function notify(method, params = {}) {
1988
- if (exitError) {
1989
- return;
1990
- }
1991
- child.stdin.write(
1992
- encodeMcpMessage({
1993
- jsonrpc: '2.0',
1994
- method,
1995
- params,
1996
- }),
1997
- );
1998
- }
1999
-
2000
- async function close() {
2001
- if (!exitError) {
2002
- await request('shutdown', 'shutdown');
2003
- notify('exit');
2004
- child.stdin.end();
2005
- }
2006
-
2007
- if (child.exitCode !== null || child.signalCode !== null) {
2008
- return;
2009
- }
2010
-
2011
- await new Promise((resolvePromise) => {
2012
- child.on('exit', () => resolvePromise());
2013
- });
2014
- }
2015
-
2016
- return {
2017
- request,
2018
- notify,
2019
- close,
2020
- readStderr() {
2021
- return stderr.trim();
2022
- },
2023
- };
2024
- }
2025
-
2026
- async function probeMcpServer(params) {
2027
- const client = createInstallMcpClient(params.command, params.args, {
2028
- cwd: params.cwd,
2029
- env: params.env,
2030
- });
2031
-
2032
- let timerId;
2033
- const timeout = new Promise((_, reject) => {
2034
- timerId = setTimeout(() => {
2035
- reject(
2036
- new Error(
2037
- `${params.label} did not complete an MCP handshake within ${INSTALL_VERIFY_TIMEOUT_MS}ms.`,
2038
- ),
2039
- );
2040
- }, INSTALL_VERIFY_TIMEOUT_MS);
2041
- });
2042
-
2043
- try {
2044
- const result = await Promise.race([
2045
- (async () => {
2046
- const initialize = await client.request('init', 'initialize', {
2047
- protocolVersion: MCP_PROTOCOL_VERSION,
2048
- capabilities: {},
2049
- clientInfo: {
2050
- name: 'audit-code-verify-install',
2051
- version: packageVersion,
2052
- },
2053
- });
2054
- client.notify('notifications/initialized');
2055
- const tools = await client.request('tools', 'tools/list');
2056
- const resources = await client.request('resources', 'resources/list');
2057
- await client.close();
2058
- return {
2059
- initialize,
2060
- tools,
2061
- resources,
2062
- stderr: client.readStderr(),
2063
- };
2064
- })(),
2065
- timeout,
2066
- ]);
2067
- clearTimeout(timerId);
2068
- return result;
2069
- } catch (error) {
2070
- clearTimeout(timerId);
2071
- const stderr = client.readStderr();
2072
- try {
2073
- await client.close();
2074
- } catch {
2075
- // already failed or exited
2076
- }
2077
- const suffix = stderr.length > 0 ? ` ${stderr}` : '';
2078
- throw new Error(`${error instanceof Error ? error.message : String(error)}${suffix}`);
2079
- }
2080
- }
2081
-
2082
1293
  async function collectVerifyCheck(target, id, fn) {
2083
1294
  try {
2084
1295
  const details = await fn();
@@ -2246,39 +1457,6 @@ async function verifyInstalledBootstrap(argv) {
2246
1457
  };
2247
1458
  });
2248
1459
 
2249
- await collectVerifyCheck(generalChecks, 'shared_launcher_file', async () => {
2250
- const launcher = await readFile(assetPaths.mcpLauncherPath, 'utf8');
2251
- if (!launcher.includes('Unable to locate an audit-code executable')) {
2252
- throw new Error(`Shared MCP launcher is missing the executable resolution fallback message: ${assetPaths.mcpLauncherPath}`);
2253
- }
2254
- if (!launcher.includes('sourcePackageRoot')) {
2255
- throw new Error(`Shared MCP launcher is missing the package-source fallback hint: ${assetPaths.mcpLauncherPath}`);
2256
- }
2257
- return {
2258
- summary: 'Shared MCP launcher is present and includes resolver fallbacks.',
2259
- path: assetPaths.mcpLauncherPath,
2260
- };
2261
- });
2262
-
2263
- await collectVerifyCheck(generalChecks, 'shared_launcher_mcp', async () => {
2264
- const probe = await probeMcpServer({
2265
- label: 'Shared MCP launcher',
2266
- command: process.execPath,
2267
- args: [assetPaths.mcpLauncherPath],
2268
- cwd: root,
2269
- });
2270
- const toolNames = (probe.tools?.tools ?? []).map((tool) => tool.name);
2271
- if (!toolNames.includes('start_audit')) {
2272
- throw new Error('Shared MCP launcher did not expose the start_audit tool.');
2273
- }
2274
- return {
2275
- summary: 'Shared MCP launcher completed an MCP handshake.',
2276
- server_name: probe.initialize?.serverInfo?.name ?? null,
2277
- tool_count: toolNames.length,
2278
- resource_count: (probe.resources?.resources ?? []).length,
2279
- };
2280
- });
2281
-
2282
1460
  for (const hostKey of selectedHosts) {
2283
1461
  const checks = [];
2284
1462
  const hostEntry = hostCatalog.get(hostKey);
@@ -2473,16 +1651,6 @@ async function detectBootstrapRefreshReason(root, host) {
2473
1651
  }
2474
1652
  }
2475
1653
 
2476
- const launcherPath =
2477
- assetPaths.mcpLauncherPath ?? installManifest.mcp_server_launcher_path;
2478
- const launcher = launcherPath ? await readTextIfExists(launcherPath) : null;
2479
- if (launcher === null) {
2480
- return 'missing_mcp_launcher';
2481
- }
2482
- if (!launcher.includes('Unable to locate an audit-code executable')) {
2483
- return 'stale_mcp_launcher';
2484
- }
2485
-
2486
1654
  return null;
2487
1655
  }
2488
1656
 
@@ -2506,7 +1674,6 @@ async function ensureBootstrap(argv) {
2506
1674
  host: installed.host,
2507
1675
  repo_root: installed.repo_root,
2508
1676
  install_manifest_path: installed.install_manifest_path,
2509
- mcp_server_launcher_path: installed.mcp_server_launcher_path,
2510
1677
  host_count: installed.host_guidance.length,
2511
1678
  file_count: installed.files.length,
2512
1679
  };
@@ -2542,13 +1709,11 @@ function buildInstallAssetPaths(root, profile) {
2542
1709
  const installedSkillPath = join(root, '.audit-code', 'install', 'SKILL.md');
2543
1710
  const installGuidePath = join(root, '.audit-code', 'install', INSTALL_GUIDE_FILENAME);
2544
1711
  const installManifestPath = join(root, '.audit-code', 'install', INSTALL_MANIFEST_FILENAME);
2545
- const mcpLauncherPath = join(root, '.audit-code', 'install', MCP_LAUNCHER_FILENAME);
2546
1712
  return {
2547
1713
  installedPromptPath,
2548
1714
  installedSkillPath,
2549
1715
  installGuidePath,
2550
1716
  installManifestPath,
2551
- mcpLauncherPath,
2552
1717
  agentsInstructionsPath: profile.writeAgents ? join(root, 'AGENTS.md') : null,
2553
1718
  copilotInstructionsPath: profile.writeCopilotInstructions
2554
1719
  ? join(root, '.github', 'copilot-instructions.md')
@@ -2559,24 +1724,9 @@ function buildInstallAssetPaths(root, profile) {
2559
1724
  codexPromptPath: profile.writeCodex
2560
1725
  ? join(root, '.codex', 'skills', 'audit-code', 'audit-code.prompt.md')
2561
1726
  : null,
2562
- codexMcpSetupPath: profile.writeCodex
2563
- ? join(root, '.audit-code', 'install', 'codex', 'MCP-SETUP.md')
2564
- : null,
2565
1727
  codexAutomationRecipePath: profile.writeCodex
2566
1728
  ? join(root, '.audit-code', 'install', 'codex', 'RE-AUDIT-AUTOMATION.md')
2567
1729
  : null,
2568
- claudeDesktopProjectTemplatePath: profile.writeClaudeDesktop
2569
- ? join(root, '.audit-code', 'install', 'claude-desktop', 'PROJECT-TEMPLATE.md')
2570
- : null,
2571
- claudeDesktopRemoteConnectorPath: profile.writeClaudeDesktop
2572
- ? join(root, '.audit-code', 'install', 'claude-desktop', 'remote-mcp-connector.json')
2573
- : null,
2574
- claudeDesktopDxtPath: profile.writeClaudeDesktop
2575
- ? join(root, '.audit-code', 'install', 'claude-desktop', 'auditor-lambda.dxt')
2576
- : null,
2577
- claudeDesktopMcpbPath: profile.writeClaudeDesktop
2578
- ? join(root, '.audit-code', 'install', 'claude-desktop', 'auditor-lambda.mcpb')
2579
- : null,
2580
1730
  opencodeConfigPath: profile.writeOpenCode
2581
1731
  ? join(root, 'opencode.json')
2582
1732
  : null,
@@ -2586,9 +1736,6 @@ function buildInstallAssetPaths(root, profile) {
2586
1736
  vscodeAgentPath: profile.writeVSCode
2587
1737
  ? join(root, '.github', 'agents', 'auditor.agent.md')
2588
1738
  : null,
2589
- vscodeMcpConfigPath: profile.writeVSCode
2590
- ? join(root, '.vscode', 'mcp.json')
2591
- : null,
2592
1739
  antigravityPlanningGuidePath: profile.writeAntigravity
2593
1740
  ? join(root, '.audit-code', 'install', 'antigravity', 'PLANNING-MODE.md')
2594
1741
  : null,
@@ -2601,7 +1748,7 @@ function buildInstallAssetPaths(root, profile) {
2601
1748
  };
2602
1749
  }
2603
1750
 
2604
- // Always-written core assets (installed prompt + skill, shared MCP launcher,
1751
+ // Always-written core assets (installed prompt + skill,
2605
1752
  // AGENTS/copilot compatibility directive blocks) plus legacy-surface cleanup.
2606
1753
  async function writeCoreInstallAssets(root, assetPaths, promptSource, skillSource) {
2607
1754
  const results = [];
@@ -2611,9 +1758,6 @@ async function writeCoreInstallAssets(root, assetPaths, promptSource, skillSourc
2611
1758
  }
2612
1759
  results.push(await writeGeneratedMarkdown(assetPaths.installedPromptPath, promptSource));
2613
1760
  results.push(await writeGeneratedMarkdown(assetPaths.installedSkillPath, skillSource));
2614
- results.push(
2615
- await writeGeneratedMarkdown(assetPaths.mcpLauncherPath, renderSharedMcpLauncher(repoRoot)),
2616
- );
2617
1761
 
2618
1762
  const compatibilityBlockTargets = [
2619
1763
  assetPaths.agentsInstructionsPath,
@@ -2634,37 +1778,14 @@ async function writeCoreInstallAssets(root, assetPaths, promptSource, skillSourc
2634
1778
  return results;
2635
1779
  }
2636
1780
 
2637
- async function writeCodexAssets(assetPaths, promptSource, skillSource, root) {
1781
+ async function writeCodexAssets(assetPaths, promptSource, skillSource) {
2638
1782
  return [
2639
1783
  await writeGeneratedMarkdown(assetPaths.codexSkillPath, skillSource),
2640
1784
  await writeGeneratedMarkdown(assetPaths.codexPromptPath, promptSource),
2641
- await writeGeneratedMarkdown(assetPaths.codexMcpSetupPath, renderCodexMcpSetupGuide(root)),
2642
1785
  await writeGeneratedMarkdown(assetPaths.codexAutomationRecipePath, renderCodexAutomationRecipe()),
2643
1786
  ];
2644
1787
  }
2645
1788
 
2646
- // Builds the Claude Desktop DXT/MCPB bundle (mutating assetPaths with the
2647
- // produced bundle paths) and writes the project template + remote connector.
2648
- async function writeClaudeDesktopAssets(assetPaths, root) {
2649
- const results = [];
2650
- const claudeDesktopBundle = await buildClaudeDesktopBundle(root, results);
2651
- assetPaths.claudeDesktopDxtPath = claudeDesktopBundle.dxtPath;
2652
- assetPaths.claudeDesktopMcpbPath = claudeDesktopBundle.mcpbPath;
2653
- results.push(
2654
- await writeGeneratedMarkdown(
2655
- assetPaths.claudeDesktopProjectTemplatePath,
2656
- renderClaudeDesktopProjectTemplate(),
2657
- ),
2658
- );
2659
- results.push(
2660
- await writeGeneratedJson(
2661
- assetPaths.claudeDesktopRemoteConnectorPath,
2662
- JSON.parse(renderClaudeDesktopRemoteConnectorTemplate()),
2663
- ),
2664
- );
2665
- return results;
2666
- }
2667
-
2668
1789
  async function writeOpenCodeAssets(assetPaths, root) {
2669
1790
  return [
2670
1791
  await writeMergedGeneratedJson(
@@ -2689,11 +1810,6 @@ async function writeVSCodeAssets(assetPaths, promptBody) {
2689
1810
  ),
2690
1811
  ),
2691
1812
  await writeGeneratedMarkdown(assetPaths.vscodeAgentPath, renderVSCodeAgentFile()),
2692
- await writeMergedGeneratedJson(
2693
- assetPaths.vscodeMcpConfigPath,
2694
- 'VS Code MCP config',
2695
- buildMergedVSCodeMcpConfig,
2696
- ),
2697
1813
  ];
2698
1814
  }
2699
1815
 
@@ -2722,17 +1838,13 @@ async function installBootstrap(argv, options = {}) {
2722
1838
  installedSkillPath,
2723
1839
  installGuidePath,
2724
1840
  installManifestPath,
2725
- mcpLauncherPath,
2726
1841
  } = assetPaths;
2727
1842
 
2728
1843
  const results = [];
2729
1844
  results.push(...await writeCoreInstallAssets(root, assetPaths, promptSource, skillSource));
2730
1845
 
2731
1846
  if (profile.writeCodex) {
2732
- results.push(...await writeCodexAssets(assetPaths, promptSource, skillSource, root));
2733
- }
2734
- if (profile.writeClaudeDesktop) {
2735
- results.push(...await writeClaudeDesktopAssets(assetPaths, root));
1847
+ results.push(...await writeCodexAssets(assetPaths, promptSource, skillSource));
2736
1848
  }
2737
1849
  if (profile.writeOpenCode) {
2738
1850
  results.push(...await writeOpenCodeAssets(assetPaths, root));
@@ -2758,7 +1870,6 @@ async function installBootstrap(argv, options = {}) {
2758
1870
  installed_skill_path: installedSkillPath,
2759
1871
  install_guide_path: installGuidePath,
2760
1872
  install_manifest_path: installManifestPath,
2761
- mcp_server_launcher_path: mcpLauncherPath,
2762
1873
  source_prompt_path: resolve(promptAssetPath),
2763
1874
  source_skill_path: resolve(skillAssetPath),
2764
1875
  asset_paths: assetPaths,
@@ -2774,7 +1885,6 @@ async function installBootstrap(argv, options = {}) {
2774
1885
  installedPromptPath,
2775
1886
  installedSkillPath,
2776
1887
  installManifestPath,
2777
- mcpLauncherPath,
2778
1888
  hostGuidance,
2779
1889
  }),
2780
1890
  ),
@@ -2796,7 +1906,6 @@ async function installBootstrap(argv, options = {}) {
2796
1906
  installed_skill_path: installedSkillPath,
2797
1907
  install_guide_path: installGuidePath,
2798
1908
  install_manifest_path: installManifestPath,
2799
- mcp_server_launcher_path: mcpLauncherPath,
2800
1909
  source_prompt_path: resolve(promptAssetPath),
2801
1910
  source_skill_path: resolve(skillAssetPath),
2802
1911
  files: results,
@@ -2810,22 +1919,12 @@ async function installBootstrap(argv, options = {}) {
2810
1919
  agents: assetPaths.agentsInstructionsPath,
2811
1920
  copilot_instructions: assetPaths.copilotInstructionsPath,
2812
1921
  },
2813
- mcp_surfaces: {
2814
- vscode_workspace: assetPaths.vscodeMcpConfigPath,
2815
- opencode_project: assetPaths.opencodeConfigPath,
2816
- codex_setup: assetPaths.codexMcpSetupPath,
2817
- shared_launcher: mcpLauncherPath,
2818
- claude_desktop_dxt: assetPaths.claudeDesktopDxtPath,
2819
- claude_desktop_mcpb: assetPaths.claudeDesktopMcpbPath,
2820
- antigravity_planning_guide: assetPaths.antigravityPlanningGuidePath,
2821
- },
2822
1922
  host_guidance: hostGuidance,
2823
1923
  unsupported_hosts: [],
2824
1924
  next_steps: [
2825
1925
  'Open the repository in your preferred host and follow the matching host_guidance entry.',
2826
- `Open ${installGuidePath} for repo-local quick-start steps for Codex, Claude Desktop, OpenCode, VS Code, and Antigravity.`,
2827
- 'Run `audit-code verify-install` from the repository root to smoke-test the generated launchers and host configs.',
2828
- 'Use the shared MCP launcher as the source of truth for local stdio MCP registration across hosts.',
1926
+ `Open ${installGuidePath} for repo-local quick-start steps for Codex, OpenCode, VS Code, and Antigravity.`,
1927
+ 'Run `audit-code verify-install` from the repository root to smoke-test the generated host configs.',
2829
1928
  ],
2830
1929
  };
2831
1930