auditor-lambda 0.9.1 → 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 (43) hide show
  1. package/README.md +2 -9
  2. package/audit-code-wrapper-lib.mjs +19 -915
  3. package/dispatch/merge-results.mjs +1 -1
  4. package/dist/cli/auditStep.d.ts +1 -33
  5. package/dist/cli/dispatch.d.ts +47 -0
  6. package/dist/cli/dispatch.js +116 -1
  7. package/dist/cli/mergeAndIngestCommand.js +55 -8
  8. package/dist/cli/nextStepCommand.js +43 -15
  9. package/dist/cli/prompts.d.ts +2 -0
  10. package/dist/cli/prompts.js +9 -0
  11. package/dist/cli/reviewRun.js +1 -1
  12. package/dist/cli/runToCompletion.js +21 -8
  13. package/dist/cli/semanticReviewStep.js +12 -1
  14. package/dist/cli/steps.d.ts +15 -0
  15. package/dist/cli.js +1 -8
  16. package/dist/io/artifacts.d.ts +9 -1
  17. package/dist/io/artifacts.js +7 -0
  18. package/dist/io/runArtifacts.d.ts +14 -0
  19. package/dist/io/runArtifacts.js +23 -0
  20. package/dist/orchestrator/designReviewPrompt.d.ts +4 -1
  21. package/dist/orchestrator/designReviewPrompt.js +43 -2
  22. package/dist/orchestrator/executorResult.d.ts +25 -0
  23. package/dist/orchestrator/intakeExecutors.d.ts +19 -1
  24. package/dist/orchestrator/intakeExecutors.js +89 -3
  25. package/dist/orchestrator/nextStep.d.ts +1 -0
  26. package/dist/orchestrator/nextStep.js +1 -1
  27. package/dist/orchestrator/state.js +8 -1
  28. package/dist/providers/constants.d.ts +1 -1
  29. package/dist/providers/constants.js +1 -1
  30. package/dist/reporting/synthesis.d.ts +8 -0
  31. package/dist/reporting/synthesis.js +16 -1
  32. package/dist/supervisor/operatorHandoff.js +8 -1
  33. package/dist/types/auditScope.d.ts +16 -2
  34. package/dist/validation/sessionConfig.js +35 -0
  35. package/docs/contracts.md +0 -16
  36. package/docs/operator-guide.md +6 -8
  37. package/package.json +1 -1
  38. package/schemas/audit_findings.schema.json +1 -0
  39. package/scripts/postinstall.mjs +0 -174
  40. package/skills/audit-code/SKILL.md +17 -1
  41. package/skills/audit-code/audit-code.prompt.md +25 -0
  42. package/dist/mcp/server.d.ts +0 -72
  43. 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,383 +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
