auditor-lambda 0.9.2 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -9
- package/audit-code-wrapper-lib.mjs +19 -920
- package/dist/cli/args.d.ts +11 -0
- package/dist/cli/args.js +14 -1
- package/dist/cli/auditStep.d.ts +1 -33
- package/dist/cli/dispatch.d.ts +47 -0
- package/dist/cli/dispatch.js +146 -11
- package/dist/cli/mergeAndIngestCommand.js +36 -9
- package/dist/cli/nextStepCommand.js +3 -1
- package/dist/cli/prompts.d.ts +2 -0
- package/dist/cli/prompts.js +11 -0
- package/dist/cli/semanticReviewStep.js +12 -1
- package/dist/cli/steps.d.ts +15 -0
- package/dist/cli.js +1 -8
- package/dist/io/artifacts.d.ts +9 -1
- package/dist/io/artifacts.js +7 -0
- package/dist/io/runArtifacts.d.ts +14 -0
- package/dist/io/runArtifacts.js +23 -0
- package/dist/orchestrator/designReviewPrompt.d.ts +4 -1
- package/dist/orchestrator/designReviewPrompt.js +43 -2
- package/dist/orchestrator/executorResult.d.ts +25 -0
- package/dist/orchestrator/intakeExecutors.d.ts +19 -1
- package/dist/orchestrator/intakeExecutors.js +89 -3
- package/dist/orchestrator/nextStep.d.ts +1 -0
- package/dist/orchestrator/nextStep.js +1 -1
- package/dist/orchestrator/state.js +8 -1
- package/dist/providers/constants.d.ts +1 -1
- package/dist/providers/constants.js +1 -1
- package/dist/quota/index.d.ts +2 -0
- package/dist/quota/index.js +4 -0
- package/dist/reporting/synthesis.d.ts +8 -0
- package/dist/reporting/synthesis.js +16 -1
- package/dist/supervisor/operatorHandoff.js +2 -0
- package/dist/types/auditScope.d.ts +16 -2
- package/dist/validation/sessionConfig.js +35 -0
- package/docs/contracts.md +0 -16
- package/docs/operator-guide.md +6 -8
- package/package.json +1 -1
- package/schemas/audit_findings.schema.json +1 -0
- package/scripts/postinstall.mjs +0 -174
- package/skills/audit-code/SKILL.md +17 -1
- package/skills/audit-code/audit-code.prompt.md +25 -0
- package/dist/mcp/server.d.ts +0 -72
- 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
|
|
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
|
|
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.
|
|
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-
|
|
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
|
|
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
|
|
1059
|
+
setup_kind: 'prompt+agent',
|
|
1629
1060
|
summary:
|
|
1630
|
-
'Use the generated prompt file and custom agent for next-step-first VS Code integration
|
|
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
|
|
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.
|
|
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
|
|
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(
|
|
1719
|
-
throw new Error(`Antigravity guide must reference
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
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
|
|
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,
|
|
2827
|
-
'Run `audit-code verify-install` from the repository root to smoke-test the generated
|
|
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
|
|