@mmerterden/multi-agent-pipeline 20.8.1 → 20.8.2
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/CHANGELOG.md +36 -0
- package/docs/facts.json +3 -3
- package/index.js +1 -0
- package/install/_codex-agents.mjs +1 -1
- package/install/_common.mjs +486 -53
- package/install/_mcp-register.mjs +173 -117
- package/install/claude.mjs +281 -220
- package/install/codex.mjs +7 -7
- package/install/copilot.mjs +13 -11
- package/install/index.mjs +92 -27
- package/install/templates/claude-hooks.json +9 -9
- package/manifest.json +75 -78
- package/package.json +4 -1
- package/pipeline/commands/multi-agent/update/SKILL.md +28 -17
- package/pipeline/lib/confusables.json +79 -33
- package/pipeline/lib/extract-conventions.sh +3 -3
- package/pipeline/lib/json-file-lock.mjs +27 -7
- package/pipeline/lib/normalize-text.mjs +86 -17
- package/pipeline/lib/outbound-gate.mjs +13 -4
- package/pipeline/lib/redact.mjs +87 -14
- package/pipeline/multi-agent-refs/analysis/evidence.md +1 -1
- package/pipeline/multi-agent-refs/analysis/synthesis.md +1 -1
- package/pipeline/multi-agent-refs/component-dispatch.md +1 -1
- package/pipeline/multi-agent-refs/conventions-defaults.md +1 -1
- package/pipeline/multi-agent-refs/features/unattended-security.md +2 -2
- package/pipeline/scripts/agent-guard.py +150 -25
- package/pipeline/scripts/audit-log.sh +3 -4
- package/pipeline/scripts/autopilot-runner.mjs +14 -5
- package/pipeline/scripts/doctor.mjs +8 -2
- package/pipeline/scripts/log-metric.sh +9 -3
- package/pipeline/scripts/migrate-prefs.mjs +18 -4
- package/pipeline/scripts/pre-commit-check.sh +119 -31
- package/pipeline/scripts/scan-agent-config.sh +9 -9
- package/pipeline/scripts/unattended_policy.py +12 -3
- package/pipeline/scripts/uninstall.mjs +88 -1
- package/pipeline/scripts/usage-identity.mjs +1 -1
- package/pipeline/scripts/usage-register.mjs +1 -1
- package/pipeline/skills/.skill-manifest.json +11 -11
- package/pipeline/skills/shared/external/callkit-voip/SKILL.md +6 -3
- package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +43 -0
- package/pipeline/skills/shared/external/core-nfc/SKILL.md +31 -0
- package/pipeline/skills/shared/external/ios-coding-standard/references/rules.yml +2 -2
- package/pipeline/skills/shared/external/ios-module-structure/modules/_TEMPLATE.yml +1 -1
- package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +3 -3
- package/pipeline/skills/shared/external/localization-reuse-map/example-mapping.json +2 -1
- package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +14 -13
- package/pipeline/skills/shared/external/localization-reuse-map/reference/publish-and-snapshot.md +2 -2
- package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +7 -7
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/_shared.py +105 -4
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-artifact.py +20 -5
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-annotations.py +8 -7
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-legacy-labels.py +7 -8
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/publish-confluence.py +20 -7
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-key-shots.py +4 -3
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-overlay.py +8 -7
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-legacy-values.py +15 -8
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +17 -9
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/scan-screen-keys.py +39 -17
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/verify-map.py +28 -7
- package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +5 -4
- package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +3 -2
- package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +2 -2
- package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +1 -1
- package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +4 -4
- package/pipeline/skills/shared/external/permissionkit/SKILL.md +15 -6
- package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +2 -1
- package/pipeline/skills/shared/external/push-notifications/SKILL.md +8 -4
- package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +1 -1
- package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +25 -6
- package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +1 -1
- package/pipeline/skills/shared/external/skill-creator/template.md +1 -1
- package/pipeline/skills/shared/external/vision-framework/SKILL.md +3 -1
- package/pipeline/scripts/gen-ref-toc.mjs +0 -279
- package/pipeline/scripts/make-manifest.mjs +0 -199
- package/pipeline/scripts/scorecard-snapshot.mjs +0 -178
package/install/codex.mjs
CHANGED
|
@@ -241,7 +241,7 @@ function installRouterSkill(pipelineSrc, skillsDir) {
|
|
|
241
241
|
|
|
242
242
|
// ensureRealDir only swaps a --link-era symlink for a real dir; ensureDir
|
|
243
243
|
// creates a missing one. Every owned tree below needs both.
|
|
244
|
-
ensureRealDir(skillsDir);
|
|
244
|
+
skillsDir = ensureRealDir(skillsDir, { userOwned: true });
|
|
245
245
|
ensureDir(skillsDir);
|
|
246
246
|
pruneLegacyCommandSkills(skillsDir);
|
|
247
247
|
|
|
@@ -297,7 +297,7 @@ function installRefs(pipelineSrc, dest) {
|
|
|
297
297
|
const refsSrc = join(pipelineSrc, "multi-agent-refs");
|
|
298
298
|
const commandsSrc = join(pipelineSrc, "commands", "multi-agent");
|
|
299
299
|
|
|
300
|
-
ensureRealDir(dest);
|
|
300
|
+
if (ensureRealDir(dest) === null) return;
|
|
301
301
|
ensureDir(dest);
|
|
302
302
|
wipeDir(dest);
|
|
303
303
|
|
|
@@ -373,7 +373,7 @@ function installPersonas(pipelineSrc, dest) {
|
|
|
373
373
|
* orchestrator - one spec, two entry points.
|
|
374
374
|
*/
|
|
375
375
|
function installPrompt(promptsDir) {
|
|
376
|
-
ensureRealDir(promptsDir);
|
|
376
|
+
promptsDir = ensureRealDir(promptsDir, { userOwned: true });
|
|
377
377
|
ensureDir(promptsDir);
|
|
378
378
|
const body = [
|
|
379
379
|
"Run the multi-agent development pipeline.",
|
|
@@ -409,7 +409,7 @@ function installSkillRefs(pipelineSrc, dest, home, platformFlag) {
|
|
|
409
409
|
const externalSrc = join(pipelineSrc, "skills", "shared", "external");
|
|
410
410
|
const coreSrc = join(pipelineSrc, "skills", "shared", "core");
|
|
411
411
|
|
|
412
|
-
ensureRealDir(dest);
|
|
412
|
+
if (ensureRealDir(dest) === null) return;
|
|
413
413
|
ensureDir(dest);
|
|
414
414
|
wipeDir(dest);
|
|
415
415
|
|
|
@@ -482,7 +482,7 @@ function installScripts(pipelineSrc, dest, useSymlinks) {
|
|
|
482
482
|
const src = join(pipelineSrc, "scripts");
|
|
483
483
|
if (!existsSync(src)) return;
|
|
484
484
|
if (!useSymlinks) {
|
|
485
|
-
ensureRealDir(dest);
|
|
485
|
+
if (ensureRealDir(dest) === null) return;
|
|
486
486
|
ensureDir(dest);
|
|
487
487
|
}
|
|
488
488
|
wipeDir(dest);
|
|
@@ -512,7 +512,7 @@ function installTemplates(pipelineSrc, dest, useSymlinks) {
|
|
|
512
512
|
const src = join(dirname(pipelineSrc), "install", "templates");
|
|
513
513
|
if (!existsSync(src)) return;
|
|
514
514
|
if (!useSymlinks) {
|
|
515
|
-
ensureRealDir(dest);
|
|
515
|
+
if (ensureRealDir(dest) === null) return;
|
|
516
516
|
ensureDir(dest);
|
|
517
517
|
}
|
|
518
518
|
wipeDir(dest);
|
|
@@ -524,7 +524,7 @@ function installTree(name, pipelineSrc, dest, useSymlinks) {
|
|
|
524
524
|
const src = join(pipelineSrc, name);
|
|
525
525
|
if (!existsSync(src)) return;
|
|
526
526
|
if (!useSymlinks) {
|
|
527
|
-
ensureRealDir(dest);
|
|
527
|
+
if (ensureRealDir(dest) === null) return;
|
|
528
528
|
ensureDir(dest);
|
|
529
529
|
}
|
|
530
530
|
wipeDir(dest);
|
package/install/copilot.mjs
CHANGED
|
@@ -225,7 +225,7 @@ function installScripts(pipelineSrc, dest, useSymlinks) {
|
|
|
225
225
|
if (!existsSync(scriptsSrc)) return;
|
|
226
226
|
// Replace a --link-era symlink with a real dir before wiping/copying so the
|
|
227
227
|
// install can never land inside the developer's repo checkout.
|
|
228
|
-
if (!useSymlinks
|
|
228
|
+
if (!useSymlinks && ensureRealDir(dest) === null) return;
|
|
229
229
|
wipeDir(dest);
|
|
230
230
|
copyDir(scriptsSrc, dest, { exclude: DEV_ONLY_SCRIPTS, useSymlinks });
|
|
231
231
|
// Count files actually excluded by walking the tree: DEV_ONLY_SCRIPTS mixes
|
|
@@ -243,11 +243,12 @@ function installAgents(pipelineSrc, dest, useSymlinks) {
|
|
|
243
243
|
// ~/.copilot/agents also holds user-authored agent files. Never wipe the
|
|
244
244
|
// whole dir; remove only the pipeline-shipped agent files (name set derived
|
|
245
245
|
// from the source tree so it cannot go stale), then copy the fresh set in.
|
|
246
|
+
let target = dest;
|
|
246
247
|
if (!useSymlinks) {
|
|
247
|
-
ensureRealDir(dest);
|
|
248
|
-
removePipelineAgentFiles(
|
|
248
|
+
target = ensureRealDir(dest, { userOwned: true });
|
|
249
|
+
removePipelineAgentFiles(target, agentsSrc);
|
|
249
250
|
}
|
|
250
|
-
copyDir(agentsSrc,
|
|
251
|
+
copyDir(agentsSrc, target, { useSymlinks });
|
|
251
252
|
console.log(` -> ${countFiles(agentsSrc)} files copied to ${dest}`);
|
|
252
253
|
}
|
|
253
254
|
|
|
@@ -255,7 +256,7 @@ function installSchemas(pipelineSrc, dest, useSymlinks) {
|
|
|
255
256
|
console.log(" [Copilot CLI] Installing JSON schemas...");
|
|
256
257
|
const schemasSrc = join(pipelineSrc, "schemas");
|
|
257
258
|
if (!existsSync(schemasSrc)) return;
|
|
258
|
-
if (!useSymlinks
|
|
259
|
+
if (!useSymlinks && ensureRealDir(dest) === null) return;
|
|
259
260
|
wipeDir(dest);
|
|
260
261
|
copyDir(schemasSrc, dest, { useSymlinks });
|
|
261
262
|
console.log(` -> ${countFiles(schemasSrc)} files copied to ${dest}`);
|
|
@@ -269,7 +270,7 @@ function installTemplates(pipelineSrc, dest, useSymlinks) {
|
|
|
269
270
|
console.log(" [Copilot CLI] Installing templates...");
|
|
270
271
|
const templatesSrc = join(dirname(pipelineSrc), "install", "templates");
|
|
271
272
|
if (!existsSync(templatesSrc)) return;
|
|
272
|
-
if (!useSymlinks
|
|
273
|
+
if (!useSymlinks && ensureRealDir(dest) === null) return;
|
|
273
274
|
wipeDir(dest);
|
|
274
275
|
copyDir(templatesSrc, dest, { useSymlinks });
|
|
275
276
|
console.log(` -> ${countFiles(templatesSrc)} files copied to ${dest}`);
|
|
@@ -279,7 +280,7 @@ function installLib(pipelineSrc, dest, useSymlinks) {
|
|
|
279
280
|
console.log(" [Copilot CLI] Installing shell libraries...");
|
|
280
281
|
const libSrc = join(pipelineSrc, "lib");
|
|
281
282
|
if (!existsSync(libSrc)) return;
|
|
282
|
-
if (!useSymlinks
|
|
283
|
+
if (!useSymlinks && ensureRealDir(dest) === null) return;
|
|
283
284
|
wipeDir(dest);
|
|
284
285
|
copyDir(libSrc, dest, { useSymlinks });
|
|
285
286
|
console.log(` -> ${countFiles(libSrc)} files copied to ${dest}`);
|
|
@@ -299,7 +300,7 @@ function installRules(pipelineSrc, dest, useSymlinks) {
|
|
|
299
300
|
console.log(" [Copilot CLI] Installing convention rules...");
|
|
300
301
|
const rulesSrc = join(pipelineSrc, "rules");
|
|
301
302
|
if (!existsSync(rulesSrc)) return;
|
|
302
|
-
if (!useSymlinks
|
|
303
|
+
if (!useSymlinks && ensureRealDir(dest) === null) return;
|
|
303
304
|
wipeDir(dest);
|
|
304
305
|
if (useSymlinks) {
|
|
305
306
|
copyDir(rulesSrc, dest, { useSymlinks });
|
|
@@ -318,15 +319,16 @@ function installRules(pipelineSrc, dest, useSymlinks) {
|
|
|
318
319
|
}
|
|
319
320
|
|
|
320
321
|
function installSkills(opts) {
|
|
321
|
-
const { home, pipelineSrc,
|
|
322
|
+
const { home, pipelineSrc, indexOnly, useSymlinks, platformFlag } = opts;
|
|
322
323
|
console.log(" [Copilot CLI] Installing skills...");
|
|
323
324
|
|
|
324
325
|
// The skills root is always a real directory, in --link mode too: the manifest,
|
|
325
326
|
// index and README written below are generated files, and an older --link
|
|
326
327
|
// install pointed the whole root at pipeline/skills/shared/core, so every one
|
|
327
328
|
// of those writes (and the external / plugin symlinks) landed in the checkout.
|
|
328
|
-
// Link mode now links each authored skill dir individually instead.
|
|
329
|
-
|
|
329
|
+
// Link mode now links each authored skill dir individually instead. A
|
|
330
|
+
// symlink elsewhere (the user's own skills repo) is written through.
|
|
331
|
+
const dest = ensureRealDir(opts.dest, { pipelineSrc, userOwned: true });
|
|
330
332
|
|
|
331
333
|
if (indexOnly) {
|
|
332
334
|
try {
|
package/install/index.mjs
CHANGED
|
@@ -12,7 +12,7 @@ import { dirname } from "path";
|
|
|
12
12
|
import { execFileSync } from "node:child_process";
|
|
13
13
|
import { fileURLToPath } from "url";
|
|
14
14
|
|
|
15
|
-
import { readFileSync } from "fs";
|
|
15
|
+
import { existsSync, readFileSync } from "fs";
|
|
16
16
|
import { join } from "path";
|
|
17
17
|
|
|
18
18
|
import { installClaude } from "./claude.mjs";
|
|
@@ -59,6 +59,7 @@ export async function runInstall(argv) {
|
|
|
59
59
|
const KNOWN_FLAGS = [
|
|
60
60
|
...TOOL_FLAGS,
|
|
61
61
|
"--all",
|
|
62
|
+
"--installed",
|
|
62
63
|
"--link",
|
|
63
64
|
"--index-only",
|
|
64
65
|
"--dry-run",
|
|
@@ -82,13 +83,26 @@ export async function runInstall(argv) {
|
|
|
82
83
|
const dryRun = flags.includes("--dry-run");
|
|
83
84
|
setDryRun(dryRun);
|
|
84
85
|
|
|
85
|
-
const
|
|
86
|
+
const installed = flags.includes("--installed") ? installedTargets(HOME) : null;
|
|
87
|
+
const isExplicitlyTargeted =
|
|
88
|
+
flags.some((f) => TOOL_FLAGS.includes(f)) ||
|
|
89
|
+
flags.includes("--all") ||
|
|
90
|
+
Boolean(installed && (installed.claude || installed.copilot || installed.codex));
|
|
91
|
+
if (installed && !isExplicitlyTargeted) {
|
|
92
|
+
console.log(" --installed: no target carries a version stamp yet; installing Claude Code.");
|
|
93
|
+
}
|
|
86
94
|
|
|
87
|
-
const forClaude =
|
|
95
|
+
const forClaude =
|
|
96
|
+
flags.includes("--claude") ||
|
|
97
|
+
flags.includes("--all") ||
|
|
98
|
+
Boolean(installed?.claude) ||
|
|
99
|
+
!isExplicitlyTargeted;
|
|
88
100
|
|
|
89
|
-
const forCopilot =
|
|
101
|
+
const forCopilot =
|
|
102
|
+
flags.includes("--copilot") || flags.includes("--all") || Boolean(installed?.copilot);
|
|
90
103
|
|
|
91
|
-
const forCodex =
|
|
104
|
+
const forCodex =
|
|
105
|
+
flags.includes("--codex") || flags.includes("--all") || Boolean(installed?.codex);
|
|
92
106
|
|
|
93
107
|
const useSymlinks = flags.includes("--link");
|
|
94
108
|
const indexOnly = flags.includes("--index-only");
|
|
@@ -111,9 +125,14 @@ export async function runInstall(argv) {
|
|
|
111
125
|
if (dryRun) console.log(" (dry-run: no files will be written)");
|
|
112
126
|
console.log("");
|
|
113
127
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
128
|
+
try {
|
|
129
|
+
if (forClaude) installClaude(installerCtx);
|
|
130
|
+
if (forCopilot) installCopilot(installerCtx);
|
|
131
|
+
if (forCodex) installCodex(installerCtx);
|
|
132
|
+
} catch (err) {
|
|
133
|
+
reportInstallFailure(err);
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
117
136
|
|
|
118
137
|
// Version marker: update-check.sh falls back to this for npx-only installs
|
|
119
138
|
// that have no pipeline repo clone to read a version from.
|
|
@@ -136,11 +155,53 @@ export async function runInstall(argv) {
|
|
|
136
155
|
}
|
|
137
156
|
|
|
138
157
|
/**
|
|
139
|
-
*
|
|
140
|
-
*
|
|
158
|
+
* One line for a failed install, and a non-zero exit from the caller. The
|
|
159
|
+
* stack trace is for debugging the installer itself, so it prints only with
|
|
160
|
+
* MULTI_AGENT_INSTALL_DEBUG=1.
|
|
141
161
|
*
|
|
142
|
-
* @param {
|
|
162
|
+
* @param {unknown} err
|
|
163
|
+
*/
|
|
164
|
+
function reportInstallFailure(err) {
|
|
165
|
+
const reason =
|
|
166
|
+
err?.code === "INSTALL_INCOMPLETE"
|
|
167
|
+
? err.message
|
|
168
|
+
: `${err?.code ? `${err.code}: ` : ""}${String(err?.message || err).split("\n")[0]}`;
|
|
169
|
+
console.error("");
|
|
170
|
+
console.error(` install incomplete: ${reason}.`);
|
|
171
|
+
console.error(" Fix the cause and re-run the same install command.");
|
|
172
|
+
if (process.env.MULTI_AGENT_INSTALL_DEBUG === "1" && err?.stack) {
|
|
173
|
+
console.error(err.stack);
|
|
174
|
+
if (err.cause?.stack) console.error(err.cause.stack);
|
|
175
|
+
} else {
|
|
176
|
+
console.error(" (MULTI_AGENT_INSTALL_DEBUG=1 prints the stack trace.)");
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/** Version stamp each target's installer writes. */
|
|
181
|
+
export function versionStampPaths(home) {
|
|
182
|
+
return {
|
|
183
|
+
claude: join(home, ".claude", ".pipeline-version"),
|
|
184
|
+
copilot: join(home, ".copilot", ".pipeline-version"),
|
|
185
|
+
codex: join(home, ".codex", ".pipeline-version"),
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* The targets an earlier install laid down, told by their version stamps.
|
|
191
|
+
* `--installed` uses it so an update refreshes what is there and nothing else.
|
|
192
|
+
*
|
|
193
|
+
* @param {string} home
|
|
194
|
+
* @returns {{claude: boolean, copilot: boolean, codex: boolean}}
|
|
143
195
|
*/
|
|
196
|
+
export function installedTargets(home) {
|
|
197
|
+
const stamps = versionStampPaths(home);
|
|
198
|
+
return {
|
|
199
|
+
claude: existsSync(stamps.claude),
|
|
200
|
+
copilot: existsSync(stamps.copilot),
|
|
201
|
+
codex: existsSync(stamps.codex),
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
144
205
|
/**
|
|
145
206
|
* Print the unattended permission profile, then apply it. Printing first is the
|
|
146
207
|
* contract: an installer that widens a permission set has to say what it is
|
|
@@ -196,6 +257,12 @@ function applyUnattended({ home, forClaude, dryRun = false }) {
|
|
|
196
257
|
}
|
|
197
258
|
}
|
|
198
259
|
|
|
260
|
+
/**
|
|
261
|
+
* Stamp the installed package version into each target so the advisory
|
|
262
|
+
* update check works without a repo clone. Failure is non-fatal.
|
|
263
|
+
*
|
|
264
|
+
* @param {{home: string, forClaude: boolean, forCopilot: boolean, forCodex?: boolean}} opts
|
|
265
|
+
*/
|
|
199
266
|
export function writeVersionMarkers({ home, forClaude, forCopilot, forCodex }) {
|
|
200
267
|
let version;
|
|
201
268
|
try {
|
|
@@ -204,10 +271,11 @@ export function writeVersionMarkers({ home, forClaude, forCopilot, forCodex }) {
|
|
|
204
271
|
return;
|
|
205
272
|
}
|
|
206
273
|
if (!version) return;
|
|
274
|
+
const stamps = versionStampPaths(home);
|
|
207
275
|
const targets = [];
|
|
208
|
-
if (forClaude) targets.push(
|
|
209
|
-
if (forCopilot) targets.push(
|
|
210
|
-
if (forCodex) targets.push(
|
|
276
|
+
if (forClaude) targets.push(stamps.claude);
|
|
277
|
+
if (forCopilot) targets.push(stamps.copilot);
|
|
278
|
+
if (forCodex) targets.push(stamps.codex);
|
|
211
279
|
for (const target of targets) {
|
|
212
280
|
try {
|
|
213
281
|
writeFile(target, `${version}\n`);
|
|
@@ -217,12 +285,8 @@ export function writeVersionMarkers({ home, forClaude, forCopilot, forCodex }) {
|
|
|
217
285
|
}
|
|
218
286
|
}
|
|
219
287
|
|
|
220
|
-
/**
|
|
221
|
-
* @param {string[]} flags
|
|
222
|
-
* @returns {"ios"|"android"|"all"}
|
|
223
|
-
*/
|
|
224
288
|
// Presence check only - never a hard requirement. The pipeline's own engine is
|
|
225
|
-
// node; jq is a convenience several shell helpers
|
|
289
|
+
// node; jq is a convenience several shell helpers reach for.
|
|
226
290
|
function hasJq() {
|
|
227
291
|
try {
|
|
228
292
|
execFileSync("jq", ["--version"], { stdio: "ignore", timeout: 3000 });
|
|
@@ -232,6 +296,10 @@ function hasJq() {
|
|
|
232
296
|
}
|
|
233
297
|
}
|
|
234
298
|
|
|
299
|
+
/**
|
|
300
|
+
* @param {string[]} flags
|
|
301
|
+
* @returns {"ios"|"android"|"all"}
|
|
302
|
+
*/
|
|
235
303
|
function parsePlatformFlag(flags) {
|
|
236
304
|
const raw = flags.find((f) => f.startsWith("--platform="));
|
|
237
305
|
if (!raw) return "all";
|
|
@@ -272,9 +340,8 @@ function printSummary(opts) {
|
|
|
272
340
|
console.log("");
|
|
273
341
|
}
|
|
274
342
|
|
|
275
|
-
//
|
|
276
|
-
//
|
|
277
|
-
// hand-registered entry became the only reason it worked on any given machine.
|
|
343
|
+
// Each installer registers the server itself; the lines below name the
|
|
344
|
+
// command it ran, for a host whose CLI was not on PATH.
|
|
278
345
|
console.log(" For UI testing, the multi-agent-toolkit MCP server is registered automatically:");
|
|
279
346
|
if (forClaude) {
|
|
280
347
|
console.log(
|
|
@@ -291,11 +358,9 @@ function printSummary(opts) {
|
|
|
291
358
|
" Skipped only when the host CLI is not on PATH - the command to run is printed above.",
|
|
292
359
|
);
|
|
293
360
|
console.log("");
|
|
294
|
-
// jq is not a declared engine and
|
|
295
|
-
//
|
|
296
|
-
//
|
|
297
|
-
// updates look like bugs, not like an absent tool. Say it once, here, where
|
|
298
|
-
// somebody can act on it.
|
|
361
|
+
// jq is not a declared engine and not every macOS ships it. Several runtime
|
|
362
|
+
// paths skip in silence without it, which reads as a bug rather than an
|
|
363
|
+
// absent tool, so the install says it once, where somebody can act on it.
|
|
299
364
|
if (!hasJq()) {
|
|
300
365
|
console.log(" Note: jq was not found on PATH.");
|
|
301
366
|
console.log(" Everything installs and the pipeline runs, but a few shell");
|
|
@@ -7,13 +7,13 @@
|
|
|
7
7
|
"hooks": [
|
|
8
8
|
{
|
|
9
9
|
"type": "command",
|
|
10
|
-
"command": "bash $HOME/.claude/scripts/pre-commit-check.sh",
|
|
10
|
+
"command": "bash \"$HOME/.claude/scripts/pre-commit-check.sh\"",
|
|
11
11
|
"timeout": 15,
|
|
12
12
|
"statusMessage": "Scanning staged changes for secrets..."
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
15
|
"type": "command",
|
|
16
|
-
"command": "bash $HOME/.claude/scripts/agent-guard.sh",
|
|
16
|
+
"command": "bash \"$HOME/.claude/scripts/agent-guard.sh\"",
|
|
17
17
|
"timeout": 10,
|
|
18
18
|
"statusMessage": "Checking commit/push safety (attribution + force-push)..."
|
|
19
19
|
}
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"hooks": [
|
|
25
25
|
{
|
|
26
26
|
"type": "command",
|
|
27
|
-
"command": "bash $HOME/.claude/scripts/agent-guard.sh",
|
|
27
|
+
"command": "bash \"$HOME/.claude/scripts/agent-guard.sh\"",
|
|
28
28
|
"timeout": 10,
|
|
29
29
|
"statusMessage": "Checking the edit target..."
|
|
30
30
|
}
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"hooks": [
|
|
36
36
|
{
|
|
37
37
|
"type": "command",
|
|
38
|
-
"command": "bash $HOME/.claude/scripts/agent-guard.sh",
|
|
38
|
+
"command": "bash \"$HOME/.claude/scripts/agent-guard.sh\"",
|
|
39
39
|
"timeout": 10,
|
|
40
40
|
"statusMessage": "Checking the fetch host..."
|
|
41
41
|
}
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"hooks": [
|
|
47
47
|
{
|
|
48
48
|
"type": "command",
|
|
49
|
-
"command": "bash $HOME/.claude/scripts/check-read-size.sh",
|
|
49
|
+
"command": "bash \"$HOME/.claude/scripts/check-read-size.sh\"",
|
|
50
50
|
"timeout": 10,
|
|
51
51
|
"statusMessage": "Checking read size..."
|
|
52
52
|
}
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"hooks": [
|
|
59
59
|
{
|
|
60
60
|
"type": "command",
|
|
61
|
-
"command": "bash $HOME/.claude/scripts/capture-flush.sh --quiet",
|
|
61
|
+
"command": "bash \"$HOME/.claude/scripts/capture-flush.sh\" --quiet",
|
|
62
62
|
"timeout": 20,
|
|
63
63
|
"statusMessage": "Persisting what this run learned before compaction..."
|
|
64
64
|
}
|
|
@@ -70,13 +70,13 @@
|
|
|
70
70
|
"hooks": [
|
|
71
71
|
{
|
|
72
72
|
"type": "command",
|
|
73
|
-
"command": "bash $HOME/.claude/scripts/capture-flush.sh --if-stale --quiet",
|
|
73
|
+
"command": "bash \"$HOME/.claude/scripts/capture-flush.sh\" --if-stale --quiet",
|
|
74
74
|
"timeout": 20,
|
|
75
75
|
"statusMessage": "Persisting what this run learned..."
|
|
76
76
|
},
|
|
77
77
|
{
|
|
78
78
|
"type": "command",
|
|
79
|
-
"command": "bash $HOME/.claude/scripts/note-session.sh",
|
|
79
|
+
"command": "bash \"$HOME/.claude/scripts/note-session.sh\"",
|
|
80
80
|
"timeout": 20,
|
|
81
81
|
"statusMessage": "Noting this session..."
|
|
82
82
|
}
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
"hooks": [
|
|
90
90
|
{
|
|
91
91
|
"type": "command",
|
|
92
|
-
"command": "bash $HOME/.claude/scripts/capture-resume.sh",
|
|
92
|
+
"command": "bash \"$HOME/.claude/scripts/capture-resume.sh\"",
|
|
93
93
|
"timeout": 10,
|
|
94
94
|
"statusMessage": "Checking for unfinished runs..."
|
|
95
95
|
}
|