@mmerterden/multi-agent-pipeline 20.13.0 → 20.15.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 (153) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +8 -6
  3. package/README.tr.md +7 -5
  4. package/docs/architecture.md +3 -3
  5. package/docs/ecosystem.md +5 -5
  6. package/docs/facts.json +4 -4
  7. package/install/catalog-history.json +1 -1
  8. package/manifest.json +156 -96
  9. package/package.json +1 -1
  10. package/pipeline/commands/multi-agent/analysis/SKILL.md +11 -80
  11. package/pipeline/commands/multi-agent/autopilot/SKILL.md +2 -23
  12. package/pipeline/commands/multi-agent/autopilot-off/SKILL.md +24 -45
  13. package/pipeline/commands/multi-agent/channels/SKILL.md +11 -63
  14. package/pipeline/commands/multi-agent/design-check/SKILL.md +43 -178
  15. package/pipeline/commands/multi-agent/diff-explain/SKILL.md +2 -0
  16. package/pipeline/commands/multi-agent/estimate/SKILL.md +65 -0
  17. package/pipeline/commands/multi-agent/help/SKILL.md +5 -546
  18. package/pipeline/commands/multi-agent/kill/SKILL.md +13 -18
  19. package/pipeline/commands/multi-agent/refactor/SKILL.md +7 -76
  20. package/pipeline/commands/multi-agent/review-analysis/SKILL.md +1 -1
  21. package/pipeline/commands/multi-agent/scenario-audit/SKILL.md +79 -0
  22. package/pipeline/commands/multi-agent/serve/SKILL.md +6 -3
  23. package/pipeline/commands/multi-agent/setup/SKILL.md +12 -365
  24. package/pipeline/commands/multi-agent/status/SKILL.md +2 -0
  25. package/pipeline/commands/multi-agent/store-ready/SKILL.md +56 -184
  26. package/pipeline/commands/multi-agent/sync/SKILL.md +14 -267
  27. package/pipeline/contract/CHANGELOG.md +52 -0
  28. package/pipeline/contract/README.md +41 -1
  29. package/pipeline/contract/build.mjs +49 -7
  30. package/pipeline/contract/fixtures/error-invalid-request.json +1 -1
  31. package/pipeline/contract/fixtures/error-unauthorized.json +1 -1
  32. package/pipeline/contract/fixtures/error-unsigned.json +1 -1
  33. package/pipeline/contract/fixtures/launch-plan.json +1 -2
  34. package/pipeline/contract/fixtures/runs-awaiting-question.json +10 -3
  35. package/pipeline/contract/fixtures/runs-empty.json +1 -1
  36. package/pipeline/contract/fixtures/runs-failed.json +19 -6
  37. package/pipeline/contract/fixtures/runs-pr-opened-redacted.json +25 -8
  38. package/pipeline/contract/fixtures/runs-pr-opened.json +25 -8
  39. package/pipeline/contract/fixtures/runs-running.json +31 -4
  40. package/pipeline/contract/frozen/toolbox.json +13 -0
  41. package/pipeline/contract/manifest.json +112 -10
  42. package/pipeline/contract/types/index.d.ts +186 -17
  43. package/pipeline/lib/claude-sessions.mjs +93 -0
  44. package/pipeline/lib/credential-resolve.mjs +39 -0
  45. package/pipeline/lib/gc-report.sh +64 -0
  46. package/pipeline/lib/unattended-settings-location.mjs +4 -0
  47. package/pipeline/lib/workspace-trust.mjs +73 -0
  48. package/pipeline/multi-agent-refs/analysis/intake.md +5 -3
  49. package/pipeline/multi-agent-refs/analysis/locked.md +8 -7
  50. package/pipeline/multi-agent-refs/analysis/render.md +4 -3
  51. package/pipeline/multi-agent-refs/analysis/resolve.md +1 -1
  52. package/pipeline/multi-agent-refs/analysis/resume.md +37 -0
  53. package/pipeline/multi-agent-refs/analysis/reusable-refs.md +25 -0
  54. package/pipeline/multi-agent-refs/channels/board.md +17 -0
  55. package/pipeline/multi-agent-refs/channels/multi-repo.md +15 -0
  56. package/pipeline/multi-agent-refs/cross-cli-contract.md +4 -4
  57. package/pipeline/multi-agent-refs/design-check/build-launch.md +14 -0
  58. package/pipeline/multi-agent-refs/design-check/compare.md +44 -0
  59. package/pipeline/multi-agent-refs/design-check/drive-capture.md +35 -0
  60. package/pipeline/multi-agent-refs/design-check/export.md +37 -0
  61. package/pipeline/multi-agent-refs/design-check/figma-mapping.md +11 -0
  62. package/pipeline/multi-agent-refs/design-check/init-inventory.md +56 -0
  63. package/pipeline/multi-agent-refs/design-check/mcp-currency-gate.md +41 -0
  64. package/pipeline/multi-agent-refs/features/analysis-outline.md +55 -0
  65. package/pipeline/multi-agent-refs/features/analysis-sources.md +60 -0
  66. package/pipeline/multi-agent-refs/help/en.md +273 -0
  67. package/pipeline/multi-agent-refs/help/tr.md +271 -0
  68. package/pipeline/multi-agent-refs/orchestrator/operations.md +99 -0
  69. package/pipeline/multi-agent-refs/orchestrator/phase-0-projects.md +72 -0
  70. package/pipeline/multi-agent-refs/orchestrator/phase-3-user-test.md +40 -0
  71. package/pipeline/multi-agent-refs/orchestrator/phase-4-5-projects.md +68 -0
  72. package/pipeline/multi-agent-refs/orchestrator/skill-loading.md +99 -0
  73. package/pipeline/multi-agent-refs/phases/phase-0-init.md +3 -2
  74. package/pipeline/multi-agent-refs/phases/phase-1-plan.md +1 -1
  75. package/pipeline/multi-agent-refs/phases/phase-2-dev.md +1 -1
  76. package/pipeline/multi-agent-refs/picker-contract.md +29 -0
  77. package/pipeline/multi-agent-refs/refactor/drift.md +49 -0
  78. package/pipeline/multi-agent-refs/refactor/run-errors.md +46 -0
  79. package/pipeline/multi-agent-refs/setup/discovery.md +84 -0
  80. package/pipeline/multi-agent-refs/setup/figma.md +27 -0
  81. package/pipeline/multi-agent-refs/setup/identity-routing.md +60 -0
  82. package/pipeline/multi-agent-refs/setup/token-save-flow.md +201 -0
  83. package/pipeline/multi-agent-refs/store-ready/build.md +49 -0
  84. package/pipeline/multi-agent-refs/store-ready/gate-1-static.md +37 -0
  85. package/pipeline/multi-agent-refs/store-ready/gate-3-policy.md +31 -0
  86. package/pipeline/multi-agent-refs/store-ready/preflight.md +50 -0
  87. package/pipeline/multi-agent-refs/store-ready/report.md +40 -0
  88. package/pipeline/multi-agent-refs/sync/codex.md +43 -0
  89. package/pipeline/multi-agent-refs/sync/dev-toolkit.md +174 -0
  90. package/pipeline/multi-agent-refs/sync/stack-plugins.md +51 -0
  91. package/pipeline/multi-agent-refs/tracker-contract.md +29 -4
  92. package/pipeline/schemas/agent-state.schema.json +13 -4
  93. package/pipeline/schemas/analysis-spec.schema.json +56 -4
  94. package/pipeline/schemas/autopilot-off-request.schema.json +20 -0
  95. package/pipeline/schemas/autopilot-off.schema.json +24 -0
  96. package/pipeline/schemas/autopilot-status.schema.json +63 -0
  97. package/pipeline/schemas/contract-error.schema.json +13 -2
  98. package/pipeline/schemas/gc-request.schema.json +31 -0
  99. package/pipeline/schemas/gc.schema.json +116 -0
  100. package/pipeline/schemas/kill-request.schema.json +22 -0
  101. package/pipeline/schemas/kill.schema.json +118 -0
  102. package/pipeline/schemas/launch-plan.schema.json +11 -2
  103. package/pipeline/schemas/launch-request.schema.json +7 -2
  104. package/pipeline/schemas/launch.json +65 -4
  105. package/pipeline/schemas/launch.schema.json +23 -8
  106. package/pipeline/schemas/prefs.schema.json +3 -3
  107. package/pipeline/schemas/repos.schema.json +39 -0
  108. package/pipeline/schemas/resume-request.schema.json +37 -0
  109. package/pipeline/schemas/run-log.schema.json +32 -0
  110. package/pipeline/schemas/run-questions.json +5 -1
  111. package/pipeline/schemas/run-questions.schema.json +1 -1
  112. package/pipeline/schemas/runs-index.schema.json +59 -3
  113. package/pipeline/scripts/_run-paths.mjs +8 -2
  114. package/pipeline/scripts/analysis-conform-coverage.mjs +96 -0
  115. package/pipeline/scripts/analysis-sources.mjs +264 -0
  116. package/pipeline/scripts/autopilot-control.mjs +223 -0
  117. package/pipeline/scripts/autopilot-runner.mjs +14 -39
  118. package/pipeline/scripts/build-references.mjs +5 -1
  119. package/pipeline/scripts/confluence-readback.mjs +4 -23
  120. package/pipeline/scripts/contract-server.mjs +373 -7
  121. package/pipeline/scripts/doctor.mjs +5 -2
  122. package/pipeline/scripts/estimate.mjs +223 -0
  123. package/pipeline/scripts/gate-ledger.mjs +64 -3
  124. package/pipeline/scripts/gc-plan.mjs +288 -0
  125. package/pipeline/scripts/gc-refs.sh +33 -2
  126. package/pipeline/scripts/gc-tmp.sh +33 -2
  127. package/pipeline/scripts/gc-worktrees.sh +42 -3
  128. package/pipeline/scripts/gen-mode-dispatch.mjs +3 -24
  129. package/pipeline/scripts/launch-request.mjs +182 -10
  130. package/pipeline/scripts/phase-tracker.sh +62 -1
  131. package/pipeline/scripts/run-kill.mjs +232 -0
  132. package/pipeline/scripts/run-log.mjs +111 -0
  133. package/pipeline/scripts/runs-index.mjs +177 -11
  134. package/pipeline/scripts/scenario-audit.mjs +245 -0
  135. package/pipeline/scripts/validate-analysis-doc.mjs +84 -6
  136. package/pipeline/skills/.skill-manifest.json +24 -16
  137. package/pipeline/skills/shared/README.md +5 -3
  138. package/pipeline/skills/shared/core/multi-agent/SKILL.md +51 -450
  139. package/pipeline/skills/shared/core/multi-agent-analysis/SKILL.md +7 -1
  140. package/pipeline/skills/shared/core/multi-agent-autopilot-off/SKILL.md +26 -44
  141. package/pipeline/skills/shared/core/multi-agent-design-check/SKILL.md +31 -127
  142. package/pipeline/skills/shared/core/multi-agent-estimate/SKILL.md +61 -0
  143. package/pipeline/skills/shared/core/multi-agent-kill/SKILL.md +14 -19
  144. package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +7 -76
  145. package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +1 -1
  146. package/pipeline/skills/shared/core/multi-agent-review-analysis/SKILL.md +1 -1
  147. package/pipeline/skills/shared/core/multi-agent-review-issue/SKILL.md +1 -1
  148. package/pipeline/skills/shared/core/multi-agent-review-jira/SKILL.md +1 -1
  149. package/pipeline/skills/shared/core/multi-agent-scenario-audit/SKILL.md +77 -0
  150. package/pipeline/skills/shared/core/multi-agent-serve/SKILL.md +6 -3
  151. package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +205 -324
  152. package/pipeline/skills/shared/core/multi-agent-store-ready/SKILL.md +5 -0
  153. package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +4 -4
