@mmerterden/multi-agent-pipeline 12.3.0 → 12.5.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.
- package/CHANGELOG.md +71 -0
- package/package.json +1 -1
- package/pipeline/commands/multi-agent/forget/SKILL.md +29 -0
- package/pipeline/commands/multi-agent/help/SKILL.md +18 -0
- package/pipeline/commands/multi-agent/routines/SKILL.md +30 -0
- package/pipeline/commands/multi-agent/save/SKILL.md +46 -0
- package/pipeline/commands/multi-agent/sync/SKILL.md +4 -4
- package/pipeline/lib/extract-conventions.sh +1 -0
- package/pipeline/lib/repo-cache.sh +1 -0
- package/pipeline/lib/shadow-git.sh +8 -0
- package/pipeline/multi-agent-refs/cross-cli-contract.md +4 -3
- package/pipeline/multi-agent-refs/phases/phase-0-init.md +9 -1
- package/pipeline/multi-agent-refs/phases/phase-4-review.md +3 -2
- package/pipeline/multi-agent-refs/phases/phase-5-test.md +10 -0
- package/pipeline/multi-agent-refs/phases.md +2 -0
- package/pipeline/multi-agent-refs/prompt-assembly.md +31 -0
- package/pipeline/schemas/learnings-ledger.schema.json +4 -0
- package/pipeline/schemas/migrations/prefs-2.3.0-to-2.4.0.mjs +32 -0
- package/pipeline/schemas/prefs.schema.json +36 -1
- package/pipeline/schemas/token-budget.json +2 -2
- package/pipeline/schemas/triage-corpus.schema.json +5 -1
- package/pipeline/scripts/eval-mine-corpus.mjs +19 -5
- package/pipeline/scripts/fixtures/install-layout.tsv +7 -7
- package/pipeline/scripts/gc-worktrees.sh +23 -1
- package/pipeline/scripts/learning-curve.mjs +167 -0
- package/pipeline/scripts/learnings-ledger.mjs +9 -2
- package/pipeline/scripts/migrate-prefs.mjs +8 -1
- package/pipeline/scripts/repo-map.mjs +1 -1
- package/pipeline/scripts/routine-registry.mjs +226 -0
- package/pipeline/scripts/smoke-generate-issue.sh +3 -3
- package/pipeline/scripts/smoke-learning-curve.sh +61 -0
- package/pipeline/scripts/smoke-migrate-state.sh +3 -3
- package/pipeline/scripts/smoke-pref-migration.sh +8 -6
- package/pipeline/scripts/smoke-review-readiness.sh +1 -1
- package/pipeline/scripts/smoke-routines.sh +84 -0
- package/pipeline/scripts/triage-memory.mjs +48 -10
- package/pipeline/skills/shared/core/multi-agent-forget/SKILL.md +22 -0
- package/pipeline/skills/shared/core/multi-agent-routines/SKILL.md +20 -0
- package/pipeline/skills/shared/core/multi-agent-save/SKILL.md +27 -0
- package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +4 -4
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# smoke-routines.sh - contract for routine-registry.mjs, the backend of the
|
|
3
|
+
# user-defined routine commands (/multi-agent:save, :routines, :forget).
|
|
4
|
+
|
|
5
|
+
set -uo pipefail
|
|
6
|
+
|
|
7
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
8
|
+
RR="$SCRIPT_DIR/routine-registry.mjs"
|
|
9
|
+
|
|
10
|
+
PASS=0
|
|
11
|
+
FAIL=0
|
|
12
|
+
record_pass() { PASS=$((PASS + 1)); printf ' \342\234\223 %s\n' "$1"; }
|
|
13
|
+
record_fail() { FAIL=$((FAIL + 1)); printf ' \342\234\227 %s\n' "$1"; }
|
|
14
|
+
|
|
15
|
+
printf '\342\206\222 smoke-routines: routine-registry backend contract\n'
|
|
16
|
+
|
|
17
|
+
tmp=$(mktemp -d "${TMPDIR:-/tmp}/routines.XXXXXX")
|
|
18
|
+
trap 'rm -rf "$tmp"' EXIT
|
|
19
|
+
H="$tmp/home"
|
|
20
|
+
mkdir -p "$H/.claude/commands/multi-agent"
|
|
21
|
+
printf '{"global":{}}\n' > "$H/.claude/multi-agent-preferences.json"
|
|
22
|
+
printf 'Run steps 1-6 of the checkin service migration.\n' > "$tmp/body.md"
|
|
23
|
+
|
|
24
|
+
# 1. add -> writes a local-only command dir + registry entry
|
|
25
|
+
node "$RR" add --name checkin-services --description "Checkin servis kontrolu" \
|
|
26
|
+
--source "CLAUDE.md" --body-file "$tmp/body.md" --home "$H" >/dev/null 2>&1
|
|
27
|
+
skill="$H/.claude/commands/multi-agent/checkin-services/SKILL.md"
|
|
28
|
+
if [ -f "$skill" ] && grep -qx "local-only: true" "$skill"; then
|
|
29
|
+
record_pass "add writes a local-only command SKILL.md"
|
|
30
|
+
else
|
|
31
|
+
record_fail "add did not write a local-only routine command"
|
|
32
|
+
fi
|
|
33
|
+
if node "$RR" list --json --home "$H" | grep -q '"name": "checkin-services"'; then
|
|
34
|
+
record_pass "registry records the routine"
|
|
35
|
+
else
|
|
36
|
+
record_fail "registry missing the routine"
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
# 2. add is name-collision safe (same name rejected)
|
|
40
|
+
node "$RR" add --name checkin-services --description x --source y --body-file "$tmp/body.md" --home "$H" >/dev/null 2>&1
|
|
41
|
+
[ "$?" -eq 1 ] && record_pass "duplicate name rejected" || record_fail "duplicate name should reject"
|
|
42
|
+
|
|
43
|
+
# 3. invalid name rejected
|
|
44
|
+
node "$RR" add --name "Bad Name" --description x --source y --body-file "$tmp/body.md" --home "$H" >/dev/null 2>&1
|
|
45
|
+
[ "$?" -eq 1 ] && record_pass "invalid name rejected" || record_fail "invalid name should reject"
|
|
46
|
+
|
|
47
|
+
# 4. shipped-command guard: never remove a non-local-only command
|
|
48
|
+
mkdir -p "$H/.claude/commands/multi-agent/status"
|
|
49
|
+
printf -- '---\ndescription: "shipped"\n---\nbody\n' > "$H/.claude/commands/multi-agent/status/SKILL.md"
|
|
50
|
+
node "$RR" remove --name status --home "$H" >/dev/null 2>&1
|
|
51
|
+
if [ "$?" -eq 1 ] && [ -d "$H/.claude/commands/multi-agent/status" ]; then
|
|
52
|
+
record_pass "refuses to remove a shipped command"
|
|
53
|
+
else
|
|
54
|
+
record_fail "shipped command must be protected"
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
# 5. sync backstop proxy: the generated routine carries local-only:true, which is
|
|
58
|
+
# exactly what sync/SKILL.md greps to keep it out of the public repo.
|
|
59
|
+
if grep -qx "local-only: true" "$skill"; then
|
|
60
|
+
record_pass "routine is sync-excluded (local-only marker present)"
|
|
61
|
+
else
|
|
62
|
+
record_fail "routine missing local-only marker (would leak on sync)"
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
# 6. remove -> deletes dir + registry entry
|
|
66
|
+
node "$RR" remove --name checkin-services --home "$H" >/dev/null 2>&1
|
|
67
|
+
if [ ! -d "$H/.claude/commands/multi-agent/checkin-services" ] \
|
|
68
|
+
&& ! node "$RR" list --json --home "$H" | grep -q "checkin-services"; then
|
|
69
|
+
record_pass "remove deletes dir + registry entry"
|
|
70
|
+
else
|
|
71
|
+
record_fail "remove left dir or registry entry behind"
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
# 7. install preservation proxy: snapshotLocalOnlyWrappers keys on local-only:true.
|
|
75
|
+
# Re-add, then confirm the marker survives a simulated namespace re-read.
|
|
76
|
+
node "$RR" add --name my-routine --description d --source s --body-file "$tmp/body.md" --home "$H" >/dev/null 2>&1
|
|
77
|
+
if grep -qx "local-only: true" "$H/.claude/commands/multi-agent/my-routine/SKILL.md"; then
|
|
78
|
+
record_pass "re-added routine keeps the install-preserving marker"
|
|
79
|
+
else
|
|
80
|
+
record_fail "re-added routine lost its local-only marker"
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
printf '\n\342\225\220\342\225\220 smoke-routines: %d passed, %d failed \342\225\220\342\225\220\n' "$PASS" "$FAIL"
|
|
84
|
+
[ "$FAIL" -eq 0 ]
|
|
@@ -84,6 +84,33 @@ function ensureDir(p) {
|
|
|
84
84
|
mkdirSync(dirname(p), { recursive: true });
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
// Freshness gate (P1): stamp each finding with the git blob SHA of its file at
|
|
88
|
+
// ingest time; on query, if the file's current content hash differs, the hit is
|
|
89
|
+
// flagged stale so a reused finding is verified, not trusted blindly.
|
|
90
|
+
function repoTop() {
|
|
91
|
+
try {
|
|
92
|
+
return execFileSync("git", ["rev-parse", "--show-toplevel"], {
|
|
93
|
+
encoding: "utf8",
|
|
94
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
95
|
+
}).trim() || null;
|
|
96
|
+
} catch {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function fileSha(file, top) {
|
|
102
|
+
if (!file || !top) return null;
|
|
103
|
+
try {
|
|
104
|
+
return execFileSync("git", ["hash-object", "--", file], {
|
|
105
|
+
cwd: top,
|
|
106
|
+
encoding: "utf8",
|
|
107
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
108
|
+
}).trim() || null;
|
|
109
|
+
} catch {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
87
114
|
const STOP = new Set([
|
|
88
115
|
"the","a","an","and","or","but","of","in","on","at","to","for","with","by","is","are",
|
|
89
116
|
"be","been","being","this","that","these","those","it","its","as","not","no","do","does",
|
|
@@ -157,6 +184,7 @@ function ingest() {
|
|
|
157
184
|
catch (e) { die(`cannot parse triage JSON: ${e.message}`, 1); }
|
|
158
185
|
|
|
159
186
|
const ts = new Date().toISOString();
|
|
187
|
+
const top = repoTop();
|
|
160
188
|
const corpus = readCorpus(slug);
|
|
161
189
|
const seen = new Set(corpus.map((r) => `${r.task_id}::${r.classification}::${r.file}::${r.issue}`));
|
|
162
190
|
|
|
@@ -188,6 +216,7 @@ function ingest() {
|
|
|
188
216
|
fix: f.fix || null,
|
|
189
217
|
reason: f._reason || null,
|
|
190
218
|
reviewer: f.reviewer || null,
|
|
219
|
+
file_sha: fileSha(file, top),
|
|
191
220
|
};
|
|
192
221
|
writeRow(slug, row);
|
|
193
222
|
seen.add(key);
|
|
@@ -212,21 +241,30 @@ function query() {
|
|
|
212
241
|
const qTokens = tokenize(issueText);
|
|
213
242
|
const fileRe = fileGlob ? globToRegExp(fileGlob) : null;
|
|
214
243
|
const filtered = fileRe ? corpus.filter((r) => fileRe.test(r.file || "")) : corpus.slice();
|
|
244
|
+
const top = repoTop();
|
|
215
245
|
const ranked = filtered
|
|
216
246
|
.map((r) => ({ row: r, score: score(qTokens, r) }))
|
|
217
247
|
.filter((x) => x.score > 0 || qTokens.size === 0)
|
|
218
248
|
.sort((a, b) => b.score - a.score)
|
|
219
249
|
.slice(0, topN)
|
|
220
|
-
.map(({ row, score }) =>
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
250
|
+
.map(({ row, score }) => {
|
|
251
|
+
// Freshness: null when we cannot compare (no stored sha, or file gone /
|
|
252
|
+
// not in a git repo); true means the file changed since the finding was
|
|
253
|
+
// recorded, so verify before reusing.
|
|
254
|
+
const cur = row.file_sha ? fileSha(row.file, top) : null;
|
|
255
|
+
const stale = row.file_sha && cur ? cur !== row.file_sha : null;
|
|
256
|
+
return {
|
|
257
|
+
taskId: row.task_id,
|
|
258
|
+
classification: row.classification,
|
|
259
|
+
severity: row.severity,
|
|
260
|
+
file: row.file,
|
|
261
|
+
line: row.line,
|
|
262
|
+
issue: row.issue,
|
|
263
|
+
reason: row.reason,
|
|
264
|
+
stale,
|
|
265
|
+
score: Math.round(score * 1000) / 1000,
|
|
266
|
+
};
|
|
267
|
+
});
|
|
230
268
|
process.stdout.write(JSON.stringify({ ok: true, slug, total: filtered.length, hits: ranked }) + "\n");
|
|
231
269
|
process.exit(0);
|
|
232
270
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: multi-agent-forget
|
|
3
|
+
language: en
|
|
4
|
+
description: "Remove a saved /multi-agent routine (created by /multi-agent:save): deletes its local-only command and its registry entry. Asks which one and confirms."
|
|
5
|
+
user-invocable: true
|
|
6
|
+
argument-hint: "[name]"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# multi-agent-forget - Remove a Routine
|
|
10
|
+
|
|
11
|
+
Delete a routine saved via `/multi-agent:save`. Backed by `$HOME/.copilot/scripts/routine-registry.mjs`.
|
|
12
|
+
|
|
13
|
+
## Steps
|
|
14
|
+
|
|
15
|
+
1. Resolve which routine: from `$ARGUMENTS`, else `routine-registry.mjs list --json` + `AskUserQuestion` (in `outputLanguage`). None -> nothing to forget.
|
|
16
|
+
2. Confirm via `AskUserQuestion`: "Remove /multi-agent:<name>?" (Remove / Cancel). Anything but Remove -> stop.
|
|
17
|
+
3. `node "$HOME/.copilot/scripts/routine-registry.mjs" remove --name "<name>"` (backend refuses to remove a shipped command; only a registered `local-only: true` dir).
|
|
18
|
+
4. Report removed; note the autocomplete entry clears on the next session reload.
|
|
19
|
+
|
|
20
|
+
## Notes
|
|
21
|
+
|
|
22
|
+
- Only user-saved routines can be forgotten. See `/multi-agent:routines` for the list.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: multi-agent-routines
|
|
3
|
+
language: en
|
|
4
|
+
description: "List your saved /multi-agent routines (from /multi-agent:save) with what each one does, rendered in outputLanguage."
|
|
5
|
+
user-invocable: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# multi-agent-routines - List Saved Routines
|
|
9
|
+
|
|
10
|
+
Show every routine saved via `/multi-agent:save`. Read-only. Backed by `$HOME/.copilot/scripts/routine-registry.mjs`.
|
|
11
|
+
|
|
12
|
+
## Steps
|
|
13
|
+
|
|
14
|
+
1. `node "$HOME/.copilot/scripts/routine-registry.mjs" list --json`
|
|
15
|
+
2. Render in `outputLanguage`: empty -> say there are none yet and point to `/multi-agent:save`; otherwise a compact table of `/multi-agent:<name>` + description + created date.
|
|
16
|
+
3. Flag any registry entry with no matching command dir (or vice versa) as `needs repair`; never modify anything.
|
|
17
|
+
|
|
18
|
+
## Notes
|
|
19
|
+
|
|
20
|
+
- Add with `/multi-agent:save`, remove with `/multi-agent:forget <name>`. Routines are local-only and never synced.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: multi-agent-save
|
|
3
|
+
language: en
|
|
4
|
+
description: "Save a recurring job as a reusable /multi-agent:<name> command. Reviews the conversation + your CLAUDE.md for candidate routines, you pick one and name it; stored local-only, never synced."
|
|
5
|
+
user-invocable: true
|
|
6
|
+
argument-hint: "[name]"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# multi-agent-save - Save a Routine
|
|
10
|
+
|
|
11
|
+
**Input**: $ARGUMENTS (optional routine name)
|
|
12
|
+
|
|
13
|
+
Turn a recurring procedure into a reusable `/multi-agent:<name>` command. The routine is stored local-only (a `local-only: true` command + a `prefs.global.routines` entry) and is never synced. Backed by `$HOME/.copilot/scripts/routine-registry.mjs`.
|
|
14
|
+
|
|
15
|
+
## Steps
|
|
16
|
+
|
|
17
|
+
1. Distill candidates from what was just done (primary): group the tasks executed this session into coherent, repeatable jobs (suggested name + one-line summary + ordered steps). Then add named end-to-end procedures from `$HOME/.claude/CLAUDE.md`.
|
|
18
|
+
2. `AskUserQuestion` with `multiSelect: true` (in `outputLanguage`): one option per candidate + an always-present `Other` free-text. One selected -> that routine; several selected -> combine into ONE routine (steps concatenated in shown order, single name); `Other` -> user types it. Empty is not consent.
|
|
19
|
+
3. Name the command (from `$ARGUMENTS` or ask); validate `^[a-z0-9][a-z0-9-]*$`, <= 40 chars; the backend rejects collisions.
|
|
20
|
+
4. Write the full procedure body to a temp file (single candidate: embed its steps, reference the CLAUDE.md section by name when that is the source; combined: concatenate the selected candidates' steps in order under numbered phase headings). Do not invent steps.
|
|
21
|
+
5. Save: `node "$HOME/.copilot/scripts/routine-registry.mjs" add --name "<name>" --description "<summary>" --source "<source>" --body-file "/tmp/routine-<name>.md"`.
|
|
22
|
+
6. Report it is available as `/multi-agent:<name>` after a session reload; offer to run it now.
|
|
23
|
+
|
|
24
|
+
## Notes
|
|
25
|
+
|
|
26
|
+
- Never writes under a repo `pipeline/` tree; routines live only under the CLI home.
|
|
27
|
+
- List with `/multi-agent:routines`; remove with `/multi-agent:forget <name>`.
|
|
@@ -29,7 +29,7 @@ Run all steps automatically:
|
|
|
29
29
|
|
|
30
30
|
```
|
|
31
31
|
Step 1: DETECT Compare timestamps, find stale targets
|
|
32
|
-
Step 2: COPILOT Claude Code -> Copilot CLI (instructions +
|
|
32
|
+
Step 2: COPILOT Claude Code -> Copilot CLI (instructions + 41 sub-command skills)
|
|
33
33
|
Step 3: REPO Claude Code -> pipeline repo (genericized, personal data scrub)
|
|
34
34
|
Step 4: WEBSITE Version + phase/model counts -> {website-host} (i18n + projects.ts)
|
|
35
35
|
Step 5: Commit Commit + push all changed repos
|
|
@@ -136,14 +136,14 @@ When invoked with the `release` argument:
|
|
|
136
136
|
|-------------|-------------|
|
|
137
137
|
| `~/.claude/commands/multi-agent/{cmd}.md` | `~/.copilot/skills/multi-agent-{cmd}/SKILL.md` |
|
|
138
138
|
|
|
139
|
-
**
|
|
139
|
+
**41 commands are synced** (canonical inventory - must match `cross-cli-contract.md` section 1; drift = contract violation):
|
|
140
140
|
|
|
141
141
|
```
|
|
142
142
|
analysis, analysis-resolve, autopilot, build-optimize, channels, create-jira, dev,
|
|
143
|
-
dev-autopilot, dev-local, dev-local-autopilot, diff-explain, finish, garbage-collect,
|
|
143
|
+
dev-autopilot, dev-local, dev-local-autopilot, diff-explain, finish, forget, garbage-collect,
|
|
144
144
|
help, issue, jira, kill, language, local,
|
|
145
145
|
local-autopilot, log, manual-test, prune-logs, purge, refactor, resume, review, review-issue, review-jira,
|
|
146
|
-
scan, search, setup, stack, status, sync, test, uninstall, update
|
|
146
|
+
routines, save, scan, search, setup, stack, status, sync, test, uninstall, update
|
|
147
147
|
```
|
|
148
148
|
|
|
149
149
|
**NOT synced**: `refs/*` - Lazy-load references, Claude Code specific
|