@mmerterden/multi-agent-pipeline 20.24.0 → 20.25.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.
Files changed (86) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +6 -5
  3. package/README.tr.md +6 -5
  4. package/docs/architecture.md +3 -3
  5. package/docs/ecosystem.md +5 -5
  6. package/docs/facts.json +7 -6
  7. package/docs/features.md +9 -4
  8. package/install/catalog-history.json +1 -1
  9. package/install/templates/claude-hooks.json +1 -1
  10. package/install/templates/codex-hooks.json +18 -0
  11. package/manifest.json +89 -82
  12. package/package.json +1 -1
  13. package/pipeline/agents/task-clarifier.md +1 -1
  14. package/pipeline/commands/multi-agent/deps/SKILL.md +61 -0
  15. package/pipeline/commands/multi-agent/model/SKILL.md +2 -2
  16. package/pipeline/commands/multi-agent/postmortem/SKILL.md +18 -6
  17. package/pipeline/commands/multi-agent/review/SKILL.md +5 -5
  18. package/pipeline/commands/multi-agent/route-on/SKILL.md +1 -1
  19. package/pipeline/commands/multi-agent/setup/SKILL.md +7 -5
  20. package/pipeline/commands/multi-agent/sync/SKILL.md +3 -3
  21. package/pipeline/commands/multi-agent/testflight-validation/SKILL.md +2 -3
  22. package/pipeline/contract/fixtures/runs-failed.json +1 -1
  23. package/pipeline/contract/fixtures/runs-old-schema.json +1 -1
  24. package/pipeline/contract/fixtures/runs-pr-opened-redacted.json +1 -1
  25. package/pipeline/contract/fixtures/runs-pr-opened.json +1 -1
  26. package/pipeline/contract/fixtures/runs-running.json +1 -1
  27. package/pipeline/lib/credential-inventory.sh +5 -5
  28. package/pipeline/lib/fetch-crashlytics.sh +6 -8
  29. package/pipeline/lib/model-rung.sh +1 -1
  30. package/pipeline/lib/plan-todos.sh +21 -4
  31. package/pipeline/lib/post-pr-review.sh +4 -6
  32. package/pipeline/lib/route-state.sh +1 -1
  33. package/pipeline/lib/shadow-git.sh +4 -5
  34. package/pipeline/multi-agent-refs/cross-cli-contract.md +8 -9
  35. package/pipeline/multi-agent-refs/features/cost-analysis.md +4 -0
  36. package/pipeline/multi-agent-refs/features/dep-bump.md +176 -0
  37. package/pipeline/multi-agent-refs/features/model-fallback.md +17 -12
  38. package/pipeline/multi-agent-refs/help/en.md +1 -0
  39. package/pipeline/multi-agent-refs/help/tr.md +1 -0
  40. package/pipeline/multi-agent-refs/phases/phase-0-init.md +1 -1
  41. package/pipeline/multi-agent-refs/phases/phase-2-dev.md +2 -0
  42. package/pipeline/multi-agent-refs/phases/phase-3-review.md +5 -5
  43. package/pipeline/multi-agent-refs/picker-contract.md +1 -1
  44. package/pipeline/multi-agent-refs/tracker-contract.md +6 -6
  45. package/pipeline/schemas/agent-state.schema.json +5 -0
  46. package/pipeline/schemas/phases.json +4 -0
  47. package/pipeline/schemas/plan-todos.schema.json +4 -4
  48. package/pipeline/schemas/prefs.schema.json +27 -4
  49. package/pipeline/scripts/_code-graph.mjs +2 -2
  50. package/pipeline/scripts/_transcript-hosts.mjs +406 -0
  51. package/pipeline/scripts/build-stack-plugins.mjs +3 -3
  52. package/pipeline/scripts/capture-flush.sh +7 -7
  53. package/pipeline/scripts/code-graph-rules/android.json +1 -1
  54. package/pipeline/scripts/cost-analyze.mjs +26 -19
  55. package/pipeline/scripts/cost-table.json +35 -19
  56. package/pipeline/scripts/dep-bump.mjs +1556 -0
  57. package/pipeline/scripts/edit-syntax-gate.mjs +151 -29
  58. package/pipeline/scripts/edit-syntax-gate.sh +9 -6
  59. package/pipeline/scripts/gc-abandoned.sh +2 -2
  60. package/pipeline/scripts/gen-mode-dispatch.mjs +3 -3
  61. package/pipeline/scripts/git-path.mjs +1 -2
  62. package/pipeline/scripts/host-hooks.mjs +265 -0
  63. package/pipeline/scripts/jira-attach.sh +1 -1
  64. package/pipeline/scripts/keychain.py +3 -3
  65. package/pipeline/scripts/output-quality-check.sh +1 -1
  66. package/pipeline/scripts/phase-tracker.sh +5 -6
  67. package/pipeline/scripts/phase0-exit-gate.mjs +3 -3
  68. package/pipeline/scripts/pre-push-check.sh +3 -6
  69. package/pipeline/scripts/transcript-index.mjs +423 -242
  70. package/pipeline/scripts/uninstall.mjs +90 -4
  71. package/pipeline/scripts/update-issue-progress.sh +4 -6
  72. package/pipeline/scripts/usage-report.mjs +2 -2
  73. package/pipeline/skills/.skill-manifest.json +14 -10
  74. package/pipeline/skills/.skills-index.json +12 -1
  75. package/pipeline/skills/shared/README.md +4 -3
  76. package/pipeline/skills/shared/core/multi-agent/SKILL.md +6 -6
  77. package/pipeline/skills/shared/core/multi-agent-deps/SKILL.md +60 -0
  78. package/pipeline/skills/shared/core/multi-agent-model/SKILL.md +2 -2
  79. package/pipeline/skills/shared/core/multi-agent-postmortem/SKILL.md +10 -7
  80. package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +5 -5
  81. package/pipeline/skills/shared/core/multi-agent-route-on/SKILL.md +1 -1
  82. package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +7 -5
  83. package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +3 -3
  84. package/pipeline/skills/shared/core/multi-agent-testflight-validation/SKILL.md +2 -3
  85. package/pipeline/skills/shared/external/ios-coding-standard/references/rules.yml +2 -2
  86. package/pipeline/skills/skills-index.md +2 -1