- await cp(join(repoRoot, 'skills', 'audit-code'), join(bundleRoot, 'skills', 'audit-code'), { recursive: true, force: true });
1281
- await writeFile(join(bundleRoot, 'audit-code.mjs'), await readFile(join(repoRoot, 'audit-code.mjs')));
1282
- await writeFile(join(bundleRoot, 'audit-code-wrapper-lib.mjs'), await readFile(join(repoRoot, 'audit-code-wrapper-lib.mjs')));
1283
- await writeFile(join(bundleRoot, 'package.json'), await readFile(join(repoRoot, 'package.json')));
1284
-
1285
- try {
1286
- const req = createRequire(join(repoRoot, 'package.json'));
1287
- const sharedEntry = req.resolve('@audit-tools/shared');
1288
- let sharedRoot = dirname(sharedEntry);
1289
- while (sharedRoot !== dirname(sharedRoot) && !(await fileExists(join(sharedRoot, 'package.json')))) {
1290
- sharedRoot = dirname(sharedRoot);
1291
- }
1292
- const bundleSharedRoot = join(bundleRoot, 'node_modules', '@audit-tools', 'shared');
1293
- await mkdir(bundleSharedRoot, { recursive: true });
1294
- await cp(join(sharedRoot, 'dist'), join(bundleSharedRoot, 'dist'), { recursive: true, force: true });
1295
- await writeFile(join(bundleSharedRoot, 'package.json'), await readFile(join(sharedRoot, 'package.json')));
1296
- } catch {
1297
- // @audit-tools/shared not resolvable — bundle will use runtime resolution
1298
- }
1299
-
1300
- return { bundleExisted };
1301
- }
1302
-
1303
- // Source for the bundle's server/index.js shim: it spawns the bundled
1304
- // audit-code.mjs in MCP mode against the user-configured repo root.
1305
- function renderClaudeDesktopServerEntry() {
1306
- return [
1307
- "import { spawn } from 'node:child_process';",
1308
- "import { dirname, join } from 'node:path';",
1309
- "import { fileURLToPath } from 'node:url';",
1310
- '',
1311
- 'const serverDir = dirname(fileURLToPath(import.meta.url));',
1312
- "const bundleRoot = join(serverDir, '..');",
1313
- "const repoRoot = process.env.AUDIT_CODE_REPO_ROOT;",
1314
- "const artifactsDir = process.env.AUDIT_CODE_ARTIFACTS_DIR || (repoRoot ? join(repoRoot, '.audit-artifacts') : undefined);",
1315
- '',
1316
- 'if (!repoRoot) {',
1317
- " console.error('AUDIT_CODE_REPO_ROOT must be configured before launching the auditor MCP bundle.');",
1318
- ' process.exit(1);',
1319
- '}',
1320
- '',
1321
- "const child = spawn(process.execPath, [join(bundleRoot, 'audit-code.mjs'), 'mcp', '--root', repoRoot, '--artifacts-dir', artifactsDir], {",
1322
- " cwd: repoRoot,",
1323
- ' env: process.env,',
1324
- " stdio: ['inherit', 'inherit', 'inherit'],",
1325
- '});',
1326
- '',
1327
- "child.on('exit', (code) => {",
1328
- ' process.exitCode = code ?? 1;',
1329
- '});',
1330
- '',
1331
- ].join('\n');
1332
- }
1333
-
1334
- // The DXT/MCPB manifest.json describing the bundled node MCP server and its
1335
- // Claude Desktop user-config inputs.
1336
- function buildClaudeDesktopManifest() {
1337
- return {
1338
- manifest_version: '0.3',
1339
- name: 'auditor-lambda',
1340
- display_name: 'Auditor Lambda',
1341
- version: packageVersion,
1342
- description: 'Compatibility MCP bundle for the /audit-code autonomous audit workflow.',
1343
- long_description:
1344
- 'Runs a local compatibility MCP adapter whose start and continue tools return the same audit-code next-step contract as the direct CLI loop.',
1345
- author: {
1346
- name: 'auditor-lambda',
1347
- url: 'https://github.com/OhOkThisIsFine/auditor-lambda',
1348
- },
1349
- repository: {
1350
- type: 'git',
1351
- url: 'https://github.com/OhOkThisIsFine/auditor-lambda.git',
1352
- },
1353
- documentation: 'https://github.com/OhOkThisIsFine/auditor-lambda/tree/main/docs',
1354
- support: 'https://github.com/OhOkThisIsFine/auditor-lambda/issues',
1355
- license: 'MIT',
1356
- compatibility: {
1357
- claude_desktop: '>=1.0.0',
1358
- platforms: ['darwin', 'win32', 'linux'],
1359
- runtimes: {
1360
- node: '>=20.0.0',
1361
- },
1362
- },
1363
- tools_generated: true,
1364
- prompts_generated: true,
1365
- server: {
1366
- type: 'node',
1367
- entry_point: 'server/index.js',
1368
- mcp_config: {
1369
- command: 'node',
1370
- args: ['${__dirname}/server/index.js'],
1371
- env: {
1372
- AUDIT_CODE_REPO_ROOT: '${user_config.repo_root}',
1373
- AUDIT_CODE_ARTIFACTS_DIR: '${user_config.artifacts_dir}',
1374
- },
1375
- },
1376
- },
1377
- user_config: {
1378
- repo_root: {
1379
- type: 'directory',
1380
- title: 'Repository Root',
1381
- description: 'Repository to audit with auditor-lambda.',
1382
- required: true,
1383
- },
1384
- artifacts_dir: {
1385
- type: 'directory',
1386
- title: 'Artifacts Directory',
1387
- description: 'Optional override for the audit artifacts directory.',
1388
- required: false,
1389
- },
1390
- },
1391
- };
1392
- }
1393
-
1394
- // Orchestrates the Claude Desktop bundle: copy files, write the server shim and
1395
- // manifest, then zip into the .dxt / .mcpb archives. Pushes each generated file
1396
- // into `results`.
1397
- async function buildClaudeDesktopBundle(root, results) {
1398
- const bundleRoot = join(root, '.audit-code', 'install', 'claude-desktop', 'bundle');
1399
- const serverRoot = join(bundleRoot, 'server');
1400
- const manifestPath = join(bundleRoot, 'manifest.json');
1401
- const serverEntrypointPath = join(serverRoot, 'index.js');
1402
- const dxtPath = join(root, '.audit-code', 'install', 'claude-desktop', 'auditor-lambda.dxt');
1403
- const mcpbPath = join(root, '.audit-code', 'install', 'claude-desktop', 'auditor-lambda.mcpb');
1404
-
1405
- const { bundleExisted } = await copyClaudeDesktopBundleFiles(bundleRoot, serverRoot);
1406
- results.push({ path: bundleRoot, mode: bundleExisted ? 'updated' : 'created' });
1407
-
1408
- results.push(
1409
- await writeGeneratedMarkdown(serverEntrypointPath, renderClaudeDesktopServerEntry()),
1410
- );
1411
- results.push(await writeGeneratedJson(manifestPath, buildClaudeDesktopManifest()));
1412
-
1413
- const archive = await createStoredZipBuffer(bundleRoot);
1414
- results.push(await writeGeneratedBinary(dxtPath, archive));
1415
- results.push(await writeGeneratedBinary(mcpbPath, archive));
1416
-
1417
- return {
1418
- bundleRoot,
1419
- manifestPath,
1420
- dxtPath,
1421
- mcpbPath,
1422
- serverEntrypointPath,
1423
- };
1424
- }
1425
-
1426
968
  const INSTALL_PROFILE_FLAGS = [
1427
969
  'writeVSCode',
1428
970
  'writeCopilotInstructions',
1429
971
  'writeOpenCode',
1430
972
  'writeCodex',
1431
- 'writeClaudeDesktop',
1432
973
  'writeAntigravity',
1433
974
  'writeAgents',
1434
975
  ];
1435
976
 
