@mmerterden/multi-agent-pipeline 16.28.0 → 16.29.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 +75 -2
- package/README.md +4 -4
- package/README.tr.md +3 -3
- package/docs/architecture.md +3 -3
- package/docs/ecosystem.md +5 -5
- package/install/claude.mjs +17 -0
- package/package.json +1 -1
- package/pipeline/commands/multi-agent/analysis-jira/SKILL.md +93 -0
- package/pipeline/commands/multi-agent/doctor/SKILL.md +78 -0
- package/pipeline/commands/multi-agent/help/SKILL.md +2 -0
- package/pipeline/commands/multi-agent/setup/SKILL.md +14 -1
- package/pipeline/commands/multi-agent/sync/SKILL.md +12 -9
- package/pipeline/commands/multi-agent/update/SKILL.md +12 -0
- package/pipeline/lib/_jira-auth.sh +99 -0
- package/pipeline/lib/analysis-jira-write.sh +203 -0
- package/pipeline/lib/issue-fetcher.sh +4 -4
- package/pipeline/multi-agent-refs/analysis/render.md +1 -1
- package/pipeline/multi-agent-refs/cross-cli-contract.md +3 -3
- package/pipeline/multi-agent-refs/features/analysis-jira.md +128 -0
- package/pipeline/multi-agent-refs/features/doctor.md +197 -0
- package/pipeline/multi-agent-refs/features/model-fallback.md +2 -2
- package/pipeline/multi-agent-refs/phases/phase-0-init.md +9 -7
- package/pipeline/multi-agent-refs/picker-contract.md +35 -0
- package/pipeline/multi-agent-refs/tracker-contract.md +5 -1
- package/pipeline/preferences-template.json +1 -1
- package/pipeline/schemas/agent-state.schema.json +5 -0
- package/pipeline/schemas/analysis-spec.schema.json +336 -95
- package/pipeline/schemas/prefs.schema.json +60 -2
- package/pipeline/scripts/analysis-story-tree.mjs +441 -0
- package/pipeline/scripts/doctor.mjs +758 -0
- package/pipeline/scripts/phase-tracker.sh +97 -17
- package/pipeline/scripts/scan-agent-config.sh +48 -10
- package/pipeline/scripts/skill-siblings.mjs +1 -1
- package/pipeline/skills/shared/core/multi-agent-analysis-jira/SKILL.md +94 -0
- package/pipeline/skills/shared/core/multi-agent-doctor/SKILL.md +79 -0
- package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +13 -0
- package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +9 -6
- package/pipeline/skills/shared/core/multi-agent-update/SKILL.md +18 -0
|
@@ -570,10 +570,11 @@ tracker_next_hint() {
|
|
|
570
570
|
[ "${TRACKER_QUIET:-0}" = "1" ] && return 0
|
|
571
571
|
name=$(load_state | jq -r --arg id "$pid" '(.phases[] | select(.id == $id) | .name) // ""')
|
|
572
572
|
case "$(host_kind)" in
|
|
573
|
-
|
|
574
|
-
#
|
|
575
|
-
#
|
|
576
|
-
|
|
573
|
+
claude) mirror="TaskUpdate(\"$(subjects "$pid")\", status=\"$status\") - the subject is re-read from \`phase-tracker.sh subjects $pid\` so the widget carries the model, the elapsed time and the tokens; if TaskUpdate is not one of your tools, paste the card above into your reply VERBATIM in a code block (every phase on its own line, keep the elapsed and token columns; do not redraw or compact it)" ;;
|
|
574
|
+
# Not every session carries the task tools: Claude Code provides them by
|
|
575
|
+
# default only up to Opus 4.7 / Sonnet 4.6, a default that landed in
|
|
576
|
+
# v2.1.268. Naming the fallback on the same line is what keeps a newer model
|
|
577
|
+
# from advancing eight phases in silence.
|
|
577
578
|
codex) mirror="update_plan: set step \"Phase $pid $name\" to $status (send the FULL step list, it is not a delta)" ;;
|
|
578
579
|
*) mirror="no task widget on this host - reprint the card above inside your reply text" ;;
|
|
579
580
|
esac
|
|
@@ -664,6 +665,61 @@ EOF
|
|
|
664
665
|
printf '\n'
|
|
665
666
|
}
|
|
666
667
|
|
|
668
|
+
# The native widget renders one row per task and gives us exactly one string to
|
|
669
|
+
# fill it: the subject. So the numbers a reader wants - which model is spending,
|
|
670
|
+
# how long the phase has run, what it cost - have to travel IN the subject or not
|
|
671
|
+
# at all. `render` already computes all of it for the fallback card; this prints
|
|
672
|
+
# the same values in the one shape the host will accept.
|
|
673
|
+
#
|
|
674
|
+
# Every segment is omitted while it is empty, so a pending phase is just its name
|
|
675
|
+
# and a finished one carries its whole bill. Separator is ` - `, not a middle dot:
|
|
676
|
+
# a subject is a task title and travels through surfaces that are not a terminal.
|
|
677
|
+
subjects() {
|
|
678
|
+
need_jq
|
|
679
|
+
local state want="${1:-}"
|
|
680
|
+
state=$(load_state)
|
|
681
|
+
local prices_json='{"prices":{}}'
|
|
682
|
+
if [ -f "$COST_TABLE" ]; then
|
|
683
|
+
prices_json=$(cat "$COST_TABLE" 2>/dev/null) || prices_json='{"prices":{}}'
|
|
684
|
+
echo "$prices_json" | jq empty 2>/dev/null || prices_json='{"prices":{}}'
|
|
685
|
+
fi
|
|
686
|
+
local now_s; now_s=$(now_epoch)
|
|
687
|
+
local rows
|
|
688
|
+
rows=$(echo "$state" | jq -r --argjson prices "$prices_json" "$COST_JQ_DEFS"'
|
|
689
|
+
def usd_of(p): cost_usd_of($prices.prices[p.model // ""] // null; (p.tokens_in // 0); (p.tokens_out // 0); (p.tokens_cached // 0));
|
|
690
|
+
.phases // []
|
|
691
|
+
| sort_by(.id | (tonumber? // 9999))
|
|
692
|
+
| .[] | [
|
|
693
|
+
(.id // ""), (.name // ""), (.status // ""),
|
|
694
|
+
(.started_at // ""), (.completed_at // ""), (.model // ""),
|
|
695
|
+
(((.tokens_in // 0) + (.tokens_out // 0)) | tostring),
|
|
696
|
+
(usd_of(.) | if . == null then "" else (((. * 100) | floor) / 100 | tostring) end)
|
|
697
|
+
] | join("\u001f")')
|
|
698
|
+
local pid pname pstatus p_start p_end pmodel ptok pusd
|
|
699
|
+
while IFS=$'\x1f' read -r pid pname pstatus p_start p_end pmodel ptok pusd; do
|
|
700
|
+
[ -n "$pid" ] || continue
|
|
701
|
+
[ -z "$want" ] || [ "$want" = "$pid" ] || continue
|
|
702
|
+
local line="Phase $pid $pname"
|
|
703
|
+
[ -n "$pmodel" ] && line="$line - $pmodel"
|
|
704
|
+
local s_ep e_ep el=""
|
|
705
|
+
s_ep=$(iso_to_epoch "$p_start")
|
|
706
|
+
e_ep=$(iso_to_epoch "$p_end")
|
|
707
|
+
if [ -n "$s_ep" ]; then
|
|
708
|
+
case "$pstatus" in
|
|
709
|
+
completed|failed|skipped) [ -n "$e_ep" ] && el=$((e_ep - s_ep)) ;;
|
|
710
|
+
in_progress) el=$((now_s - s_ep)) ;;
|
|
711
|
+
esac
|
|
712
|
+
fi
|
|
713
|
+
if [ -n "$el" ] && [ "$el" -lt 0 ] 2>/dev/null; then el=0; fi
|
|
714
|
+
[ -n "$el" ] && line="$line - $(format_elapsed "$el")"
|
|
715
|
+
if [ "${ptok:-0}" -gt 0 ] 2>/dev/null; then
|
|
716
|
+
line="$line - $(format_tokens "$ptok") tok"
|
|
717
|
+
[ -n "$pusd" ] && line="$line - $(printf '~$%.2f' "$pusd" 2>/dev/null || echo '')"
|
|
718
|
+
fi
|
|
719
|
+
printf '%s\n' "$line"
|
|
720
|
+
done <<< "$rows"
|
|
721
|
+
}
|
|
722
|
+
|
|
667
723
|
render() {
|
|
668
724
|
need_jq
|
|
669
725
|
local state
|
|
@@ -1159,6 +1215,10 @@ GATE
|
|
|
1159
1215
|
fi
|
|
1160
1216
|
;;
|
|
1161
1217
|
|
|
1218
|
+
subjects)
|
|
1219
|
+
subjects "${1:-}"
|
|
1220
|
+
;;
|
|
1221
|
+
|
|
1162
1222
|
tiles)
|
|
1163
1223
|
need_jq
|
|
1164
1224
|
tiles_state=$(load_state)
|
|
@@ -1169,22 +1229,42 @@ GATE
|
|
|
1169
1229
|
}
|
|
1170
1230
|
case "$(host_kind)" in
|
|
1171
1231
|
claude)
|
|
1172
|
-
# The
|
|
1173
|
-
#
|
|
1174
|
-
#
|
|
1175
|
-
#
|
|
1176
|
-
#
|
|
1177
|
-
#
|
|
1178
|
-
#
|
|
1232
|
+
# The task tools are not in every session, and the reason is the model,
|
|
1233
|
+
# not the CLI version. Claude Code provides TaskCreate / TaskUpdate by
|
|
1234
|
+
# default only on Claude 3.x, Opus 4 through 4.7, Sonnet 4 through 4.6
|
|
1235
|
+
# and Haiku 4.5; on any newer model it leaves them out unless the user
|
|
1236
|
+
# opts in, and that default landed in v2.1.268. This contract was written
|
|
1237
|
+
# when the tools were universal and stayed true for years, so nothing
|
|
1238
|
+
# noticed: the tracker state was written correctly, every phase advanced,
|
|
1239
|
+
# and the screen stayed empty for a whole run.
|
|
1240
|
+
#
|
|
1241
|
+
# A shell script cannot probe the model's tool list, so the branch is
|
|
1242
|
+
# taken where the information actually lives - the model knows which
|
|
1243
|
+
# tools it has. And the fallback is not enough on its own: a user looking
|
|
1244
|
+
# at a missing widget needs the one command that brings it back, which is
|
|
1245
|
+
# why the opt-in is printed next to it.
|
|
1179
1246
|
echo "REQUIRED - create one native tile per phase, in this exact order,"
|
|
1180
1247
|
echo "BEFORE any TaskUpdate. The widget renders by creation order, not by"
|
|
1181
1248
|
echo "phase number, so an out-of-order call scrambles the stack."
|
|
1182
|
-
|
|
1249
|
+
subjects | sed 's/^/ TaskCreate(subject: "/; s/$/")/'
|
|
1250
|
+
echo
|
|
1251
|
+
echo "At every phase boundary re-run \`phase-tracker.sh subjects <id>\` and"
|
|
1252
|
+
echo "pass that line as the subject of the TaskUpdate. The subject is the only"
|
|
1253
|
+
echo "string the native widget renders, so the model, the elapsed time and the"
|
|
1254
|
+
echo "token count reach the user through it or not at all."
|
|
1183
1255
|
echo
|
|
1184
|
-
echo "IF TaskCreate IS NOT ONE OF YOUR TOOLS this
|
|
1185
|
-
echo "
|
|
1186
|
-
echo "
|
|
1187
|
-
echo "
|
|
1256
|
+
echo "IF TaskCreate IS NOT ONE OF YOUR TOOLS this session's model does not"
|
|
1257
|
+
echo "carry them (default since v2.1.268 on models newer than Opus 4.7 /"
|
|
1258
|
+
echo "Sonnet 4.6). Then the card below IS the widget, and at every phase"
|
|
1259
|
+
echo "boundary you run \`phase-tracker.sh render\` and paste its output"
|
|
1260
|
+
echo "into your reply VERBATIM, inside a code block - every phase on"
|
|
1261
|
+
echo "its own line, with the elapsed time, the token count and the total"
|
|
1262
|
+
echo "row exactly as printed. Do NOT redraw it, do not compact phases"
|
|
1263
|
+
echo "onto one line, do not drop the columns: those numbers are the"
|
|
1264
|
+
echo "whole reason the card is worth showing. Tool output is collapsed,"
|
|
1265
|
+
echo "so a card left in stdout never reaches the user."
|
|
1266
|
+
echo "Say once, in outputLanguage, that the native widget returns with:"
|
|
1267
|
+
echo " CLAUDE_CODE_ENABLE_TODO_TOOLS=1 claude"
|
|
1188
1268
|
echo
|
|
1189
1269
|
render
|
|
1190
1270
|
;;
|
|
@@ -1212,7 +1292,7 @@ GATE
|
|
|
1212
1292
|
;;
|
|
1213
1293
|
|
|
1214
1294
|
*)
|
|
1215
|
-
echo "phase-tracker: unknown action '$ACTION' (use init|add|update|sub|tokens|model|meta|now|cost|render)" >&2
|
|
1295
|
+
echo "phase-tracker: unknown action '$ACTION' (use init|add|update|sub|tokens|model|meta|now|cost|render|subjects)" >&2
|
|
1216
1296
|
exit 64
|
|
1217
1297
|
;;
|
|
1218
1298
|
esac
|
|
@@ -18,7 +18,24 @@ set -uo pipefail
|
|
|
18
18
|
|
|
19
19
|
# ROOT defaults to the repo root; SCAN_ROOT overrides it (used by the smoke test
|
|
20
20
|
# to point at a fixture tree of planted-bad configs).
|
|
21
|
-
|
|
21
|
+
#
|
|
22
|
+
# Two layouts, and this script ships into the second one. From the checkout, $0
|
|
23
|
+
# is <repo>/pipeline/scripts/... and `../..` is the repo. From an install it is
|
|
24
|
+
# ~/.claude/scripts/... and `../..` is the HOME directory, where none of the
|
|
25
|
+
# shipped config paths exist - the scan then found zero files and called itself
|
|
26
|
+
# clean. Same defect class as the one skill-siblings.mjs carried, so it gets the
|
|
27
|
+
# same two-candidate resolution: try the repo layout, fall back to the install.
|
|
28
|
+
if [ -n "${SCAN_ROOT:-}" ]; then
|
|
29
|
+
ROOT="$SCAN_ROOT"
|
|
30
|
+
else
|
|
31
|
+
_here="$(cd "$(dirname "$0")" && pwd)"
|
|
32
|
+
_repo="$(cd "$_here/../.." && pwd)"
|
|
33
|
+
if [ -d "$_repo/pipeline/agents" ]; then
|
|
34
|
+
ROOT="$_repo"
|
|
35
|
+
else
|
|
36
|
+
ROOT="$HOME/.claude"
|
|
37
|
+
fi
|
|
38
|
+
fi
|
|
22
39
|
|
|
23
40
|
HIGH=0; MED=0
|
|
24
41
|
high() { HIGH=$((HIGH+1)); echo " [HIGH] $1"; }
|
|
@@ -27,18 +44,39 @@ med() { MED=$((MED+1)); echo " [MEDIUM] $1"; }
|
|
|
27
44
|
# Shipped config surface (globs expanded safely; missing paths are skipped).
|
|
28
45
|
TARGETS=()
|
|
29
46
|
add() { [ -e "$1" ] && TARGETS+=("$1"); }
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
47
|
+
# The same surface under either layout: `pipeline/`-prefixed in the checkout,
|
|
48
|
+
# flat under ~/.claude once installed.
|
|
49
|
+
if [ -d "$ROOT/pipeline/agents" ]; then
|
|
50
|
+
add "$ROOT/install/templates/claude-hooks.json"
|
|
51
|
+
add "$ROOT/install/templates/copilot-instructions.md"
|
|
52
|
+
add "$ROOT/pipeline/preferences-template.json"
|
|
53
|
+
for f in "$ROOT"/pipeline/agents/*.md; do add "$f"; done
|
|
54
|
+
# (figma component skills + their scripts now live in the ai-*-toolkit
|
|
55
|
+
# marketplace plugin, not in this repo, so there is nothing figma to scan here.)
|
|
56
|
+
add "$ROOT/pipeline/scripts/agent-guard.sh"
|
|
57
|
+
add "$ROOT/pipeline/scripts/pre-commit-check.sh"
|
|
58
|
+
else
|
|
59
|
+
# settings.json is deliberately NOT in this list. It is the USER's file, not
|
|
60
|
+
# something the pipeline ships, and their own permission choices are theirs to
|
|
61
|
+
# make - scanning it turned a personal setting into a release blocker.
|
|
62
|
+
for f in "$ROOT"/templates/*; do add "$f"; done
|
|
63
|
+
for f in "$ROOT"/agents/*.md; do add "$f"; done
|
|
64
|
+
add "$ROOT/scripts/agent-guard.sh"
|
|
65
|
+
add "$ROOT/scripts/pre-commit-check.sh"
|
|
66
|
+
fi
|
|
38
67
|
|
|
39
68
|
rel() { echo "${1#$ROOT/}"; }
|
|
40
69
|
|
|
41
|
-
echo "→ scanning ${#TARGETS[@]} shipped config files"
|
|
70
|
+
echo "→ scanning ${#TARGETS[@]} shipped config files (root: $ROOT)"
|
|
71
|
+
|
|
72
|
+
# Zero targets is a resolution failure, not a clean bill: `"${TARGETS[@]}"` on an
|
|
73
|
+
# empty array is also an unbound-variable error under bash 3.2 with `set -u`, so
|
|
74
|
+
# the script died here instead of saying what went wrong.
|
|
75
|
+
if [ "${#TARGETS[@]}" -eq 0 ]; then
|
|
76
|
+
echo " [HIGH] no shipped config file found under $ROOT - nothing was scanned"
|
|
77
|
+
echo "→ config hygiene: 1 HIGH, 0 MEDIUM"
|
|
78
|
+
exit 1
|
|
79
|
+
fi
|
|
42
80
|
|
|
43
81
|
for f in "${TARGETS[@]}"; do
|
|
44
82
|
[ -f "$f" ] || continue
|
|
@@ -60,7 +60,7 @@ const CMD_DIR = IN_REPO ? REPO_CMD_DIR : join(HOME, ".claude", "commands", "mult
|
|
|
60
60
|
const CORE_DIR = join(REPO_ROOT, "pipeline", "skills", "shared", "core");
|
|
61
61
|
const COPILOT_DIR = join(HOME, ".copilot", "skills");
|
|
62
62
|
const CODEX_DIR = join(HOME, ".codex", "multi-agent-refs", "commands");
|
|
63
|
-
// The dispatcher is the one skill Codex installs as a SKILL: the
|
|
63
|
+
// The dispatcher is the one skill Codex installs as a SKILL: the sub-commands
|
|
64
64
|
// become refs there, because Codex truncates a large skills block. Resolving it
|
|
65
65
|
// under the refs tree like the others reported a false "absent" - and a sibling
|
|
66
66
|
// check that invents a missing copy is worse than none, since it sends the next
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: multi-agent-analysis-jira
|
|
3
|
+
language: en
|
|
4
|
+
description: "Turn a rendered analysis document into a Jira story tree: derive stories from the document's own rule ids, check coverage both ways, preview every byte, then create only what does not already exist. Use when an analysis is final and the work needs tickets."
|
|
5
|
+
user-invocable: true
|
|
6
|
+
argument-hint: "[analysis.md] [--project KEY] - optional; with no argument, pick from the documents this run emitted"
|
|
7
|
+
not-for: create-jira, jira
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# multi-agent analysis-jira
|
|
11
|
+
|
|
12
|
+
**Input**: $ARGUMENTS
|
|
13
|
+
|
|
14
|
+
Reads an analysis document as a work breakdown and creates the tree. It never
|
|
15
|
+
invents a story: every node comes from an id the document defines.
|
|
16
|
+
|
|
17
|
+
Contract, severities and reasoning:
|
|
18
|
+
`$HOME/.claude/multi-agent-refs/features/analysis-jira.md`.
|
|
19
|
+
|
|
20
|
+
## Phase 1 - Plan, offline
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
node "$HOME/.claude/scripts/analysis-story-tree.mjs" "<analysis.md>" --json > /tmp/ma-plan.json
|
|
24
|
+
node "$HOME/.claude/scripts/analysis-story-tree.mjs" "<analysis.md>"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Exit 4 means the document still carries an open placeholder. Stop and report it:
|
|
28
|
+
the step is `/multi-agent:analysis-resolve`, and a tree built from an open
|
|
29
|
+
question publishes the gap as work somebody is now assigned.
|
|
30
|
+
|
|
31
|
+
Exit 2 means nothing could be derived. Say so; do not improvise a tree.
|
|
32
|
+
|
|
33
|
+
## Phase 2 - Preview, in full
|
|
34
|
+
|
|
35
|
+
Show the human-readable output verbatim, in `outputLanguage`. It already carries
|
|
36
|
+
what makes a preview meaningful:
|
|
37
|
+
|
|
38
|
+
- every node, its source ids and its identity label
|
|
39
|
+
- the coverage verdict **on its own line**
|
|
40
|
+
- every field beside the pref key it came from, so a wrong setting shows here
|
|
41
|
+
rather than in Jira afterwards
|
|
42
|
+
- the write count
|
|
43
|
+
|
|
44
|
+
Then the dry run, which is what proves the writer agrees with the plan:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
bash "$HOME/.claude/lib/analysis-jira-write.sh" \
|
|
48
|
+
--plan /tmp/ma-plan.json --project "<KEY>" --dry-run
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Phase 3 - Approve
|
|
52
|
+
|
|
53
|
+
One `AskUserQuestion`. When the verdict is `ok` or `incomplete`:
|
|
54
|
+
|
|
55
|
+
- **Create the tree** - proceed
|
|
56
|
+
- **Show a node in full** - print one node's body, ask again
|
|
57
|
+
- **Cancel** - stop, write nothing
|
|
58
|
+
|
|
59
|
+
When the verdict is `unverifiable`, the approve option is **replaced**, never
|
|
60
|
+
reworded:
|
|
61
|
+
|
|
62
|
+
- **Create it, unverified** - the tree will be written and recorded as unchecked
|
|
63
|
+
- **Show a node in full**
|
|
64
|
+
- **Cancel**
|
|
65
|
+
|
|
66
|
+
A run that could not be checked is allowed. One that looks checked when it was
|
|
67
|
+
not is the defect, so the approval has to name it and a plain "Approve" must not
|
|
68
|
+
be reachable.
|
|
69
|
+
|
|
70
|
+
`incomplete` prints its uncovered and invented ids before the question. An
|
|
71
|
+
invented id means the plan cites something the document does not define - treat
|
|
72
|
+
that as a defect in the plan, not a warning to click past.
|
|
73
|
+
|
|
74
|
+
## Phase 4 - Write
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
bash "$HOME/.claude/lib/analysis-jira-write.sh" \
|
|
78
|
+
--plan /tmp/ma-plan.json --project "<KEY>"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
It searches by label first and skips what exists. Re-running is safe and is the
|
|
82
|
+
intended recovery from any failure: the ledger makes a half-written tree
|
|
83
|
+
findable rather than duplicable.
|
|
84
|
+
|
|
85
|
+
**Never pass `--force`-like flags, and never update an existing node.** Jira has
|
|
86
|
+
no backup path for fields other than description.
|
|
87
|
+
|
|
88
|
+
## Phase 5 - Report
|
|
89
|
+
|
|
90
|
+
Keys created, keys skipped, the coverage verdict, and the ledger path. If the
|
|
91
|
+
verdict was `unverifiable`, say that in the report too - not only at approval
|
|
92
|
+
time, because the report is what gets pasted elsewhere.
|
|
93
|
+
|
|
94
|
+
**Stop. No worktree, no branch, no dev chain.**
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: multi-agent-doctor
|
|
3
|
+
language: en
|
|
4
|
+
description: "Health check for the installed pipeline: layout, preferences, credentials, hooks and host capabilities, each with one actionable step. Exit code is the verdict. Use when a run failed for an environmental reason, before a sync, or after an update."
|
|
5
|
+
user-invocable: true
|
|
6
|
+
argument-hint: "[--probe] [--explain] [--json] [--list-checks] - optional; --probe also makes one network request per configured service"
|
|
7
|
+
not-for: scan, setup
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# multi-agent doctor
|
|
11
|
+
|
|
12
|
+
**Input**: $ARGUMENTS
|
|
13
|
+
|
|
14
|
+
Answers one question about this machine: **would a run work here, and if not,
|
|
15
|
+
what is the single next step?**
|
|
16
|
+
|
|
17
|
+
Every failure it reports has already reached a user, and each one arrived the
|
|
18
|
+
same way - late, mid-run, after the pickers had been answered. A missing script
|
|
19
|
+
fails at the call. Malformed preferences fail after Phase 0 has asked five
|
|
20
|
+
questions. A token in a remote URL does not fail at all; it leaks.
|
|
21
|
+
|
|
22
|
+
## Run it
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
node "$HOME/.claude/scripts/doctor.mjs" $ARGUMENTS
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Then report the output in `outputLanguage`. Do not re-word the steps: each line
|
|
29
|
+
already carries one imperative step, and paraphrasing is how a step turns into
|
|
30
|
+
advice.
|
|
31
|
+
|
|
32
|
+
**Answer the one check a script cannot.** `task-tools` asks whether THIS session
|
|
33
|
+
carries `TaskCreate` / `TaskUpdate`, and only the agent can see its own tool
|
|
34
|
+
list. Pass what you know:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
node "$HOME/.claude/scripts/doctor.mjs" --task-tools=yes # they are in your tools
|
|
38
|
+
node "$HOME/.claude/scripts/doctor.mjs" --task-tools=no # they are not
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Without the flag that check prints `SKIP`, which is correct - reporting "absent"
|
|
42
|
+
from a script that never looked is the defect this check is about.
|
|
43
|
+
|
|
44
|
+
## The exit code is the product
|
|
45
|
+
|
|
46
|
+
| Code | Meaning |
|
|
47
|
+
|---|---|
|
|
48
|
+
| 0 | healthy |
|
|
49
|
+
| 1 | degraded - at least one WARN |
|
|
50
|
+
| 2 | blocked - a run will fail or leak |
|
|
51
|
+
| 3 | usage error |
|
|
52
|
+
| 4 | indeterminate - the layout did not resolve, so nothing was checked |
|
|
53
|
+
|
|
54
|
+
4 matters as much as 2. Without it, "I could not look" borrows the code for
|
|
55
|
+
"I looked and it is fine".
|
|
56
|
+
|
|
57
|
+
## What it does not do
|
|
58
|
+
|
|
59
|
+
It recommends; it never fixes. It does not rewrite a remote URL, edit
|
|
60
|
+
`settings.json`, or touch a credential. A remote carrying a token may be the only
|
|
61
|
+
credential that repo has, the remote may be a mirror a script depends on
|
|
62
|
+
verbatim, and this can run inside a checkout the user does not own.
|
|
63
|
+
|
|
64
|
+
For an embedded credential the honest step is **not** "hide it". A token that
|
|
65
|
+
reached `.git/config` is already burned - it is in the shell history and readable
|
|
66
|
+
by anything that can read the working tree. The step is to revoke it at its host.
|
|
67
|
+
|
|
68
|
+
## Flags
|
|
69
|
+
|
|
70
|
+
| Flag | Effect |
|
|
71
|
+
|---|---|
|
|
72
|
+
| `--probe` | also make one authenticated request per configured service, and start the MCP server to count its tools. Off by default: a network check is the user's decision to spend. |
|
|
73
|
+
| `--explain` | print the detail behind a finding (which scripts, which repos) |
|
|
74
|
+
| `--json` | the same verdict in machine form, same exit code |
|
|
75
|
+
| `--list-checks` | the check ids, one per line |
|
|
76
|
+
| `--task-tools=yes\|no` | answer the check only the caller can see |
|
|
77
|
+
|
|
78
|
+
Every check, its severity and its reasoning:
|
|
79
|
+
`$HOME/.claude/multi-agent-refs/features/doctor.md`.
|
|
@@ -5,6 +5,19 @@ description: "First-run setup wizard: keychain token discovery, Git Identity onb
|
|
|
5
5
|
user-invocable: true
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
+
## Step 0 - What is actually wrong
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
node "$HOME/.claude/scripts/doctor.mjs"
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Run it before the first question and again at the end. The first run turns setup
|
|
15
|
+
from a fixed script into a targeted one: there is no point asking for a token
|
|
16
|
+
that is already mapped and answering. The second run is the only honest way to
|
|
17
|
+
end - "setup complete" is a claim, and the doctor's exit code is the evidence for
|
|
18
|
+
or against it. Report both in `outputLanguage`, and if the second run still shows
|
|
19
|
+
a BLOCK, say so plainly rather than closing on the word "complete".
|
|
20
|
+
|
|
8
21
|
## Setup (Keychain Token + Git Identity Onboarding)
|
|
9
22
|
|
|
10
23
|
Self-contained setup - works with inline `security` commands, no external script **required**. If `$HOME/.claude/scripts/keychain-save.sh` exists, it can be used as an interactive alternative but is not mandatory. The `setup` command starts interactive onboarding.
|
|
@@ -30,9 +30,10 @@ When invoked, it synchronizes all targets in order. It detects what changed, upd
|
|
|
30
30
|
Run all steps automatically:
|
|
31
31
|
|
|
32
32
|
```
|
|
33
|
+
Step 0: DOCTOR node $HOME/.claude/scripts/doctor.mjs - exit 2 or 4 STOPS the sync
|
|
33
34
|
Step 1: DETECT Compare timestamps, find stale targets
|
|
34
|
-
Step 2: COPILOT Claude Code -> Copilot CLI (instructions +
|
|
35
|
-
Step 2b: CODEX Claude Code -> Codex CLI (1 router skill +
|
|
35
|
+
Step 2: COPILOT Claude Code -> Copilot CLI (instructions + 53 sub-command skills)
|
|
36
|
+
Step 2b: CODEX Claude Code -> Codex CLI (1 router skill + 53 specs as refs + 8 agent TOML)
|
|
36
37
|
Step 3: REPO Claude Code -> pipeline repo (genericized, personal data scrub)
|
|
37
38
|
Step 3d: DEV-TOOLKIT Companion MCP server -> detect movement, ship gates, commit + publish
|
|
38
39
|
Step 4: WEBSITE Version + phase/model counts -> {website-host} (i18n + projects.ts)
|
|
@@ -40,6 +41,8 @@ Step 5: Commit Commit + push all changed repos
|
|
|
40
41
|
Step 6: Report Summary: synced targets, changed files, deploy status, multi-agent-toolkit version
|
|
41
42
|
```
|
|
42
43
|
|
|
44
|
+
**Step 0 is a gate, not a report.** Syncing a blocked install copies one fault onto five surfaces, and the copies are what people then debug. Exit 4 stops too: the layout did not resolve, so nothing was checked, and syncing from an unknown state is worse than not syncing.
|
|
45
|
+
|
|
43
46
|
If nothing is stale -> report "All targets up to date" and stop.
|
|
44
47
|
|
|
45
48
|
## Special inputs
|
|
@@ -98,7 +101,7 @@ If nothing is stale -> report "All targets up to date" and stop.
|
|
|
98
101
|
## Codex Sync (Step 2b)
|
|
99
102
|
|
|
100
103
|
This step does **not** hand-copy files. The Codex tree is a *transform* of the Claude
|
|
101
|
-
tree, not a mirror: the
|
|
104
|
+
tree, not a mirror: the 53 sub-command specs become reference files (Codex silently
|
|
102
105
|
truncates its skills block - see `cross-cli-contract.md` 2.6), every reference to a
|
|
103
106
|
CLI-owned tree is retargeted (`agents/<persona>.md` becomes `.toml`, the dispatcher
|
|
104
107
|
becomes the router skill), the 8 personas are regenerated as TOML with a model +
|
|
@@ -224,11 +227,11 @@ When invoked with the `release` argument:
|
|
|
224
227
|
|-------------|-------------|
|
|
225
228
|
| `~/.claude/commands/multi-agent/{cmd}/SKILL.md` | `~/.copilot/skills/multi-agent-{cmd}/SKILL.md` |
|
|
226
229
|
|
|
227
|
-
**
|
|
230
|
+
**53 commands are synced** (canonical inventory - must match `cross-cli-contract.md` section 1; drift = contract violation):
|
|
228
231
|
|
|
229
232
|
```
|
|
230
|
-
analysis, analysis-resolve, autopilot, build-optimize, channels,
|
|
231
|
-
complaint-analysis, create-jira, design-check, diff-explain, feedback,
|
|
233
|
+
analysis, analysis-jira, analysis-resolve, autopilot, build-optimize, channels,
|
|
234
|
+
complaint-analysis, create-jira, design-check, doctor, diff-explain, feedback,
|
|
232
235
|
forget, garbage-collect, graph, help, ios-coding-standard, issue, jira,
|
|
233
236
|
kill, language, local, local-autopilot, log, manual-test, prune-logs,
|
|
234
237
|
prune-prompts, purge, refactor, resume, resume-local, review,
|
|
@@ -6,6 +6,24 @@ user-invocable: true
|
|
|
6
6
|
argument-hint: ""
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## After the install, check it
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
node "$HOME/.claude/scripts/doctor.mjs"
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
An update is the moment the layout changes, so it is the moment a layout check is
|
|
16
|
+
worth most: a script that moved, a host tree that did not get the copy, a version
|
|
17
|
+
stamp that disagrees with the package. Report the result in `outputLanguage`.
|
|
18
|
+
Exit 2 means the update left the install in a state a run will fail from - say
|
|
19
|
+
that, do not report "updated" and stop.
|
|
20
|
+
|
|
21
|
+
# multi-agent update
|
|
22
|
+
|
|
23
|
+
Update the pipeline in one command. The npm registry is the single update channel: the latest published release is downloaded and installed. Existing preferences are preserved; only skill / script / schema files are refreshed.
|
|
24
|
+
|
|
25
|
+
A git clone of the pipeline repo is a maintainer workspace, kept in sync by `/multi-agent:sync` - it is never consulted here. A fix that only exists on `main` reaches users when a release is published, not before.
|
|
26
|
+
|
|
9
27
|
# multi-agent-update - Pipeline Update
|
|
10
28
|
|
|
11
29
|
Update the pipeline with a single command. Preferences are preserved; only skill/script/schema files are refreshed.
|