@@ -0,0 +1,176 @@
1
+ # Feature: Dependency Bump and Fix
2
+
3
+ <!-- toc -->
4
+ - [1. Shape of a run](#1-shape-of-a-run)
5
+ - [2. The script](#2-the-script)
6
+ - [3. What each phase does](#3-what-each-phase-does)
7
+ - [4. Scope of a fix round](#4-scope-of-a-fix-round)
8
+ - [5. Rollback](#5-rollback)
9
+ - [6. Settings](#6-settings)
10
+ - [7. Never](#7-never)
11
+ <!-- /toc -->
12
+
13
+ **Pattern**: bump one dependency, build and test, and when the bump breaks
14
+ something, fix only that breakage. A bump PR that also refactors, reformats or
15
+ "while I was here" fixes unrelated code cannot be reviewed as a bump, and a fix
16
+ loop with no cap turns a version bump into an open-ended rewrite.
17
+
18
+ Entry: `/multi-agent:deps [package[@version]] [--major]`. It is the normal
19
+ pipeline with a fixed task, not a second flow: same Phase 0 intake, worktree,
20
+ branch rules, Phase 2 dev agent and exit gate, Phase 3 review gates, Phase 4
21
+ commit and PR rules, Phase 5 channels.
22
+
23
+ ## 1. Shape of a run
24
+
25
+ | Field | Value |
26
+ |---|---|
27
+ | `state.mode` | `"deps"` |
28
+ | `state.taskType` | `chore` |
29
+ | Branch | `chore/deps-{kebab(name)}-{kebab(to)}`, kebab and collision rules from Phase 0 Step 4 |
30
+ | Commit | `chore(deps): bump {name} from {from} to {to}`, taken verbatim from `dep-bump.mjs apply` (`commitMessage`), plus ` [{jiraId}]` when the run carries one |
31
+ | PR body | the bump, its risk, the lockfile command, `alsoMoves`, the changelog excerpt, each fix and the error line it answers; `Ref:` / `Related:`, never `Closes` / `Fixes` / `Resolves` |
32
+ | `state.depBump` | the apply output plus `rounds`, `scope` and, on rollback, `rolledBack` and `stillFailing` |
33
+
34
+ ## 2. The script
35
+
36
+ `$HOME/.claude/scripts/dep-bump.mjs` owns every deterministic step; the model
37
+ never edits a version string by hand. JSON on stdout.
38
+
39
+ | Command | Does |
40
+ |---|---|
41
+ | `detect --dir D` | Ecosystems and manifests: SwiftPM `Package.swift`, Gradle `gradle/*.versions.toml`, npm `package.json`, pip `requirements*.txt` / `pyproject.toml`, each with its lockfile |
42
+ | `list --dir D [--registry]` | Candidates: `current` (lockfile, else declared), `latest`, `latestInMajor` (highest non-breaking), `risk`, `riskInMajor`, `source` |
43
+ | `apply --dir D --ecosystem E --name N --to V [--allow-major]` | One bump: manifest edit plus the lockfile through the ecosystem tool; writes `.pipeline/dep-bump.json` |
44
+ | `surface --dir D --ecosystem E --name N` | Files that import or reference the dependency |
45
+ | `scope --dir D [--log L]` | Files changed since the recorded base, split into `inScope` (manifest, lockfile and the surface recorded at apply), `newImporters` and `outOfScope`; exit 1 when anything is out of scope or a new importer has no cited error line |
46
+ | `notes --dir D --ecosystem E --name N --from A --to B` | The local changelog sections between the two versions, else the repository URL to read release notes from |
47
+ | `rollback --dir D` | Restores what the bump owns (manifest, lockfile, the files `scope` saw the fix touch in scope) from the recorded base and removes those the base lacks; every other change is left in place and listed under `kept` |
48
+ | `config` | The resolved `depBump.*` settings |
49
+
50
+ SwiftPM identities compare case-insensitively (`--name Alamofire` and
51
+ `alamofire` are one package). The surface covers every module name the package
52
+ is imported under: the identity, the repository name in the url, the products
53
+ named by `.product(name:package:)` and by-name target dependencies in the
54
+ package manifests. Packages an Xcode project adds through File > Packages keep
55
+ their pins in `*.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved`
56
+ or `*.xcworkspace/xcshareddata/swiftpm/Package.resolved` and their requirement
57
+ in `project.pbxproj`. `detect` and `list` report them with `readOnly: true` and
58
+ a note; `apply` refuses them (exit 1), because dep-bump does not edit
59
+ `project.pbxproj`. Such a bump is made in Xcode.
60
+
61
+ For Gradle the surface is the build scripts that name the catalog alias and
62
+ the Kotlin and Java files whose imports start at the Maven group
63
+ (`com.google.code.gson`), the artifact id or the alias stem, each with an
64
+ optional major suffix (`okhttp3` for `com.squareup.okhttp3:okhttp`, `retrofit2`
65
+ for `retrofit`). A library whose package root is none of these (Gson's
66
+ `com.google.gson`) is not found by `surface`, so a fix in such a file is out of
67
+ scope and needs the error line that names it, cited per file (section 4).
68
+
69
+ Offline listing reads what is already on disk: the lockfile for the current
70
+ version, SwiftPM `.build/checkouts/<id>` tags and the Gradle module cache for
71
+ newer ones. `--registry` asks the ecosystem's own tool (`npm view`,
72
+ `git ls-remote --tags`, Maven or PyPI metadata over `curl`); a failed query is
73
+ a `note` on that package, never a failed listing. Registry and lockfile tools
74
+ run in the manifest's directory (a workspace member's lockfile tool in the
75
+ workspace root), so the repo's own `.npmrc` registries and scopes apply. A
76
+ name or url that does not fit its ecosystem's grammar (a url that is not
77
+ http(s), ssh, git, file or `git@host:`, a name starting with `-`) is never
78
+ passed to a tool; the package gets a `registry query skipped` note.
79
+
80
+ Risk follows semver: a major step is breaking, and so is a minor step under
81
+ `0.x` and any step under `0.0.x`. `+build` metadata is ignored, and for Gradle
82
+ a Maven release qualifier (`-jre`, `-android`, `.Final`, `-RELEASE`, `.GA`,
83
+ `.SP1`) is part of a stable version, not a prerelease. A version that does not
84
+ parse is `unknown` and is treated as major, and so is a prerelease target.
85
+ `apply` exits 3 on a major, unknown or prerelease bump without `--allow-major`,
86
+ and touches nothing.
87
+
88
+ A pip requirement with several clauses (`foo>=1.0,<2.0`) is bumped on its
89
+ primary clause, the first `==`, `===`, `~=`, `>=` or `>`; `<`, `<=` and `!=`
90
+ are never primary, and a requirement made only of them is not listed. When
91
+ another clause would exclude the target (`<2.0` against `2.1`), `apply` exits 1
92
+ and changes nothing: rewriting a bound the repo set is a decision, not part of
93
+ the bump.
94
+
95
+ `apply` refuses a worktree with uncommitted changes to tracked files (exit 1,
96
+ `dirty` lists them), so the base it records holds no work of anyone else's.
97
+
98
+ `apply` is atomic. When the lockfile tool fails, the manifest and the lockfile
99
+ are restored byte for byte and the tool's output tail is in `lock.output`.
100
+ Lockfile tools: `swift package resolve`, `./gradlew dependencies --write-locks`
101
+ (only with a `gradle.lockfile`), the resolved npm-family manager with scripts
102
+ disabled (`package-manager.mjs`; yarn 2 and later take `--mode=skip-build`, yarn
103
+ 1 `--ignore-scripts`), `poetry lock` on Poetry 2 and `poetry lock --no-update`
104
+ before it, `uv lock --upgrade-package`. A workspace member's lockfile is the
105
+ workspace root's (the nearest directory above it with a lockfile and a
106
+ `workspaces` field or `pnpm-workspace.yaml`), and the tool runs there; a
107
+ lockfile above the manifest in a directory that declares no workspaces fails
108
+ the bump rather than letting it go ahead with no lockfile. Membership is not
109
+ matched against the `workspaces` globs. A shared Gradle `version.ref` moves every module bound to
110
+ it; `alsoMoves` names them and they join the surface.
111
+
112
+ ## 3. What each phase does
113
+
114
+ | Phase | In a deps run |
115
+ |---|---|
116
+ | 0 Init | Candidate pick and the major gate happen in the command before Phase 0. Then the normal intake (account, repo, base branch, workspace) with the free-text task `chore(deps): bump {name} from {from} to {to}`, `taskType` `chore`, branch from section 1 |
117
+ | 1 Plan | No analysis document (`chore`). The plan is fixed: one todo, "apply the bump", plus one per failing area once Phase 2 has a red run. `notes` output and the `list` record are the plan's evidence. The approval gate shows the bump, its risk and `alsoMoves` |
118
+ | 2 Dev | `apply` in the worktree first, before any agent runs. Then the Phase 2 exit gate as written (build, lint, tests, evidence gates). Green: straight to Phase 3 with no dev agent. Red: fix rounds (section 4) |
119
+ | 3 Review | The standard gates and reviewers over the whole diff. `scope` runs first; every `outOfScope` file is a blocking finding unless the round's report ties it to a build or test error line |
120
+ | 4 Commit | `commitMessage` from `apply`, the PR body from section 1. Never auto-close an issue |
121
+ | 5 Report | Channels as in every mode |
122
+
123
+ ## 4. Scope of a fix round
124
+
125
+ A round is one Phase 2 dev dispatch, given exactly this:
126
+
127
+ - the failing build or test log tail, from the exit gate;
128
+ - `surface` output: the files that use the dependency;
129
+ - the `notes` excerpt (breaking changes, migration notes). With no local
130
+ changelog, read the release notes for the versions in between from the
131
+ repository URL it returns (`gh release view`, the releases page) when
132
+ reachable, and say when they were not;
133
+ - the rule: change only what the bump broke. A file outside the surface may be
134
+ touched only when a compile or test error names it, and the report cites that
135
+ error line per file.
136
+
137
+ The surface is the one `apply` recorded. A file that starts importing the
138
+ dependency during a fix round does not join it: `scope` reports it under
139
+ `newImporters`, and each one passes only when the build or test log handed to
140
+ `scope --log` has an error line naming that file. The line is returned as
141
+ `cited`; a new importer with `cited: null` fails scope like an out-of-scope
142
+ file.
143
+
144
+ After each round: `scope --log <exit-gate log>`, then the exit gate again. Out-of-scope files with no
145
+ cited error are reverted before the next round. Green ends the loop. Every round
146
+ is recorded in `state.depBump.rounds[]` with the files it touched and the
147
+ errors it answered.
148
+
149
+ ## 5. Rollback
150
+
151
+ A run still red after `depBump.maxFixRounds` rounds (default 2), or out of
152
+ scope after its last round, is not committed: `dep-bump.mjs rollback` returns
153
+ the manifest, the lockfile and the files the fix rounds touched to the recorded
154
+ base, removes the ones the base did not have, and leaves every other change in
155
+ place (`kept`); the run ends with a report instead of a PR. The report names the bump, each round, the errors still failing with their
156
+ log lines, the files that would need to change and the changelog section that
157
+ explains it. `state.depBump.rolledBack` is `true`. The branch is left with no
158
+ commit; nothing is pushed.
159
+
160
+ ## 6. Settings
161
+
162
+ | Key | Default | Effect |
163
+ |---|---|---|
164
+ | `depBump.maxFixRounds` | 2 | Fix rounds before rollback; 0 rolls back any bump that is not green as-is |
165
+ | `depBump.queryRegistry` | true | `list` gets `--registry`; false lists offline only |
166
+
167
+ Read through `node "$HOME/.claude/scripts/dep-bump.mjs" config`. Asserted by
168
+ `test/dep-bump.test.mjs` and `smoke-dep-bump.sh`.
169
+
170
+ ## 7. Never
171
+
172
+ - A major, unparseable or prerelease bump without `--major` or an explicit confirmation.
173
+ - A version edit by hand, or a lockfile edited as text.
174
+ - More than one dependency per run (a shared `version.ref` is one bump).
175
+ - A fix outside the bump's surface with no error line behind it.
176
+ - A commit after the round cap is reached red.
@@ -11,17 +11,17 @@
11
11
  - [Codex CLI](#codex-cli)
12
12
  <!-- /toc -->
13
13
 
14
- > Contract last revised in **v10.6.0** (Fable 5 restored as top tier). The version tag here tracks the last substantive change to this contract, not the pipeline release.
14
+ > Contract last revised in **v20.25.0** (current Claude generation; Copilot CLI model ids per rung). The version tag here tracks the last substantive change to this contract, not the pipeline release.
15
15
 
16
16
  Personas route to the top available intelligence tier they declare in
17
17
  `preferredModel`. That tier can be quota-limited or temporarily unavailable.
18
18
  This contract defines when and how the orchestrator falls back, deterministically,
19
19
  without ever editing persona files at runtime.
20
20
 
21
- > **Fable 5 available again (2026-07).** `claude-fable-5` is the top tier once
22
- > more. Architect (`ios/android/backend-architect`), Reviewer-1 (`code-reviewer`),
21
+ > **Fable is the top tier.** The `fable` rung resolves to `claude-fable-5-1`.
22
+ > Architect (`ios/android/backend-architect`), Reviewer-1 (`code-reviewer`),
23
23
  > and triage personas declare `preferredModel: fable` - the deepest-reasoning
24
- > roles. **If Fable 5 is unavailable, the first fallback is opus (`claude-opus-5`).**
24
+ > roles. **If Fable is unavailable, the first fallback is opus (`claude-opus-5-5`).**
25
25
  > Security and other `preferredModel: opus` personas keep opus as their top tier.
26
26
  > The `premiumTierUntil` date gate stays in the contract as a generic mechanism
27
27
  > for any plan-window-limited premium tier.
@@ -35,7 +35,7 @@ fable -> opus -> sonnet -> haiku
35
35
  The orchestrator walks **one step down per trigger** from whichever tier a
36
36
  persona prefers: a `fable` persona degrades `fable -> opus` first, then
37
37
  `opus -> sonnet`, then `sonnet -> haiku`; an `opus` persona starts at
38
- `opus -> sonnet`. So a Fable 5 outage transparently promotes Opus 5 into the
38
+ `opus -> sonnet`. So a Fable outage transparently promotes Opus into the
39
39
  architect/reviewer roles with no file edits.
40
40
 
41
41
  ### Rung names are the contract; model IDs are not
@@ -46,11 +46,16 @@ model ID each rung resolves to lives in exactly two places: `scripts/cost-table.
46
46
  `phases/phase-3-review.md`. A generation move edits those; it never renames a rung and
47
47
  never touches a persona file.
48
48
 
49
- Current resolution: `fable` -> `claude-fable-5`, `opus` -> `claude-opus-5`,
50
- `sonnet` -> `claude-sonnet-5`, `haiku` -> `claude-haiku-4-5`.
49
+ Current resolution: `fable` -> `claude-fable-5-1`, `opus` -> `claude-opus-5-5`,
50
+ `sonnet` -> `claude-sonnet-5-5`, `haiku` -> `claude-haiku-5-5`. These are the Claude Code
51
+ wire IDs. Copilot CLI dispatches only the models `copilot help config` lists, with dotted
52
+ names, so its column in the reviewer table names those (`claude-opus-4.7`,
53
+ `claude-sonnet-4.6`), recorded per rung as `copilotModelId` in the cost table (haiku:
54
+ `claude-haiku-4.5`). The fable rung has none and is not offered on Copilot CLI; a persona
55
+ that prefers it dispatches the opus rung there.
51
56
 
52
- **Rate limits do not follow the rung.** Claude Opus 5 draws on a pool separate from
53
- the combined Opus 4.x pool, so a generation move does not inherit the previous
57
+ **Rate limits do not follow the rung.** A new generation can draw on a rate-limit pool
58
+ separate from the previous one, so a generation move does not inherit the previous
54
59
  generation's headroom. Budget-ceiling downgrades below are unaffected - they read the
55
60
  cost ledger, not the provider's quota - but a 429 on the opus rung after a generation
56
61
  move is a limits question, not a fallback-contract question.
@@ -119,8 +124,8 @@ Scope is Claude Code only, and the reason differs per host:
119
124
 
120
125
  | Host | Effect of `fableEnabled: false` | Why |
121
126
  |---|---|---|
122
- | Claude Code | Every `preferredModel: fable` persona (`ios/android/backend-architect`, `code-reviewer`, triage) starts on `opus` | This is the only host where the rung means Fable 5 |
123
- | Copilot CLI | none | Fable 5 is not offered there; its personas never sat on this rung |
127
+ | Claude Code | Every `preferredModel: fable` persona (`ios/android/backend-architect`, `code-reviewer`, triage) starts on `opus` | This is the only host where the rung means Fable 5.1 |
128
+ | Copilot CLI | none | Fable is not offered there; its personas never sat on this rung |
124
129
  | Codex CLI | none, deliberately | The `fable` rung there means `gpt-5.6 @ xhigh`, a different model on a different account. Switching it off from a knob named after an Anthropic model would surprise a Codex user, so it does not |
125
130
 
126
131
  **Phase 4 loses a reviewer, and says so.** Reviewer 1 lands on `opus`, which
@@ -250,7 +255,7 @@ better internals.
250
255
  - No edits to `pipeline/agents/*.md` at runtime; frontmatter is install-time
251
256
  configuration only.
252
257
  - Copilot CLI reviewer set is out of scope: Copilot CLI pins its own three
253
- reviewer models (GPT-5.4 + Opus + Sonnet - Fable 5 is not offered there) and
258
+ reviewer models (GPT-5.4 + Opus + Sonnet - Fable is not offered there) and
254
259
  does not use this persona ladder. Only Claude Code dispatches Reviewer-1 on
255
260
  Fable.
256
261
 
@@ -61,6 +61,7 @@ Pipeline entries:
61
61
 
62
62
  /multi-agent "task" Worktree
63
63
  /multi-agent:autopilot "task" Worktree, no questions
64
+ /multi-agent:deps [pkg[@ver]] [--major] Bump one dependency, fix only what the bump broke, review, PR; rolls back past depBump.maxFixRounds
64
65
 
65
66
  Phase 0 Step 5b asks where the branch lives; there is no flag for it.
66
67
  autopilot skips every confirmation INCLUDING the plan gate and the workspace
@@ -61,6 +61,7 @@ Pipeline girişleri:
61
61
 
62
62
  /multi-agent "task" Worktree var
63
63
  /multi-agent:autopilot "task" Worktree var, soru yok
64
+ /multi-agent:deps [paket[@sürüm]] [--major] Tek bağımlılığı yükselt, yalnızca yükseltmenin kırdığını düzelt, review, PR; depBump.maxFixRounds aşılınca geri alır
64
65
 
65
66
  Faz 0 Adım 5b branch'in nerede yaşayacağını sorar; bayrağı yok.
66
67
  autopilot plan kapısı ve çalışma alanı sorusu dahil her onayı atlar, otomatik
@@ -652,7 +652,7 @@ Log: `Phase 0 Step 7.7: testDepth = {unit|unit+ui|unit+mcp} (source {user|autopi
652
652
 
653
653
  5. Phase 1 Analysis reads `state.clarification.userAnswers` (when present) as additional context - fold answers into the Explore prompt so downstream phases inherit the resolution.
654
654
 
655
- **Reference:** `$HOME/.claude/agents/task-clarifier.md` - scoring rubric, question-quality rules and the ~$0.0025-per-call cost note.
655
+ **Reference:** `$HOME/.claude/agents/task-clarifier.md` - scoring rubric, question-quality rules and the ~$0.0004-per-call cost note.
656
656
 
657
657
  #### Telemetry
658
658
 
@@ -57,6 +57,8 @@ Phase 2 consumes the Phase 1 output object conforming to `$HOME/.claude/schemas/
57
57
 
58
58
  **Shadow-Git checkpoints (opt-in)**: gated by `prefs.global.shadowGit.enabled` (default: `false`). When enabled, the orchestrator snapshots the worktree via `$HOME/.claude/lib/shadow-git.sh` so sub-phase rollback is possible without touching the project's real `.git` history. Lifecycle: `shadow-git.sh init` (Phase 0 baseline), `shadow-git.sh snapshot` (per step after `plan-todos complete`), `shadow-git.sh restore <sha> --files` (rollback). Modes: `per-todo-step` (default) or `per-tool-call`. Full wiring + storage cap: `$HOME/.claude/multi-agent-refs/features/shadow-git.md`.
59
59
 
60
+ **Dependency bump** (`state.mode == "deps"`): `dep-bump.mjs apply` first, then capped fix rounds: `$HOME/.claude/multi-agent-refs/features/dep-bump.md`.
61
+
60
62
  #### Component tasks - delegated dispatch (taskType === "component")
61
63
 
62
64
  When Phase 0 Step 7 classified the task as `component`, Phase 2 delegates the entire phase to the enabled `ai-<platform>-toolkit` marketplace plugin's component skill (`create-component`, fallback `create-ui-component`) via the Skill tool and does NOT run the TDD loop below. The dispatch layer passes the plugin skill the analysis Section 6 (Bileşen Envanteri) entry + Section 13.1 conventions for the named component as context. Because plugin skills do not write pipeline state, the **dispatch layer** (not the skill) owns `state.phases["2"].subphases[]`, recording a coarse component-build row - multi-agent's `phase-tracker` reads that array with no special case. Plugin resolution (dual-name), dispatch call, failure/resume, multi-repo, and the intentional cross-CLI divergence live in `$HOME/.claude/multi-agent-refs/component-dispatch.md` - read it before editing component-task behaviour here. Phase 2 still owns: progress line `-> dispatching create-component <name>`, `retryCount` cap at 3, and fallthrough to the TDD path when dispatch prerequisites are missing (`taskType` absent OR the plugin is not enabled in this repo -> log anomaly, halt or run TDD per component-dispatch.md).
@@ -237,10 +237,10 @@ Launch Agent instances **in parallel** using the shared `code-reviewer` subagent
237
237
 
238
238
  | Reviewer | subagent_type | Claude Code | Copilot CLI | Codex CLI | Focus | Skills Referenced |
239
239
  | ---------- | --------------- | --- | --- | --- | --- | --- |
240
- | Reviewer 1 | `code-reviewer` | `claude-fable-5` | `claude-opus-5` | `gpt-5.6` @ `xhigh` | Deep security + architecture | `api-security-best-practices`, `architecture` |
241
- | Reviewer 2 | `code-reviewer` | `claude-opus-5` | `gpt-5.4` | `gpt-5.4` @ `high` | Edge cases, different perspective | cross-model diversity |
242
- | Reviewer 3 | `code-reviewer` | `claude-sonnet-5` | `claude-sonnet-5` | `gpt-5.6` @ `medium` | Quality + correctness + naming | `ai-backend-toolkit:clean-code`, stack-specific skill |
243
- | Triage | triage persona | `claude-fable-5` | `claude-opus-5` | `gpt-5.6` @ `max` | Filter false positives + out-of-scope | - |
240
+ | Reviewer 1 | `code-reviewer` | `claude-fable-5-1` | `claude-opus-4.7` | `gpt-5.6` @ `xhigh` | Deep security + architecture | `api-security-best-practices`, `architecture` |
241
+ | Reviewer 2 | `code-reviewer` | `claude-opus-5-5` | `gpt-5.4` | `gpt-5.4` @ `high` | Edge cases, different perspective | cross-model diversity |
242
+ | Reviewer 3 | `code-reviewer` | `claude-sonnet-5-5` | `claude-sonnet-4.6` | `gpt-5.6` @ `medium` | Quality + correctness + naming | `ai-backend-toolkit:clean-code`, stack-specific skill |
243
+ | Triage | triage persona | `claude-fable-5-1` | `claude-opus-4.7` | `gpt-5.6` @ `max` | Filter false positives + out-of-scope | - |
244
244
 
245
245
  Reviewer count per host: **Claude Code 3, Copilot CLI 3, Codex CLI 3** - **2** on Claude Code with the fable rung off, per `$HOME/.claude/multi-agent-refs/features/model-fallback.md`.
246
246
 
@@ -265,7 +265,7 @@ borderline finding. Where the diversity budget goes instead:
265
265
 
266
266
  Each reviewer inherits the `code-reviewer` agent's focus areas (Security, Architecture, Quality, Performance) and output contract. The orchestrator overrides only the model and the stack-specific skill per-reviewer - no prompt duplication.
267
267
 
268
- **Model override wiring:** `code-reviewer.md` declares `preferredModel: fable`, so Reviewer 1 uses the persona default (Fable 5). Reviewer 2 (`claude-opus-5` on Claude Code, `gpt-5.4` elsewhere) and Reviewer 3 (`claude-sonnet-5`) set `PHASE_MODEL_OVERRIDE=<model>` before dispatch - the orchestrator exports `CLAUDE_CODE_SUBAGENT_MODEL` on Claude Code, or passes `--model` on Copilot CLI. Full precedence rule: `skills/shared/core/multi-agent/SKILL.md#agent-dispatch--per-persona-model-routing`. Fable dispatches are subject to the fallback contract (`$HOME/.claude/multi-agent-refs/features/model-fallback.md`): dispatch-error retry walks `fable -> opus -> sonnet` and budget-ceiling downgrade.
268
+ **Model override wiring:** `code-reviewer.md` declares `preferredModel: fable`, so Reviewer 1 uses the persona default (Fable 5.1). Reviewer 2 (`claude-opus-5-5` on Claude Code, `gpt-5.4` elsewhere) and Reviewer 3 (sonnet rung, per host above) set `PHASE_MODEL_OVERRIDE=<model>` before dispatch - the orchestrator exports `CLAUDE_CODE_SUBAGENT_MODEL` on Claude Code, or passes `--model` on Copilot CLI. Full precedence rule: `skills/shared/core/multi-agent/SKILL.md#agent-dispatch--per-persona-model-routing`. Fable dispatches are subject to the fallback contract (`$HOME/.claude/multi-agent-refs/features/model-fallback.md`): dispatch-error retry walks `fable -> opus -> sonnet` and budget-ceiling downgrade.
269
269
 
270
270
  **Stack-specific skills loaded per reviewer** (from Phase 1 `detectedStack`). All three columns are used on every host; Reviewer 2 reads them as Opus on Claude Code and as GPT-5.4 elsewhere.
271
271
 
@@ -190,6 +190,6 @@ park it writes `agent-state.json` beside its tracker with `taskId`,
190
190
 
191
191
  ## Deterministic gates note
192
192
 
193
- Claude Code's `PreToolUse` exit-2 hooks are the HARD blocking gates. Three ship, none needing run-specific arguments so they are naturally hookable: (1) `pre-commit-check.sh` scans the staged diff on every `git commit` and blocks on a detected secret; (2) `agent-guard.sh` runs on `git commit` + `git push` and blocks AI/assistant attribution in a commit message and force-push to a protected branch (main/master/develop); (3) `check-read-size.sh` runs on `Read` and on the shell commands that read a file whole, and routes an oversized read to a cheap worker (`bulk-read.sh`) instead of the caller's own rung. The first two inspect what a run WRITES; the third inspects what it pays to READ, and it is inert until `bulkRead.mode` is set to `observe` or `enforce`, so merging the block changes nothing until the user opts in. Its `observe` mode blocks nothing and only logs, which is how the baseline is measured before anything is routed. All three are self-contained and never execute the inspected command. On an internal error they let the call through in an attended session; `agent-guard.sh` blocks instead under `MULTI_AGENT_UNATTENDED=1`, where nobody is watching to notice a gap. Three capture hooks ship in the same block and block nothing: `SessionEnd` runs `capture-flush.sh --if-stale` (writing a killed run's findings into the per-repo stores, so they do not depend on the run reaching Phase 5) plus `note-session.sh` (the mechanical shape of a non-pipeline session: tools used, commands that failed, calls the user refused - never an argument, never any output), `PreCompact` runs `capture-flush.sh` without `--if-stale` (a compaction summarizes a long phase mid-flight, so it is the moment unflushed findings are at risk; the staleness test exists only so a session exit does not re-flush a finished run, and both store writes are idempotent), and `SessionStart` runs `capture-resume.sh`, at most two lines about an unfinished run and a stale observation queue. None of them calls a model; all exit 0 on every path. One `PostToolUse` hook ships in the same block and blocks nothing either: `edit-syntax-gate.sh` on `Edit|Write|MultiEdit` parses the file the edit just wrote (`swiftc -parse`, `node --check`, `py_compile` into a temp dir, `JSON.parse`, `bash -n`; Kotlin is skipped, no parser answers inside its 2 s deadline) and hands a syntax error to the model as `additionalContext`; it is silent when a parser is missing or slow, and inert until `editSyntaxGate.enabled` is true. Every registration here is Claude Code's: Codex has a `PostToolUse` event and Copilot CLI a `postToolUse` one, but the installer registers none of the pipeline's hooks on either host, so this gate is Claude Code only for now. The recommended hook block ships at `install/templates/claude-hooks.json`; `multi-agent:setup` offers to merge it into `~/.claude/settings.json`. The other deterministic gates (evidence, consensus, intent, learnings) are invoked by the pipeline phases with per-run arguments (a build-log path, the triage JSON, the free-text input), so they are phase-enforced by contract, not OS-hookable.
193
+ Claude Code's `PreToolUse` exit-2 hooks are the HARD blocking gates. Three ship, none needing run-specific arguments so they are naturally hookable: (1) `pre-commit-check.sh` scans the staged diff on every `git commit` and blocks on a detected secret; (2) `agent-guard.sh` runs on `git commit` + `git push` and blocks AI/assistant attribution in a commit message and force-push to a protected branch (main/master/develop); (3) `check-read-size.sh` runs on `Read` and on the shell commands that read a file whole, and routes an oversized read to a cheap worker (`bulk-read.sh`) instead of the caller's own rung. The first two inspect what a run WRITES; the third inspects what it pays to READ, and it is inert until `bulkRead.mode` is set to `observe` or `enforce`, so merging the block changes nothing until the user opts in. Its `observe` mode blocks nothing and only logs, which is how the baseline is measured before anything is routed. All three are self-contained and never execute the inspected command. On an internal error they let the call through in an attended session; `agent-guard.sh` blocks instead under `MULTI_AGENT_UNATTENDED=1`, where nobody is watching to notice a gap. Three capture hooks ship in the same block and block nothing: `SessionEnd` runs `capture-flush.sh --if-stale` (writing a killed run's findings into the per-repo stores, so they do not depend on the run reaching Phase 5) plus `note-session.sh` (the mechanical shape of a non-pipeline session: tools used, commands that failed, calls the user refused - never an argument, never any output), `PreCompact` runs `capture-flush.sh` without `--if-stale` (a compaction summarizes a long phase mid-flight, so it is the moment unflushed findings are at risk; the staleness test exists only so a session exit does not re-flush a finished run, and both store writes are idempotent), and `SessionStart` runs `capture-resume.sh`, at most two lines about an unfinished run and a stale observation queue. None of them calls a model; all exit 0 on every path. One `PostToolUse` hook ships in the same block and blocks nothing either: `edit-syntax-gate.sh` on `Edit|Write|MultiEdit` parses the file the edit just wrote (`swiftc -parse`, `node --check`, `py_compile` into a temp dir, `JSON.parse`, `bash -n`; Kotlin is skipped, no parser answers inside its 2 s deadline) and hands a syntax error to the model as `additionalContext`; it is silent when a parser is missing or slow, and inert until `editSyntaxGate.enabled` is true. The syntax gate also runs on Codex, on `PostToolUse` for `apply_patch` (every file the patch adds, updates or moves to). `multi-agent:setup` Step 8 asks once and registers it there with `host-hooks.mjs install --host codex` from `install/templates/codex-hooks.json`: idempotent, leaving every other hook alone, `status` reports it and uninstall removes it. Codex runs it only after the user trusts it in `/hooks`, which the helper says. Copilot CLI gets no registration: as of 1.0.45 it discards a `postToolUse` hook's output and applies no matcher, so the gate would cost a spawn per tool call and say nothing. Every other registration here is Claude Code's. The recommended hook block ships at `install/templates/claude-hooks.json`; `multi-agent:setup` offers to merge it into `~/.claude/settings.json`. The other deterministic gates (evidence, consensus, intent, learnings) are invoked by the pipeline phases with per-run arguments (a build-log path, the triage JSON, the free-text input), so they are phase-enforced by contract, not OS-hookable.
194
194
 
195
195
  Copilot CLI has no `PreToolUse` equivalent, so the secret scan there is workflow-enforced (run as a phase step, not OS-blocked) plus a CI smoke-gate step.
@@ -146,11 +146,11 @@ acted on, not read.
146
146
  #### Accounting is a gate, not a request
147
147
 
148
148
  `update <N> completed` exits **3** for phases 1-4 when nothing was recorded via
149
- `tokens`. The alternative is what shipped for months: the docs asked for the
150
- call, `smoke-tracker-tokens-invocation.sh` linted that the docs *mention* the
151
- call, and no run made it - every phase priced at `-`, every completion line
152
- printed without numbers, and every gate green. A lint over prose cannot observe
153
- a runtime omission; the tool that would have received the call can.
149
+ `tokens`. A doc that asks for the call, and a lint
150
+ (`smoke-tracker-tokens-invocation.sh`) that checks the doc *mentions* it, cannot
151
+ see a run that skips it: every phase would price at `-` and every completion line
152
+ would print without numbers while every gate passes. A lint over prose cannot
153
+ observe a runtime omission; the tool that would have received the call can.
154
154
 
155
155
  The refusal is recoverable and loses no work:
156
156
 
@@ -160,7 +160,7 @@ phase-tracker.sh tokens <N> <in> <out> [cached]
160
160
  phase-tracker.sh update <N> completed
161
161
  ```
162
162
 
163
- `model` resolves a full model id to its cost-table family (`claude-opus-5` →
163
+ `model` resolves a full model id to its cost-table family (`claude-opus-5-5` →
164
164
  `opus`) and says so out loud when it cannot, because an unpriced name is the
165
165
  other way a phase silently costs nothing. A phase that truly ran no LLM call
166
166
  completes with `--no-llm`, which is recorded and keeps it out of the run
@@ -782,6 +782,11 @@
782
782
  "enum": ["component", "bugfix", "feature", "refactor", "chore"],
783
783
  "description": "Phase 0 Step 7 classification. Phase 2 branches on it, and phase0-exit-gate.mjs fails a run that reaches Phase 1 without it. A Figma reference forces component."
784
784
  },
785
+ "depBump": {
786
+ "type": ["object", "null"],
787
+ "additionalProperties": true,
788
+ "description": "A /multi-agent:deps run (state.mode \"deps\"): the bump dep-bump.mjs applied (ecosystem, name, manifest, from, to, risk, lock, alsoMoves, commitMessage), the fix rounds taken against depBump.maxFixRounds, the scope verdict and, when the cap was reached, rolledBack plus what still failed. Contract: multi-agent-refs/features/dep-bump.md."
789
+ },
785
790
  "plan": {
786
791
  "type": ["object", "null"],
787
792
  "description": "The Phase 1 plan as a Todo list, written by plan-todos.sh when prefs.global.planTodos.enabled is true. Shape: plan-todos.schema.json, which plan-todos.sh validates on write, including the optional todos[].type, the todos[].tdd evidence record, the drift record (the todo ended off-plan) and the needsReplan flag (a step it depends on drifted; it does not start until confirm-replan); absent when the opt-in is off."
@@ -73,6 +73,10 @@
73
73
  "analysis": {
74
74
  "phases": [0, 1, 3, 4, 5],
75
75
  "autopilot": false
76
+ },
77
+ "deps": {
78
+ "phases": [0, 1, 2, 3, 4, 5],
79
+ "autopilot": false
76
80
  }
77
81
  },
78
82
  "thresholds": {
@@ -27,8 +27,8 @@
27
27
  "properties": {
28
28
  "id": {
29
29
  "type": "string",
30
- "pattern": "^t[0-9]+$",
31
- "description": "Stable identifier (t1, t2, ...). Used in dependency edges + progress lines."
30
+ "pattern": "^[tT][0-9]+$",
31
+ "description": "Stable identifier: t1, t2 when written directly, T1, T2 when converted from a planning-output document. Used in dependency edges and progress lines."
32
32
  },
33
33
  "task": {
34
34
  "type": "string",
@@ -43,7 +43,7 @@
43
43
  "type": "array",
44
44
  "default": [],
45
45
  "description": "Array of todo IDs that must reach `completed` (or `skipped`) before this one can move to `in_progress`. Empty for parallelizable steps.",
46
- "items": { "type": "string", "pattern": "^t[0-9]+$" }
46
+ "items": { "type": "string", "pattern": "^[tT][0-9]+$" }
47
47
  },
48
48
  "startedAt": { "type": "string", "format": "date-time" },
49
49
  "completedAt": { "type": "string", "format": "date-time" },
@@ -148,7 +148,7 @@
148
148
  "properties": {
149
149
  "because": {
150
150
  "type": "string",
151
- "pattern": "^t[0-9]+$",
151
+ "pattern": "^[tT][0-9]+$",
152
152
  "description": "The step that drifted."
153
153
  },
154
154
  "at": { "type": "string", "format": "date-time" },
@@ -568,7 +568,7 @@
568
568
  "fableEnabled": {
569
569
  "type": "boolean",
570
570
  "default": false,
571
- "description": "Whether the fable rung is available at all on Claude Code. Ships OFF: the top rung is the most expensive thing a run can reach, and a cost control that is on by default is not a control. false makes every persona that declares preferredModel: fable dispatch on opus from the first call, with no dispatch attempt on fable and no error to recover from - a cost control, not a fallback. Claude Code only: Copilot CLI does not offer Fable 5, and on Codex CLI the fable rung means gpt-5.6 @ xhigh, which this switch deliberately does not touch. Turning it off also collapses the Phase 3 Claude Code reviewer panel from three to two (Reviewer 1 lands on opus, which Reviewer 2 already holds), and consensus.reviewerCount records 2."
571
+ "description": "Whether the fable rung is available at all on Claude Code. Ships OFF: the top rung is the most expensive thing a run can reach, and a cost control that is on by default is not a control. false makes every persona that declares preferredModel: fable dispatch on opus from the first call, with no dispatch attempt on fable and no error to recover from - a cost control, not a fallback. Claude Code only: Copilot CLI does not offer Fable, and on Codex CLI the fable rung means gpt-5.6 @ xhigh, which this switch deliberately does not touch. Turning it off also collapses the Phase 3 Claude Code reviewer panel from three to two (Reviewer 1 lands on opus, which Reviewer 2 already holds), and consensus.reviewerCount records 2."
572
572
  },
573
573
  "onDispatchError": {
574
574
  "type": "boolean",
@@ -1211,7 +1211,7 @@
1211
1211
  "clarifyAmbiguous": {
1212
1212
  "type": "object",
1213
1213
  "additionalProperties": false,
1214
- "description": "v8.6+ - Phase 0 Step 9 clarifying-question loop. Before Phase 1 starts, a cheap Haiku classifier scores task ambiguity (0-10) and emits up to N questions if score < threshold. Cost: ~$0.0025 per Haiku call. Off by default - flip on for teams burned by ambiguity-driven rework or when working on cross-team issues where the spec lives in someone else's head.",
1214
+ "description": "v8.6+ - Phase 0 Step 9 clarifying-question loop. Before Phase 1 starts, a cheap Haiku classifier scores task ambiguity (0-10) and emits up to N questions if score < threshold. Cost: ~$0.0004 per Haiku call. Off by default - flip on for teams burned by ambiguity-driven rework or when working on cross-team issues where the spec lives in someone else's head.",
1215
1215
  "properties": {
1216
1216
  "enabled": {
1217
1217
  "type": "boolean",
@@ -1841,7 +1841,7 @@
1841
1841
  "editSyntaxGate": {
1842
1842
  "type": "object",
1843
1843
  "additionalProperties": false,
1844
- "description": "Parse the file an Edit / Write / MultiEdit just wrote and tell the model when it no longer parses: swiftc -parse, node --check, python3 py_compile (bytecode to a temp dir), JSON.parse, bash -n, chosen by extension, each under a 2 s deadline. Kotlin and every other extension are skipped. The hook is pipeline/scripts/edit-syntax-gate.sh (PostToolUse, Claude Code, installed from install/templates/claude-hooks.json). It never blocks: the message arrives as PostToolUse context and the hook exits 0. A parser that is not installed or runs past the deadline means no message.",
1844
+ "description": "Parse the file an edit just wrote and tell the model when it no longer parses: swiftc -parse, node --check, python3 py_compile (bytecode to a temp dir), JSON.parse, bash -n, chosen by extension, each under a 2 s deadline. Kotlin and every other extension are skipped. The hook is pipeline/scripts/edit-syntax-gate.sh: PostToolUse on Claude Code (install/templates/claude-hooks.json) and on Codex apply_patch (codex-hooks.json, registered by host-hooks.mjs). Copilot CLI is not registered: as of 1.0.45 it discards postToolUse output. It never blocks: the message arrives as PostToolUse context and the hook exits 0. A parser that is not installed or runs past the deadline means no message.",
1845
1845
  "properties": {
1846
1846
  "enabled": {
1847
1847
  "type": "boolean",
@@ -1884,6 +1884,29 @@
1884
1884
  "timeoutSec": 120
1885
1885
  }
1886
1886
  },
1887
+ "depBump": {
1888
+ "type": "object",
1889
+ "additionalProperties": false,
1890
+ "description": "/multi-agent:deps (multi-agent-refs/features/dep-bump.md): bump one dependency, build and test, fix only the breakage the bump caused, review and open a PR. pipeline/scripts/dep-bump.mjs applies the bump and reads these settings through its config command.",
1891
+ "properties": {
1892
+ "maxFixRounds": {
1893
+ "type": "integer",
1894
+ "minimum": 0,
1895
+ "maximum": 5,
1896
+ "default": 2,
1897
+ "description": "Fix rounds a red build or test run may take after the bump. When the cap is reached and the run is still red, the worktree is rolled back to the recorded base and the run reports what broke instead of committing. 0 means a bump that does not pass as-is is rolled back at once."
1898
+ },
1899
+ "queryRegistry": {
1900
+ "type": "boolean",
1901
+ "default": true,
1902
+ "description": "true = the candidate list asks the package registry for newer versions through the ecosystem's own tool (npm view, git ls-remote, Maven or PyPI metadata). A failed query is noted per package and the list falls back to the manifests, lockfiles and local caches. false = offline listing only."
1903
+ }
1904
+ },
1905
+ "default": {
1906
+ "maxFixRounds": 2,
1907
+ "queryRegistry": true
1908
+ }
1909
+ },
1887
1910
  "bulkRead": {
1888
1911
  "type": "object",
1889
1912
  "additionalProperties": false,
@@ -2006,7 +2029,7 @@
2006
2029
  },
2007
2030
  "localRepo": {
2008
2031
  "type": "string",
2009
- "description": "Repo that localPath is relative to, e.g. $HOME/multi-agent-plugins. Without it localPath reads as relative to the current repo, which is how both entries came to point at the UPSTREAM tree and stayed wrong through a rename: nothing in the config said which checkout held the derived copies."
2032
+ "description": "Repo that localPath is relative to, e.g. $HOME/multi-agent-plugins. Without it localPath reads as relative to the current repo, so an entry can silently point at the UPSTREAM tree: nothing else in the config says which checkout holds the derived copies."
2010
2033
  },
2011
2034
  "upstreamMarketplace": {
2012
2035
  "type": "string",
@@ -212,8 +212,8 @@ const IMPORT_LINE_RE = /^[ \t]*import[ \t].*$/gm;
212
212
  *
213
213
  * Swift's submodule form - `import class DesignKit.PrimaryButton` - otherwise
214
214
  * feeds the `class` definition pattern, which registers the MODULE name as a
215
- * declared type. On a large Swift app that alone lifted two module names into
216
- * the top ten god-nodes, which is how the bug surfaced. Imports are extracted
215
+ * declared type. On a large Swift app that alone lifts module names into the
216
+ * top ten god-nodes. Imports are extracted
217
217
  * before this runs, so nothing is lost.
218
218
  *
219
219
  * @param {string} stripped - output of stripCode