1436
977
  const INSTALL_HOST_ORDER = [
1437
978
  'codex',
1438
- 'claude-desktop',
1439
979
  'opencode',
1440
980
  'vscode',
1441
981
  'antigravity',
@@ -1452,7 +992,6 @@ const INSTALL_HOST_DEFINITIONS = {
1452
992
  primary_path_key: 'agentsInstructionsPath',
1453
993
  supporting_path_keys: [
1454
994
  'installedPromptPath',
1455
- 'mcpLauncherPath',
1456
995
  ],
1457
996
  steps: [
1458
997
  'Open this repository in Codex.',
@@ -1475,119 +1014,16 @@ const INSTALL_HOST_DEFINITIONS = {
1475
1014
  });
1476
1015
  },
1477
1016
  },
1478
- 'claude-desktop': {
1479
- host: 'claude-desktop',
1480
- label: 'Claude Desktop',
1481
- support_level: 'supported',
1482
- setup_kind: 'local-mcp-bundle',
1483
- summary:
1484
- 'Install the generated local MCP compatibility bundle in Claude Desktop, then use the project template and prompt asset as supporting context.',
1485
- primary_path_key: 'claudeDesktopDxtPath',
1486
- supporting_path_keys: [
1487
- 'claudeDesktopMcpbPath',
1488
- 'claudeDesktopProjectTemplatePath',
1489
- 'claudeDesktopRemoteConnectorPath',
1490
- 'installedPromptPath',
1491
- ],
1492
- steps: [
1493
- 'Open Claude Desktop Settings and install the generated `.dxt` bundle.',
1494
- 'Configure the repository root when prompted so the bundle can launch the local auditor MCP adapter.',
1495
- 'Use the project template and prompt asset to kick off `/audit-code` in conversation.',
1496
- ],
1497
- profile: {
1498
- writeClaudeDesktop: true,
1499
- },
1500
- async verify({ checks, root, assetPaths, collectVerifyCheck: collect }) {
1501
- const bundleManifestPath = join(
1502
- root,
1503
- '.audit-code',
1504
- 'install',
1505
- 'claude-desktop',
1506
- 'bundle',
1507
- 'manifest.json',
1508
- );
1509
- const bundleServerPath = join(
1510
- root,
1511
- '.audit-code',
1512
- 'install',
1513
- 'claude-desktop',
1514
- 'bundle',
1515
- 'server',
1516
- 'index.js',
1517
- );
1518
-
1519
- await collect(checks, 'claude_bundle_manifest', async () => {
1520
- const manifest = await readJson(bundleManifestPath, 'Claude Desktop bundle manifest');
1521
- if (manifest?.server?.entry_point !== 'server/index.js') {
1522
- throw new Error(`Claude Desktop bundle manifest has an unexpected entry_point: ${manifest?.server?.entry_point ?? 'missing'}.`);
1523
- }
1524
- return {
1525
- summary: 'Claude Desktop bundle manifest parsed successfully.',
1526
- path: bundleManifestPath,
1527
- };
1528
- });
1529
- await collect(checks, 'claude_connector_template', async () => {
1530
- const connector = await readJson(
1531
- assetPaths.claudeDesktopRemoteConnectorPath,
1532
- 'Claude Desktop remote connector template',
1533
- );
1534
- if (connector?.transport !== 'remote-mcp') {
1535
- throw new Error(`Claude Desktop remote connector transport must be "remote-mcp", got ${connector?.transport ?? 'missing'}.`);
1536
- }
1537
- return {
1538
- summary: 'Claude Desktop remote connector template parsed successfully.',
1539
- path: assetPaths.claudeDesktopRemoteConnectorPath,
1540
- };
1541
- });
1542
- await collect(checks, 'claude_dxt_archive', async () => ({
1543
- summary: 'Claude Desktop .dxt bundle is present.',
1544
- path: assetPaths.claudeDesktopDxtPath,
1545
- size_bytes: await verifyZipFile(
1546
- assetPaths.claudeDesktopDxtPath,
1547
- 'Claude Desktop .dxt bundle',
1548
- ),
1549
- }));
1550
- await collect(checks, 'claude_mcpb_archive', async () => ({
1551
- summary: 'Claude Desktop .mcpb bundle is present.',
1552
- path: assetPaths.claudeDesktopMcpbPath,
1553
- size_bytes: await verifyZipFile(
1554
- assetPaths.claudeDesktopMcpbPath,
1555
- 'Claude Desktop .mcpb bundle',
1556
- ),
1557
- }));
1558
- await collect(checks, 'claude_bundle_mcp', async () => {
1559
- const probe = await probeMcpServer({
1560
- label: 'Claude Desktop bundle server',
1561
- command: process.execPath,
1562
- args: [bundleServerPath],
1563
- cwd: root,
1564
- env: {
1565
- AUDIT_CODE_REPO_ROOT: root,
1566
- AUDIT_CODE_ARTIFACTS_DIR: join(root, '.audit-artifacts'),
1567
- },
1568
- });
1569
- const toolNames = (probe.tools?.tools ?? []).map((tool) => tool.name);
1570
- if (!toolNames.includes('start_audit')) {
1571
- throw new Error('Claude Desktop bundle server did not expose the start_audit tool.');
1572
- }
1573
- return {
1574
- summary: 'Claude Desktop bundle completed an MCP handshake.',
1575
- tool_count: toolNames.length,
1576
- };
1577
- });
1578
- },
1579
- },
1580
1017
  opencode: {
1581
1018
  host: 'opencode',
1582
1019
  label: 'OpenCode',
1583
1020
  support_level: 'supported',
1584
- setup_kind: 'global-command+project-mcp',
1021
+ setup_kind: 'global-command+project-permissions',
1585
1022
  summary:
1586
- '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.',
1587
1024
  primary_path_key: 'opencodeConfigPath',
1588
1025
  supporting_path_keys: [
1589
1026
  'agentsInstructionsPath',
1590
- 'mcpLauncherPath',
1591
1027
  ],
1592
1028
  steps: [
1593
1029
  'Open this repository in OpenCode.',
@@ -1620,19 +1056,17 @@ const INSTALL_HOST_DEFINITIONS = {
1620
1056
  host: 'vscode',
1621
1057
  label: 'VS Code',
1622
1058
  support_level: 'supported',
1623
- setup_kind: 'prompt+agent+mcp',
1059
+ setup_kind: 'prompt+agent',
1624
1060
  summary:
1625
- '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.',
1626
1062
  primary_path_key: 'vscodePromptPath',
1627
1063
  supporting_path_keys: [
1628
1064
  'vscodeAgentPath',
1629
- 'vscodeMcpConfigPath',
1630
1065
  'copilotInstructionsPath',
1631
1066
  ],
1632
1067
  steps: [
1633
1068
  'Open this repository in VS Code with Copilot.',
1634
1069
  'Invoke `/audit-code` from the generated prompt or chat so the workflow calls `audit-code next-step` directly.',
1635
- 'Use the workspace MCP adapter only when direct shell access is unavailable.',
1636
1070
  ],
1637
1071
  profile: {
1638
1072
  writeVSCode: true,
@@ -1656,42 +1090,27 @@ const INSTALL_HOST_DEFINITIONS = {
1656
1090
  path: assetPaths.vscodePromptPath,
1657
1091
  };
1658
1092
  });
1659
- await collect(checks, 'vscode_mcp_config', async () => {
1660
- const config = await readJson(assetPaths.vscodeMcpConfigPath, 'VS Code MCP config');
1661
- const args = config?.servers?.auditor?.args;
1662
- if (config?.servers?.auditor?.command !== 'node') {
1663
- throw new Error(`VS Code MCP config must use node as the command, got ${config?.servers?.auditor?.command ?? 'missing'}.`);
1664
- }
1665
- if (!Array.isArray(args) || args[0] !== '${workspaceFolder}/.audit-code/install/run-mcp-server.mjs') {
1666
- throw new Error(`VS Code MCP config must point at \${workspaceFolder}/.audit-code/install/${MCP_LAUNCHER_FILENAME}.`);
1667
- }
1668
- return {
1669
- summary: 'VS Code MCP config parsed successfully.',
1670
- path: assetPaths.vscodeMcpConfigPath,
1671
- };
1672
- });
1673
1093
  },
1674
1094
  },