@@ -11,16 +11,17 @@ allowed-tools: Agent, Bash, Read, Write, Edit, Glob, Grep, TaskCreate, TaskUpdat
11
11
 
12
12
  # /multi-agent:design-check - Mock-mode vs Figma design audit
13
13
 
14
- Local, on-device design-conformance auditor. It runs the app in a **mock mode** on a simulator / emulator and compares each screen (and every mock variant the build exposes) against its Figma design at the **pixel + geometry + typography + color** level, then produces a detailed report.
14
+ Local, on-device design-conformance auditor. Runs the app in a **mock mode** on a simulator / emulator and compares each screen (and every mock variant the build exposes) against its Figma design at the **pixel + geometry + typography + color** level, then produces a detailed report.
15
15
 
16
- **Local-only**: no CI/CD, no cron, no commits, no PR. It is a read-only audit that writes a report to `~/DesignChecks/`. The worktree exists only to build the Debug app without touching the user's working tree.
16
+ **Local-only**: no CI/CD, no cron, no commits, no PR. Read-only audit; writes a report to `~/DesignChecks/`. The worktree only isolates the Debug build from the user's working tree.
17
17
 
18
- > **Language (read FIRST)**: Two independent axes.
19
- >
20
- > 1. **`prefs.global.promptLanguage` is always `en`** - this spec and every instruction to the LLM stay English.
21
- > 2. **`prefs.global.outputLanguage` is user-selectable** - applies to conversational lines and the human-readable parts of the report. Pass it to `design_report` as `report.lang`; the engine defaults to English and ships an `en` + `tr` label pack, plus per-key `report.labels` overrides.
22
- >
23
- > Regardless of `outputLanguage`, these stay English: `AskUserQuestion` `header` chips, branch names, file paths, code identifiers, log lines. Option `label`s follow `outputLanguage` like the rest of the picker copy. Full contract: `$HOME/.claude/multi-agent-refs/rules.md` "Language Application".
18
+ > **Language (read FIRST)**: `prefs.global.promptLanguage` is always `en` - this spec and every instruction to the LLM stay English. `prefs.global.outputLanguage` applies to conversational lines and the human-readable parts of the report; pass it to `design_report` as `report.lang` (engine defaults to English, ships `en` + `tr` label packs, per-key `report.labels` overrides). `AskUserQuestion` `header` chips, branch names, file paths, code identifiers and log lines stay English; option `label`s follow `outputLanguage`. Full contract: `$HOME/.claude/multi-agent-refs/rules.md` "Language Application".
19
+
20
+ ## Gotchas
21
+
22
+ - A scope that matches no inventory target is an error, not an empty run; print the closest ids and stop.
23
+ - The coverage gate fails the run when a target was neither audited nor skipped with a reason. "Not reached" is not "passed".
24
+ - A Figma variant with no matching mock state is a finding about the mock, not a pass for the screen.
24
25
 
