@mmerterden/multi-agent-pipeline 10.8.0 → 10.12.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 +182 -0
- package/README.md +3 -1
- package/docs/engineering.md +76 -0
- package/docs/features.md +40 -36
- package/package.json +1 -1
- package/pipeline/commands/multi-agent/channels.md +42 -6
- package/pipeline/commands/multi-agent/finish.md +15 -6
- package/pipeline/commands/multi-agent/generate-bug.md +33 -0
- package/pipeline/commands/multi-agent/generate-task.md +33 -0
- package/pipeline/commands/multi-agent/help.md +12 -0
- package/pipeline/commands/multi-agent/manual-test.md +9 -2
- package/pipeline/commands/multi-agent/refs/channels/pr.md +1 -1
- package/pipeline/commands/multi-agent/refs/cross-cli-contract.md +7 -6
- package/pipeline/commands/multi-agent/refs/generate-issue.md +197 -0
- package/pipeline/commands/multi-agent/refs/keychain.md +12 -0
- package/pipeline/commands/multi-agent/refs/phases/phase-0-init.md +40 -2
- package/pipeline/commands/multi-agent/refs/phases/phase-3-dev.md +12 -0
- package/pipeline/commands/multi-agent/refs/phases/phase-4-review.md +4 -23
- package/pipeline/commands/multi-agent/refs/phases/phase-5-test.md +6 -1
- package/pipeline/commands/multi-agent/refs/phases/phase-7-report.md +5 -1
- package/pipeline/commands/multi-agent/refs/progress-contract.md +1 -0
- package/pipeline/commands/multi-agent/refs/tracker-contract.md +56 -13
- package/pipeline/commands/multi-agent/resume.md +6 -2
- package/pipeline/commands/multi-agent/sync.md +5 -5
- package/pipeline/commands/multi-agent.md +4 -0
- package/pipeline/lib/figma-mcp-refresh.sh +79 -0
- package/pipeline/preferences-template.json +2 -1
- package/pipeline/schemas/prefs.schema.json +35 -0
- package/pipeline/schemas/token-budget.json +7 -7
- package/pipeline/scripts/README.md +1 -0
- package/pipeline/scripts/fixtures/install-layout.tsv +6 -6
- package/pipeline/scripts/phase-tracker.sh +134 -22
- package/pipeline/scripts/smoke-channels-approval-gate.sh +60 -0
- package/pipeline/scripts/smoke-generate-issue.sh +114 -0
- package/pipeline/scripts/smoke-phase-tracker.sh +69 -0
- package/pipeline/scripts/smoke-progress-contract.sh +9 -0
- package/pipeline/scripts/smoke-tasklist-ordering.sh +1 -0
- package/pipeline/scripts/smoke-token-preflight.sh +82 -0
- package/pipeline/scripts/smoke-tracker-contract.sh +62 -0
- package/pipeline/scripts/smoke-update-check.sh +122 -0
- package/pipeline/scripts/update-check.sh +82 -0
- package/pipeline/skills/.skills-index.json +22 -4
- package/pipeline/skills/shared/core/multi-agent/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-channels/SKILL.md +4 -2
- package/pipeline/skills/shared/core/multi-agent-generate-bug/SKILL.md +39 -0
- package/pipeline/skills/shared/core/multi-agent-generate-task/SKILL.md +39 -0
- package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +4 -0
- package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +5 -5
- package/pipeline/skills/skills-index.md +5 -3
|
@@ -58,8 +58,9 @@ Phases by mode:
|
|
|
58
58
|
| Mode | Phases |
|
|
59
59
|
|---|---|
|
|
60
60
|
| Full pipeline | 0,1,2,3,4,5,6,7 |
|
|
61
|
-
| `--dev` | 0,3,6,7 |
|
|
62
|
-
| `--autopilot`, `--dev autopilot` |
|
|
61
|
+
| `--dev` | 0,3,5,6,7 |
|
|
62
|
+
| `--dev autopilot`, `--dev local`, `--dev local autopilot` | 0,3,6,7 (Phase 5 interactive test gate dropped) |
|
|
63
|
+
| `--autopilot` | same as full pipeline, with confirmations skipped |
|
|
63
64
|
|
|
64
65
|
Register each phase:
|
|
65
66
|
|
|
@@ -118,9 +119,10 @@ Mode-specific phase sets:
|
|
|
118
119
|
| Mode | TaskCreate set (in order) |
|
|
119
120
|
|---|---|
|
|
120
121
|
| Full pipeline (`/multi-agent`, `:autopilot`, `:local`, `:local-autopilot`) | 0 → 1 → 2 → 3 → 4 → 5 → 6 → 7 (all 8) |
|
|
121
|
-
| `:dev
|
|
122
|
+
| `:dev` | 0 → 3 → 5 → 6 → 7 (5 phases - 1/2/4 omitted entirely) |
|
|
123
|
+
| `:dev-autopilot`, `:dev-local`, `:dev-local-autopilot` | 0 → 3 → 6 → 7 (4 phases - 1/2/4/5 omitted entirely; the autopilot/local variants drop the interactive Phase 5 test gate) |
|
|
122
124
|
|
|
123
|
-
Note: in `--dev` modes the omitted phases (1, 2, 4) **do not get TaskCreate calls at all** - they're not part of the mode's phase set. The "[SKIPPED]" pattern above only applies if a normally-included phase is conditionally skipped at runtime.
|
|
125
|
+
Note: in `--dev` modes the omitted phases (1, 2, 4 - plus 5 in the autopilot/local variants) **do not get TaskCreate calls at all** - they're not part of the mode's phase set. The "[SKIPPED]" pattern above only applies if a normally-included phase is conditionally skipped at runtime. The authoritative per-mode set is the `for p in ...` init block in each mode's own entry doc; this table mirrors those blocks.
|
|
124
126
|
|
|
125
127
|
**Enforcement**: `smoke-tasklist-ordering.sh` scans every mode entry point doc (`commands/multi-agent.md`, `commands/multi-agent/{autopilot,local,local-autopilot,dev,dev-autopilot,dev-local,dev-local-autopilot}.md` + Copilot mirrors) for the explicit "in phase-number order" rule. Inventory drift fails the smoke.
|
|
126
128
|
|
|
@@ -172,23 +174,40 @@ TaskUpdate({taskId: <dev_task>, activeForm: "Editing TopBarView.swift"})
|
|
|
172
174
|
TaskUpdate({taskId: <dev_task>, activeForm: "Running xcodebuild test"})
|
|
173
175
|
```
|
|
174
176
|
|
|
175
|
-
**Other CLIs** - `meta
|
|
177
|
+
**Other CLIs** - the dedicated `now` action (quiet: writes `meta.Now`, never renders; the card picks it up at the next boundary render/update):
|
|
176
178
|
```bash
|
|
177
|
-
bash $HOME/.claude/scripts/phase-tracker.sh
|
|
178
|
-
bash $HOME/.claude/scripts/phase-tracker.sh render
|
|
179
|
+
bash $HOME/.claude/scripts/phase-tracker.sh now 3 "editing TopBarView.swift"
|
|
179
180
|
```
|
|
180
181
|
|
|
181
|
-
The `Now`
|
|
182
|
+
The `Now` value shows up in the bordered card as `Now: editing TopBarView.swift` (truncated to 60 chars by the script).
|
|
183
|
+
|
|
184
|
+
**Progress-line mirror (required).** Every `normal`-tier progress line from the progress contract's canonical "When to emit" set is ALSO mirrored to the active phase, so the tracker always answers "what is it doing right now":
|
|
185
|
+
|
|
186
|
+
- Claude Code: `TaskUpdate({activeForm: "<line text, arrow prefix stripped>"})`
|
|
187
|
+
- Other CLIs: `phase-tracker.sh now <N> "<line text, arrow prefix stripped>"`
|
|
188
|
+
|
|
189
|
+
Throttling rules: mirror only canonical-set lines (`verbose`-tier internals are not mirrored); at most one mirror per emitted line; skip the mirror when the text is identical to the last mirrored value; the mirror itself never triggers a render. Text is truncated to 60 chars.
|
|
190
|
+
|
|
191
|
+
### Delegated phases - mirror limitation + chunked dispatch (required)
|
|
192
|
+
|
|
193
|
+
When a phase's work is delegated to a subagent (Phase 3 Dev on Opus in `--dev` modes, `figma-to-component` dispatch, Phase 1 explorers, Phase 4 reviewers), the visual channel freezes for the duration of the Agent call: the orchestrator is blocked while the call is in flight, so it cannot fire `TaskUpdate` / `now` / `tokens`, and a subagent cannot drive the parent session's TaskList (its own TaskCreate/TaskUpdate calls land on an invisible child list). The progress-line mirror above can therefore only fire while the orchestrator holds control. Rules:
|
|
194
|
+
|
|
195
|
+
1. **Pre-dispatch marker.** Immediately before every Agent call, set the active-phase line to the delegation itself, so the frozen interval at least states what is running and on which model:
|
|
196
|
+
- Claude Code: `TaskUpdate({activeForm: "Dev subagent (opus): <task subject>"})`
|
|
197
|
+
- Other CLIs: `phase-tracker.sh now <N> "dev subagent (opus): <task subject>"`
|
|
198
|
+
2. **Chunk long delegations.** A phase whose delegated work spans multiple tasks MUST NOT go out as one monolithic Agent call. Dispatch per task (the Phase 2 task graph, or in `--dev` mode the self-generated task list, is the natural chunk boundary) so the orchestrator regains control at each boundary and refreshes `activeForm`, `tokens`, and `now` between chunks. Single-task phases and inherently atomic dispatches (one reviewer, one explorer) are exempt.
|
|
199
|
+
3. **Post-chunk accounting.** When each chunk returns, record its token estimate (`phase-tracker.sh tokens <N> <in> <out>`) before dispatching the next chunk - not accumulated once at phase end.
|
|
182
200
|
|
|
183
201
|
### 5. Token accounting - automatic (manual top-up optional)
|
|
184
202
|
|
|
185
203
|
The native TaskList header automatically prints `↑Nk tokens · thought for Ns` - Claude Code uses session-level metrics. For per-phase token attribution:
|
|
186
204
|
|
|
187
205
|
```bash
|
|
188
|
-
bash $HOME/.claude/scripts/phase-tracker.sh tokens <N> <input_count> <output_count>
|
|
206
|
+
bash $HOME/.claude/scripts/phase-tracker.sh tokens <N> <input_count> <output_count> [cached_count]
|
|
207
|
+
bash $HOME/.claude/scripts/phase-tracker.sh model <N> <model_name>
|
|
189
208
|
```
|
|
190
209
|
|
|
191
|
-
Token counts are additive - multiple calls accumulate. Stored per phase in the state file; surfaced in `:log` reports.
|
|
210
|
+
Token counts are additive - multiple calls accumulate. `input_count` is FRESH input (cache-exclusive); the optional 4th arg is the prompt-cache-read count, priced at the discounted rate. `model` tags the phase so the card and the cost helper can price it. Stored per phase in the state file; surfaced in `:log` reports, on the bash card tile (`<elapsed> · <tok> tok · ~$<usd>`), and in the card footer (total USD + cached tokens).
|
|
192
211
|
|
|
193
212
|
**MANDATORY: per-phase token narration on completion (v9.10.2).** The native
|
|
194
213
|
TaskList widget cannot display per-phase tokens - it shows name, status, and
|
|
@@ -203,9 +222,22 @@ Phase <N> <name> tamamlandi - ~<in> giris / ~<out> cikis token (<model>, ~$<usd>
|
|
|
203
222
|
Phase <N> <name> done - ~<in> in / ~<out> out tokens (<model>, ~$<usd>)
|
|
204
223
|
```
|
|
205
224
|
|
|
206
|
-
USD comes from `
|
|
207
|
-
|
|
208
|
-
|
|
225
|
+
USD comes from `phase-tracker.sh cost <N>` - the single pricing implementation
|
|
226
|
+
(cost-table.json rates, cached tokens at the discounted rate, floored to
|
|
227
|
+
cents; prints `-` when the model is unknown). Do not re-implement the math
|
|
228
|
+
inline. Phases with zero recorded tokens print `(no LLM calls)` instead of
|
|
229
|
+
fabricating numbers.
|
|
230
|
+
|
|
231
|
+
**Completion tile suffix (Claude Code).** The native widget cannot show
|
|
232
|
+
per-phase tokens, but subject edits after creation are safe (tile order is
|
|
233
|
+
fixed at TaskCreate time). So on phase completion, in addition to the
|
|
234
|
+
narration line, append the spend to the tile subject:
|
|
235
|
+
|
|
236
|
+
```text
|
|
237
|
+
TaskUpdate({taskId: <phase_task>, subject: "Phase 3: Dev · ~35k tok · ~$0.26"})
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Skip the suffix when the phase recorded zero tokens (subject stays clean).
|
|
209
241
|
|
|
210
242
|
**Honesty note:** on Claude Code the orchestrator does not receive its own
|
|
211
243
|
usage metering, so per-phase counts are content-size estimates (chars/4 for
|
|
@@ -259,11 +291,22 @@ When `/multi-agent:resume <task_id>` is called:
|
|
|
259
291
|
|
|
260
292
|
The `tasklist_id` meta from the previous session is replaced with the new IDs during resume.
|
|
261
293
|
|
|
294
|
+
## Continuation runs (finish / manual-test)
|
|
295
|
+
|
|
296
|
+
A pre-existing `tracker-state.json` for the task is never re-initialized. Rules for any command that continues an earlier run (`/multi-agent:finish`, `/multi-agent:manual-test`, resume):
|
|
297
|
+
|
|
298
|
+
1. `init` runs ONLY when no state file exists for the task. Otherwise the existing file is kept - phase history (elapsed, tokens, model, meta) survives.
|
|
299
|
+
2. The continuing command re-declares its phase set with `add` - `add` is idempotent, so existing phases keep their name, status, and token history; only genuinely new phases are appended. The card renders phases sorted by numeric id, so mixed sets stay in order.
|
|
300
|
+
3. If Phase 5 was left `in_progress` with `Now: awaiting local test (user)`, the continuing command marks it `update 5 completed` + `meta 5 Result "local test done (user)"` before its own work starts (finish may re-open it with `update 5 in_progress` when its build+test gate runs; elapsed keeps the original `started_at`, which is acceptable).
|
|
301
|
+
4. On Claude Code, rebuild the FULL TaskList from the state file (completed tiles included) in phase order before any `TaskUpdate`, refreshing every `tasklist_id` meta - exactly the Resume behaviour above.
|
|
302
|
+
5. Print ONE line in `outputLanguage` summarizing the inherited history, e.g. `Continuing PROJ-12345: phases 0-3 finished earlier (12m, 38.4k tok, ~$0.74)` (USD via `cost total`), then `render`.
|
|
303
|
+
|
|
262
304
|
## Anti-patterns
|
|
263
305
|
|
|
264
306
|
❌ **TaskList only** → `:resume` will not work; no run history is preserved.
|
|
265
307
|
❌ **`phase-tracker.sh` only** in Claude Code → the user sees no widget, only bash stdout snapshots - the #1 source of "I see no phases" complaints.
|
|
266
308
|
❌ **Wiring `phase-tracker.sh render` to `statusLine` config** → it drops below the screen as a placeholder; the user complained, removed in v7.9.0.
|
|
309
|
+
❌ **One monolithic subagent call for a whole multi-task phase** → the tile freezes for the entire phase (no `activeForm`, no `tokens`, no `now`) - the user sees a dead widget for 20+ minutes. Chunk per task; see "Delegated phases" above.
|
|
267
310
|
|
|
268
311
|
## Verification
|
|
269
312
|
|
|
@@ -31,6 +31,10 @@ Resume a paused or failed task from the last successful phase.
|
|
|
31
31
|
- Phase 3 code → already in the worktree
|
|
32
32
|
- Recent `git log --oneline -10` in the worktree grounds what was actually committed vs. claimed.
|
|
33
33
|
|
|
34
|
-
4. **
|
|
34
|
+
4. **Rebuild the phase tiles** - load `tracker-state.json` for the task (never re-init it; `refs/tracker-contract.md` "Resume behaviour" + "Continuation runs"):
|
|
35
|
+
- Claude Code: `TaskCreate` every phase from the state file in phase order, then `TaskUpdate` each to its stored status, and replace every `tasklist_id` meta with the new IDs.
|
|
36
|
+
- Other CLIs: a single `bash $HOME/.claude/scripts/phase-tracker.sh render`.
|
|
35
37
|
|
|
36
|
-
5. **
|
|
38
|
+
5. **Continue the pipeline** - start from the next phase (same pipeline as the main multi-agent command).
|
|
39
|
+
|
|
40
|
+
6. **Log**: `🔄 Resumed {JIRA-KEY}-{id} from Phase {N}`
|
|
@@ -58,7 +58,7 @@ Run every step automatically:
|
|
|
58
58
|
Step 0: FIGMA_SYNC SKIP (deprecated - feedback_figma_source_deprecated)
|
|
59
59
|
Step 1: PLATFORM Detect macOS / Linux / Windows (Git Bash / WSL); export PLATFORM env
|
|
60
60
|
Step 1.5: DETECT Compare timestamps, find stale targets
|
|
61
|
-
Step 2: COPILOT Claude Code -> Copilot CLI (instructions +
|
|
61
|
+
Step 2: COPILOT Claude Code -> Copilot CLI (instructions + 37 sub-command skills)
|
|
62
62
|
Step 3: REPO Claude Code -> pipeline repo (genericized, personal data scrub, bash -n on all sh)
|
|
63
63
|
Step 3c: PLUGINS pipeline shared/external -> multi-agent-plugins marketplace (rebuild knowledge/,
|
|
64
64
|
bump changed plugins' patch version, commit + push the plugins repo)
|
|
@@ -277,14 +277,14 @@ This runs on the Claude <-> Copilot axis — the two CLIs the pipeline supports
|
|
|
277
277
|
|-------------|-------------|
|
|
278
278
|
| `~/.claude/commands/multi-agent/{cmd}.md` | `~/.copilot/skills/multi-agent-{cmd}/SKILL.md` |
|
|
279
279
|
|
|
280
|
-
**
|
|
280
|
+
**37 commands are synced** (canonical inventory - must match `cross-cli-contract.md` section 1; drift = contract violation):
|
|
281
281
|
|
|
282
282
|
```
|
|
283
283
|
analysis, analysis-resolve, autopilot, build-optimize, channels, delete, dev,
|
|
284
284
|
dev-autopilot, dev-local, dev-local-autopilot, diff-explain, finish, garbage-collect,
|
|
285
|
-
help, issue, jira, kill, language, local,
|
|
286
|
-
prune-logs, purge, refactor, resume, review,
|
|
287
|
-
sync, test, update
|
|
285
|
+
generate-bug, generate-task, help, issue, jira, kill, language, local,
|
|
286
|
+
local-autopilot, log, manual-test, prune-logs, purge, refactor, resume, review,
|
|
287
|
+
scan, search, setup, stack, status, sync, test, update
|
|
288
288
|
```
|
|
289
289
|
|
|
290
290
|
**NOT synced**: `refs/*` - lazy-load references, Claude Code specific
|
|
@@ -77,6 +77,8 @@ Lib scripts (`~/.claude/lib/`):
|
|
|
77
77
|
| `analysis ["<feature>"]` | Standalone feature-spec analizi: Figma / Swagger / Confluence / Jira / repo girdileri sabit 7-bölümlük şablona dökülür, humanizer'dan geçer, Local/Confluence/Jira hedef(ler)ine post edilir. Worktree veya commit yok. Dev'e zincirleme yok. |
|
|
78
78
|
| `build-optimize` | iOS-only Xcode build performance wrapper. Vendored `xcode-build-orchestrator`'a dispatch eder; benchmark + compilation / project / SPM analyzer'lar + recommend-first plan `.build-benchmark/optimization-plan.md`. Non-iOS stack'lerde fail-fast. |
|
|
79
79
|
| `channels [PR-url\|#N\|Jira-url\|Jira-id] [--channels pr,jira,confluence,wiki] [--content normal,test,auto-diff,note] [--message "..."]` | Post task report to multi-select channels (PR description, Jira comment, Confluence page, Wiki pages) with multi-select content sources. Humanizer pass per-channel. Bitbucket PR updates use reviewer-preserving PUT. Phase 7 delegates to this command; also invocable post-hoc for fixes made outside the pipeline. No worktree. |
|
|
80
|
+
| `generate-task ["desc"] [figma-url]` | Create a standards-compliant Jira **Task**: mines the project's recent Tasks for conventions (summary format, template, labels, priority), detects the active sprint, asks about unknown fields, then full draft preview + explicit approval before create. No worktree, no commits. |
|
|
81
|
+
| `generate-bug ["desc"] [figma-url]` | Create a standards-compliant Jira **Bug**: same convention mining + active-sprint detection; free-text logs/devices map to Steps to Reproduce / Environment; full draft preview + explicit approval before create. No worktree, no commits. |
|
|
80
82
|
| `test` or `test [args]` | UI Bug Hunter - screenshot + tap + analyze on booted simulator via MCP (read `$HOME/.claude/commands/sim-test.md`). `/multi-agent:test` also resolves here via the `commands/multi-agent/test.md` delegate. |
|
|
81
83
|
| `manual-test [#id]` | Phase 5 standalone Manual Test - checks out the task branch, prints Xcode / SourceTree hints, waits for user verdict (`ok` / `fix: ...`). |
|
|
82
84
|
| `stack [ios\|android\|backend\|mobile\|all]` | Swap skills for next conversation. No arg = show current stack. |
|
|
@@ -116,6 +118,8 @@ This command uses lazy loading for token efficiency. Read the relevant sub-file
|
|
|
116
118
|
| `local-autopilot` | `$HOME/.claude/commands/multi-agent/local-autopilot.md` |
|
|
117
119
|
| `dev-local` | `$HOME/.claude/commands/multi-agent/dev-local.md` |
|
|
118
120
|
| `dev-local-autopilot` | `$HOME/.claude/commands/multi-agent/dev-local-autopilot.md` |
|
|
121
|
+
| `generate-task` | `$HOME/.claude/commands/multi-agent/generate-task.md` (loads `refs/generate-issue.md`) |
|
|
122
|
+
| `generate-bug` | `$HOME/.claude/commands/multi-agent/generate-bug.md` (loads `refs/generate-issue.md`) |
|
|
119
123
|
| `stack` | `$HOME/.claude/commands/multi-agent/stack.md` |
|
|
120
124
|
| `language` | Handled inline - set/show prompt language in preferences |
|
|
121
125
|
| SwiftUI component task (iOS) | `$HOME/.claude/commands/multi-agent/refs/swiftui-guide.md` |
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# figma-mcp-refresh.sh - silent Figma MCP (figu_) token renewal via OAuth refresh grant.
|
|
3
|
+
#
|
|
4
|
+
# Used by the Phase 0 token pre-flight (refs/phases/phase-0-init.md Step 0.7) and the
|
|
5
|
+
# expired-token decision (refs/keychain.md). Never prints token values - status lines only.
|
|
6
|
+
#
|
|
7
|
+
# Flow:
|
|
8
|
+
# 1. Resolve the access-token Keychain name from prefs.global.keychainMapping.figma_mcp.
|
|
9
|
+
# 2. Read the refresh token from "<name>_Refresh" (written by the user's generation script).
|
|
10
|
+
# 3. Read client credentials from .figma-oauth.json next to prefs.global.tokenScripts.figma_mcp.
|
|
11
|
+
# 4. POST grant_type=refresh_token to the Figma token endpoint.
|
|
12
|
+
# 5. On success save the new access token (and rotated refresh token) back to the Keychain.
|
|
13
|
+
#
|
|
14
|
+
# Exit codes:
|
|
15
|
+
# 0 renewed (access token replaced in Keychain)
|
|
16
|
+
# 1 refresh grant rejected by Figma (refresh token dead - run the generation script)
|
|
17
|
+
# 2 prerequisites missing (no mapping / no refresh entry / no oauth config)
|
|
18
|
+
|
|
19
|
+
set -euo pipefail
|
|
20
|
+
|
|
21
|
+
PREFS_FILE="${PREFS_FILE:-$HOME/.claude/multi-agent-preferences.json}"
|
|
22
|
+
TOKEN_ENDPOINT="https://api.figma.com/v1/oauth/token"
|
|
23
|
+
ACCOUNT="${USER:-$(whoami)}"
|
|
24
|
+
|
|
25
|
+
say() { printf '%s\n' "$*"; }
|
|
26
|
+
|
|
27
|
+
[ -f "$PREFS_FILE" ] || { say "figma-mcp-refresh: prefs file missing ($PREFS_FILE)"; exit 2; }
|
|
28
|
+
|
|
29
|
+
KEY_NAME=$(jq -r '.global.keychainMapping.figma_mcp // empty' "$PREFS_FILE")
|
|
30
|
+
[ -n "$KEY_NAME" ] || { say "figma-mcp-refresh: keychainMapping.figma_mcp not set"; exit 2; }
|
|
31
|
+
|
|
32
|
+
REFRESH_KEY="${KEY_NAME}_Refresh"
|
|
33
|
+
REFRESH_TOKEN=$(security find-generic-password -s "$REFRESH_KEY" -w 2>/dev/null || true)
|
|
34
|
+
[ -n "$REFRESH_TOKEN" ] || { say "figma-mcp-refresh: no refresh token at '$REFRESH_KEY'"; exit 2; }
|
|
35
|
+
|
|
36
|
+
SCRIPT_PATH=$(jq -r '.global.tokenScripts.figma_mcp // empty' "$PREFS_FILE")
|
|
37
|
+
OAUTH_CONFIG=""
|
|
38
|
+
if [ -n "$SCRIPT_PATH" ]; then
|
|
39
|
+
OAUTH_CONFIG="$(dirname "$SCRIPT_PATH")/.figma-oauth.json"
|
|
40
|
+
fi
|
|
41
|
+
[ -n "$OAUTH_CONFIG" ] && [ -f "$OAUTH_CONFIG" ] || { say "figma-mcp-refresh: .figma-oauth.json not found (tokenScripts.figma_mcp unset or sibling config missing)"; exit 2; }
|
|
42
|
+
|
|
43
|
+
CLIENT_ID=$(jq -r '.client_id // empty' "$OAUTH_CONFIG")
|
|
44
|
+
CLIENT_SECRET=$(jq -r '.client_secret // empty' "$OAUTH_CONFIG")
|
|
45
|
+
[ -n "$CLIENT_ID" ] || { say "figma-mcp-refresh: client_id missing in .figma-oauth.json"; exit 2; }
|
|
46
|
+
|
|
47
|
+
CURL_ARGS=(
|
|
48
|
+
--data-urlencode "grant_type=refresh_token"
|
|
49
|
+
--data-urlencode "refresh_token=${REFRESH_TOKEN}"
|
|
50
|
+
--data-urlencode "client_id=${CLIENT_ID}"
|
|
51
|
+
)
|
|
52
|
+
[ -n "$CLIENT_SECRET" ] && CURL_ARGS+=( --data-urlencode "client_secret=${CLIENT_SECRET}" )
|
|
53
|
+
|
|
54
|
+
RESPONSE=$(curl -s --max-time 20 -X POST "$TOKEN_ENDPOINT" \
|
|
55
|
+
-H "Content-Type: application/x-www-form-urlencoded" \
|
|
56
|
+
"${CURL_ARGS[@]}")
|
|
57
|
+
|
|
58
|
+
NEW_ACCESS=$(printf '%s' "$RESPONSE" | jq -r '.access_token // empty' 2>/dev/null || true)
|
|
59
|
+
NEW_REFRESH=$(printf '%s' "$RESPONSE" | jq -r '.refresh_token // empty' 2>/dev/null || true)
|
|
60
|
+
EXPIRES_IN=$(printf '%s' "$RESPONSE" | jq -r '.expires_in // "?"' 2>/dev/null || true)
|
|
61
|
+
|
|
62
|
+
if [ -z "$NEW_ACCESS" ]; then
|
|
63
|
+
ERR=$(printf '%s' "$RESPONSE" | jq -r '.error // .message // "unknown"' 2>/dev/null || echo "unknown")
|
|
64
|
+
say "figma-mcp-refresh: refresh grant rejected ($ERR) - regenerate via tokenScripts.figma_mcp"
|
|
65
|
+
exit 1
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
# Save new access token first, then the rotated refresh token - order matters so a
|
|
69
|
+
# mid-write failure never leaves us with a lost refresh token AND a stale access token.
|
|
70
|
+
security delete-generic-password -s "$KEY_NAME" -a "$ACCOUNT" >/dev/null 2>&1 || true
|
|
71
|
+
security add-generic-password -s "$KEY_NAME" -a "$ACCOUNT" -w "$NEW_ACCESS" -T "" -U
|
|
72
|
+
|
|
73
|
+
if [ -n "$NEW_REFRESH" ]; then
|
|
74
|
+
security delete-generic-password -s "$REFRESH_KEY" -a "$ACCOUNT" >/dev/null 2>&1 || true
|
|
75
|
+
security add-generic-password -s "$REFRESH_KEY" -a "$ACCOUNT" -w "$NEW_REFRESH" -T "" -U
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
say "figma-mcp-refresh: renewed '$KEY_NAME' (expires_in=${EXPIRES_IN}s, refresh $( [ -n "$NEW_REFRESH" ] && echo rotated || echo unchanged ))"
|
|
79
|
+
exit 0
|
|
@@ -179,6 +179,17 @@
|
|
|
179
179
|
}
|
|
180
180
|
}
|
|
181
181
|
},
|
|
182
|
+
"tokenScripts": {
|
|
183
|
+
"type": "object",
|
|
184
|
+
"additionalProperties": {
|
|
185
|
+
"type": [
|
|
186
|
+
"string",
|
|
187
|
+
"null"
|
|
188
|
+
]
|
|
189
|
+
},
|
|
190
|
+
"default": {},
|
|
191
|
+
"description": "Maps service ids to user-owned token generation scripts (absolute paths, personal - never synced). Used by the Phase 0 token pre-flight: figma_mcp silent renewal reads the .figma-oauth.json next to tokenScripts.figma_mcp; the 'Regenerate now (script)' option runs the script itself."
|
|
192
|
+
},
|
|
182
193
|
"platformIdentityRouting": {
|
|
183
194
|
"type": "object",
|
|
184
195
|
"description": "v2.1.0+. Maps repo URL glob patterns to identity names. Used in Phase 0 to auto-select git identity + PAT based on repo origin. Prevents corporate identity leaking into personal repos and vice versa.",
|
|
@@ -701,6 +712,30 @@
|
|
|
701
712
|
"default": false,
|
|
702
713
|
"description": "v6.1.0+ \u2014 Phase 4 Step 2.5 rebuttal round. When reviewers disagree (mixed blocker/approved verdict), each reviewer is re-prompted with the others' opposing arguments for one additional round before triage. Lifts signal quality on ambiguous findings at ~1\u00d7 Step 2 token cost. Off by default \u2014 flip for security-critical or release-branch reviews."
|
|
703
714
|
},
|
|
715
|
+
"updateCheck": {
|
|
716
|
+
"type": "object",
|
|
717
|
+
"additionalProperties": false,
|
|
718
|
+
"description": "v10.9+ - Phase 0 Step 0.6 advisory version check. Once per ttlHours window, a bounded (3s) registry read compares the installed version against dist-tags.latest. Newer version found: interactive modes ask 'Update now / Continue' (yes runs the /multi-agent:update flow, then the run continues); autopilot logs one line and never asks. Offline/failed checks are silent; the step never blocks the pipeline.",
|
|
719
|
+
"properties": {
|
|
720
|
+
"enabled": {
|
|
721
|
+
"type": "boolean",
|
|
722
|
+
"default": true,
|
|
723
|
+
"description": "Master switch. On by default - the cost is at most one 3s-bounded curl per ttlHours."
|
|
724
|
+
},
|
|
725
|
+
"ttlHours": {
|
|
726
|
+
"type": "integer",
|
|
727
|
+
"minimum": 1,
|
|
728
|
+
"maximum": 168,
|
|
729
|
+
"default": 24,
|
|
730
|
+
"description": "Cache window for the registry read."
|
|
731
|
+
},
|
|
732
|
+
"autoUpdate": {
|
|
733
|
+
"type": "boolean",
|
|
734
|
+
"default": false,
|
|
735
|
+
"description": "When true, skip the question and run the update flow automatically before the run starts (interactive AND autopilot). Off by default - self-modifying ~/.claude without asking is a surprise."
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
},
|
|
704
739
|
"verifyByTest": {
|
|
705
740
|
"type": "object",
|
|
706
741
|
"additionalProperties": false,
|
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
"$id": "https://github.com/mmerterden/multi-agent-pipeline/pipeline/schemas/token-budget.json",
|
|
4
4
|
"description": "Per-phase token budget for lazy-loaded pipeline docs. Enforced by smoke-token-budget.sh.",
|
|
5
5
|
"phases": {
|
|
6
|
-
"phase-0-init": { "max_tokens":
|
|
6
|
+
"phase-0-init": { "max_tokens": 12400, "warn_tokens": 10900 },
|
|
7
7
|
"phase-1-analysis": { "max_tokens": 3750, "warn_tokens": 3300 },
|
|
8
8
|
"phase-2-planning": { "max_tokens": 6500, "warn_tokens": 5750 },
|
|
9
|
-
"phase-3-dev": { "max_tokens":
|
|
10
|
-
"phase-4-review": { "max_tokens":
|
|
11
|
-
"phase-5-test": { "max_tokens":
|
|
12
|
-
"phase-6-commit": { "max_tokens":
|
|
9
|
+
"phase-3-dev": { "max_tokens": 7900, "warn_tokens": 6950 },
|
|
10
|
+
"phase-4-review": { "max_tokens": 13250, "warn_tokens": 11650 },
|
|
11
|
+
"phase-5-test": { "max_tokens": 2550, "warn_tokens": 2250 },
|
|
12
|
+
"phase-6-commit": { "max_tokens": 6150, "warn_tokens": 5400 },
|
|
13
13
|
"phase-7-report": { "max_tokens": 5600, "warn_tokens": 4950 }
|
|
14
14
|
},
|
|
15
|
-
"total_max_tokens":
|
|
16
|
-
"note": "Token estimate = ceil(chars / 4). Per-phase budget rule: warn = current+10% (rounded to nearest 50), max = current+25%. Gives ~6 edit cycles of headroom before warn trips - intentionally quiet under normal maintenance, loud when a phase grows unusually. Only the active phase is loaded (lazy). Recalibrated at v10.0.0 after the validator/consistency/simplifier/lesson gate contracts landed in phases 1-4 (prose
|
|
15
|
+
"total_max_tokens": 50000,
|
|
16
|
+
"note": "Token estimate = ceil(chars / 4). Per-phase budget rule: warn = current+10% (rounded to nearest 50), max = current+25%. Gives ~6 edit cycles of headroom before warn trips - intentionally quiet under normal maintenance, loud when a phase grows unusually. Only the active phase is loaded (lazy). Recalibrated at v10.0.0 after the validator/consistency/simplifier/lesson gate contracts landed in phases 1-4. Recalibrated again at v10.9.0 after the verify-by-test (Phase 4 Step 3.7), update-check (Phase 0 Step 0.6), immutable-test (Phase 3 GREEN) and redTests re-entry contracts landed - Step 3.7 prose was compressed to a pointer into refs/features/verify-by-test.md before the recalibration."
|
|
17
17
|
}
|
|
@@ -24,6 +24,7 @@ Validate contracts. Each emits `══ <name> smoke: N passed, M failed ══`
|
|
|
24
24
|
- `smoke-phase4-triage.sh` - Phase 4 reviewer → triage flow
|
|
25
25
|
- `smoke-verify-by-test.sh` - Phase 4 Step 3.7 verify-by-test contract (v10.8.0)
|
|
26
26
|
- `smoke-handoff-contract.sh` - phase-boundary structured handoff + handoff-first resume (v10.8.0)
|
|
27
|
+
- `smoke-update-check.sh` - Phase 0 Step 0.6 advisory update-check contract (v10.9.0)
|
|
27
28
|
|
|
28
29
|
### Schema + state
|
|
29
30
|
- `smoke-schema-validation.sh` - all JSON schemas validate
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
.claude/CLAUDE.md 1
|
|
2
2
|
.claude/agents 8
|
|
3
|
-
.claude/commands
|
|
4
|
-
.claude/lib
|
|
3
|
+
.claude/commands 92
|
|
4
|
+
.claude/lib 24
|
|
5
5
|
.claude/multi-agent-preferences.json 1
|
|
6
6
|
.claude/rules 12
|
|
7
7
|
.claude/schemas 23
|
|
8
|
-
.claude/scripts
|
|
8
|
+
.claude/scripts 174
|
|
9
9
|
.claude/settings.json 1
|
|
10
10
|
.claude/skills 560
|
|
11
11
|
.copilot/agents 8
|
|
12
12
|
.copilot/copilot-instructions.md 1
|
|
13
|
-
.copilot/lib
|
|
13
|
+
.copilot/lib 24
|
|
14
14
|
.copilot/schemas 23
|
|
15
|
-
.copilot/scripts
|
|
16
|
-
.copilot/skills
|
|
15
|
+
.copilot/scripts 174
|
|
16
|
+
.copilot/skills 598
|