@mmerterden/multi-agent-pipeline 10.9.0 → 11.0.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 +170 -0
- package/README.md +1 -1
- 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.md +34 -0
- package/pipeline/commands/multi-agent/help.md +10 -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 +267 -0
- package/pipeline/commands/multi-agent/refs/keychain.md +12 -0
- package/pipeline/commands/multi-agent/refs/phases/phase-0-init.md +31 -2
- package/pipeline/commands/multi-agent/refs/phases/phase-3-dev.md +2 -0
- package/pipeline/commands/multi-agent/refs/phases/phase-4-review.md +2 -0
- 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 +9 -9
- package/pipeline/commands/multi-agent.md +2 -0
- package/pipeline/lib/figma-mcp-refresh.sh +79 -0
- package/pipeline/preferences-template.json +2 -1
- package/pipeline/schemas/prefs.schema.json +11 -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 +119 -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/skills/.skills-index.json +13 -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/SKILL.md +51 -0
- package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +2 -0
- package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +5 -5
- package/pipeline/skills/skills-index.md +4 -3
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
# Generate Issue - Shared Flow (generate)
|
|
2
|
+
|
|
3
|
+
> **TLDR** - Shared 12-step flow for `/multi-agent:generate`. Asks the issue type (Task / Bug / Story), mines the target project's existing same-type issues to learn team conventions, detects the active sprint, drafts a standards-compliant issue from a fixed standard template with auto-sizing sections, asks the user about every genuinely unknown field, renders a full preview, and creates the Jira issue only after explicit approval. Creates exactly one Jira issue per run - no branches, no commits, no worktrees.
|
|
4
|
+
|
|
5
|
+
Consumed by `generate.md`. This ref is never invoked directly.
|
|
6
|
+
|
|
7
|
+
## Hard rules (must not regress)
|
|
8
|
+
|
|
9
|
+
- **Approval gate is absolute.** Step [9/12] (full preview + explicit approval) runs on every invocation. There is no autopilot variant of this command and no preference that skips the gate. `Cancel` means nothing was created.
|
|
10
|
+
- **Never invent content.** Anything the user did not supply and mining could not derive stays an open question (step [8/12]) or is omitted entirely - never fabricated repro steps, environments, acceptance criteria, or test pass/fail results.
|
|
11
|
+
- **Standard template is the baseline.** The description structure comes from the type's standard template (see [7/12]), not from a mined heading set. Mining informs summary prefix, labels, components, priority norm, sprint placement, and test-scenario style - never replaces the standard section skeleton.
|
|
12
|
+
- **Auto-sizing.** A conditional section renders only when its trigger is present. No empty placeholder headings - if there is nothing to put in a conditional section, it does not appear.
|
|
13
|
+
- **Issue content language follows `prefs.global.outputLanguage`.** Summary and description are written in the user's output language (intentional exception to the "external payloads stay English" default - the issue is authored FOR the user's team). Code identifiers, file paths, and URLs stay verbatim. AskUserQuestion `question`/`description` also follow `outputLanguage`; `label`/`header` stay English.
|
|
14
|
+
- **UTF-8 verbatim POST path** (same as `refs/channels/jira.md`): description body goes to a file, `jq -n --rawfile` builds the payload, `curl --data-binary @file` ships it. Never round-trip through `unicode_escape`/`latin-1`, never hand-roll a re-encoding helper. Jira wiki markup (`h3.` headings, `[text|url]` links), real newlines, no HTML entities.
|
|
15
|
+
- **Humanizer pass** on the description body after composition, before the preview render.
|
|
16
|
+
- **Read-only until approval.** Steps 1-9 perform only GET requests. The first write of any kind is the `POST /rest/api/2/issue` in step [10/12].
|
|
17
|
+
|
|
18
|
+
## Standard templates
|
|
19
|
+
|
|
20
|
+
Each type has a standard section skeleton. `A` = always present. `C` = conditional (renders only when its trigger fires).
|
|
21
|
+
|
|
22
|
+
| Type | Section | Presence | Trigger (for `C`) |
|
|
23
|
+
|---|---|---|---|
|
|
24
|
+
| **Task** | Detailed Description | A | |
|
|
25
|
+
| | Scope | A | |
|
|
26
|
+
| | Acceptance Criteria | A | |
|
|
27
|
+
| | Test Scenarios | A | populated from mined test-scenario style; skeleton derived from AC when the project has no prior style |
|
|
28
|
+
| | API Contract / Swagger | C | Swagger URL, OpenAPI/contract snippet, or explicit endpoint mention in input |
|
|
29
|
+
| | Design Reference | C | Figma URL given |
|
|
30
|
+
| | Screenshots | C | user pasted image(s) or a Figma screenshot was fetched |
|
|
31
|
+
| | Notes | C | real content only |
|
|
32
|
+
| **Bug** | Detailed Description | A | |
|
|
33
|
+
| | Steps to Reproduce | A | |
|
|
34
|
+
| | Expected Result | A | |
|
|
35
|
+
| | Actual Result | A | |
|
|
36
|
+
| | Environment | A | |
|
|
37
|
+
| | Screenshots / Logs | C | user pasted image(s) or log/stack-trace text |
|
|
38
|
+
| | Regression / Test Scenario | C | derivable from the repro; else omitted |
|
|
39
|
+
| | API Contract | C | API-related bug + Swagger/contract/endpoint given |
|
|
40
|
+
| | Design Reference | C | Figma URL given |
|
|
41
|
+
| | Notes | C | real content only |
|
|
42
|
+
| **Story** | User Story (`As a ... I want ... so that ...`) | A | |
|
|
43
|
+
| | Detailed Description | A | |
|
|
44
|
+
| | Scope | A | |
|
|
45
|
+
| | Acceptance Criteria | A | |
|
|
46
|
+
| | Test Scenarios | A | same as Task |
|
|
47
|
+
| | API Contract / Swagger | C | Swagger URL / contract / endpoint mention |
|
|
48
|
+
| | Design Reference | C | Figma URL given |
|
|
49
|
+
| | Screenshots | C | user pasted image(s) or Figma screenshot fetched |
|
|
50
|
+
| | Dependencies / Notes | C | real content only |
|
|
51
|
+
|
|
52
|
+
Section headings render in `outputLanguage` (e.g. tr: "Detaylı Açıklama", "Kapsam", "Kabul Kriterleri", "Test Senaryoları", "Adımlar", "Beklenen Sonuç", "Gerçekleşen Sonuç", "Ortam", "Ekran Görüntüleri", "API Contract", "Design Reference", "Notlar").
|
|
53
|
+
|
|
54
|
+
## Flow
|
|
55
|
+
|
|
56
|
+
### [1/12] Pick account (`_account-picker`)
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
ACCOUNTS=$(~/.claude/lib/account-resolver.sh --providers jira)
|
|
60
|
+
TOKEN=$(~/.claude/lib/credential-store.sh get "$ACCOUNT_JIRA_TOKEN_KEY")
|
|
61
|
+
```
|
|
62
|
+
- Single account → auto-select silently (picker-contract behavior); multiple → AskUserQuestion.
|
|
63
|
+
- Output: `ACCOUNT_JIRA_TOKEN_KEY`, `ACCOUNT_JIRA_HOST`.
|
|
64
|
+
- Token missing/expired → Token Save Flow from `setup.md` inline; user skips → abort, nothing created.
|
|
65
|
+
|
|
66
|
+
### [2/12] Resolve project key
|
|
67
|
+
|
|
68
|
+
Fallback chain (same as `refs/issue-jira-triad.md` Create path):
|
|
69
|
+
1. `figmaConfig.jira.projectKey` (per-project config, when running inside a configured repo)
|
|
70
|
+
2. `prefs.global.defaultJiraKey`
|
|
71
|
+
3. Fetch and ask:
|
|
72
|
+
```bash
|
|
73
|
+
curl -s -H "Authorization: Bearer $TOKEN" \
|
|
74
|
+
"https://$ACCOUNT_JIRA_HOST/rest/api/2/project" \
|
|
75
|
+
| python3 -c 'import json,sys; [print(p["key"]+"\t"+p["name"]) for p in json.load(sys.stdin)]'
|
|
76
|
+
```
|
|
77
|
+
AskUserQuestion (single-select) → cache the choice to `prefs.global.defaultJiraKey`.
|
|
78
|
+
- Output: `PROJECT_KEY`.
|
|
79
|
+
|
|
80
|
+
### [3/12] Pick issue type
|
|
81
|
+
|
|
82
|
+
AskUserQuestion (single-select, `question` in `outputLanguage`, e.g. tr: "Ne oluşturmak istiyorsun?"): `Task` / `Bug` / `Story`. Never inferred silently.
|
|
83
|
+
- Output: `ISSUE_TYPE`. Selects the standard template from the table above.
|
|
84
|
+
- The chosen type drives the mining JQL in [5/12], the required-field discovery in [5/12], and the section skeleton in [7/12].
|
|
85
|
+
|
|
86
|
+
### [4/12] Parse input
|
|
87
|
+
|
|
88
|
+
- Any `figma.com` URL in `$ARGUMENTS` → `FIGMA_URL`. Node-id normalization: `-` → `:`. Branch URLs use `branchKey` as effective `fileKey` (see `rules/figma-pipeline.md` URL parsing).
|
|
89
|
+
- Any OpenAPI/Swagger URL (path or query contains `swagger`, `openapi`, `/v2/api-docs`, `/v3/api-docs`, or a `.json`/`.yaml` spec) → `SWAGGER_URL`.
|
|
90
|
+
- Pasted images (chat attachments) → `USER_SCREENSHOTS[]`. Pasted log/stack-trace text → kept with `FREE_TEXT` and later mapped to the Screenshots / Logs section (Bug) or Notes.
|
|
91
|
+
- Everything else → `FREE_TEXT`.
|
|
92
|
+
- All of `FREE_TEXT`/`FIGMA_URL`/`SWAGGER_URL`/`USER_SCREENSHOTS` empty → AskUserQuestion (free-text, in `outputLanguage`): "Describe the {type} you want to open."
|
|
93
|
+
- `FIGMA_URL`, `SWAGGER_URL`, and screenshots are always optional. Never ask for them; only use them when given.
|
|
94
|
+
|
|
95
|
+
### [5/12] Convention mining + field discovery + sprint detection (read-only)
|
|
96
|
+
|
|
97
|
+
Three GET groups. Run them before drafting anything.
|
|
98
|
+
|
|
99
|
+
**5a. Sample recent same-type issues:**
|
|
100
|
+
```bash
|
|
101
|
+
JQL="project = ${PROJECT_KEY} AND issuetype = ${ISSUE_TYPE} ORDER BY created DESC"
|
|
102
|
+
curl -s -H "Authorization: Bearer $TOKEN" \
|
|
103
|
+
"https://$ACCOUNT_JIRA_HOST/rest/api/2/search?jql=$(printf '%s' "$JQL" | python3 -c 'import sys,urllib.parse; print(urllib.parse.quote(sys.stdin.read()))')&fields=summary,description,labels,components,priority,fixVersions,issuelinks&maxResults=30"
|
|
104
|
+
```
|
|
105
|
+
Extract from the sample (thresholds are guidance, not hard gates):
|
|
106
|
+
- **Summary prefix pattern**: leading `[...]` or `AREA:` token frequency. Appears in >= 40% of samples → adopt as suggested prefix; top 2-3 prefixes become AskUserQuestion options in step 8 when ambiguous.
|
|
107
|
+
- **Top labels / components**: top 5 each by frequency → option lists for step 8.
|
|
108
|
+
- **Priority norm**: modal priority for this issuetype → pre-filled default, editable in preview. (Bug priorities often skew higher - respect the project's own norm.)
|
|
109
|
+
- **Epic usage rate**: share of sampled issues carrying an epic link → decides whether step 8 asks for an epic.
|
|
110
|
+
- **Test-scenario style** (Task / Story, and Bug regression): detect how the project expresses test scenarios in the sampled descriptions and links, in priority order:
|
|
111
|
+
1. Linked test issues - `issuelinks` pointing at a `Test`-family issuetype (Xray / Zephyr). If present, the standard Test Scenarios section references those linked tests rather than inlining steps.
|
|
112
|
+
2. A dedicated description heading (`Test Scenarios`, `Test Cases`, `QA`, `Senaryolar`, checklist blocks). If a style is shared by >= 40% of samples, reuse that exact format (heading name + bullet/checklist/table shape).
|
|
113
|
+
3. No prior style → inline a Test Scenarios skeleton derived from the Acceptance Criteria (one scenario per criterion, Given/When/Then or the project's dominant shape). Skeleton only - the user edits it in preview; pass/fail data is never fabricated.
|
|
114
|
+
|
|
115
|
+
**5b. Field discovery (createmeta):**
|
|
116
|
+
```bash
|
|
117
|
+
curl -s -H "Authorization: Bearer $TOKEN" \
|
|
118
|
+
"https://$ACCOUNT_JIRA_HOST/rest/api/2/issue/createmeta?projectKeys=${PROJECT_KEY}&issuetypeNames=${ISSUE_TYPE}&expand=projects.issuetypes.fields"
|
|
119
|
+
```
|
|
120
|
+
- 404 or empty `projects[]` (newer Jira DC deprecates the classic form) → fall back to the paged endpoint: `GET /rest/api/2/issue/createmeta/{PROJECT_KEY}/issuetypes` then `GET /rest/api/2/issue/createmeta/{PROJECT_KEY}/issuetypes/{issuetypeId}`.
|
|
121
|
+
- Every field with `required: true` beyond project/issuetype/summary/description/reporter → step 8 question (options from `allowedValues` when present, free-text fallback).
|
|
122
|
+
- Generic custom-field detection by `schema.custom` id - never assume field ids:
|
|
123
|
+
- Sprint: `com.pyxis.greenhopper.jira:gh-sprint`
|
|
124
|
+
- Epic Link: `com.pyxis.greenhopper.jira:gh-epic-link`
|
|
125
|
+
- Team-like fields: case-insensitive name match on `Team`
|
|
126
|
+
- 403 → warn "cannot read project field metadata", continue with template defaults; required fields surface reactively via the 400 path in step 10.
|
|
127
|
+
|
|
128
|
+
**5c. Board + active sprint (Agile REST):**
|
|
129
|
+
```bash
|
|
130
|
+
curl -s -H "Authorization: Bearer $TOKEN" \
|
|
131
|
+
"https://$ACCOUNT_JIRA_HOST/rest/agile/1.0/board?projectKeyOrId=${PROJECT_KEY}"
|
|
132
|
+
curl -s -H "Authorization: Bearer $TOKEN" \
|
|
133
|
+
"https://$ACCOUNT_JIRA_HOST/rest/agile/1.0/board/${BOARD_ID}/sprint?state=active"
|
|
134
|
+
```
|
|
135
|
+
- Multiple boards → AskUserQuestion (board name + type). One board → silent. Zero boards or Agile API 404 → the sprint option is silently omitted; the preview notes "backlog only (no board found)".
|
|
136
|
+
- Active sprint found → remember `SPRINT_ID` + name for the step 8 placement choice. None → backlog only; if a `state=future` sprint exists, mention it in the preview as information.
|
|
137
|
+
|
|
138
|
+
### [6/12] External context (only for the sources actually provided)
|
|
139
|
+
|
|
140
|
+
Each source is failure-isolated and never blocks issue creation.
|
|
141
|
+
|
|
142
|
+
**6a. Figma** (only when `FIGMA_URL` is set):
|
|
143
|
+
Follow the 3-tier chain from `rules/figma-pipeline.md`: Tier 1 MCP (`get_design_context` / `get_screenshot`, one re-auth retry) → Tier 2 REST (`keychainMapping.figma_pat`) → Tier 3 ask the user for a screenshot or proceed link-only.
|
|
144
|
+
|
|
145
|
+
> This command is standalone (same class as `/multi-agent:analysis`), so Figma MCP use here is allowed - it is not a dev-phase violation under the "No MCP outside analysis phase" rule.
|
|
146
|
+
|
|
147
|
+
- Output: frame name, node id, optional screenshot PNG in `/tmp/generate-issue-$$-figma.png` for the step 11 attachment opt-in.
|
|
148
|
+
- Any tier failure degrades gracefully; link-only is always acceptable.
|
|
149
|
+
|
|
150
|
+
**6b. Swagger / API contract** (only when `SWAGGER_URL` is set or a contract snippet was pasted):
|
|
151
|
+
- `SWAGGER_URL` set → fetch the spec, then extract **only the referenced endpoints**: if `FREE_TEXT` names specific paths / operationIds / tags, extract those; otherwise summarize the single tag or path group the user pointed at. Never crawl or dump the whole spec.
|
|
152
|
+
```bash
|
|
153
|
+
curl -s "$SWAGGER_URL" -o /tmp/generate-issue-$$-swagger.json # add auth header only if the user supplied one
|
|
154
|
+
```
|
|
155
|
+
Parse with `python3`/`jq` to pull, per referenced endpoint: HTTP method + path, a one-line summary, and the key request/response fields (names + types, not the full schema).
|
|
156
|
+
- Only a pasted contract snippet → summarize that snippet (endpoints + key fields).
|
|
157
|
+
- Output: an `API Contract` section body: `{METHOD} {path}` + summary + key request/response fields, plus `[Swagger|{SWAGGER_URL}]` when a URL was given.
|
|
158
|
+
- Fetch failure / unreachable / no matching endpoint → degrade to link-only (or omit the section if nothing usable) and note it in the preview. Never block issue creation.
|
|
159
|
+
|
|
160
|
+
**6c. Screenshots**: `USER_SCREENSHOTS[]` from step 4 are staged for the step 11 attachment opt-in; each attached image is referenced inline in the relevant section with Jira wiki `!filename|thumbnail!` markup.
|
|
161
|
+
|
|
162
|
+
### [7/12] Compose draft
|
|
163
|
+
|
|
164
|
+
Write summary + description in `outputLanguage` from the type's **standard template** (baseline, not mined headings):
|
|
165
|
+
- **Summary**: `{minedPrefix} {concise title}`, truncated to 255 chars.
|
|
166
|
+
- **Description**: render the type's standard section skeleton in Jira wiki markup (`h3.` headings), applying auto-sizing:
|
|
167
|
+
- **Always-present** sections are filled from `FREE_TEXT` (+ mining for Test Scenarios style). If an always-present section has no user content and cannot be derived, it stays an explicit open question for step 8 - it is not fabricated.
|
|
168
|
+
- **Conditional** sections render only when their trigger fired (see the Standard templates table): Design Reference when `FIGMA_URL` set (`[Figma|{FIGMA_URL}]` + frame name + node id); API Contract when 6b produced a body; Screenshots when images were staged; Notes/Dependencies only with real content. Otherwise the heading is omitted entirely.
|
|
169
|
+
- Bug: logs / stack traces / device+OS mentions from `FREE_TEXT` map into Environment and Screenshots / Logs; anything underivable becomes a step-8 question.
|
|
170
|
+
- Run the humanizer skill on the description body.
|
|
171
|
+
- Write the final body to `/tmp/generate-issue-$$.txt` (UTF-8, real newlines) for the `--rawfile` POST.
|
|
172
|
+
|
|
173
|
+
### [8/12] Clarifying questions (only genuinely unknown fields)
|
|
174
|
+
|
|
175
|
+
Batched AskUserQuestion(s), each with a "Skip / leave unset" option where Jira allows it:
|
|
176
|
+
- **Component**: mined top components + "none" - only when the project uses components.
|
|
177
|
+
- **Epic link**: only when 5a epic usage rate is high. Options from `project = {KEY} AND issuetype = Epic AND statusCategory != Done`.
|
|
178
|
+
- **Priority**: only when the mined norm is ambiguous; otherwise pre-fill the norm and let the preview edit change it.
|
|
179
|
+
- **Labels**: mined top labels, multiSelect.
|
|
180
|
+
- **Assignee**: "me / unassigned / someone else".
|
|
181
|
+
- **Sprint placement**: "Active sprint: {name}" vs "Backlog" - only when an active sprint exists.
|
|
182
|
+
- **Required custom fields** from 5b not yet resolved (allowedValues as options).
|
|
183
|
+
- **Always-present sections still empty**: Bug Steps to Reproduce / Environment, or a Task/Story with no derivable Scope / Acceptance Criteria → ask here.
|
|
184
|
+
|
|
185
|
+
Rule: never ask about anything already answerable from mining or the input. Regardless of how complete the draft looks, step 9 always runs.
|
|
186
|
+
|
|
187
|
+
### [9/12] Full preview + approval gate (never skipped)
|
|
188
|
+
|
|
189
|
+
Render the complete issue in chat: project, issuetype, summary, the full description body, priority, labels, components, epic, assignee, sprint/backlog placement, attachment plan (Figma + user screenshots upload - default off, opt-in).
|
|
190
|
+
|
|
191
|
+
Then AskUserQuestion (`question` in `outputLanguage`, e.g. tr: "Bu sekilde olusturuyorum, onayliyor musun?"):
|
|
192
|
+
|
|
193
|
+
| Option | Behavior |
|
|
194
|
+
|---|---|
|
|
195
|
+
| `Approve` | Proceed to step 10 |
|
|
196
|
+
| `Edit` | Free-text "what should change?" → apply → re-render the FULL preview → re-ask. Loop, no iteration cap |
|
|
197
|
+
| `Cancel` | Stop. Nothing was created; say so explicitly |
|
|
198
|
+
|
|
199
|
+
This gate has no bypass. No flag, mode, or preference suppresses it.
|
|
200
|
+
|
|
201
|
+
### [10/12] Create
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
jq -n --rawfile desc /tmp/generate-issue-$$.txt \
|
|
205
|
+
--arg key "$PROJECT_KEY" --arg type "$ISSUE_TYPE" --arg summary "$SUMMARY" \
|
|
206
|
+
'{fields: {project: {key: $key}, issuetype: {name: $type}, summary: $summary, description: $desc}}' \
|
|
207
|
+
> /tmp/generate-issue-$$-payload.json
|
|
208
|
+
# merge approved optional fields (priority / labels / components / epic / assignee / required customs) into .fields with jq before POST
|
|
209
|
+
curl -sS -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
|
|
210
|
+
--data-binary @/tmp/generate-issue-$$-payload.json \
|
|
211
|
+
"https://$ACCOUNT_JIRA_HOST/rest/api/2/issue"
|
|
212
|
+
```
|
|
213
|
+
- Parse `key` from the response → `NEW_KEY`.
|
|
214
|
+
- 400 with field errors → show Jira's per-field error verbatim, return to step 8 for exactly those fields, then re-run step 9 (full preview again).
|
|
215
|
+
|
|
216
|
+
### [11/12] Post-create steps
|
|
217
|
+
|
|
218
|
+
Each step is failure-isolated: on error, warn + continue - the issue already exists.
|
|
219
|
+
|
|
220
|
+
1. **Sprint** (when chosen in step 8/9):
|
|
221
|
+
```bash
|
|
222
|
+
jq -n --arg key "$NEW_KEY" '{issues: [$key]}' > /tmp/generate-issue-$$-sprint.json
|
|
223
|
+
curl -sS -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
|
|
224
|
+
--data-binary @/tmp/generate-issue-$$-sprint.json \
|
|
225
|
+
"https://$ACCOUNT_JIRA_HOST/rest/agile/1.0/sprint/${SPRINT_ID}/issue"
|
|
226
|
+
```
|
|
227
|
+
Post-create move instead of a Sprint custom field in the create payload: field-id-agnostic, works on every Jira Software instance.
|
|
228
|
+
2. **Figma remote link** (when `FIGMA_URL` set):
|
|
229
|
+
```bash
|
|
230
|
+
curl -sS -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
|
|
231
|
+
-d '{"object":{"url":"'"$FIGMA_URL"'","title":"Figma design"}}' \
|
|
232
|
+
"https://$ACCOUNT_JIRA_HOST/rest/api/2/issue/${NEW_KEY}/remotelink"
|
|
233
|
+
```
|
|
234
|
+
3. **Swagger remote link** (when `SWAGGER_URL` set):
|
|
235
|
+
```bash
|
|
236
|
+
curl -sS -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
|
|
237
|
+
-d '{"object":{"url":"'"$SWAGGER_URL"'","title":"API contract"}}' \
|
|
238
|
+
"https://$ACCOUNT_JIRA_HOST/rest/api/2/issue/${NEW_KEY}/remotelink"
|
|
239
|
+
```
|
|
240
|
+
4. **Screenshot / image attachments** (only when opted in during preview - Figma render and/or user-pasted images):
|
|
241
|
+
```bash
|
|
242
|
+
curl -sS -X POST -H "Authorization: Bearer $TOKEN" -H "X-Atlassian-Token: no-check" \
|
|
243
|
+
-F "file=@/tmp/generate-issue-$$-figma.png" \
|
|
244
|
+
"https://$ACCOUNT_JIRA_HOST/rest/api/2/issue/${NEW_KEY}/attachments"
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### [12/12] Report
|
|
248
|
+
|
|
249
|
+
```
|
|
250
|
+
Created {NEW_KEY}: https://{ACCOUNT_JIRA_HOST}/browse/{NEW_KEY}
|
|
251
|
+
```
|
|
252
|
+
Plus one line per post-create step that ran (sprint placement, remote links, attachments) and any that were skipped with reason.
|
|
253
|
+
|
|
254
|
+
## Error paths
|
|
255
|
+
|
|
256
|
+
| Condition | Behavior |
|
|
257
|
+
|---|---|
|
|
258
|
+
| Token missing/expired (401) | Token Save Flow from `setup.md` inline; user skips → abort with message, nothing created |
|
|
259
|
+
| Search 403 / createmeta denied | Warn "cannot read project conventions/fields"; continue with standard-template defaults; required fields asked reactively on 400 |
|
|
260
|
+
| Zero sampled issues (new project) | Skip mining, use standard template + AC-derived test-scenario skeleton, note in preview "no prior issues to learn from" |
|
|
261
|
+
| Agile API 404 / no boards | Omit sprint choice, backlog implied, say so in preview |
|
|
262
|
+
| No active sprint | Offer backlog only; mention the next `state=future` sprint when one exists |
|
|
263
|
+
| Figma Tier 1 fails | Tier 2; Tier 2 fails → Tier 3 (ask screenshot or link-only). Never block issue creation on Figma |
|
|
264
|
+
| Swagger fetch fails / unreachable | Degrade to link-only, or omit the API Contract section if nothing usable; note in preview. Never block issue creation |
|
|
265
|
+
| Create 400 (field errors) | Show per-field errors, loop back to step 8 for those fields, re-preview |
|
|
266
|
+
| Create 5xx / network | Show the error, offer one retry, then abort - keep `/tmp/generate-issue-$$.txt` and print its path so the draft survives |
|
|
267
|
+
| Post-create step failure | Warn + continue (issue exists); print a manual-fix hint |
|
|
@@ -21,6 +21,18 @@ When a token resolves but the service rejects it (401 / 403), do not silently sk
|
|
|
21
21
|
|
|
22
22
|
The question asks a *choice*; the replacement value still flows through the clipboard, never chat. `smoke-no-token-prompt.sh` greps for value-prompts (`enter token`, `paste token`, `API key:`) - decision labels like `Regenerate` / `Skip and continue` do not trip it.
|
|
23
23
|
|
|
24
|
+
Expiry is also checked **proactively at init**: Phase 0 Step 0.7 (`refs/phases/phase-0-init.md`) probes every token the run will need with one cheap call each (cached via `global.serviceStatus`, TTL 300s) and runs this same decision at init instead of waiting for the first mid-run 401. The mid-run 401 path stays as the safety net.
|
|
25
|
+
|
|
26
|
+
#### Figma MCP token lifecycle (critical)
|
|
27
|
+
|
|
28
|
+
`figma_mcp` is the only OAuth token in the registry (`figu_` prefix, ~90-day expiry); everything else is a long-lived PAT. A dead MCP token silently degrades every Figma consumer to Tier 2/3, so its expiry is handled specially:
|
|
29
|
+
|
|
30
|
+
1. **Refresh token**: the generation flow stores a refresh token under `<keychainMapping.figma_mcp>_Refresh`. `~/.claude/lib/figma-mcp-refresh.sh` performs a silent renewal (OAuth refresh grant; client credentials read from the `.figma-oauth.json` next to `prefs.global.tokenScripts.figma_mcp`). Exit 0 = renewed in place, no user interaction. This ALWAYS runs before any question is asked.
|
|
31
|
+
2. **Generation script**: `prefs.global.tokenScripts.figma_mcp` may point to a user-owned script that produces a fresh MCP token via Dynamic Client Registration + browser OAuth and saves it to the Keychain. When silent renewal fails, the expired-token question offers **Regenerate now (script)** which runs it (interactive runs only - it opens a browser).
|
|
32
|
+
3. **Fallbacks**: Token Save Flow (clipboard) or continue degraded on Tier 2 (REST PAT), per the Phase 0 Step 0.7 decision table.
|
|
33
|
+
|
|
34
|
+
`prefs.global.tokenScripts` maps service ids to user-owned generation scripts (`{"figma_mcp": "/path/to/start_mcp.sh"}`); paths are personal and live only in the local preferences file - never in synced command files. Script output is status lines only - token values never enter chat or logs.
|
|
35
|
+
|
|
24
36
|
Reasons:
|
|
25
37
|
- Asking for a token in chat leaks it into the conversation transcript and any audit log.
|
|
26
38
|
- The user has already configured the keychain; missing/expired is a setup issue, not a per-run issue.
|
|
@@ -107,6 +107,35 @@ Run `bash pipeline/scripts/update-check.sh` (cached per `updateCheck.ttlHours`,
|
|
|
107
107
|
|
|
108
108
|
Advisory - NEVER blocks. Must run BEFORE Step 6 (worktree creation) so an accepted update cannot mutate `~/.claude` under a mid-phase run.
|
|
109
109
|
|
|
110
|
+
#### Step 0.7 - Token expiry pre-flight (runs before Step 1 fetch)
|
|
111
|
+
|
|
112
|
+
Validate the tokens THIS run will need before any of them is used mid-phase. Scope is derived, not exhaustive:
|
|
113
|
+
|
|
114
|
+
| Run signal | Tokens to probe | Cheap probe (1 call each) |
|
|
115
|
+
|---|---|---|
|
|
116
|
+
| Input is Jira-id / Jira-url | `jira` | `GET /rest/api/2/myself` |
|
|
117
|
+
| Input is GitHub issue / repo#N | `github` | `gh auth status` (or `GET /user`) |
|
|
118
|
+
| Remote is Bitbucket | `bitbucket_token` | `GET /rest/api/1.0/application-properties` |
|
|
119
|
+
| `reportChannels.confluence` true | `confluence` | `GET /rest/api/user/current` |
|
|
120
|
+
| Task carries a Figma reference | `figma_mcp` (Tier 1), `figma` (Tier 2) | MCP `initialize` POST to `mcp.figma.com/mcp`; `GET api.figma.com/v1/me` |
|
|
121
|
+
|
|
122
|
+
Results are cached in `global.serviceStatus` (existing TTL contract, default 300s) - a probe that ran in the last 5 minutes is not repeated.
|
|
123
|
+
|
|
124
|
+
**Valid** → continue silently (one log line: `→ token pre-flight: N ok`).
|
|
125
|
+
|
|
126
|
+
**Figma MCP expired / rejected - CRITICAL path.** The `figma_mcp` OAuth token (`figu_`) expires on a schedule (90 days), unlike the PATs. Because a dead MCP token silently degrades every Figma consumer to Tier 2/3 and has cost rebuild rounds, an expired `figma_mcp` is never deferred to mid-run:
|
|
127
|
+
|
|
128
|
+
1. **Silent renewal first**: run `~/.claude/lib/figma-mcp-refresh.sh` (refresh grant via `<key>_Refresh` + the `.figma-oauth.json` client credentials next to `prefs.global.tokenScripts.figma_mcp`). Exit 0 → re-probe, log `→ figma mcp token renewed silently`, continue. No question asked.
|
|
129
|
+
2. **Renewal impossible/rejected** (exit 1/2) → AskUserQuestion at init (`question`/`description` in `outputLanguage`): "Figma MCP token expired - update it now?"
|
|
130
|
+
- **Regenerate now (script)** - shown only when `prefs.global.tokenScripts.figma_mcp` is set: run that script (browser OAuth flow), then re-probe and continue.
|
|
131
|
+
- **Save a new token** - Token Save Flow from `setup.md` (clipboard path).
|
|
132
|
+
- **Continue degraded** - proceed on Tier 2 (REST PAT) for this run; log the downgrade.
|
|
133
|
+
3. **Autopilot**: silent renewal only; if it fails, log `→ figma mcp token expired (autopilot: continuing on tier 2)` and continue degraded - never prompt.
|
|
134
|
+
|
|
135
|
+
**Other tokens expired / rejected** → run the Expired-token decision from `refs/keychain.md` Rule 1 HERE at init (Regenerate / Use a different token / Skip and continue) instead of waiting for the first mid-run 401. A token that is structurally required for the input (e.g. the Jira PAT for a Jira-ID input) halts on skip, since Step 1 cannot fetch without it. Autopilot: skip-and-degrade semantics per Rule 1, halt only on structurally required tokens.
|
|
136
|
+
|
|
137
|
+
Probe failures caused by network (timeout, DNS) are NOT treated as expiry - log and continue; the mid-run 401 path still exists as the safety net.
|
|
138
|
+
|
|
110
139
|
#### Step 1 - Parse Input
|
|
111
140
|
|
|
112
141
|
**Branch from input**: If the user provided a branch name after the issue reference (space-separated), store as `baseBranch` and skip Step 3. Otherwise Step 3 asks interactively.
|
|
@@ -526,8 +555,8 @@ Log: `Phase 0 Step 7: taskType = {component|bugfix|feature|refactor|chore}`
|
|
|
526
555
|
After each clarifier call:
|
|
527
556
|
|
|
528
557
|
```bash
|
|
529
|
-
pipeline/scripts/log-metric.sh "$TASK_ID" 0 clarify.call \
|
|
530
|
-
score=$SCORE questions=$Q stop_and_ask=$STOP autopilot_mode=$AP \
|
|
558
|
+
LOG_METRIC_FORWARD_TO_TRACKER=1 pipeline/scripts/log-metric.sh "$TASK_ID" 0 clarify.call \
|
|
559
|
+
model=haiku score=$SCORE questions=$Q stop_and_ask=$STOP autopilot_mode=$AP \
|
|
531
560
|
duration_ms=$D tokens_in=$TI tokens_out=$TO
|
|
532
561
|
```
|
|
533
562
|
|
|
@@ -296,6 +296,8 @@ When `agent-state.json.onlyDevelop === true`, Phase 3 runs self-contained with *
|
|
|
296
296
|
|
|
297
297
|
**Combinable with autopilot**: `--dev autopilot` = zero interaction. Init → Dev → auto-commit → auto-PR → Report.
|
|
298
298
|
|
|
299
|
+
**Tracker visibility during Opus dispatch**: on Claude Code the model switch to Opus happens via subagent dispatch, and the parent widget cannot move while an Agent call is in flight. Dispatch per task from the self-generated task list (never one monolithic call for the whole phase), set the pre-dispatch `activeForm` marker, and record tokens between chunks - full rules in `refs/tracker-contract.md` section "Delegated phases".
|
|
300
|
+
|
|
299
301
|
---
|
|
300
302
|
|
|
301
303
|
#### v2.1.0+ Multi-Repo Mode
|
|
@@ -157,6 +157,8 @@ When `state.evidence.figma[]` is non-empty, the reviewer subagents MUST receive
|
|
|
157
157
|
|
|
158
158
|
Visual-fidelity mismatches against the captured screenshot are BLOCKING findings, not nits:
|
|
159
159
|
|
|
160
|
+
- Canonical component usage: the Code Connect-mapped component is used verbatim - a sound-alike substitute, a forked copy, or ad-hoc inline UI where a mapping exists is blocking (Phase 3 "Design fidelity contract")
|
|
161
|
+
- Inter-component spacing: gaps, paddings, and alignment BETWEEN components match the design's measured values mapped to spacing tokens - invented numeric values are blocking
|
|
160
162
|
- Avatar icon (presence, glyph, shape, position)
|
|
161
163
|
- Field grouping (one rounded box vs two; separator vs gap)
|
|
162
164
|
- Character counter visibility
|
|
@@ -95,7 +95,12 @@ Tier 1 / Tier 2 records print `screenshotUrl` from the captured evidence (Tier 2
|
|
|
95
95
|
"ok" -> proceeds to Phase 6 (WIP commit will be replaced via git reset HEAD~1 + proper commit)
|
|
96
96
|
"fix: ..." -> worktree is recreated, returns to Phase 3
|
|
97
97
|
```
|
|
98
|
-
5.
|
|
98
|
+
5. Mark the tracker as waiting, then wait for the user response:
|
|
99
|
+
```bash
|
|
100
|
+
bash $HOME/.claude/scripts/phase-tracker.sh now 5 "awaiting local test (user)"
|
|
101
|
+
bash $HOME/.claude/scripts/phase-tracker.sh render
|
|
102
|
+
```
|
|
103
|
+
The waiting state persists in `tracker-state.json` across the handoff; `/multi-agent:finish` and `/multi-agent:manual-test` CONTINUE this state file and never re-init it (`refs/tracker-contract.md` "Continuation runs").
|
|
99
104
|
6. If fix needed:
|
|
100
105
|
- Branch already has WIP commit (from step 2) - changes are safe
|
|
101
106
|
- Recreate worktree from branch: `git -C $PROJECT_ROOT worktree add {worktree-path} {branch}`
|
|
@@ -101,6 +101,8 @@ Tracker: `phase-tracker.sh sub 7 1 "Channels dispatch" completed` (or `failed` i
|
|
|
101
101
|
|
|
102
102
|
Runs only when `state.tracker.kind === "github-issue"`. The Issue adapter is mandatory whenever the run was triggered from a GitHub issue - no exceptions, no "I'll just update the flags" shortcut. Full template + rules: `refs/channels/issue-comment.md`.
|
|
103
103
|
|
|
104
|
+
**Approval gate:** interactive runs show the composed comment body (and the Progress-flag diff intent) through the same preview + approval gate as channels Step 6 (`channels.md`) before posting - Approve & post / Edit / Cancel. Autopilot posts directly.
|
|
105
|
+
|
|
104
106
|
Two paired actions, in order:
|
|
105
107
|
|
|
106
108
|
```bash
|
|
@@ -182,9 +184,11 @@ Skipped sections: when `planTodos.enabled` is false or no `plan.todos[]` was emi
|
|
|
182
184
|
(embed `aggregate-metrics.mjs --since=<30 days ago> --json` output as collapsed JSON)
|
|
183
185
|
```
|
|
184
186
|
|
|
185
|
-
**Telemetry emission** (mandatory): emit final event:
|
|
187
|
+
**Telemetry emission** (mandatory): forward the phase's own LLM spend (humanizer + report compose calls) to the tracker, then emit the final event:
|
|
186
188
|
|
|
187
189
|
```bash
|
|
190
|
+
LOG_METRIC_FORWARD_TO_TRACKER=1 pipeline/scripts/log-metric.sh "$TASK_ID" 7 report.compose \
|
|
191
|
+
model=$REPORT_MODEL tokens_in=$R_IN tokens_out=$R_OUT duration_ms=$R_DUR
|
|
188
192
|
pipeline/scripts/log-metric.sh "$TASK_ID" 7 task.completed \
|
|
189
193
|
phases=$PHASE_COUNT review_cycles=$CYCLES lang=$PROMPT_LANG \
|
|
190
194
|
channels_pr=$PR_STATUS channels_jira=$JIRA_STATUS \
|
|
@@ -21,6 +21,7 @@ Today pipeline users see a phase banner (`→ Phase 3: Dev`) and then silence fo
|
|
|
21
21
|
- **verb** - lowercase present participle or imperative, one word: `fetching`, `reading`, `running`, `writing`, `posting`, `waiting`, `dispatching`, `retrying`, `building`, `committing`, `checking`.
|
|
22
22
|
- **object** - what is being acted on: file basename, API endpoint last segment, subagent name, command, smoke name.
|
|
23
23
|
- **target** - optional, human-readable scope: repo name, ticket ID, URL host.
|
|
24
|
+
- **Live mirror to the phase tracker**: each `normal`-tier emitted line is also mirrored to the active phase per `refs/tracker-contract.md` "Active phase" (Claude Code `TaskUpdate activeForm`, other CLIs `phase-tracker.sh now`) - the authoritative throttling rules live there.
|
|
24
25
|
|
|
25
26
|
### Examples
|
|
26
27
|
|
|
@@ -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 + 36 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)
|
|
@@ -169,7 +169,7 @@ If nothing is stale → report "All targets up to date" and stop.
|
|
|
169
169
|
|
|
170
170
|
## Stack-Plugin Sync (Step 3c)
|
|
171
171
|
|
|
172
|
-
Stack skills are distributed as versioned plugins in the `
|
|
172
|
+
Stack skills are distributed as versioned plugins in the `mmerterden/multi-agent-plugins` marketplace. The pipeline's `pipeline/skills/shared/external/` is the **single authoring source**; the marketplace is a derived, versioned publish artifact. This step rebuilds it and publishes only when something changed.
|
|
173
173
|
|
|
174
174
|
**Source of truth:** author/vendor knowledge skills in `pipeline/skills/shared/external/` (the pipeline's own phases also consume them). The plugins' authored lifecycle skills (`index` / `reference` / `workflow` / `tools`) live in the plugins repo and are never touched by sync.
|
|
175
175
|
|
|
@@ -177,7 +177,7 @@ Stack skills are distributed as versioned plugins in the `{owner}/multi-agent-pl
|
|
|
177
177
|
|
|
178
178
|
```bash
|
|
179
179
|
PLUGINS_REPO="$HOME/multi-agent-plugins"
|
|
180
|
-
[ ! -d "$PLUGINS_REPO/.git" ] && gh repo clone
|
|
180
|
+
[ ! -d "$PLUGINS_REPO/.git" ] && gh repo clone mmerterden/multi-agent-plugins "$PLUGINS_REPO"
|
|
181
181
|
cd "$PLUGINS_REPO" && git pull origin main
|
|
182
182
|
|
|
183
183
|
# 1. Preview what would change (routing + version bumps), no writes:
|
|
@@ -197,10 +197,10 @@ node "$HOME/multi-agent-pipeline/pipeline/scripts/build-stack-plugins.mjs"
|
|
|
197
197
|
```bash
|
|
198
198
|
cd "$PLUGINS_REPO"
|
|
199
199
|
if ! git diff --quiet; then
|
|
200
|
-
git config user.name "
|
|
200
|
+
git config user.name "Mert Erden"; git config user.email "mmerterden@gmail.com"
|
|
201
201
|
git add -A
|
|
202
202
|
git commit -m "chore: rebuild stack plugins from pipeline shared/external"
|
|
203
|
-
gh auth switch --user
|
|
203
|
+
gh auth switch --user mmerterden 2>/dev/null || true
|
|
204
204
|
git push origin main
|
|
205
205
|
fi
|
|
206
206
|
```
|
|
@@ -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
|
+
**36 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, 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
|