25
26
  ## Scope - `$ARGUMENTS`
26
27
 
@@ -33,7 +34,7 @@ The scope decides which **inventory targets** (Phase 0 step 5) the run must audi
33
34
  | `screen@variant` | `order-status@expired` | One target |
34
35
  | target id | `scenario-case:orderstatusoutcome-expired` | One target, exactly |
35
36
  | Figma URL(s) | `https://figma.com/design/...?node-id=1-2` | Only the frames those URLs name |
36
- | `--resume` | `/multi-agent:design-check --resume` | The unaudited remainder of the most recent run for this repo + module |
37
+ | `--resume` | `--resume` | The unaudited remainder of the most recent run for this repo + module |
37
38
  | combinations | `seat-map summary@semi-success` | Union of the above, space- or newline-separated |
38
39
 
39
40
  A scope that matches **no** inventory target is an error, not an empty run: print the closest inventory ids and halt.
@@ -77,104 +78,38 @@ Every Phase 0 / Phase 2 decision uses a native `AskUserQuestion` picker per `pic
77
78
 
78
79
  ## Phase 0 - Init, Feasibility Gate & Inventory
79
80
 
80
- 0. **MCP CURRENCY GATE (first, before anything expensive)** - an MCP stdio server publishes its tool list once at `initialize` and never re-reads the code, so a session connected to a server process that started before the last update keeps serving the OLD tool list while still reporting "connected". Finding that out after a Debug build wastes the whole run.
81
-
82
- Assert both halves before continuing:
83
-
84
- a. **Session** - `mcp__multi-agent-toolkit__design_scenario_inventory` must be present in the tools available to you, and `mcp__multi-agent-toolkit__design_visual_compare` must accept `live_region`. Absent → the session is bound to a stale process.
85
-
86
- b. **Disk** - probe what a fresh connection WOULD serve. Launch it as registered; under npx `args[0]` is `-y`, not a path.
87
- ```bash
88
- MA_MCP_CMD=$(python3 -c "import json,os,shlex;e=json.load(open(os.path.expanduser('~/.claude.json')))['mcpServers']['multi-agent-toolkit'];print(shlex.join([e['command']]+e.get('args',[])))")
89
- printf '%s\n%s\n' \
90
- '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"probe","version":"1"}}}' \
91
- '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' \
92
- | eval "$MA_MCP_CMD" 2>/dev/null | python3 -c "
93
- import sys,json
94
- for l in sys.stdin:
95
- try: m=json.loads(l)
96
- except: continue
97
- if m.get('id')==1: print('version',m['result']['serverInfo']['version'])
98
- if m.get('id')==2:
99
- n=[t['name'] for t in m['result']['tools']]
100
- print('tools',len(n),'inventory','design_scenario_inventory' in n)"
101
- ```
102
-
103
-
104
- Branch on the two results:
105
- - **disk OK, session missing the tool** → **HALT** and tell the user to reconnect: `/mcp` → `multi-agent-toolkit` → Reconnect. Note the tool-count tell (a stale build advertises one fewer `design_*` tool). If a reconnect does not take, stale server processes may be lingering - `pgrep -f multi-agent-toolkit-mcp/index.js` with `ps -o lstart=` shows their start times, and any that predate the code's mtime cannot serve the current tools.
106
- - **disk itself stale** (older version, or `inventory False`) → **HALT**: the checkout needs updating before a reconnect can help.
107
- - **both current** → continue.
108
-
109
- Never work around a stale server by substituting a local `node` call for the missing tool: the run would silently lose the coverage gate and region alignment, which is exactly the failure this gate exists to prevent.
110
-
111
- 1. **Repo picker** - reuse `$HOME/.claude/multi-agent-refs/_repo-picker.md`. The account picker is skipped (Figma token is user-supplied, no Jira/GitHub fetch happens) unless Confluence export is enabled, in which case resolve the Confluence token via `account-resolver.sh`.
112
- 2. **Module / dev-context picker** - reuse `$HOME/.claude/multi-agent-refs/_dev-context.md`. Auto-suggest submodules from `.gitmodules` (`submodule-detector.sh`); the user selects the single module to audit (multi-module allowed - each is audited independently).
113
- 3. **Platform detect** - `.xcodeproj` / `Package.swift` → iOS; `build.gradle*` → Android (same markers as `phase-0-init.md`). Persist `state.designCheck.platform`.
114
- 4. **MOCK FEASIBILITY GATE** - run against the selected module path:
115
- ```
116
- mcp__multi-agent-toolkit__design_mock_detect({ repo_path: "<module path>", platform: "<ios|android>",
117
- extra_keys: <design-check-config mock.keys, if any> })
118
- ```
119
- Branch on `supported`:
120
- - **`false`** → try the **snapshot lane** before halting: a screen renderable from its own view model (filled, flow-advanced, no backend) is auditable without a runtime mock switch. Ask via `AskUserQuestion`, persist `state.designCheck.captureLane = "snapshot"`. State the trade: snapshots reach modules mocks cannot and cannot flip an in-app variant, so the target set is whatever the view model can be built into. Declined or not renderable → **HALT** with `reason`. Never fabricate a comparison.
121
- - **`"debug-only"`** → surface an `AskUserQuestion` warning: mocks are compiled into the Debug build via `#if DEBUG` DI, so **variants cannot be toggled at launch** - only the default Debug state is comparable. Options (label + description in `outputLanguage`): option 1 semantically "Continue" - audit the single default Debug state only; option 2 semantically "Cancel" - stop.
122
- - **`true`** → continue. Persist `state.designCheck.mock = <detect result>` (mechanism, activation, variantsHint, evidence).
123
- 5. **SCENARIO INVENTORY (this is the audit's target set)**:
124
- ```
125
- mcp__multi-agent-toolkit__design_scenario_inventory({ repo_path: "<module path>", platform,
126
- targets_file: <config inventory.targetsFile>,
127
- extra_launch_args: <config inventory.extraLaunchArgs>,
128
- extra_targets: <config inventory.extraTargets>,
129
- ignore_targets: <config inventory.ignoreTargets> })
130
- ```
131
- Returns `targets[]` - each `{ id, kind, label, screen, driver, cost, evidence }` - plus `plan[]`, `relaunchCount`, `groups[]`, `byKind`, `byCost`, `ignored[]`, `truncated`, `scanStrategy`. Kinds: `launch-arg`, `scenario-case`, **`prefix-code`** (a mock repository branching on the prefix of the reference the user types - usually the LARGEST group, and the one a selector-only search misses entirely), `code-scenario`, `fixture`, `deep-link`.
132
-
133
- This list, not the agent's reading of the code or what the UI exposes to tapping, is what the run is measured against. Persist verbatim to `state.designCheck.inventory`.
134
- - `targetCount: 0` → warn that no state driver was found and that only the default launch state can be audited; a `debug-only` project lands here.
135
- - `truncated: true` → the inventory hit its cap, so the target set is INCOMPLETE. Say so now, and pass `coverage.truncatedInventory: true` in Phase 4 so the gate fails rather than reporting a clean percentage of a partial denominator. Narrow the scope to a screen and work through the module in `--resume` steps.
81
+ 0. **MCP CURRENCY GATE (first, before anything expensive)** - a session started before the last update serves the OLD tool list while reporting "connected". Check both halves before the Debug build: (a) **session** - `design_scenario_inventory` is available and `design_visual_compare` accepts `live_region`; (b) **disk** - probe what a fresh connection would serve. Disk OK but session stale → **HALT**, tell the user to reconnect (`/mcp` → `multi-agent-toolkit` → Reconnect). Disk stale → **HALT**, the checkout needs updating. Both current → continue. Never substitute a local `node` call for a missing tool: the run would silently lose the coverage gate and region alignment. Full procedure: `$HOME/.claude/multi-agent-refs/design-check/mcp-currency-gate.md`. Read it for Phase 0 step 0.
82
+ 1. **Repo picker** - `$HOME/.claude/multi-agent-refs/_repo-picker.md`. Account picker skipped unless Confluence export is enabled.
83
+ 2. **Module / dev-context picker** - `$HOME/.claude/multi-agent-refs/_dev-context.md`; multi-module allowed, each audited independently.
84
+ 3. **Platform detect** - persist `state.designCheck.platform`.
85
+ 4. **MOCK FEASIBILITY GATE** - `mcp__multi-agent-toolkit__design_mock_detect` on the selected module path. Branch on `supported`:
86
+ - **`false`** → try the **snapshot lane** before halting: a screen renderable from its own view model is auditable without a runtime mock switch. Ask via `AskUserQuestion`, persist `state.designCheck.captureLane = "snapshot"`, and state the trade (no in-app variant flips). Declined or not renderable → **HALT** with `reason`. Never fabricate a comparison.
87
+ - **`"debug-only"`** → `AskUserQuestion` warning: variants cannot be toggled at launch, only the default Debug state is comparable. Continue / Cancel.
88
+ - **`true`** → continue; persist `state.designCheck.mock`.
89
+ 5. **SCENARIO INVENTORY (this is the audit's target set)** - `mcp__multi-agent-toolkit__design_scenario_inventory` with the config's inventory overrides. This list, not the agent's reading of the code or what the UI exposes to tapping, is what the run is measured against. Persist verbatim to `state.designCheck.inventory`.
90
+ - `targetCount: 0` → warn that no state driver was found and only the default launch state can be audited; a `debug-only` project lands here.
91
+ - `truncated: true` → the target set is INCOMPLETE. Say so now, and pass `coverage.truncatedInventory: true` in Phase 4 so the gate fails rather than reporting a clean percentage of a partial denominator. Narrow the scope to a screen and work through the module in `--resume` steps.
136
92
  - `ignored[]` non-empty → list what the config dropped, so a stale `ignoreTargets` cannot quietly shrink the audit.
137
- 6. **Scope resolve** - intersect `$ARGUMENTS` (grammar above) with `inventory.targets`. Persist `state.designCheck.scope = { argument, targetIds[] }`.
93
+ 6. **Scope resolve** - intersect `$ARGUMENTS` with `inventory.targets`; persist `state.designCheck.scope = { argument, targetIds[] }`. Print the set grouped by screen as `<n> targets · <relaunchCount> relaunches` (cost from `plan`, not the target count). Ask for confirmation only when `relaunchCount` exceeds `config coverage.confirmAbove` (default 25), as a cost estimate; never propose a smaller scope as the easy path.
94
+ 7. **`--resume`** - scope = the latest `run-state.json` targets minus `covered` minus `skipped`. No previous run → tell the user and fall back to whole-module scope after confirmation.
95
+ 8. **Report dir** - create `~/DesignChecks/{repo}__{module}/{UTC-timestamp}/` (+ `assets/`) now, persist `state.designCheck.reportDir`; it exists before driving starts.
96
+ 9. **Worktree** - `{projectRoot}/.worktrees/{taskId}`, `taskId` = `DC-<shortId>`, **never under $HOME**; prune stale locks and add the residue guard first. Local mode is not offered.
138
97
 
139
- Print the resolved set grouped by screen **with its relaunch cost**: `<n> targets · <relaunchCount> relaunches`. Read the cost from `plan`, not from the target count - one relaunch serves every in-app target on that screen, so a 50-target module is typically a dozen relaunches, not fifty. **Whole-module is the intended default**; only ask for confirmation when `relaunchCount` exceeds `config coverage.confirmAbove` (default 25), and phrase it as a cost estimate, not as an invitation to shrink the audit. Never propose a smaller scope as the easy path - a scoped run is for resuming or for a focused re-check, not for avoiding work.
140
- 7. **`--resume`** - read the most recent `~/DesignChecks/{repo}__{module}/*/run-state.json`; the scope becomes that run's targets minus its `covered` and minus its `skipped` entries. Skips carry a reason and are honoured, so a resume covers the genuinely unaudited remainder. No previous run → tell the user and fall back to whole-module scope after confirmation.
141
- 8. **Report dir** - create `~/DesignChecks/{repo}__{module}/{UTC-timestamp}/` (and `assets/` inside it) now, and persist it as `state.designCheck.reportDir`. Phase 3 writes captures, comparison images, and `run-state.json` into it, so it must exist before driving starts - not at export time. This is report output, not a worktree; $HOME is intended here.
142
- 9. **Worktree** - build the Debug app in an isolated worktree so the user's tree is untouched. Follow the `phase-0-init.md` Step 6 worktree location convention exactly: `{projectRoot}/.worktrees/{taskId}` with `taskId` = `DC-<shortId>`, **never under $HOME** (the `.worktrees` segment is fixed, not a preference). Stale-lock heal (`git worktree prune`) + residue guard (`.worktrees/` in `.git/info/exclude`) first. Local mode is not offered - the audit always uses a worktree checkout of the current branch's HEAD (no fetch/push).
143
-
144
- Persist `agent-state.json` with `taskId`, `mode: "design-check"`, `projectRoot`, `worktreePath` and `designCheck` (which carries `module` and `platform`).
98
+ Then persist `agent-state.json`. Full procedure: `$HOME/.claude/multi-agent-refs/design-check/init-inventory.md`. Read it for Phase 0 steps 1-9.
145
99
 
146
100
  ## Phase 1 - Build & Launch (mock)
147
101
 
148
- 1. **Debug build** in the worktree (mock activation requires the Debug configuration):
149
- - iOS: `mcp__multi-agent-toolkit__ios_xcodebuild({ workspace|project, scheme, configuration: "Debug", action: "build", destination: "generic/platform=iOS Simulator" })`. Drill failures via `ios_xcresult`.
150
- - Android: `./gradlew :<module>:assembleDebug` (or `installDebug`) via Bash.
151
- 2. **Boot device + install**: iOS `ios_list_devices` → `ios_boot_device` → install the built `.app` (`xcrun simctl install`). Android: ensure an emulator is running, `adb install -r <apk>`.
152
- 3. **Deterministic state**: iOS `ios_status_bar({ preset: "clean" })` (09:41 / full battery); set a fixed appearance + locale so captures are stable across runs.
153
- 4. **Launch in mock mode** using the activation from Phase 0:
154
- ```
155
- mcp__multi-agent-toolkit__design_mock_launch({ platform, bundle_id|package_name,
156
- launch_arg: state.designCheck.mock.activation.launchArg, // iOS, e.g. "-debugMockMode YES"
157
- intent_extra: state.designCheck.mock.activation.intentExtra }) // Android
158
- ```
159
- For `debug-only` there is no switch - just launch the Debug build. The build is installed once and stays installed: Phase 3 relaunches it per target rather than rebuilding.
102
+ Debug build in the worktree (mocks need Debug), boot, install once, fix status bar / appearance / locale, launch via `design_mock_launch` with the Phase 0 activation (`debug-only`: plain launch). Phase 3 relaunches, never rebuilds. Full procedure: `$HOME/.claude/multi-agent-refs/design-check/build-launch.md`. Read it for Phase 1.
160
103
 
161
104
  ## Phase 2 - Figma fetch & variant mapping (module-scoped)
162
105
 
163
106
  Figma **discovery** happens only here: the frame tree is fetched once and no later phase browses Figma looking for candidates. Phase 3 may still fetch a specific node the user hands over in the 3.3 batch-ask - that is a targeted fetch of an already-identified frame, not discovery, and it is the only Figma call allowed after this phase.
164
107
 
165
- 1. Resolve the Figma URL (`$ARGUMENTS` or ask via `AskUserQuestion`). Parse `fileKey` + `nodeId` (`figma.com/design/{fileKey}/...?node-id={id}`; convert `-`→`:` in node ids).
166
- 2. `mcp__claude_ai_Figma__get_metadata({ fileKey, nodeId })` → the frame tree. Treat direct child frames as **candidate variants**.
167
- 3. **Map inventory targets → Figma frames**: match each scoped target's `screen` + `label` (and `state.designCheck.mock.variantsHint`) to frame names by similarity.
168
- - Confident 1:1 match → accept.
169
- - **Ambiguous or unmatched** → deferred to the Phase 3.3 batch-ask, where the live capture can be shown alongside the question. Never guess silently.
170
- - `debug-only` projects → a single variant (the default state) mapped to the primary frame.
171
- 4. For each mapped variant: `mcp__claude_ai_Figma__get_screenshot` (the design render PNG, download locally) and `mcp__claude_ai_Figma__get_design_context` (node geometry: `absoluteBoundingBox`, `itemSpacing`, paddings, text `fontSize`/`fontFamily`, `fills` colors, and any `CodeConnectSnippet` component name). Flatten the node subtree with the geometry helper into a `figma_spec` element list. Record the Figma frame size (`figmaFrame`).
172
-
173
- Persist the variant list + spec + PNG paths to `state.designCheck.variants[]`.
108
+ Fetch the frame tree, map each scoped target to a frame, fetch screenshot + design context per variant, persist `state.designCheck.variants[]`. **Ambiguous or unmatched → defer to the Phase 3.3 batch-ask. Never guess silently.** Full procedure: `$HOME/.claude/multi-agent-refs/design-check/figma-mapping.md`. Read it for Phase 2.
174
109
 
175
110
  ## Phase 3 - Drive every scoped target → capture → match → batch-ask → compare
176
111
 
177
- **This phase iterates `state.designCheck.scope.targetIds` - a finite list decided in Phase 0. It ends when every id is resolved, not when the UI stops offering new taps.** Tap-walking alone cannot reach a state that needs a different launch argument, a different scenario case, or a typed scenario code, which is exactly how a module's error / edge states go missing.
112
+ **This phase iterates `state.designCheck.scope.targetIds` - a finite list decided in Phase 0. It ends when every id is resolved, not when the UI stops offering new taps.** Tap-walking alone cannot reach a state that needs a different launch argument, scenario case, or typed scenario code - which is how a module's error / edge states go missing.
178
113
 
179
114
  ### 3.0 What every capture is compared against
180
115
 
@@ -182,69 +117,23 @@ Persist the variant list + spec + PNG paths to `state.designCheck.variants[]`.
182
117
 
183
118
  ### 3.1 Drive the inventory's plan, batch by batch
184
119
 
185
- **Follow `inventory.plan`, filtered to the scoped ids.** Each batch is one launch: the batch's relaunch target opens a screen, and every in-app target for that same screen is then flipped while the app is already sitting there. Driving the plan is what makes full coverage affordable - target-by-target relaunching is what made earlier runs give up a third of the way in.
186
-
187
- For each batch:
188
- 1. Launch once with the batch's `launch` driver (or the plain mock activation for the `(default launch)` batch).
189
- 2. Navigate to the screen (`ios_tap` / `ios_swipe` / `ios_type_text` route through idb).
190
- 3. Capture the batch's relaunch target.
191
- 4. For each in-app target in the batch: flip its selector (scenario case / scenario code), let the screen re-render, capture. **No relaunch between these.**
192
-
193
- Per-target activation by `driver.type`:
194
-
195
- | `driver.type` | Activation |
196
- |---|---|
197
- | `launch-arg` | `design_mock_launch({ launch_arg: "<mock activation> <driver.launchArg>" })` - the mock switch AND the target's flag together |
198
- | `intent-extra` | `design_mock_launch({ intent_extra: "<mock extra> <driver.intentExtra>" })` |
199
- | `scenario` | Set `driver.enum` to `driver.case` through the build's debug scenario picker (navigate to it, select, return), then drive the flow that consumes it |
200
- | `code` (from `prefix-code`) | Type a reference beginning with `driver.code` at the entry field the flow starts from, then walk to `driver.appliesTo`. The prefix decides which fixture the mock repository returns, so this is how most per-screen variants are reached |
201
- | `code` (from `code-scenario`) | Same entry field, but the code is flow-wide rather than owned by one screen |
202
- | `fixture` | Activate the launch arg / scenario that reads `driver.file`; when nothing does, the target is a skip with reason "fixture not reachable from any driver" |
203
- | `deep-link` | `ios_open_url` / `android_open_url` with `driver.url` |
204
- | `manual` | Config-declared: follow the config's note, or skip with that note as the reason |
120
+ **Follow `inventory.plan`, filtered to the scoped ids.** Each batch is one launch: the relaunch target opens a screen, then every in-app target for that screen is flipped while the app sits there - **no relaunch between them**. Driving the plan is what makes full coverage affordable. Activate each target by its `driver.type`, and capture the tap-reachable sub-states (sheets, modals, inline errors) under `<id>#<sub-label>`. Each capture (screenshot + `design_ui_geometry`) goes to `state.designCheck.captured[]`. **Persist `state` and `run-state.json` after every capture**, so a run that dies mid-way resumes from where it stopped. Full procedure (driver table, capture mechanics): `$HOME/.claude/multi-agent-refs/design-check/drive-capture.md`. Read it for Phase 3.1.
205
121
 
206
- While a target's state is on screen, also capture the **sub-states reachable from it by tapping** - overlays, bottom sheets, modals, popups, inline errors, QR / share sheets. These cost no relaunch and belong to the target that exposed them; record them as additional captures under that target id (`<id>#<sub-label>`).
207
-
208
- For each capture: `ios_screenshot` (save PNG into the Phase 0 report dir) + `mcp__multi-agent-toolkit__design_ui_geometry` (live boxes + screen size) → append to `state.designCheck.captured[]` with the target id and a human label. **Persist `state` and `run-state.json` after every capture**, so a run that dies mid-way resumes from where it stopped instead of starting over.
209
-
210
- If a target cannot be reached, record it immediately as `{ id, reason }` in `state.designCheck.skipped[]` with a concrete reason ("scenario picker not present in this build", "needs a live order", "crashes on launch: <symbol>"). "Requires a scenario / prefix / launch-arg" is **not** a reason - it describes the work, which is this phase's job.
122
+ An unreachable target is recorded immediately as `{ id, reason }` in `state.designCheck.skipped[]` with a concrete reason. "Requires a scenario / prefix / launch-arg" is **not** a reason - it describes the work, which is this phase's job.
211
123
 
212
124
  ### 3.2 Match each capture → Figma frame (auto)
213
125
 
214
- For each captured screen, resolve its Figma frame: drill the relevant board (`get_metadata` result from Phase 2), match by structure/content; accept only a **confident** match. Add matched → `pairs[]`.
126
+ Accept only a **confident** match against the Phase 2 tree; matched → `pairs[]`.
215
127
 
216
128
  ### 3.3 Batch-ask the user for EVERYTHING unmatched (ONE prompt, WITH the visual)
217
129
 
218
- Collect ALL captures with no confident Figma match into a single list and ask the user ONCE - never guess, never show a wrong frame. **For each unmatched screen you MUST SHOW its captured live screenshot** (render/attach the PNG so they see exactly which visual you mean), name the screen, and ask for the Figma node-id / URL (in `outputLanguage`). Optionally list your best-guess candidate frame names. The user supplies the node-id/URL per shown screenshot; each becomes a confirmed pair. A screen the user declines to map is a skip with reason "no Figma frame supplied".
130
+ Collect ALL captures with no confident Figma match into a single list and ask the user ONCE - never guess, never show a wrong frame. **For each unmatched screen you MUST SHOW its captured live screenshot**, name the screen, and ask for the Figma node-id / URL (in `outputLanguage`). Each answer becomes a confirmed pair. A screen the user declines to map is a skip with reason "no Figma frame supplied".
219
131
 
220
132
  ### 3.4 Compare ALL pairs in one pass
221
133
 
222
- For each pair (matched + user-supplied), fetch `get_screenshot` + `get_design_context`, then:
223
- ```
224
- mcp__multi-agent-toolkit__design_visual_compare({
225
- figma_png, live_png, out_dir: "<report dir>/assets", label: "<variant>",
226
- figma_spec, live_geometry, figma_frame, live_screen,
227
- crop_top_live: <status-bar px>, // strip device chrome the Figma frame lacks
228
- tolerance_px: 2, color_tolerance: 3, max_diff_pct: 1.0 })
229
- ```
230
- Collect `findings` (spacing / size / position in px, color ΔE with hex, typography), `perceptualPct`, and the written image paths (figma / live / diff / overlay / side-by-side).
231
-
232
- **Bottom sheets, modals, and any partial overlay need region alignment.** Their Figma frame covers only the sheet, while the capture is the whole screen. Passing that pair as-is stretches a full screen onto a sheet-shaped frame, which misplaces every element inside the sheet and buries the real defect in noise. So for any capture whose frame is not full-screen:
233
-
234
- ```
235
- mcp__multi-agent-toolkit__design_visual_compare({ ...as above,
236
- live_region: <the sheet container's {x,y,w,h} from design_ui_geometry>,
237
- expected_region: <where the design puts that sheet, same units> })
238
- ```
239
- - `live_region` rebases the comparison onto the sheet's own box. Take it from the `design_ui_geometry` element that is the sheet container (the outermost element whose height is well under the screen's and which holds the sheet's content), NOT from a guess.
240
- - `expected_region` comes from the Figma frame's own placement inside its parent screen frame. With it, the engine emits an `inset` finding per edge.
241
- - `crop_top_live` is ignored when `live_region` is given - the region crop has already excluded device chrome.
242
-
243
- **Edge insets are defects, not tolerances.** A design that shows a sheet flush to the screen edges is not satisfied by one floating in from them, and the reverse is equally wrong. Report every `inset` finding as a deviation with its px delta; never absorb a side gap as "close enough", never raise `tolerance_px` to make one disappear. The same applies to the sheet's internal content padding, which the normal element pairing measures once the region alignment is right.
244
-
245
- **Component reference (best-effort)**: if a Figma atom carries a Code Connect component name and the repo has a matching `*.figma.swift` / `*.figma.kt`, attach that component's reference render to the variant's `componentRefs`.
134
+ `design_visual_compare` per pair (matched + user-supplied) with `tolerance_px: 2, color_tolerance: 3, max_diff_pct: 1.0`. **Bottom sheets, modals, and any partial overlay need region alignment** (`live_region` from the sheet container in `design_ui_geometry`, never a guess, plus `expected_region` from the Figma placement). Attach Code Connect refs (best-effort); compose a paste-ready fix prompt. Full procedure (match, batch-ask mechanics, compare call, region alignment): `$HOME/.claude/multi-agent-refs/design-check/compare.md`. Read it for Phase 3.2-3.4.
246
135
 
247
- **Fix prompt**: from the findings, compose a ready-to-paste developer prompt (target file/screen + each deviation with expected vs actual token/value) so the user can hand it straight to an agent to apply the fix.
136
+ **Edge insets are defects, not tolerances.** Report every `inset` finding as a deviation with its px delta; never absorb a side gap as "close enough", never raise `tolerance_px` to make one disappear.
248
137
 
249
138
  ### 3.5 Close the ledger
250
139
 
@@ -255,48 +144,24 @@ Every scoped target id must end in exactly one bucket:
255
144
 
256
145
  Write `run-state.json` into the Phase 0 report dir with `{ targetIds, covered, skipped }` so `--resume` can pick up the remainder. An id in neither bucket is a bug in this phase, and Phase 4's gate will fail the run for it.
257
146
 
258
- Before leaving this phase, compare `covered.length + skipped.length` against `scope.targetIds.length`. If they differ, the difference is a set of targets nobody decided about - go back and drive them, or record why they cannot be driven. Reaching Phase 4 with a mismatch and letting the gate report it is the worst of both worlds: the work is undone AND the run is marked incomplete.
147
+ Before leaving this phase, compare `covered.length + skipped.length` against `scope.targetIds.length`. A mismatch is a set of targets nobody decided about - go back and drive them, or record why they cannot be driven. Reaching Phase 4 with a mismatch is the worst of both worlds: the work is undone AND the run is marked incomplete.
259
148
 
260
149
  ## Phase 4 - Report, coverage gate & export
261
150
 
262
- 1. **Output dir**: `state.designCheck.reportDir`, already created in Phase 0 - Phase 3's captures and comparison images are already inside it. Do not mint a second timestamped dir here.
263
- 2. Assemble the report object:
264
- ```
265
- { project, module, platform, figmaUrl, figmaFileKey, timestamp,
266
- lang: <prefs.global.outputLanguage>,
267
- coverage: { targets: <scoped inventory targets, as the id array or the target objects>,
268
- covered: <audited id array>,
269
- skipped: [ { id, group, reason } ],
270
- truncatedInventory: <inventory.truncated>,
271
- floor: <config coverage.floor, optional> },
272
- variants: [ { name, figmaNodeId, perceptualPct, passed, compareSize, liveSize,
273
- images, findings, fixPrompt, componentRefs,
274
- walk: { components: <inventoried>, converged: <count>,
275
- didNotConverge: [ { component, attempts } ],
276
- notVerified: [ { item, tag, reason } ] } } ] }
277
- ```
278
-
279
- `walk` separates a checked screen from a viewed one. An empty `notVerified` on a run that never captured a dark or mirrored pass is a false clean - list the skip. Field definitions: `features/design-conformance.md`.
280
- Pass **ids**, not counts: the engine then names each unaccounted target in the report instead of printing an anonymous tally. `compareSize` and `liveSize` come straight from the `design_visual_compare` result.
281
- 3. **Render + export**:
282
- ```
283
- mcp__multi-agent-toolkit__design_report({ report, out_dir: state.designCheck.reportDir,
284
- formats: ["html", "pdf"] + (confluence enabled ? ["confluence"] : []) })
285
- ```
286
- - HTML: self-contained (base64 images, CSS-positioned annotations over the live capture, stacked findings, fix prompt), with the coverage gate banner at the top.
287
- - PDF: via Playwright if present; if unavailable the tool returns `pdfError` - report it and note the HTML can be printed manually.
288
- - **Confluence**: only if `figmaConfig.confluence.enabled` (or prefs). Reuse the pipeline's Confluence adapter (`/multi-agent:channels` storage-format upload) with the report HTML as the page body + PNGs as attachments. Disabled → graceful skip with a one-line note.
151
+ 1. **Output dir**: `state.designCheck.reportDir` from Phase 0; never a second timestamped dir.
152
+ 2. **Assemble** the report object: `coverage` (scoped `targets`, `covered`, `skipped` with reasons, `truncatedInventory`, optional `floor`) and per-variant results with a `walk` block (`components`, `converged`, `didNotConverge`, `notVerified`). `walk` separates a checked screen from a viewed one: an empty `notVerified` on a run that never captured a dark or mirrored pass is a false clean - list the skip. Pass **ids**, not counts.
153
+ 3. **Render + export** with `design_report` (`html` + `pdf`, + `confluence` only when enabled; disabled → graceful skip). Full procedure (report object, export formats, cleanup): `$HOME/.claude/multi-agent-refs/design-check/export.md`. Read it for Phase 4.
289
154
  4. **COVERAGE GATE (blocking, not advisory)** - read `coverage` from the tool result and persist it to `state.designCheck.coverage`:
290
155
  - `gate: "pass"` → report per-variant PASS/FAIL + findings count + report paths.
291
156
  - `gate: "fail"` → the run is **INCOMPLETE**. Print `coverageError`, the `unaccountedIds`, and the exact command that closes the gap: `/multi-agent:design-check --resume`. Do not present an incomplete audit as a finished one, do not bury the miss in a footnote, and never pad the covered list to make the gate pass.
292
157
 
293
158
  The gate is a last line of defence, not the plan. If it fires, Phase 3 left work undone - the correct response is to drive the missing targets, and only then to report.
294
- 5. Clean up the worktree (`git worktree remove --force`) unless the user asked to keep the built app. The report dir is never removed.
159
+ 5. Remove the worktree unless the user asked to keep the built app. The report dir is never removed.
295
160
 
296
161
  ## Notes
297
162
 
298
- - **Feasibility is real**: many projects legitimately cannot be audited (no launchable app, no runtime switch). Report that honestly and stop - never substitute a fabricated or partial comparison.
163
+ - **Feasibility is real**: a project with no launchable app or no runtime switch cannot be audited. Report that honestly and stop - never substitute a fabricated or partial comparison.
299
164
  - **The inventory is the contract**: Phase 0 step 5 decides what "done" means. An audit that visits the linear happy path and lists the rest as "not visited" is the failure mode this pipeline exists to prevent; the gate makes it visible instead of polite.
300
165
  - **Chunk with scope, not with silence**: a 50-target module is a legitimate multi-run job. Scope it, finish each run's gate cleanly, and let `--resume` carry the remainder.
301
- - **"Pixel perfect" is perceptual + geometric**: a Figma render never matches device dimensions 1:1, so the engine normalizes scale and crops chrome. Findings are reported with explicit px / pt / hex deltas and a tolerance, not as strict pixel equality.
302
- - The engine (`design_*` tools) is generic and project-agnostic; all project specifics (mock switch keys, extra launch args / targets, variant→node overrides, status-bar crop, coverage floor, Confluence toggle) come from `design-check-config.json` / prefs, never hardcoded.
166
+ - **"Pixel perfect" is perceptual + geometric**: scale normalized, chrome cropped; findings carry px / pt / hex deltas and a tolerance.
167
+ - The `design_*` engine is project-agnostic; project specifics (mock keys, launch args / targets, node overrides, status-bar crop, coverage floor, Confluence toggle) come from `design-check-config.json` / prefs, never hardcoded.
@@ -6,6 +6,8 @@ parameters: [{"name":"task","kind":"run-id"},{"name":"--triage","kind":"path"},{
6
6
  gui: form
7
7
  destructive: false
8
8
  confirm: none
9
+ context: fork
10
+ agent: Explore
9
11
  ---
10
12
 
11
13
  # multi-agent diff-explain - Phase 4 Triage to Diff Bridge
@@ -0,0 +1,65 @@
1
+ ---
2
+ description: "Estimate new work from similar closed Jira work: a P25-P75 range per role from logged time, with the tickets behind it and the modules touched. Read-only; never a single number, none below three samples. Use when a story, analysis or request needs an effort range."
3
+ description-tr: "Yeni işi ona benzeyen kapanmış işlerden tahmin eder: benzer bitmiş Jira kayıtlarını bulur, onlara ve rol alt görevlerine girilen süreyi okur, rol başına P25-P75 aralığını dayandığı ticket'larla ve işin dokunduğu modüllerle raporlar. Salt-okunur; asla tek sayı vermez, üç örneğin altında hiç sayı vermez."
4
+ allowed-tools: Bash, Read, Grep, AskUserQuestion
5
+ argument-hint: "<analysis.md | \"free text\"> [--project KEY]"
6
+ parameters: [{"name":"input","kind":"text","required":true},{"name":"--project","kind":"text"}]
7
+ gui: form
8
+ destructive: false
9
+ confirm: none
10
+ not-for: analysis, analysis-jira
11
+ ---
12
+
13
+ # multi-agent estimate
14
+
15
+ > **Pickers follow** `$HOME/.claude/multi-agent-refs/picker-contract.md`: never a one-option call, and branch on the option selected, not on its text.
16
+
17
+ **Input**: $ARGUMENTS
18
+
19
+ Turns history into a range. The query and the reading of the work are yours;
20
+ the arithmetic and the minimum-sample rule are the script's. Nothing is written
21
+ to Jira or anywhere else.
22
+
23
+ Script: `$HOME/.claude/scripts/estimate.mjs`.
24
+
25
+ ## Gotchas
26
+
27
+ - The query must say `statusCategory = Done`; the script refuses anything else, because open work has no final time.
28
+ - Logged time is only as good as the team's logging. A role with sub-tasks but no `timespent` has no samples; say that rather than reading it as zero effort.
29
+ - Similar means similar work, not similar words: narrow by component or label first, then by text. A query that returns fifty unrelated issues gives a confident-looking range about nothing.
30
+ - Fewer than three samples gives no number for that row. Do not fill it in from judgement.
31
+
32
+ ## Step 1 - What is being estimated
33
+
34
+ From an analysis document, read its feature name, the components or channels it
35
+ names and its story count; from free text, its nouns. Map the modules it
36
+ touches with the repo map when a repository is at hand:
37
+
38
+ ```bash
39
+ node "$HOME/.claude/scripts/repo-map.mjs" --root "<repo>" --budget 800
40
+ ```
41
+
42
+ ## Step 2 - The query
43
+
44
+ Build one JQL from the project (`--project`, else `prefs.global.issueTree.projectKey`),
45
+ `statusCategory = Done`, the components or labels found above, and at most two
46
+ `text ~` terms. Show it and let the user edit it with one `AskUserQuestion`
47
+ (**Run it** / **Edit the query** / **Cancel**).
48
+
49
+ ## Step 3 - Run
50
+
51
+ ```bash
52
+ node "$HOME/.claude/scripts/estimate.mjs" --jql "<jql>" \
53
+ --roles "$(jq -r '.global.issueTree.subtaskRoles // [] | join(",")' "$HOME/.claude/multi-agent-preferences.json")"
54
+ ```
55
+
56
+ With no roles configured the report has the total and story-point rows only.
57
+
58
+ ## Step 4 - Report
59
+
60
+ Print the table verbatim, then the modules from Step 1. Say which rows had too
61
+ little history, how many issues were sampled, and that the range describes the
62
+ past work the query found: the choice of query is judgement, the numbers are
63
+ arithmetic over it.
64
+
65
+ **Stop. No ticket is created or edited.**