1675
1095
  antigravity: {
1676
1096
  host: 'antigravity',
1677
1097
  label: 'Antigravity',
1678
1098
  support_level: 'supported',
1679
- setup_kind: 'agent-skill+gemini-command+planning-guide+mcp-ready',
1099
+ setup_kind: 'agent-skill+gemini-command+planning-guide',
1680
1100
  summary:
1681
- '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.',
1682
1102
  primary_path_key: 'antigravitySkillPath',
1683
1103
  supporting_path_keys: [
1684
1104
  'geminiCommandPath',
1685
1105
  'antigravityPlanningGuidePath',
1686
1106
  'agentsInstructionsPath',
1687
- 'mcpLauncherPath',
1688
1107
  'installedPromptPath',
1689
1108
  ],
1690
1109
  steps: [
1691
1110
  'Open this repository in Antigravity.',
1692
1111
  'The audit-code skill is automatically discovered from .agent/skills/audit-code/SKILL.md.',
1693
1112
  'The /audit-code slash command is also available from .gemini/commands/audit-code.toml.',
1694
- '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.',
1695
1114
  ],
1696
1115
  profile: {
1697
1116
  writeAntigravity: true,
@@ -1710,11 +1129,11 @@ const INSTALL_HOST_DEFINITIONS = {
1710
1129
  });
1711
1130
  await collect(checks, 'antigravity_guide', async () => {
1712
1131
  const content = await readFile(assetPaths.antigravityPlanningGuidePath, 'utf8');
1713
- if (!content.includes(MCP_LAUNCHER_FILENAME) || !content.includes(INSTALLED_PROMPT_FILENAME)) {
1714
- 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}.`);
1715
1134
  }
1716
1135
  return {
1717
- summary: 'Antigravity planning guide references the repo-local prompt asset and MCP launcher.',
1136
+ summary: 'Antigravity planning guide references the repo-local prompt asset.',
1718
1137
  path: assetPaths.antigravityPlanningGuidePath,
1719
1138
  };
1720
1139
  });
@@ -1804,7 +1223,6 @@ function renderInstallGuide({
1804
1223
  installedPromptPath,
1805
1224
  installedSkillPath,
1806
1225
  installManifestPath,
1807
- mcpLauncherPath,
1808
1226
  hostGuidance,
1809
1227
  }) {
1810
1228
  const lines = [
@@ -1816,7 +1234,6 @@ function renderInstallGuide({
1816
1234
  `- prompt asset: \`${toRepoRelativePath(root, installedPromptPath)}\``,
1817
1235
  `- skill asset: \`${toRepoRelativePath(root, installedSkillPath)}\``,
1818
1236
  `- host manifest: \`${toRepoRelativePath(root, installManifestPath)}\``,
1819
- `- shared MCP launcher: \`${toRepoRelativePath(root, mcpLauncherPath)}\``,
1820
1237
  '',
1821
1238
  'Host-specific quick starts:',
1822
1239
  ];
@@ -1849,7 +1266,7 @@ function renderInstallGuide({
1849
1266
  lines.push('', 'Backend fallback:');
1850
1267
  lines.push('- from the repository root, run `audit-code` only when you intentionally need the repo-local backend wrapper');
1851
1268
  lines.push('- run `audit-code verify-install` after bootstrap when you want to smoke-test the generated launchers and host configs');
1852
- 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');
1853
1270
 
1854
1271
  if (host !== 'all') {
1855
1272
  lines.push('');
@@ -1873,207 +1290,6 @@ async function assertDirectoryExists(path, description) {
1873
1290
  }
1874
1291
  }
1875
1292
 
1876
- function encodeMcpMessage(payload) {
1877
- const body = Buffer.from(JSON.stringify(payload), 'utf8');
1878
- return Buffer.concat([
1879
- Buffer.from(`Content-Length: ${body.length}\r\n\r\n`, 'utf8'),
1880
- body,
1881
- ]);
1882
- }
1883
-
1884
- function createInstallMcpClient(command, args, options = {}) {
1885
- const child = spawn(command, args, {
1886
- cwd: options.cwd,
1887
- env: { ...process.env, ...(options.env ?? {}) },
1888
- stdio: ['pipe', 'pipe', 'pipe'],
1889
- });
1890
-
1891
- let buffer = Buffer.alloc(0);
1892
- let stderr = '';
1893
- let exitError = null;
1894
- const pending = new Map();
1895
-
1896
- function failPending(error) {
1897
- for (const { reject } of pending.values()) {
1898
- reject(error);
1899
- }
1900
- pending.clear();
1901
- }
1902
-
1903
- child.stdout.on('data', (chunk) => {
1904
- buffer = Buffer.concat([buffer, chunk]);
1905
-
1906
- while (true) {
1907
- const separator = buffer.indexOf('\r\n\r\n');
1908
- if (separator < 0) {
1909
- return;
1910
- }
1911
-
1912
- const headerBlock = buffer.slice(0, separator).toString('utf8');
1913
- const contentLengthHeader = headerBlock
1914
- .split('\r\n')
1915
- .find((header) => header.toLowerCase().startsWith('content-length:'));
1916
- if (!contentLengthHeader) {
1917
- return;
1918
- }
1919
-
1920
- const contentLength = Number(contentLengthHeader.split(':')[1]?.trim());
1921
- const frameLength = separator + 4 + contentLength;
1922
- if (buffer.length < frameLength) {
1923
- return;
1924
- }
1925
-
1926
- const payload = JSON.parse(
1927
- buffer.slice(separator + 4, frameLength).toString('utf8'),
1928
- );
1929
- buffer = buffer.slice(frameLength);
1930
-
1931
- if (pending.has(payload.id)) {
1932
- const { resolve, reject } = pending.get(payload.id);
1933
- pending.delete(payload.id);
1934
- if (payload.error) {
1935
- reject(
1936
- new Error(payload.error.message ?? JSON.stringify(payload.error)),
1937
- );
1938
- continue;
1939
- }
1940
- resolve(payload.result);
1941
- }
1942
- }
1943
- });
1944
-
1945
- child.stderr.on('data', (chunk) => {
1946
- stderr += String(chunk);
1947
- });
1948
-
1949
- child.on('error', (error) => {
1950
- exitError = error;
1951
- failPending(error);
1952
- });
1953
-
1954
- child.on('exit', (code, signal) => {
1955
- if (exitError) {
1956
- return;
1957
- }
1958
- exitError = new Error(
1959
- `MCP process exited early with code ${code ?? 'null'}${signal ? ` and signal ${signal}` : ''}.${stderr.trim().length > 0 ? ` ${stderr.trim()}` : ''}`,
1960
- );
1961
- failPending(exitError);
1962
- });
1963
-
1964
- function request(id, method, params = {}) {
1965
- return new Promise((resolve, reject) => {
1966
- if (exitError) {
1967
- reject(exitError);
1968
- return;
1969
- }
1970
- pending.set(id, { resolve, reject });
1971
- child.stdin.write(
1972
- encodeMcpMessage({
1973
- jsonrpc: '2.0',
1974
- id,
1975
- method,
1976
- params,
1977
- }),
1978
- );
1979
- });
1980
- }
1981
-
1982
- function notify(method, params = {}) {
1983
- if (exitError) {
1984
- return;
1985
- }
1986
- child.stdin.write(
1987
- encodeMcpMessage({
1988
- jsonrpc: '2.0',
1989
- method,
1990
- params,
1991
- }),
1992
- );
1993
- }
1994
-
1995
- async function close() {
1996
- if (!exitError) {
1997
- await request('shutdown', 'shutdown');
1998
- notify('exit');
1999
- child.stdin.end();
2000
- }
2001
-
2002
- if (child.exitCode !== null || child.signalCode !== null) {
2003
- return;
2004
- }
2005
-
2006
- await new Promise((resolvePromise) => {
2007
- child.on('exit', () => resolvePromise());
2008
- });
2009
- }
2010
-
2011
- return {
2012
- request,
2013
- notify,
2014
- close,
2015
- readStderr() {
2016
- return stderr.trim();
2017
- },
2018
- };
2019
- }
2020
-
2021
- async function probeMcpServer(params) {
2022
- const client = createInstallMcpClient(params.command, params.args, {
2023
- cwd: params.cwd,
2024
- env: params.env,
2025
- });
2026
-
2027
- let timerId;
2028
- const timeout = new Promise((_, reject) => {
2029
- timerId = setTimeout(() => {
2030
- reject(
2031
- new Error(
2032
- `${params.label} did not complete an MCP handshake within ${INSTALL_VERIFY_TIMEOUT_MS}ms.`,
2033
- ),
2034
- );
2035
- }, INSTALL_VERIFY_TIMEOUT_MS);
2036
- });
2037
-
2038
- try {
2039
- const result = await Promise.race([
2040
- (async () => {
2041
- const initialize = await client.request('init', 'initialize', {
2042
- protocolVersion: MCP_PROTOCOL_VERSION,
2043
- capabilities: {},
2044
- clientInfo: {
2045
- name: 'audit-code-verify-install',
2046
- version: packageVersion,
2047
- },
2048
- });
2049
- client.notify('notifications/initialized');
2050
- const tools = await client.request('tools', 'tools/list');
2051
- const resources = await client.request('resources', 'resources/list');
2052
- await client.close();
2053
- return {
2054
- initialize,
2055
- tools,
2056
- resources,
2057
- stderr: client.readStderr(),
2058
- };
2059
- })(),
2060
- timeout,
2061
- ]);
2062
- clearTimeout(timerId);
2063
- return result;
2064
- } catch (error) {
2065
- clearTimeout(timerId);
2066
- const stderr = client.readStderr();
2067
- try {
2068
- await client.close();
2069
- } catch {
2070
- // already failed or exited
2071
- }
2072
- const suffix = stderr.length > 0 ? ` ${stderr}` : '';
2073
- throw new Error(`${error instanceof Error ? error.message : String(error)}${suffix}`);
2074
- }
2075
- }
2076
-
2077
1293
  async function collectVerifyCheck(target, id, fn) {
2078
1294
  try {
2079
1295
  const details = await fn();
@@ -2241,39 +1457,6 @@ async function verifyInstalledBootstrap(argv) {
2241
1457
  };
2242
1458
  });
2243
1459
 
2244
- await collectVerifyCheck(generalChecks, 'shared_launcher_file', async () => {
2245
- const launcher = await readFile(assetPaths.mcpLauncherPath, 'utf8');
2246
- if (!launcher.includes('Unable to locate an audit-code executable')) {
2247
- throw new Error(`Shared MCP launcher is missing the executable resolution fallback message: ${assetPaths.mcpLauncherPath}`);
2248
- }
2249
- if (!launcher.includes('sourcePackageRoot')) {
2250
- throw new Error(`Shared MCP launcher is missing the package-source fallback hint: ${assetPaths.mcpLauncherPath}`);
2251
- }
2252
- return {
2253
- summary: 'Shared MCP launcher is present and includes resolver fallbacks.',
2254
- path: assetPaths.mcpLauncherPath,
2255
- };
2256
- });
2257
-
2258
- await collectVerifyCheck(generalChecks, 'shared_launcher_mcp', async () => {
2259
- const probe = await probeMcpServer({
2260
- label: 'Shared MCP launcher',
2261
- command: process.execPath,
2262
- args: [assetPaths.mcpLauncherPath],
2263
- cwd: root,
2264
- });
2265
- const toolNames = (probe.tools?.tools ?? []).map((tool) => tool.name);
2266
- if (!toolNames.includes('start_audit')) {
2267
- throw new Error('Shared MCP launcher did not expose the start_audit tool.');
2268
- }
2269
- return {
2270
- summary: 'Shared MCP launcher completed an MCP handshake.',
2271
- server_name: probe.initialize?.serverInfo?.name ?? null,
2272
- tool_count: toolNames.length,
2273
- resource_count: (probe.resources?.resources ?? []).length,
2274
- };
2275
- });
2276
-
2277
1460
  for (const hostKey of selectedHosts) {
2278
1461
  const checks = [];
2279
1462
  const hostEntry = hostCatalog.get(hostKey);
@@ -2468,16 +1651,6 @@ async function detectBootstrapRefreshReason(root, host) {
2468
1651
  }
2469
1652
  }
2470
1653
 
2471
- const launcherPath =
2472
- assetPaths.mcpLauncherPath ?? installManifest.mcp_server_launcher_path;
2473
- const launcher = launcherPath ? await readTextIfExists(launcherPath) : null;
2474
- if (launcher === null) {
2475
- return 'missing_mcp_launcher';
2476
- }
2477
- if (!launcher.includes('Unable to locate an audit-code executable')) {
2478
- return 'stale_mcp_launcher';
2479
- }
2480
-
2481
1654
  return null;
2482
1655
  }
2483
1656
 
@@ -2501,7 +1674,6 @@ async function ensureBootstrap(argv) {
2501
1674
  host: installed.host,
2502
1675
  repo_root: installed.repo_root,
2503
1676
  install_manifest_path: installed.install_manifest_path,
2504
- mcp_server_launcher_path: installed.mcp_server_launcher_path,
2505
1677
  host_count: installed.host_guidance.length,
2506
1678
  file_count: installed.files.length,
2507
1679
  };
@@ -2537,13 +1709,11 @@ function buildInstallAssetPaths(root, profile) {
2537
1709
  const installedSkillPath = join(root, '.audit-code', 'install', 'SKILL.md');
2538
1710
  const installGuidePath = join(root, '.audit-code', 'install', INSTALL_GUIDE_FILENAME);
2539
1711
  const installManifestPath = join(root, '.audit-code', 'install', INSTALL_MANIFEST_FILENAME);
2540
- const mcpLauncherPath = join(root, '.audit-code', 'install', MCP_LAUNCHER_FILENAME);
2541
1712
  return {
2542
1713
  installedPromptPath,
2543
1714
  installedSkillPath,
2544
1715
  installGuidePath,
2545
1716
  installManifestPath,
2546
- mcpLauncherPath,
2547
1717
  agentsInstructionsPath: profile.writeAgents ? join(root, 'AGENTS.md') : null,
2548
1718
  copilotInstructionsPath: profile.writeCopilotInstructions
2549
1719
  ? join(root, '.github', 'copilot-instructions.md')
@@ -2554,24 +1724,9 @@ function buildInstallAssetPaths(root, profile) {
2554
1724
  codexPromptPath: profile.writeCodex
2555
1725
  ? join(root, '.codex', 'skills', 'audit-code', 'audit-code.prompt.md')
2556
1726
  : null,
2557
- codexMcpSetupPath: profile.writeCodex
2558
- ? join(root, '.audit-code', 'install', 'codex', 'MCP-SETUP.md')
2559
- : null,
2560
1727
  codexAutomationRecipePath: profile.writeCodex
2561
1728
  ? join(root, '.audit-code', 'install', 'codex', 'RE-AUDIT-AUTOMATION.md')
2562
1729
  : null,
2563
- claudeDesktopProjectTemplatePath: profile.writeClaudeDesktop
2564
- ? join(root, '.audit-code', 'install', 'claude-desktop', 'PROJECT-TEMPLATE.md')
2565
- : null,
2566
- claudeDesktopRemoteConnectorPath: profile.writeClaudeDesktop
2567
- ? join(root, '.audit-code', 'install', 'claude-desktop', 'remote-mcp-connector.json')
2568
- : null,
2569
- claudeDesktopDxtPath: profile.writeClaudeDesktop
2570
- ? join(root, '.audit-code', 'install', 'claude-desktop', 'auditor-lambda.dxt')
2571
- : null,
2572
- claudeDesktopMcpbPath: profile.writeClaudeDesktop
2573
- ? join(root, '.audit-code', 'install', 'claude-desktop', 'auditor-lambda.mcpb')
2574
- : null,
2575
1730
  opencodeConfigPath: profile.writeOpenCode
2576
1731
  ? join(root, 'opencode.json')
2577
1732
  : null,
@@ -2581,9 +1736,6 @@ function buildInstallAssetPaths(root, profile) {
2581
1736
  vscodeAgentPath: profile.writeVSCode
2582
1737
  ? join(root, '.github', 'agents', 'auditor.agent.md')
2583
1738
  : null,
2584
- vscodeMcpConfigPath: profile.writeVSCode
2585
- ? join(root, '.vscode', 'mcp.json')
2586
- : null,
2587
1739
  antigravityPlanningGuidePath: profile.writeAntigravity
2588
1740
  ? join(root, '.audit-code', 'install', 'antigravity', 'PLANNING-MODE.md')
2589
1741
  : null,
@@ -2596,7 +1748,7 @@ function buildInstallAssetPaths(root, profile) {
2596
1748
  };
2597
1749
  }
2598
1750
 
2599
- // Always-written core assets (installed prompt + skill, shared MCP launcher,
1751
+ // Always-written core assets (installed prompt + skill,
2600
1752
  // AGENTS/copilot compatibility directive blocks) plus legacy-surface cleanup.
2601
1753
  async function writeCoreInstallAssets(root, assetPaths, promptSource, skillSource) {
2602
1754
  const results = [];
@@ -2606,9 +1758,6 @@ async function writeCoreInstallAssets(root, assetPaths, promptSource, skillSourc
2606
1758
  }
2607
1759
  results.push(await writeGeneratedMarkdown(assetPaths.installedPromptPath, promptSource));
2608
1760
  results.push(await writeGeneratedMarkdown(assetPaths.installedSkillPath, skillSource));
2609
- results.push(
2610
- await writeGeneratedMarkdown(assetPaths.mcpLauncherPath, renderSharedMcpLauncher(repoRoot)),
2611
- );
2612
1761
 
2613
1762
  const compatibilityBlockTargets = [
2614
1763
  assetPaths.agentsInstructionsPath,
@@ -2629,37 +1778,14 @@ async function writeCoreInstallAssets(root, assetPaths, promptSource, skillSourc
2629
1778
  return results;
2630
1779
  }
2631
1780
 
2632
- async function writeCodexAssets(assetPaths, promptSource, skillSource, root) {
1781
+ async function writeCodexAssets(assetPaths, promptSource, skillSource) {
2633
1782
  return [
2634
1783
  await writeGeneratedMarkdown(assetPaths.codexSkillPath, skillSource),
2635
1784
  await writeGeneratedMarkdown(assetPaths.codexPromptPath, promptSource),
2636
- await writeGeneratedMarkdown(assetPaths.codexMcpSetupPath, renderCodexMcpSetupGuide(root)),
2637
1785
  await writeGeneratedMarkdown(assetPaths.codexAutomationRecipePath, renderCodexAutomationRecipe()),
2638
1786
  ];
2639
1787
  }
2640
1788
 
2641
- // Builds the Claude Desktop DXT/MCPB bundle (mutating assetPaths with the
2642
- // produced bundle paths) and writes the project template + remote connector.
2643
- async function writeClaudeDesktopAssets(assetPaths, root) {
2644
- const results = [];
2645
- const claudeDesktopBundle = await buildClaudeDesktopBundle(root, results);
2646
- assetPaths.claudeDesktopDxtPath = claudeDesktopBundle.dxtPath;
2647
- assetPaths.claudeDesktopMcpbPath = claudeDesktopBundle.mcpbPath;
2648
- results.push(
2649
- await writeGeneratedMarkdown(
2650
- assetPaths.claudeDesktopProjectTemplatePath,
2651
- renderClaudeDesktopProjectTemplate(),
2652
- ),
2653
- );
2654
- results.push(
2655
- await writeGeneratedJson(
2656
- assetPaths.claudeDesktopRemoteConnectorPath,
2657
- JSON.parse(renderClaudeDesktopRemoteConnectorTemplate()),
2658
- ),
2659
- );
2660
- return results;
2661
- }
2662
-
2663
1789
  async function writeOpenCodeAssets(assetPaths, root) {
2664
1790
  return [
2665
1791
  await writeMergedGeneratedJson(
@@ -2684,11 +1810,6 @@ async function writeVSCodeAssets(assetPaths, promptBody) {
2684
1810
  ),
2685
1811
  ),
2686
1812
  await writeGeneratedMarkdown(assetPaths.vscodeAgentPath, renderVSCodeAgentFile()),
2687
- await writeMergedGeneratedJson(
2688
- assetPaths.vscodeMcpConfigPath,
2689
- 'VS Code MCP config',
2690
- buildMergedVSCodeMcpConfig,
2691
- ),
2692
1813
  ];
2693
1814
  }
2694
1815
 
@@ -2717,17 +1838,13 @@ async function installBootstrap(argv, options = {}) {
2717
1838
  installedSkillPath,
2718
1839
  installGuidePath,
2719
1840
  installManifestPath,
2720
- mcpLauncherPath,
2721
1841
  } = assetPaths;
2722
1842
 
2723
1843
  const results = [];
2724
1844
  results.push(...await writeCoreInstallAssets(root, assetPaths, promptSource, skillSource));
2725
1845
 
2726
1846
  if (profile.writeCodex) {
2727
- results.push(...await writeCodexAssets(assetPaths, promptSource, skillSource, root));
2728
- }
2729
- if (profile.writeClaudeDesktop) {
2730
- results.push(...await writeClaudeDesktopAssets(assetPaths, root));
1847
+ results.push(...await writeCodexAssets(assetPaths, promptSource, skillSource));
2731
1848
  }
2732
1849
  if (profile.writeOpenCode) {
2733
1850
  results.push(...await writeOpenCodeAssets(assetPaths, root));
@@ -2753,7 +1870,6 @@ async function installBootstrap(argv, options = {}) {
2753
1870
  installed_skill_path: installedSkillPath,
2754
1871
  install_guide_path: installGuidePath,
2755
1872
  install_manifest_path: installManifestPath,
2756
- mcp_server_launcher_path: mcpLauncherPath,
2757
1873
  source_prompt_path: resolve(promptAssetPath),
2758
1874
  source_skill_path: resolve(skillAssetPath),
2759
1875
  asset_paths: assetPaths,
@@ -2769,7 +1885,6 @@ async function installBootstrap(argv, options = {}) {
2769
1885
  installedPromptPath,
2770
1886
  installedSkillPath,
2771
1887
  installManifestPath,
2772
- mcpLauncherPath,
2773
1888
  hostGuidance,
2774
1889
  }),
2775
1890
  ),
@@ -2791,7 +1906,6 @@ async function installBootstrap(argv, options = {}) {
2791
1906
  installed_skill_path: installedSkillPath,
2792
1907
  install_guide_path: installGuidePath,
2793
1908
  install_manifest_path: installManifestPath,
2794
- mcp_server_launcher_path: mcpLauncherPath,
2795
1909
  source_prompt_path: resolve(promptAssetPath),
2796
1910
  source_skill_path: resolve(skillAssetPath),
2797
1911
  files: results,
@@ -2805,22 +1919,12 @@ async function installBootstrap(argv, options = {}) {
2805
1919
  agents: assetPaths.agentsInstructionsPath,
2806
1920
  copilot_instructions: assetPaths.copilotInstructionsPath,
2807
1921
  },
2808
- mcp_surfaces: {
2809
- vscode_workspace: assetPaths.vscodeMcpConfigPath,
2810
- opencode_project: assetPaths.opencodeConfigPath,
2811
- codex_setup: assetPaths.codexMcpSetupPath,
2812
- shared_launcher: mcpLauncherPath,
2813
- claude_desktop_dxt: assetPaths.claudeDesktopDxtPath,
2814
- claude_desktop_mcpb: assetPaths.claudeDesktopMcpbPath,
2815
- antigravity_planning_guide: assetPaths.antigravityPlanningGuidePath,
2816
- },
2817
1922
  host_guidance: hostGuidance,
2818
1923
  unsupported_hosts: [],
2819
1924
  next_steps: [
2820
1925
  'Open the repository in your preferred host and follow the matching host_guidance entry.',
2821
- `Open ${installGuidePath} for repo-local quick-start steps for Codex, Claude Desktop, OpenCode, VS Code, and Antigravity.`,
2822
- 'Run `audit-code verify-install` from the repository root to smoke-test the generated launchers and host configs.',
2823
- '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.',
2824
1928
  ],
2825
1929
  };
2826
1930