@mmerterden/multi-agent-pipeline 8.6.0 → 8.6.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.
Files changed (36) hide show
  1. package/README.md +30 -49
  2. package/package.json +4 -1
  3. package/pipeline/commands/multi-agent/_account-picker.md +1 -1
  4. package/pipeline/commands/multi-agent/refs/features/dev-critic.md +44 -0
  5. package/pipeline/commands/multi-agent/refs/features/external-context-injection.md +63 -0
  6. package/pipeline/commands/multi-agent/refs/features/plan-todos.md +20 -0
  7. package/pipeline/commands/multi-agent/refs/features/prior-fix-detection.md +49 -0
  8. package/pipeline/commands/multi-agent/refs/features/repo-map.md +30 -0
  9. package/pipeline/commands/multi-agent/refs/features/shadow-git.md +24 -0
  10. package/pipeline/commands/multi-agent/refs/phases/phase-0-init.md +3 -3
  11. package/pipeline/commands/multi-agent/refs/phases/phase-1-analysis.md +4 -121
  12. package/pipeline/commands/multi-agent/refs/phases/phase-3-dev.md +4 -75
  13. package/pipeline/commands/multi-agent/refs/phases/phase-6-commit.md +1 -1
  14. package/pipeline/commands/multi-agent/setup.md +14 -6
  15. package/pipeline/commands/multi-agent/sync.md +26 -25
  16. package/pipeline/schemas/prefs.schema.json +2 -2
  17. package/pipeline/scripts/fixtures/install-layout.tsv +11 -11
  18. package/pipeline/scripts/smoke-issue-comment-template.sh +1 -1
  19. package/pipeline/scripts/smoke-personal-data.sh +5 -3
  20. package/pipeline/scripts/smoke-plan-todos.sh +5 -2
  21. package/pipeline/scripts/smoke-sync-adapters.sh +113 -0
  22. package/pipeline/scripts/smoke-sync-delegation.sh +1 -1
  23. package/pipeline/scripts/smoke-url-enrichment.sh +1 -1
  24. package/pipeline/scripts/sync-adapters.mjs +156 -0
  25. package/pipeline/skills/figma-common/figma-component-confluence-sync/SKILL.md +1 -1
  26. package/pipeline/skills/figma-common/figma-issue/SKILL.md +5 -5
  27. package/pipeline/skills/figma-common/figma-setup/SKILL.md +17 -17
  28. package/pipeline/skills/figma-common/figma-validate/SKILL.md +1 -1
  29. package/pipeline/skills/figma-ios/figma-to-component/SKILL.md +1 -1
  30. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-6-code-connect.md +5 -5
  31. package/pipeline/skills/figma-ios/figma-to-component/reference/code-connect.md +1 -1
  32. package/pipeline/skills/figma-ios/figma-to-component/reference/rest-api-script.md +1 -1
  33. package/pipeline/skills/figma-ios/figma-to-component/reference/tools.md +1 -1
  34. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase1-gather.py +1 -1
  35. package/pipeline/skills/shared/core/multi-agent-issue/SKILL.md +1 -1
  36. package/pipeline/scripts/.last-figma-sync-plan.json +0 -23
package/README.md CHANGED
@@ -18,7 +18,7 @@
18
18
  | Figma skills (iOS + Android + Common) | 37 |
19
19
  | External skill catalog (`shared/external/`) | 127 |
20
20
  | Total `SKILL.md` files across all groups | 196 |
21
- | Smoke suites | 87 |
21
+ | Smoke suites | 88 |
22
22
  | Golden-task fixtures (`pipeline/eval/golden-tasks/`) | 2 |
23
23
  | Eval-triage fixtures | 11 |
24
24
  | JSON schemas | 13 |
@@ -46,38 +46,24 @@ Full version history lives in [CHANGELOG.md](./CHANGELOG.md). Every release entr
46
46
 
47
47
  - Node.js 18+
48
48
  - Claude Code (https://claude.ai/code) **or** GitHub Copilot CLI
49
- - macOS/Linux (Keychain-based token storage is available on macOS)
50
-
51
- This is a **private package** hosted on GitHub Packages. You need:
52
-
53
- 1. **Collaborator access** to `mmerterden/multi-agent-pipeline` (granted by the repo owner).
54
- 2. A **Classic** Personal Access Token (fine-grained PATs are not fully supported for GitHub Packages on private repos).
55
-
56
- ### 1. Create a Classic PAT
57
-
58
- Go to https://github.com/settings/tokens/new?scopes=read:packages,repo and create a token with:
59
-
60
- - ✅ `read:packages`
61
- - ✅ `repo` (required for private package access)
62
-
63
- If your GitHub account belongs to an SSO-enforced organization, after creating the token click **"Configure SSO" → Authorize** on the token row.
64
-
65
- ### 2. Configure `~/.npmrc`
66
-
67
- ```bash
68
- # Replace ghp_xxx with the token from step 1
69
- echo "@mmerterden:registry=https://npm.pkg.github.com" >> ~/.npmrc
70
- echo "//npm.pkg.github.com/:_authToken=ghp_xxx" >> ~/.npmrc
71
- ```
72
-
73
- ### 3. Verify access
49
+ - macOS, Linux, or Windows (Git Bash / WSL). Native credential storage everywhere:
50
+ - **macOS** → Keychain (`security`)
51
+ - **Linux** libsecret (`secret-tool` `apt install libsecret-tools` / `dnf install libsecret`)
52
+ - **Windows** → Credential Manager (PowerShell `CredentialManager` module — `Install-Module CredentialManager`)
53
+ - Runtime CLIs the pipeline shells out to:
54
+ - `gh` (GitHub CLI) for issue / PR flows
55
+ - `jq` for JSON parsing
56
+ - `python3` (stdlib only, used by the deterministic keychain helper)
57
+ - `bash` 4+
58
+
59
+ The package is **public on npmjs.org** — no auth, no PAT, no `~/.npmrc` setup needed:
74
60
 
75
61
  ```bash
76
62
  npm view @mmerterden/multi-agent-pipeline version
77
- # → prints "3.0.0" (or newer) when everything is wired up
63
+ # → prints "8.6.1" (or newer)
78
64
  ```
79
65
 
80
- If this fails, see [Troubleshooting](#troubleshooting) below.
66
+ If `npm view` shows a stale version, run `npm cache clean --force` and retry.
81
67
 
82
68
  > **New here?** Worked end-to-end transcripts live in [`examples/`](./examples/) — bug fix from Jira, feature in autopilot, `--dev` fast path, and recovery from a broken run. Read one before you run the pipeline on your own code.
83
69
  >
@@ -87,9 +73,9 @@ If this fails, see [Troubleshooting](#troubleshooting) below.
87
73
 
88
74
  ## Quick Start
89
75
 
90
- ### Option A — Install from source (recommended, no registry auth)
76
+ ### Option A — Install from source (recommended for development)
91
77
 
92
- The simplest path. Works even if you haven't configured `~/.npmrc` yet.
78
+ Clone the repo and run the installer directly full read access to source files.
93
79
 
94
80
  ```bash
95
81
  git clone git@github.com:mmerterden/multi-agent-pipeline.git
@@ -127,7 +113,7 @@ This discovers your Keychain tokens (Jira, Bitbucket, GitHub, etc.), sets up you
127
113
 
128
114
  Update later with `git pull && npm install` inside the clone. Pin to a specific version by checking out the corresponding tag (`git tag -l` to list).
129
115
 
130
- ### Option B — npx (requires registry setup above)
116
+ ### Option B — npx (public registry, no auth)
131
117
 
132
118
  ```bash
133
119
  npx @mmerterden/multi-agent-pipeline install # Claude Code (default)
@@ -143,7 +129,7 @@ npx @mmerterden/multi-agent-pipeline uninstall # interactive, all targe
143
129
  npx @mmerterden/multi-agent-pipeline uninstall --dry-run # preview only
144
130
  ```
145
131
 
146
- ### Option C — Global install (requires registry setup above)
132
+ ### Option C — Global install (public registry, no auth)
147
133
 
148
134
  ```bash
149
135
  npm install -g @mmerterden/multi-agent-pipeline
@@ -177,32 +163,27 @@ slows down the install.
177
163
 
178
164
  ### `sh: multi-agent-pipeline: command not found`
179
165
 
180
- npx couldn't fetch the package and fell back to running it as a shell command. Registry auth is missing or wrong — re-check steps 1–3 under [Prerequisites](#prerequisites).
166
+ `npx` couldn't fetch the package. Most common causes:
181
167
 
182
- ### `npm error code E401` "User cannot be authenticated with the token provided"
168
+ - Network blocked or proxy in front of npmjs.org.
169
+ - Stale npx cache — `npx clear-npx-cache` then retry.
170
+ - Wrong package name (it is `@mmerterden/multi-agent-pipeline`, with the scope).
183
171
 
184
- Your token is being rejected by GitHub Packages. Usually one of:
185
-
186
- - PAT is fine-grained instead of **Classic**. Recreate as Classic.
187
- - PAT is missing `repo` scope. Private packages require both `read:packages` **and** `repo`.
188
- - SSO not authorized. On the token row, click **"Configure SSO" → Authorize** for the relevant org.
189
- - Token expired or revoked.
172
+ ### `npm error code E404` on `registry.npmjs.org`
190
173
 
191
- Quick diagnostic:
174
+ The package wasn't reachable. Quick checks:
192
175
 
193
176
  ```bash
194
- curl -I -H "Authorization: Bearer $(grep _authToken ~/.npmrc | tail -1 | cut -d= -f2)" \
195
- https://npm.pkg.github.com/@mmerterden%2Fmulti-agent-pipeline
177
+ curl -fsSL "https://registry.npmjs.org/@mmerterden/multi-agent-pipeline" | jq -r '."dist-tags".latest'
178
+ # Should print 8.6.1 (or newer)
196
179
  ```
197
180
 
198
- - `200` auth is fine; likely an npx cache issue (`npx clear-npx-cache`).
199
- - `401` token invalid, expired, or not SSO-authorized.
200
- - `403` — token valid but no repo access. Ask the repo owner to add you as a collaborator.
201
- - `404` — scope misconfigured in `~/.npmrc`, or package name is wrong.
181
+ - If this prints a version your local npm cache is stale; run `npm cache clean --force` and retry.
182
+ - If it 404s registry outage or scope/package-name typo. Verify the URL hits the JSON above.
202
183
 
203
- ### `npm error code E404` on `registry.npmjs.org`
184
+ ### Older PAT / GitHub Packages docs
204
185
 
205
- Your `~/.npmrc` does not have the `@mmerterden:registry=...` line. npm defaulted to public npm, which doesn't host this package. Redo step 2.
186
+ Earlier README revisions referenced GitHub Packages with a Classic PAT and `~/.npmrc` setup. The package moved to **public npmjs.org** in v8.6.1; no token, no `~/.npmrc` line is needed. If you set one up previously, you can leave it it just won't be consulted.
206
187
 
207
188
  ## Tool support
208
189
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmerterden/multi-agent-pipeline",
3
- "version": "8.6.0",
3
+ "version": "8.6.2",
4
4
  "description": "8-phase AI development pipeline. Full orchestration on Claude Code + Copilot CLI; knowledge layer (rules + skills) ports to Cursor, Windsurf, and Cline. Analysis, planning, TDD, CLI-aware parallel review with Opus triage, wiki generation, commit automation. Token-preserving uninstall.",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -46,6 +46,9 @@
46
46
  ],
47
47
  "author": "Mert Erden",
48
48
  "license": "MIT",
49
+ "publishConfig": {
50
+ "registry": "https://npm.pkg.github.com"
51
+ },
49
52
  "repository": {
50
53
  "type": "git",
51
54
  "url": "https://github.com/mmerterden/multi-agent-pipeline.git"
@@ -75,7 +75,7 @@ was used last and surfaces it first on the next autopilot invocation.
75
75
 
76
76
  ```json
77
77
  {
78
- "accountId": "m-erden3",
78
+ "accountId": "my-account",
79
79
  "accountPrefix": "${USER}",
80
80
  "tokens": {
81
81
  "github": "${USER}_Github_Access_Token",
@@ -0,0 +1,44 @@
1
+ # Feature: Dev Critic (Phase 3 Step 3.5 Evaluator-Optimizer)
2
+
3
+ **Pattern**: Anthropic's evaluator-optimizer from "Building Effective Agents" (Dec 2024). Generator (Phase 3 Dev) and critic (`agents/dev-critic.md`) loop on deterministic criteria already written in `rules/*.md` before any Phase 4 reviewer call.
4
+
5
+ **Gated by `prefs.global.devCritic.enabled`** (default: `false`). When enabled, after the generator's last edit and BEFORE Phase 4:
6
+
7
+ 1. Dispatch `dev-critic` sub-agent (Sonnet by default, tools: `Read, Grep, Glob, Bash`).
8
+ 2. Critic runs 4 deterministic gates (build / lint / test / secrets) — failure of any → `pass: false` with `blocking` finding.
9
+ 3. If gates green, critic walks the platform checklist (iOS 13-item / Android Kotlin / Backend generic — selected by Phase 1 `detectedStack`).
10
+ 4. Returns schema-validated JSON (`pipeline/schemas/dev-critic-output.schema.json`): `{pass, iteration, gates, findings[], escalate}`.
11
+
12
+ ## Loop cap (STRICT) — max 2 iterations
13
+
14
+ | Round | Behavior |
15
+ |---|---|
16
+ | 1 | Full critic pass — all gates + full checklist |
17
+ | 2 | Re-check only round-1 failures. No new findings allowed (scope creep prevention) |
18
+ | 3+ | NOT ALLOWED. Critic returns `escalate: true`; orchestrator pauses (interactive) or proceeds to Phase 4 with logged failure (autopilot) |
19
+
20
+ ## Action by severity
21
+
22
+ - `blocking` → generator MUST fix; another Dev iteration before re-critic
23
+ - `important` → generator SHOULD fix; if skipped, pass through to Phase 4 (legitimate reviewer ground)
24
+ - `suggestion` → generator's judgement; never blocks round 2
25
+
26
+ ## Telemetry
27
+
28
+ Each critic call emits `dev_critic.call` with `iteration`, `pass`, `gates_failed`, `blocking`, `important`, `duration_ms`, `tokens_in/out`. Phase 7 cost rollup lists these as `phase 3.5` line items so the net saving (Phase 4 reviewer/triage calls avoided) is measurable.
29
+
30
+ ## Off by default reason
31
+
32
+ Introduces ~1× Sonnet call per Dev iteration. On simple bug fixes the cost outweighs the benefit (Phase 4 would have caught the same thing for similar cost). Recommended on:
33
+
34
+ - Feature work (≥200 LOC diff)
35
+ - Security-touching paths (auth, keychain, network)
36
+ - Multi-file refactors where rule violations compound
37
+
38
+ ## Why this fits orchestrator-workers + evaluator-optimizer hybrid
39
+
40
+ Phase 4 is parallelization-with-voting — good for *adversarial* perspectives (security, architecture). Phase 3.5 is evaluator-optimizer — good for *deterministic* criteria (build, tests, checklists). Sending failing builds into Phase 4 wastes 2–3 reviewer calls + Opus triage; Phase 3.5 absorbs that cost at one Sonnet call.
41
+
42
+ ## Reference
43
+
44
+ See `pipeline/agents/dev-critic.md` for the full agent specification (gates, checklist enumeration, output schema, severity semantics).
@@ -0,0 +1,63 @@
1
+ # Feature: External Context Injection (Phase 1 Step 1.5)
2
+
3
+ Phase 0 Step 1b catalogued every typed external link from the task description into `state.contextLinks[]`. Phase 1 dispatches each entry to its matching fetcher and prepends the result to the analysis prompt under a **Referenced External Sources** section, so the agent doesn't re-discover what the ticket already pointed at.
4
+
5
+ ```bash
6
+ jq -c '.contextLinks // []' "$STATE_FILE" \
7
+ | python3 -c '
8
+ import json, sys, os
9
+ links = json.loads(sys.stdin.read() or "[]")
10
+ by_type = {}
11
+ for l in links:
12
+ by_type.setdefault(l["type"], []).append(l)
13
+ print(json.dumps(by_type))
14
+ ' > /tmp/context-by-type-${TASK_ID}.json
15
+ ```
16
+
17
+ ## Dispatch table
18
+
19
+ One fetcher per type. Each fetcher emits a normalized JSON view that the analysis prompt consumes as ground truth for the referenced source.
20
+
21
+ | Type | Fetcher | Output stored in |
22
+ |---|---|---|
23
+ | `crashlytics` | `~/.claude/lib/fetch-crashlytics.sh <url>` (already invoked in Phase 0 Step 1b.1 for the legacy `state.crashContext` field; Phase 1 reads that field directly) | `state.crashContext` |
24
+ | `fortify` | `~/.claude/lib/fetch-fortify.sh <url>` (already invoked in Phase 0 Step 1b.2 for the legacy `state.fortifyFinding` field; Phase 1 reads that field, Phase 4 reads the full payload for the security gate) | `state.fortifyFinding` |
25
+ | `swagger` | `~/.claude/lib/fetch-swagger.sh <url>` → endpoints[], request/response examples | `state.fetchedContext.swagger[]` |
26
+ | `confluence` | `~/.claude/lib/fetch-confluence.sh <url>` → page body, code blocks, extracted API contracts | `state.fetchedContext.confluence[]` |
27
+ | `figma` | `~/.claude/lib/fetch-figma.sh <url>` (via existing MCP / REST fallback path) when the task is a component; otherwise advisory only | `state.fetchedContext.figma[]` |
28
+ | `generic-doc` | no automatic fetcher — surfaced as advisory; the agent uses WebFetch on demand when the URL turns out to be load-bearing | n/a |
29
+
30
+ ## Exit code handling
31
+
32
+ - `0` (success) → output appended to `state.fetchedContext.<type>[]` and injected into the prompt.
33
+ - `2` (blocked / missing token) → run the inline Token Save Flow per `setup.md`; on skip, mark the entry as `{status: "skipped", reason: "missing-token"}` and continue.
34
+ - `3` (network/auth) → mark as `{status: "failed", reason: "<exit-msg>"}`, continue.
35
+ - `4`/`5`/`6` (config errors) → mark as `{status: "failed", reason: "<exit-msg>"}`, continue and log a setup hint.
36
+
37
+ Failures are never fatal at Phase 1 — the agent still runs analysis, just without the referenced source.
38
+
39
+ ## Prompt injection shape
40
+
41
+ Added immediately after the knowledge-injection block, before codebase exploration:
42
+
43
+ ```
44
+ ## Referenced External Sources
45
+
46
+ (when fetchers populated `state.fetchedContext.<type>`)
47
+ ### <type> — <url>
48
+ <fetched content, scoped to relevance>
49
+
50
+ (when fetcher pending)
51
+ ### Pending references
52
+ - <type>: <url> — <one-line metadata>
53
+ ```
54
+
55
+ The agent treats fetched content as **ground truth** for the referenced source (no re-discovery, no contradiction). Pending references are advisories — the agent decides whether to fetch via WebFetch on demand when the task hinges on that source.
56
+
57
+ ## Log line shape
58
+
59
+ ```
60
+ → context injection: total=<N>, fetched=<n>, pending=<n>, by-type={swagger:F/P, confluence:F/P, ...}
61
+ ```
62
+
63
+ `F` = fetched, `P` = pending. Empty contextLinks → `total=0`, skip the section entirely.
@@ -0,0 +1,20 @@
1
+ # Feature: Plan Todos Iteration (Phase 3)
2
+
3
+ **Gated by `prefs.global.planTodos.enabled`** (default: `false`). When enabled and Phase 2 Step 4.5 emitted a `plan.todos[]` (conforming to `pipeline/schemas/plan-todos.schema.json`), Phase 3 iterates with the helper instead of walking `tasks[]` directly:
4
+
5
+ ```bash
6
+ while next=$(bash "$HOME/.claude/lib/plan-todos.sh" next "$TASK_ID"); [ -n "$next" ]; do
7
+ id=$(printf '%s' "$next" | cut -f1)
8
+ task=$(printf '%s' "$next" | cut -f2)
9
+ bash "$HOME/.claude/lib/plan-todos.sh" start "$TASK_ID" "$id"
10
+ # ... TDD cycle for "$task" ...
11
+ if build_passed; then
12
+ bash "$HOME/.claude/lib/plan-todos.sh" complete "$TASK_ID" "$id" "${COMMIT_HASH} · tests:${TEST_COUNT}"
13
+ else
14
+ bash "$HOME/.claude/lib/plan-todos.sh" fail "$TASK_ID" "$id" "build failed after 3 retries"
15
+ break
16
+ fi
17
+ done
18
+ ```
19
+
20
+ When disabled, the loop still walks `tasks[]` from `planning-output` — `plan-todos.sh` adds visibility (status, notes, deps-respecting `next`) but the underlying TDD contract is unchanged.
@@ -0,0 +1,49 @@
1
+ # Feature: Prior Fix Detection (Phase 1 Step 0)
2
+
3
+ Before any analysis, check if this issue was already fixed by someone else.
4
+
5
+ ## Check order
6
+
7
+ 1. **Git commit search** — look for commits referencing this issue ID across all branches:
8
+
9
+ ```bash
10
+ git -C $PROJECT_ROOT log --all --oneline --grep="{jiraId}" --since="8 weeks ago"
11
+ ```
12
+
13
+ 2. **Affected file history** — after identifying key files (from issue description keywords), check recent changes:
14
+
15
+ ```bash
16
+ git -C $PROJECT_ROOT log --oneline --since="4 weeks ago" -- {affected_file_paths}
17
+ ```
18
+
19
+ 3. **Jira comments/status** — fetch latest comments to see if someone reported a fix:
20
+
21
+ ```bash
22
+ curl -s -H "Authorization: Bearer $JIRA_TOKEN" \
23
+ "$JIRA_BASE/issue/{jiraId}?fields=status,comment&expand=changelog" \
24
+ | jq '.fields.status.name, .fields.comment.comments[-3:][]?.body'
25
+ ```
26
+
27
+ ## If prior fix commit(s) found
28
+
29
+ ```
30
+ This issue appears to already have been addressed:
31
+ {hash} — {message} (by {author}, {date})
32
+
33
+ Options:
34
+ 1. Verify fix (check if cherry-pick/merge to base branch is needed)
35
+ 2. Stop pipeline (already resolved)
36
+ 3. Continue anyway (different fix needed)
37
+ ```
38
+
39
+ - Option 1 → Check if the commit exists on `baseBranch`. If not, suggest cherry-pick. Pipeline pauses.
40
+ - Option 2 → Cleanup and exit:
41
+ 1. Checkout back to base branch: `git -C $PROJECT_ROOT checkout {baseBranch}`
42
+ 2. Delete the created branch: `git -C $PROJECT_ROOT branch -D {branch}`
43
+ 3. If worktree was used: `git -C $PROJECT_ROOT worktree remove {worktreePath} --force`
44
+ 4. Set `agent-state.json` status to `"stopped_already_fixed"`. Log and exit.
45
+ - Option 3 → Continue to Step 1 as normal.
46
+
47
+ ## If no prior fix found
48
+
49
+ Continue to Step 1 (Knowledge Injection).
@@ -0,0 +1,30 @@
1
+ # Feature: Repo Map Injection (Phase 1 Step 2.5)
2
+
3
+ **Gated by `prefs.global.repoMap.enabled`** (default: `false`). Pattern source: <https://aider.chat/docs/repomap.html>.
4
+
5
+ Before launching Explore agents, run the deterministic repo map renderer and inject the result into each Explore prompt as `${REPO_MAP}`. This gives every explorer a token-budgeted overview of the most-referenced files in the repo — ranked via cross-file declaration references with TF-IDF-style credit splitting so universally-shared helper names (`pass`, `fail`, `init`) don't dominate.
6
+
7
+ ```bash
8
+ REPO_MAP=""
9
+ if [ "$(jq -r '.global.repoMap.enabled // false' "$PREFS")" = "true" ]; then
10
+ BUDGET=$(jq -r '.global.repoMap.tokenBudget // 1500' "$PREFS")
11
+ TOP=$(jq -r '.global.repoMap.topFiles // 25' "$PREFS")
12
+ INCLUDE=$(jq -r '.global.repoMap.include // empty' "$PREFS")
13
+ EXCLUDE=$(jq -r '.global.repoMap.exclude // empty' "$PREFS")
14
+ args=(--root "$WORKTREE" --budget "$BUDGET" --top "$TOP" --format md)
15
+ [ -n "$INCLUDE" ] && args+=(--include "$INCLUDE")
16
+ [ -n "$EXCLUDE" ] && args+=(--exclude "$EXCLUDE")
17
+ REPO_MAP=$(node pipeline/scripts/repo-map.mjs "${args[@]}" 2>/dev/null || echo "")
18
+ fi
19
+ ```
20
+
21
+ ## Properties
22
+
23
+ - **Deterministic** — same worktree state → same map. No embeddings, no network. Sub-second on monorepos.
24
+ - **Advisory** — Explore agents may ignore the map if they have stronger signals (Phase 0 knowledge cache, explicit user context). Never gates the pipeline.
25
+ - **Truncation-safe** — output is capped at `tokenBudget`; the script falls back to "no files extracted within budget" rather than over-spending.
26
+ - **Cost ledger** — emit `phase-1.repo_map_emitted bytes=$(wc -c <<<"$REPO_MAP") budget=$BUDGET` so Phase 7 cost summary can show the size injected.
27
+
28
+ ## When to enable
29
+
30
+ Large repos (>200 source files) where Explore otherwise spends multiple rounds finding the right starting files. Skip on small repos — the overhead exceeds the gain.
@@ -0,0 +1,24 @@
1
+ # Feature: Shadow-Git Checkpoints (Phase 3)
2
+
3
+ **Gated by `prefs.global.shadowGit.enabled`** (default: `false`). The orchestrator snapshots the worktree via `pipeline/lib/shadow-git.sh` so sub-phase rollback is possible without polluting the project's real `.git` history. Pattern source: Cline checkpoints (<https://docs.cline.bot/features/checkpoints>).
4
+
5
+ ```bash
6
+ # Phase 0 (one-time per task): initialize shadow repo + baseline snapshot.
7
+ bash "$HOME/.claude/lib/shadow-git.sh" init "$TASK_ID" "$WORKTREE"
8
+
9
+ # Per-step (mode: per-todo-step — default): snapshot AFTER each plan-todos
10
+ # step completes successfully, so restore lands on a known-good state.
11
+ bash "$HOME/.claude/lib/plan-todos.sh" complete "$TASK_ID" "$id" "$notes"
12
+ bash "$HOME/.claude/lib/shadow-git.sh" snapshot "$TASK_ID" "$WORKTREE" "step $id: $task"
13
+
14
+ # Per-mutation (mode: per-tool-call): the orchestrator hooks into every Edit/
15
+ # Write/MultiEdit/Bash-mutation tool call. Higher fidelity, ~50ms × tool-call
16
+ # overhead — recommended only for security-critical paths or experimental
17
+ # refactors where the user values fine-grained rollback over speed.
18
+
19
+ # Rollback on demand (interactive helper):
20
+ bash "$HOME/.claude/lib/shadow-git.sh" list "$TASK_ID"
21
+ bash "$HOME/.claude/lib/shadow-git.sh" restore "$TASK_ID" "$WORKTREE" <sha> --files
22
+ ```
23
+
24
+ Shadow repo location: `~/.claude/state/shadow-git/<task-id>/.git/`. Storage cap: `prefs.shadowGit.pruneAfterDays` (default 14). `/multi-agent:purge` honors this prune; manual cleanup via `shadow-git.sh prune <task-id>`.
@@ -65,7 +65,7 @@ Used for: input parsing, branch naming, commit messages.
65
65
 
66
66
  **Save rule**: After EVERY selection, append chosen value to relevant array (dedup, most recent first, max 10). Save prefs after Phase 0 and Phase 7.
67
67
 
68
- **Recents update map** (which selection writes to which prefs path):
68
+ **v2.1.0+ Recents update map** (which selection writes to which prefs path):
69
69
 
70
70
  | Selection event | Prefs path | Shape | Cap |
71
71
  |---|---|---|---|
@@ -208,7 +208,7 @@ Scan `$HOME` (maxdepth 2) for project markers (`.xcodeproj`, `Package.swift`, `b
208
208
 
209
209
  **Otherwise**: Present discovered projects as numbered list (standard UX pattern). Stack tag (`[iOS]`, `[Android]`, etc.) auto-detected from project files. Set `PROJECT_ROOT` to selected directory — all subsequent commands use `git -C $PROJECT_ROOT`. Save to `prefs.global.recentProjects` (dedup, max 10). If bare `#N` was given, now fetch GitHub issue from project's remote.
210
210
 
211
- **Multi-Repo Mode** (gated by `prefs.global.settings.multiRepoEnabled`):
211
+ **v2.1.0+ Multi-Repo Mode** (gated by `prefs.global.settings.multiRepoEnabled`):
212
212
 
213
213
  - The picker accepts space-separated numbers (`1 3 4`) for multi-select.
214
214
  - `prefs.global.recentGroups[]` (set in setup.md Step 6) surfaces at the top: pressing the group's number selects all its repos in one keystroke.
@@ -354,7 +354,7 @@ git -C $PROJECT_ROOT config user.email "{identity.email}"
354
354
 
355
355
  **If normal mode** (worktree — default): 2. Worktree path: Jira → `.worktrees/{jiraId}/`, GitHub → `.worktrees/GH{issueNo}/`, free-text → `.worktrees/task-{shortId}/` 3. `git -C $PROJECT_ROOT worktree add {path} -b {branch} origin/{baseBranch}` (if exists: enter, pull) 4. Set identity: `git -C {worktree-path} config user.name/email` 5. Create log dir + `agent-log.md` + `agent-state.json`:
356
356
 
357
- **Multi-Repo Worktree Setup**:
357
+ **v2.1.0+ Multi-Repo Worktree Setup**:
358
358
 
359
359
  When `state.projects[].length > 1`, repeat steps 2-4 **serially per repo** (worktrees are cheap; serial keeps git index sane and surfaces collisions one at a time):
360
360
 
@@ -7,50 +7,7 @@ Progress emission per `refs/progress-contract.md` — lines for each Explore dis
7
7
 
8
8
  #### Step 0 — Prior Fix Detection
9
9
 
10
- Before any analysis, check if this issue was already fixed by someone else.
11
-
12
- **Check order:**
13
-
14
- 1. **Git commit search** — look for commits referencing this issue ID across all branches:
15
-
16
- ```bash
17
- git -C $PROJECT_ROOT log --all --oneline --grep="{jiraId}" --since="8 weeks ago"
18
- ```
19
-
20
- 2. **Affected file history** — after identifying key files (from issue description keywords), check recent changes:
21
-
22
- ```bash
23
- git -C $PROJECT_ROOT log --oneline --since="4 weeks ago" -- {affected_file_paths}
24
- ```
25
-
26
- 3. **Jira comments/status** — fetch latest comments to see if someone reported a fix:
27
- ```bash
28
- curl -s -H "Authorization: Bearer $JIRA_TOKEN" \
29
- "$JIRA_BASE/issue/{jiraId}?fields=status,comment&expand=changelog" \
30
- | jq '.fields.status.name, .fields.comment.comments[-3:][]?.body'
31
- ```
32
-
33
- **If prior fix commit(s) found:**
34
-
35
- ```
36
- This issue appears to already have been addressed:
37
- {hash} — {message} (by {author}, {date})
38
-
39
- Options:
40
- 1. Verify fix (check if cherry-pick/merge to base branch is needed)
41
- 2. Stop pipeline (already resolved)
42
- 3. Continue anyway (different fix needed)
43
- ```
44
-
45
- - Option 1 → Check if the commit exists on `baseBranch`. If not, suggest cherry-pick. Pipeline pauses.
46
- - Option 2 → Cleanup and exit:
47
- 1. Checkout back to base branch: `git -C $PROJECT_ROOT checkout {baseBranch}`
48
- 2. Delete the created branch: `git -C $PROJECT_ROOT branch -D {branch}`
49
- 3. If worktree was used: `git -C $PROJECT_ROOT worktree remove {worktreePath} --force`
50
- 4. Set `agent-state.json` status to `"stopped_already_fixed"`. Log and exit.
51
- - Option 3 → Continue to Step 1 as normal.
52
-
53
- **If no prior fix found** → continue to Step 1.
10
+ Before any analysis, check if this issue was already fixed by someone else. Three signals (git commit grep on issue ID over 8 weeks, recent file-path history over 4 weeks, Jira/issue comments). On hit → prompt: Verify (cherry-pick path) / Stop (cleanup + `stopped_already_fixed` state) / Continue. Miss → Step 1. Full check commands, prompt block, and cleanup commands: `refs/features/prior-fix-detection.md`.
54
11
 
55
12
  #### Step 1 — Knowledge Injection (cached context)
56
13
 
@@ -90,63 +47,14 @@ Exit 0 with empty output = pref off or no memory on disk — skip. Otherwise the
90
47
 
91
48
  #### Step 1.5 — External Context Injection (`state.contextLinks[]`)
92
49
 
93
- Phase 0 Step 1b catalogued every typed external link from the task description into `state.contextLinks[]`. Phase 1 now dispatches each entry to its matching fetcher and prepends the result to the analysis prompt under a **Referenced External Sources** section, so the agent doesn't re-discover what the ticket already pointed at.
94
-
95
- ```bash
96
- jq -c '.contextLinks // []' "$STATE_FILE" \
97
- | python3 -c '
98
- import json, sys, os
99
- links = json.loads(sys.stdin.read() or "[]")
100
- by_type = {}
101
- for l in links:
102
- by_type.setdefault(l["type"], []).append(l)
103
- print(json.dumps(by_type))
104
- ' > /tmp/context-by-type-${TASK_ID}.json
105
- ```
106
-
107
- Dispatch table — one fetcher per type. Each fetcher emits a normalized JSON view that the analysis prompt consumes as ground truth for the referenced source.
108
-
109
- | Type | Fetcher | Output stored in |
110
- |---|---|---|
111
- | `crashlytics` | `~/.claude/lib/fetch-crashlytics.sh <url>` (already invoked in Phase 0 Step 1b.1 for the legacy `state.crashContext` field; Phase 1 reads that field directly) | `state.crashContext` |
112
- | `fortify` | `~/.claude/lib/fetch-fortify.sh <url>` (already invoked in Phase 0 Step 1b.2 for the legacy `state.fortifyFinding` field; Phase 1 reads that field, Phase 4 reads the full payload for the security gate) | `state.fortifyFinding` |
113
- | `swagger` | `~/.claude/lib/fetch-swagger.sh <url>` → endpoints[], request/response examples | `state.fetchedContext.swagger[]` |
114
- | `confluence` | `~/.claude/lib/fetch-confluence.sh <url>` → page body, code blocks, extracted API contracts | `state.fetchedContext.confluence[]` |
115
- | `figma` | `~/.claude/lib/fetch-figma.sh <url>` (via existing MCP / REST fallback path) when the task is a component; otherwise advisory only | `state.fetchedContext.figma[]` |
116
- | `generic-doc` | no automatic fetcher — surfaced as advisory; the agent uses WebFetch on demand when the URL turns out to be load-bearing | n/a |
50
+ Phase 0 Step 1b catalogued every typed external link from the task description into `state.contextLinks[]`. Phase 1 dispatches each entry to its matching fetcher (crashlytics, fortify, swagger, confluence, figma, generic-doc) and prepends results under a **Referenced External Sources** section in the analysis prompt — so the agent doesn't re-discover what the ticket already pointed at. Failures never fatal; pending refs are advisories. Full dispatch table, exit-code handling, prompt injection shape, log line shape: `refs/features/external-context-injection.md`.
117
51
 
118
- Each fetcher exit code is treated as follows:
119
- - `0` (success) → output appended to `state.fetchedContext.<type>[]` and injected into the prompt.
120
- - `2` (blocked / missing token) → run the inline Token Save Flow per `setup.md`; on skip, mark the entry as `{status: "skipped", reason: "missing-token"}` and continue.
121
- - `3` (network/auth) → mark as `{status: "failed", reason: "<exit-msg>"}`, continue.
122
- - `4`/`5`/`6` (config errors) → mark as `{status: "failed", reason: "<exit-msg>"}`, continue and log a setup hint.
123
-
124
- Failures are never fatal at Phase 1 — the agent still runs analysis, just without the referenced source.
125
-
126
- **Prompt injection shape** (added immediately after the knowledge-injection block, before codebase exploration):
127
-
128
- ```
129
- ## Referenced External Sources
130
-
131
- (when fetchers populated `state.fetchedContext.<type>`)
132
- ### <type> — <url>
133
- <fetched content, scoped to relevance>
134
-
135
- (when fetcher pending)
136
- ### Pending references
137
- - <type>: <url> — <one-line metadata>
138
- ```
139
-
140
- The agent treats fetched content as **ground truth** for the referenced source (no re-discovery, no contradiction). Pending references are advisories — the agent decides whether to fetch via WebFetch on demand when the task hinges on that source.
141
-
142
- **Log line shape**:
52
+ **Log line shape** (progress contract):
143
53
 
144
54
  ```
145
55
  → context injection: total=<N>, fetched=<n>, pending=<n>, by-type={swagger:F/P, confluence:F/P, ...}
146
56
  ```
147
57
 
148
- `F` = fetched, `P` = pending. Empty contextLinks → `total=0`, skip the section entirely.
149
-
150
58
  #### Step 2 — Stack Detection
151
59
 
152
60
  Detect the project's tech stack to load appropriate skills and tooling throughout the pipeline. Auto-detect by scanning `$PROJECT_ROOT` (maxdepth 2) for project markers:
@@ -171,32 +79,7 @@ This informs:
171
79
 
172
80
  #### Step 2.5 — Repo Map Injection (advisory, opt-in)
173
81
 
174
- **Gated by `prefs.global.repoMap.enabled`** (default: `false`). Pattern source: <https://aider.chat/docs/repomap.html>.
175
-
176
- Before launching Explore agents, run the deterministic repo map renderer and inject the result into each Explore prompt as `${REPO_MAP}`. This gives every explorer a token-budgeted overview of the most-referenced files in the repo — ranked via cross-file declaration references with TF-IDF-style credit splitting so universally-shared helper names (`pass`, `fail`, `init`) don't dominate.
177
-
178
- ```bash
179
- REPO_MAP=""
180
- if [ "$(jq -r '.global.repoMap.enabled // false' "$PREFS")" = "true" ]; then
181
- BUDGET=$(jq -r '.global.repoMap.tokenBudget // 1500' "$PREFS")
182
- TOP=$(jq -r '.global.repoMap.topFiles // 25' "$PREFS")
183
- INCLUDE=$(jq -r '.global.repoMap.include // empty' "$PREFS")
184
- EXCLUDE=$(jq -r '.global.repoMap.exclude // empty' "$PREFS")
185
- args=(--root "$WORKTREE" --budget "$BUDGET" --top "$TOP" --format md)
186
- [ -n "$INCLUDE" ] && args+=(--include "$INCLUDE")
187
- [ -n "$EXCLUDE" ] && args+=(--exclude "$EXCLUDE")
188
- REPO_MAP=$(node pipeline/scripts/repo-map.mjs "${args[@]}" 2>/dev/null || echo "")
189
- fi
190
- ```
191
-
192
- **Properties:**
193
-
194
- - **Deterministic** — same worktree state → same map. No embeddings, no network. Sub-second on monorepos.
195
- - **Advisory** — Explore agents may ignore the map if they have stronger signals (Phase 0 knowledge cache, explicit user context). Never gates the pipeline.
196
- - **Truncation-safe** — output is capped at `tokenBudget`; the script falls back to "no files extracted within budget" rather than over-spending.
197
- - **Cost ledger** — emit `phase-1.repo_map_emitted bytes=$(wc -c <<<"$REPO_MAP") budget=$BUDGET` so Phase 7 cost summary can show the size injected.
198
-
199
- **When to enable:** large repos (>200 source files) where Explore otherwise spends multiple rounds finding the right starting files. Skip on small repos — the overhead exceeds the gain.
82
+ Gated by `prefs.global.repoMap.enabled` (default: `false`). When enabled, runs `pipeline/scripts/repo-map.mjs` and injects the budgeted result into each Explore prompt as `${REPO_MAP}`. Aider-style: deterministic, no embeddings, sub-second, advisory only. Full wiring (helper invocation, properties, when-to-enable): `refs/features/repo-map.md`.
200
83
 
201
84
  #### Step 3 — Codebase Exploration
202
85