@mmerterden/multi-agent-pipeline 15.16.0 → 16.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 +124 -0
- package/README.md +2 -2
- package/README.tr.md +1 -2
- package/docs/architecture.md +2 -2
- package/docs/ecosystem.md +9 -6
- package/docs/features.md +2 -3
- package/install/_plugin-skills.mjs +28 -2
- package/install/templates/copilot-instructions.md +8 -7
- package/package.json +1 -1
- package/pipeline/commands/multi-agent/SKILL.md +5 -6
- package/pipeline/commands/multi-agent/analysis/SKILL.md +77 -588
- package/pipeline/commands/multi-agent/analysis-resolve/SKILL.md +5 -69
- package/pipeline/commands/multi-agent/channels/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/complaint-analysis/SKILL.md +5 -4
- package/pipeline/commands/multi-agent/dev/SKILL.md +8 -280
- package/pipeline/commands/multi-agent/dev-autopilot/SKILL.md +12 -124
- package/pipeline/commands/multi-agent/dev-local/SKILL.md +8 -111
- package/pipeline/commands/multi-agent/dev-local-autopilot/SKILL.md +11 -113
- package/pipeline/commands/multi-agent/help/SKILL.md +61 -56
- package/pipeline/commands/multi-agent/ios-coding-standard/SKILL.md +4 -2
- package/pipeline/commands/multi-agent/local-autopilot/SKILL.md +2 -4
- package/pipeline/commands/multi-agent/refactor/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/resume-local/SKILL.md +3 -3
- package/pipeline/commands/multi-agent/setup/SKILL.md +2 -2
- package/pipeline/commands/multi-agent/stack/SKILL.md +10 -9
- package/pipeline/commands/multi-agent/store-ready/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/sync/SKILL.md +2 -2
- package/pipeline/commands/multi-agent/update/SKILL.md +1 -1
- package/pipeline/lib/context-link-extractor.sh +38 -0
- package/pipeline/lib/fetch-document.sh +190 -0
- package/pipeline/multi-agent-refs/_dev-context.md +4 -0
- package/pipeline/multi-agent-refs/analysis/evidence.md +213 -0
- package/pipeline/multi-agent-refs/analysis/intake.md +167 -0
- package/pipeline/multi-agent-refs/analysis/locked.md +53 -0
- package/pipeline/multi-agent-refs/analysis/render.md +133 -0
- package/pipeline/multi-agent-refs/analysis/resolve.md +76 -0
- package/pipeline/multi-agent-refs/analysis/synthesis.md +98 -0
- package/pipeline/multi-agent-refs/analysis-template.md +58 -11
- package/pipeline/multi-agent-refs/complaint-analysis-template.md +1 -1
- package/pipeline/multi-agent-refs/component-dispatch.md +5 -5
- package/pipeline/multi-agent-refs/cross-cli-contract.md +9 -7
- package/pipeline/multi-agent-refs/features/skill-conformance.md +1 -1
- package/pipeline/multi-agent-refs/features/url-enrichment.md +13 -3
- package/pipeline/multi-agent-refs/knowledge.md +2 -2
- package/pipeline/multi-agent-refs/payload-contracts.md +1 -1
- package/pipeline/multi-agent-refs/phases/modes.md +73 -53
- package/pipeline/multi-agent-refs/phases/phase-0-init.md +21 -2
- package/pipeline/multi-agent-refs/phases/phase-1-analysis.md +26 -0
- package/pipeline/multi-agent-refs/phases/phase-2-planning.md +26 -12
- package/pipeline/multi-agent-refs/phases/phase-3-dev.md +17 -18
- package/pipeline/multi-agent-refs/phases/phase-4-review.md +29 -7
- package/pipeline/multi-agent-refs/phases/phase-5-test.md +1 -1
- package/pipeline/multi-agent-refs/phases/phase-6-commit.md +8 -0
- package/pipeline/multi-agent-refs/phases/phase-7-report.md +1 -1
- package/pipeline/multi-agent-refs/phases.md +9 -7
- package/pipeline/multi-agent-refs/progress-contract.md +1 -1
- package/pipeline/multi-agent-refs/readiness-review.md +2 -0
- package/pipeline/multi-agent-refs/rules.md +2 -2
- package/pipeline/multi-agent-refs/tracker-contract.md +32 -13
- package/pipeline/multi-agent-refs/wiki-capture.md +2 -2
- package/pipeline/schemas/agent-state.schema.json +3 -3
- package/pipeline/schemas/analysis-output.schema.json +17 -0
- package/pipeline/schemas/analysis-spec.schema.json +69 -1
- package/pipeline/schemas/complaint-analysis-spec.schema.json +1 -1
- package/pipeline/schemas/prefs.schema.json +47 -0
- package/pipeline/schemas/token-budget.json +2 -2
- package/pipeline/scripts/_stack-routing.mjs +17 -12
- package/pipeline/scripts/build-stack-plugins.mjs +16 -6
- package/pipeline/scripts/cost-table.json +1 -1
- package/pipeline/scripts/gen-mode-dispatch.mjs +20 -30
- package/pipeline/scripts/run-aggregator.mjs +1 -1
- package/pipeline/scripts/validate-analysis-doc.mjs +36 -3
- package/pipeline/skills/.skills-index.json +40 -7
- package/pipeline/skills/shared/README.md +12 -9
- package/pipeline/skills/shared/core/multi-agent/SKILL.md +9 -5
- package/pipeline/skills/shared/core/multi-agent-dev/SKILL.md +7 -61
- package/pipeline/skills/shared/core/multi-agent-dev-autopilot/SKILL.md +11 -51
- package/pipeline/skills/shared/core/multi-agent-dev-local/SKILL.md +7 -33
- package/pipeline/skills/shared/core/multi-agent-dev-local-autopilot/SKILL.md +10 -38
- package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +28 -18
- package/pipeline/skills/shared/core/multi-agent-ios-coding-standard/SKILL.md +4 -2
- package/pipeline/skills/shared/core/multi-agent-local-autopilot/SKILL.md +2 -4
- package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-resume-local/SKILL.md +2 -2
- package/pipeline/skills/shared/core/multi-agent-stack/SKILL.md +10 -9
- package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +2 -2
- package/pipeline/skills/shared/external/evidence-github/SKILL.md +45 -0
- package/pipeline/skills/shared/external/evidence-registry/SKILL.md +33 -0
- package/pipeline/skills/shared/external/signal-community/SKILL.md +44 -0
- package/pipeline/skills/skills-index.md +10 -7
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "Standalone feature-spec analysis. Platform-agnostic concept layer with repo-driven convention extraction (Phase 1c) and per-platform Pass B render. 23 main sections + 3 footer in Full mode; 7 sections in Lite mode (auto for small features). Collects Figma / Swagger / Confluence / Jira / Standards (Confluence + Wiki + local file) / Firebase / repo inputs. Stops after emit - does not chain into
|
|
3
|
-
description-tr: "Bağımsız özellik-spesifikasyonu analizi. Repo'dan konvansiyon çıkarımıyla (Faz 1c) platform-bağımsız kavram katmanı ve platform başına Pass B render. Full modda 23 ana + 3 dipnot bölümü; Lite modda 7 bölüm (küçük işlerde otomatik). Figma / Swagger / Confluence / Jira / Standartlar (Confluence + Wiki + yerel dosya) / Firebase / repo girdilerini toplar. Çıktıyı üretince durur -
|
|
2
|
+
description: "Standalone feature-spec analysis. Platform-agnostic concept layer with repo-driven convention extraction (Phase 1c) and per-platform Pass B render. 23 main sections + 3 footer in Full mode; 7 sections in Lite mode (auto for small features). Collects Figma / Swagger / Confluence / Jira / Standards (Confluence + Wiki + local file) / Firebase / repo inputs. Stops after emit - does not chain into a dev run. Use when a feature needs a written specification before any code, from Figma, Swagger, Confluence, Jira or repo inputs."
|
|
3
|
+
description-tr: "Bağımsız özellik-spesifikasyonu analizi. Repo'dan konvansiyon çıkarımıyla (Faz 1c) platform-bağımsız kavram katmanı ve platform başına Pass B render. Full modda 23 ana + 3 dipnot bölümü; Lite modda 7 bölüm (küçük işlerde otomatik). Figma / Swagger / Confluence / Jira / Standartlar (Confluence + Wiki + yerel dosya) / Firebase / repo girdilerini toplar. Çıktıyı üretince durur - dev koşusuna zincirlenmez."
|
|
4
4
|
argument-hint: "[\"<analysis-name>\"] [--lite | --full] [--no-cache] [--preview-conventions]"
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -18,55 +18,9 @@ This command is **independent** from the orchestrator's Phase 1 analysis (which
|
|
|
18
18
|
|
|
19
19
|
These decisions are settled. Do not surface them as `AskUserQuestion` items, do not re-derive them from context, do not invite the user to override mid-run. If the user explicitly wants one of them changed, treat that as a separate request and update this list.
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
| Category | Decisions | Concern |
|
|
26
|
-
|---|---|---|
|
|
27
|
-
| **A. Governance** | 1, 5, 6, 7, 10, 26, 27 | Run-level process rules: one feature per run, default output, auto-commit ban, punctuation policy, output picker timing, Pass B preview, evidence digest cache |
|
|
28
|
-
| **B. Citation and Evidence** | 3, 4, 8, 11, 24, 30 | Every fact in the doc traces back to a source: citation discipline, forward-looking spec, standards binding, repo-evidence reuse-first, Pass B footnote mandatory, analysis self-contained (pipeline-wide) |
|
|
29
|
-
| **C. Output Format and Structure** | 2, 9, 13, 14, 16, 17, 20, 21, 25 | How the document is laid out: section omission rule, per-platform output split, Gherkin user stories, Goals + Non-Goals paired, Files-to-Add tag, API response variants exhaustive, localization mode (ownership-aware), References at the bottom, Lite mode |
|
|
30
|
-
| **D. Design Source and Pipeline Architecture** | 12, 22, 23 | Where design comes from and how the pipeline renders: Figma 3-tier access (BLOCKING), platform-agnostic template + Pass B render, convention extraction (Phase 1c) |
|
|
31
|
-
| **E. UI, Variant, and Test Coverage** | 15, 18, 19, 28, 29, 31 | UI artefact rules: SVG default for new assets, screenshots embedded, all Figma variants drilled, SwiftUI Preview block (iOS), variant usage explicit, business-rule to acceptance-criterion to test traceability |
|
|
32
|
-
|
|
33
|
-
When citing a Locked decision in code or docs, prefer `Locked <n> (<short label>)` form so the category is inferable (e.g. `Locked 30 (analysis self-contained, category B)`).
|
|
34
|
-
|
|
35
|
-
### Full list
|
|
36
|
-
|
|
37
|
-
1. **One feature per run.** Every Figma URL, Confluence page, Jira ID, and Standards source the user supplies belongs to the **same feature**. The command never asks "which feature is this for?" or "which URL is primary?". Mixed inputs covering multiple features are treated as user error: surface the conflict, stop, and ask the user to split into separate runs.
|
|
38
|
-
2. **Section omission rule.** Sections with zero evidence are dropped entirely; no `TBD` placeholder section. Numbering remains sequential `1..N` over the rendered set.
|
|
39
|
-
3. **Citation discipline.** Every quoted UI string, endpoint path, error code, or analytics event name in Sections 2-4 must carry an inline citation: `[Figma annotation <nodeId>]` for copy taken from a Dev Mode annotation, `[Figma <nodeId>]` (MCP) or `[figma-export: <project-slug>/<screen-slug>:<nodeId>]` (local source) for design strings; `file:line` for repo evidence; `Confluence:<pageId>:<heading-slug>` for spec text. **Annotation-as-copy precedence:** when the project's `figma-config` has `annotations.enabled` and a node carries a Dev Mode annotation, that annotation is the authoritative copy for the node and the visible text layer is treated as a placeholder; cite the annotation, not the layer text. Never invent copy - blank beats a guess; a node whose annotation has the base language but is missing a target language emits a Section 20 (Risks) row rather than a fabricated value. Uncited quotes are downgraded to `[label TBD - see Open Questions]` and a row is added to Section 7 Risks. Subagent prose and Code Connect snippets are not citations.
|
|
40
|
-
4. **The spec is forward-looking.** Section bodies describe the new feature as drawn / specified. Findings that exist only in legacy code or the existing branch appear as `> Legacy reference: <text> (file:line)` blockquotes inside the relevant section, never as the lead sentence or a primary table row. A legacy-only finding with no forward counterpart goes to Section 7 Risks as a decision item: "current code does X; should the new feature keep, change, or drop this?".
|
|
41
|
-
5. **Output default = Local file.** The Phase 3.5 output picker keeps `Local file` pre-selected. Confluence and Jira outputs are never default-selected (see `analysis-output-confluence-on-request` memory).
|
|
42
|
-
6. **No auto-commit.** Even after a successful local write or Confluence post, the command never runs `git add` or `git commit`. The user does that themselves if they want.
|
|
43
|
-
7. **Humanizer punctuation policy is non-negotiable.** No em-dash, en-dash, ellipsis, curly quotes, or section sign in any emitted text. Verification grep is run before the file lands.
|
|
44
|
-
8. **Standards binding.** When `evidence.standards[]` is non-empty, Section 7 architectural decisions must cite their binding source by file plus section. Decisions that contradict a binding source go to Section 7 Risks rather than silently overriding.
|
|
45
|
-
9. **Per-platform output split.** One markdown file is produced per selected platform under `analysis/<feature>-<platform>.md`. There is no merged single file. Section duplication follows the A3 hybrid table in `$HOME/.claude/multi-agent-refs/analysis-template.md` (Sections 1 + 4 duplicated verbatim; Sections 2, 3, 5, 6, 7 projected per platform). Each file carries a YAML front-matter header naming the feature, platform, generated-at timestamp, sibling file list, and binding standards source.
|
|
46
|
-
10. **Output destination is asked after drafts exist.** Phase 3 renders each per-platform markdown to `/tmp/analysis-<feature-slug>-<timestamp>/` first. Only then does Phase 3.5 surface the output-destination picker (Local / Confluence / Jira). Drafts in `/tmp/` are the source of truth on resume; `/multi-agent:resume` re-uses them when `phase == awaiting_output_decision`.
|
|
47
|
-
11. **Repo-evidence reuse-first.** Phase 1b runs a repo-evidence collector against each selected repo, producing 13 buckets (services, dtos, useCases, validationRules, domainEntities, routes, coordinators, diConfigurators, uiComponents, tokens, localizationKeys, testingIdentifiers, analyticsEvents) with each row tagged `direct-match | same-domain | cross-cutting`. Section 7 emits `Reuse existing X (file:line)` rows for `direct-match` items and advisory rows for `cross-cutting` items. New-write tasks for items that have a `direct-match` are downgraded to Risks ("existing X candidate found; reuse or document why a new one is needed").
|
|
48
|
-
12. **MUST: Figma access - 3-tier fallback chain, pipeline-wide.** When any Figma URL or node ID is supplied (Phase 0 Step 5), Phase 1 establishes a Figma ground-truth artefact via the 3-tier chain before any UI synthesis runs: (1) Figma MCP `get_design_context` / `get_screenshot` / `get_metadata` for every referenced frame, with one re-auth retry on auth failure; (2) Figma REST API (`GET /v1/files/{fileKey}/nodes`, `GET /v1/images/{fileKey}`) using the PAT resolved through `~/.claude/lib/credential-store.sh get <logical-key>` where `<logical-key>` = `prefs.global.keychainMapping.figma`; (3) a user-attached screenshot as last resort. The tier in use is persisted as `state.figmaAccess.tier`. On Tier 1 the `CodeConnectSnippet` blocks name the exact target component consumed verbatim in Section 2 and Section 7. On Tier 2 the canonical-component decision falls back to the repo's `*.figma.swift` / `*.figma.kt` mappings keyed by `fileKey` + `nodeId`. On Tier 3 the canonical-component decision becomes "tier-3 best-fit pending design review" and produces a forced Open Question in Section 7 plus a Phase 4 `review_blocking` flag. Sound-alike alternatives, "more flexible" wrappers, and extrapolating from Confluence text-only "Component Kompozisyonu" / "Component Inventory" tables are forbidden in every tier. If all three tiers fail, halt the run and ask the user for access; never proceed with text-derived guesses. Section 7 architecture decisions must cite the node ID (Tier 1 or Tier 2) or the user-screenshot reference (Tier 3) for every UI atom row. Violations cost rebuild rounds (raw-primitive substitution; sound-alike-component swap). Generic rule rationale and checklist: see `$HOME/.claude/rules/figma-pipeline.md` "MUST: Figma access - 3-tier fallback chain (BLOCKING, pipeline-wide)". Memory: `[[figma-no-guesswork]]`.
|
|
49
|
-
13. **Gherkin user stories.** Section 4 scenarios use Given / When / Then. Plain-prose user stories are rejected at render time.
|
|
50
|
-
14. **Goals and Non-Goals are paired.** Section 2 always carries both columns. A row in only the goal column without an explicit non-goal counterpart is rejected. Vague "out of scope" phrasing does not satisfy the non-goal column; each non-goal names what is excluded.
|
|
51
|
-
15. **New assets default to SVG.** Section 8 entries marked `new` are SVG unless a documented exception is captured in the rationale column (Lottie for motion design, optimized PNG for raster-only icons). PDF, JPG, and unoptimized PNG are rejected.
|
|
52
|
-
16. **Files-to-Add tag mandatory.** Every row in Section 14 carries one tag from `Reuse | Add new | Modify`. Untagged rows fail the dispatch gate.
|
|
53
|
-
17. **API response variants exhaustive.** Section 9 lists every HTTP status code returned by the endpoint with at least one example body and the matching UI outcome. Phrases like "other errors" or "various 4xx" are rejected.
|
|
54
|
-
18. **Screenshots embedded, not linked.** Section 5 frame galleries reference local PNG files. Dispatch uploads them as Confluence multipart attachments and injects `<ac:image><ri:attachment ri:filename="..." /></ac:image>` into the page body. URL-only Figma references in Section 5 fail the dispatch gate.
|
|
55
|
-
19. **All Figma variants drilled.** When a Figma section URL is supplied, all child frames are drilled, not just the canonical default. The renderer enumerates child frames via `mcp__claude_ai_Figma__get_metadata` (Tier 1) or `figma-screenshot.sh --section` (Tier 2) and produces one Section 5.1 row per child frame.
|
|
56
|
-
20. **Localization mode (ownership-aware).** Section 10's shape is driven by the project `figma-config` `localization.ownership` (default `in-repo`). The locale set comes from `localization.locales` (default `tr, en, ar, de, es, fr, it, ru`); do not hardcode a locale list in the render.
|
|
57
|
-
- **`in-repo`** (default, historical behavior): new keys carry filled cells for every configured locale. Placeholder values `[bekleniyor: çeviri ekibi]` / `[pending: translation team]` are a soft state and the dispatch report flags `i18n_pending: <count>` as a blocker. Empty cells are rejected outright.
|
|
58
|
-
- **`externally-owned`**: per-locale values are owned by the authoring system named in `localization.authoringPipeline` and MUST NOT be hand-filled. Section 10 lists `key | status | copy source | base value | ownership` only; the gate becomes "the `localization.baseLanguage` value is present (sourced from the Figma annotation, Locked 3) AND the ownership reference is cited". A key missing its base-language value is a blocker (it renders the raw key at runtime). Fabricated per-locale values are rejected.
|
|
59
|
-
21. **References at the bottom.** The user-supplied input table is rendered as Section 21 References, not as Section 1. Readers see goals, flow, and design before sources.
|
|
60
|
-
22. **Platform-agnostic template + Pass B render.** The template (`$HOME/.claude/multi-agent-refs/analysis-template.md`) describes concepts (state holder, view, navigator, use case, repository, DTO, state model, DI register, localization key, accessibility identifier, test method) without platform-specific class names. Pass B (Phase 2b) projects each concept onto the selected platform using conventions extracted at Phase 1c.
|
|
61
|
-
23. **Convention extraction mandatory (Phase 1c).** After Phase 1b repo evidence, Phase 1c extracts seven pattern groups (folder structure, class naming, UI state model, test method naming, accessibility identifier, localization key, DI registration) per selected repo via `~/.claude/lib/extract-conventions.sh`. Output lands in `state.analysisSpec.evidence.conventions[<repo>]` with confidence levels (high / medium / low / none) and evidence file citations.
|
|
62
|
-
24. **Pass B cell footnote mandatory.** Every cell Pass B fills in Section 13 (Architecture Plan concept table) and any other per-platform projection carries a footnote of the form `^[<convention-key> <confidence>: <evidence-source>]` pointing back to Phase 1c output. Cells with `confidence: low | none` cite `conventions-defaults.md:C<n>-<platform>` and emit a row in Section 20 Risks ("convention fallback applied"). Footnote-less cells fail the dispatch gate.
|
|
63
|
-
25. **Lite mode for small features.** When Phase 1 signals indicate a small feature, Lite mode auto-activates and renders only Sections 1, 2, 4, 9, 13, 14, 21, plus optional 23 Changelog. The user can force Lite with `--lite` or force Full with `--full`. Full mode is the default for new feature analyses. **Scoring (v9.1.0+):** three independent signals - `confluenceSpecLines < 100`, `figmaFramesCount <= 1`, `repoDirectMatchCount >= 8`. Each true signal scores 1 point; Lite auto-activates at `score >= 2`. Previous AND-threshold (`v8.12.0..v9.0.x`) was too strict and forced small features into Full mode when one signal was just over the line. Explicit user flags (`--lite` / `--full`) always win over auto-scoring.
|
|
64
|
-
26. **Pass B preview before render.** Phase 2a presents the resolved convention table to the user before Phase 2b emits any platform file. The user can approve, override individual cells, or cancel. Empty answers do not imply consent (`feedback_no-inferred-defaults-from-empty-answer`); the picker re-asks on empty submit.
|
|
65
|
-
27. **Evidence digest caches Phase 1b and 1c.** `evidence_digest = sha256(featureName || sorted(platforms) || repoEvidence.summary || conventions.summary)`. When the same feature name is invoked again against the same set of repos and the digest matches, Phase 1b and 1c are skipped and the cached `evidence.repoEvidence` / `evidence.conventions` is reused. Cache TTL is 24 hours; manual invalidation via `--no-cache` flag.
|
|
66
|
-
28. **SwiftUI Preview block mandatory (iOS projection, SwiftUI only).** When the iOS file is produced AND the affected view is a SwiftUI view (detected via `import SwiftUI` + `: View` protocol conformance in `evidence.repoEvidence[<repo>].buckets.uiComponents`), Section 13.6 renders a Preview block table covering at minimum: canonical default (LTR Light), Dark, RTL, Dynamic Type accessibilityLarge, and one error variant. Loading state and edge-case variants are added when distinct from canonical. UIKit-only features (no SwiftUI view artefact) drop Section 13.6 with note `(N/A: UIKit-only feature)`. Preview macro convention (`#Preview` for Swift 5.9+ vs legacy `PreviewProvider`) is read from `evidence.conventions[<repo>].previewMacro`. Each Preview variant listed in Section 13.6 must have a matching row in Section 15.2 Snapshot Tests; a Preview without a snapshot row triggers a Section 20 Risk.
|
|
67
|
-
29. **Variant usage explicit and bounded.** Section 6 inventory rows list which variants this feature consumes per component (concrete enum case + bool value). New Section 6.X (Variant Usage Matrix) catalogues the full variant axis vs. used subset with a rationale per excluded variant. Sections 13.6 (Preview) and 15.2 (Snapshot) cover only the used subset; expanding the variant set requires updating Section 6.X first.
|
|
68
|
-
30. **Analysis as self-contained design bridge - no MCP outside analysis phase (BLOCKING, pipeline-wide).** The analysis document is the sole design source for every downstream phase. After Phase 1 of `/multi-agent:analysis` produces `analysis/<feature>-<platform>.md`, Phase 2 Planning, Phase 3 Dev, Phase 4 Review, Phase 5 Test, Phase 6 Commit, and Phase 7 Report consume only the analysis document plus repo Code Connect mappings (`*.figma.swift` / `*.figma.kt`). Calling `mcp__claude_ai_Figma__*`, hitting `api.figma.com`, or fetching a `figma.com/design/...` URL during Phase 2+ is a violation. Applies to every mode that runs Phase 2+: `/multi-agent`, `/multi-agent:autopilot`, `/multi-agent:local`, `/multi-agent:local-autopilot`, `/multi-agent:dev`, `/multi-agent:dev-autopilot`, `/multi-agent:dev-local`, `/multi-agent:dev-local-autopilot`. Hard requirement (v9.0.0): Phase 2 Pre-item and Phase 3 Pre-item (BLOCKING) abort the run when the analysis document is missing. Memory: `[[mcp-only-in-analysis]]`. Generic rule rationale and access matrix: see `$HOME/.claude/rules/figma-pipeline.md` "MUST: No MCP outside analysis phase".
|
|
69
|
-
31. **Business-rule to acceptance-criterion to test traceability (AI + human spine).** The analysis is a development handoff that both an AI implementer and a human reviewer must act on, so it is bound by one shared-ID vocabulary. Every business rule carries a stable id `BR-<slug>-NN` (Section 4.4). Each rule maps to at least one acceptance criterion written Given / When / Then (binary - two readers must not be able to disagree on pass/fail). Each acceptance criterion maps to unit-test scenarios in Section 15.1, one row per case across happy / boundary / error / empty-nil (enumerate at least the failure modes; agents hallucinate error handling when it is omitted). The same ids thread onward: Section 15.6 UI-test flows reference the `BR-` ids and use stable selectors (accessibilityIdentifier / testTag), Section 16 accessibility items reuse those identifiers, Section 11 analytics events cite their triggering rule or story, and Section 5/7 layout cells carry token + Figma node refs. Never invent copy or values (blank beats a guess; a missing source becomes a Section 20 Open Question). **Mode-aware gate:** in Full mode a business rule with no acceptance criterion, or an acceptance criterion with no Section 15.1 scenario, fails the dispatch gate. In **Lite mode Section 15 is not rendered**, so the rule-to-test half does not apply - Section 4.4 still lists each rule with its Given/When/Then acceptance criterion (the acceptance criterion is itself the testable statement), and the 15.1 mapping is deferred to whenever the feature is later analyzed in Full or implemented via `/multi-agent:dev`. The rule-to-acceptance-criterion half always holds, in both modes.
|
|
21
|
+
The full list of 31, with the category index, lives in `$HOME/.claude/multi-agent-refs/analysis/locked.md`. Read it before the run starts; it is the contract the whole flow is judged against. `/multi-agent:analysis-resolve` inherits the same list.
|
|
22
|
+
|
|
23
|
+
Cite a decision as `Locked <n> (<short label>)` so the category is inferable.
|
|
70
24
|
|
|
71
25
|
## Input
|
|
72
26
|
|
|
@@ -84,536 +38,19 @@ The template is platform-agnostic (Locked 22). It speaks in concepts (state hold
|
|
|
84
38
|
|
|
85
39
|
### Phase 0 - Intake
|
|
86
40
|
|
|
87
|
-
Sequential `AskUserQuestion`
|
|
88
|
-
|
|
89
|
-
**Step narration (required, per `$HOME/.claude/multi-agent-refs/picker-contract.md`)**: the chain length is known up front - 1 analysis-name + 1 account + 1 platform + 1 repo-round per selected platform + 1 input-URL batch + 1 coverage-options batch (so a single-platform run is 6 steps; account is skipped for local-only flows, which lowers the total). Before each step's `AskUserQuestion`, print the narrator line `<localized: "Step <i>/<n>: <what this step decides>">` in `outputLanguage`. Auto-resolved steps (single account, local-only) still print their breadcrumb with the resolution noted. This is what makes the picker show, step by step, what it is doing.
|
|
90
|
-
|
|
91
|
-
#### Step 0 - Language resolution (BLOCKING, runs before any picker)
|
|
92
|
-
|
|
93
|
-
Before emitting the first `AskUserQuestion`, read `prefs.global.outputLanguage` (`tr` or `en`, default `tr`). Every `<localized: "...">` marker in the Phase 0 picker chain (Steps 1-5) MUST be rendered in the resolved language - this is not deferred to Phase 3. Per the Language note above: `question` and `description` follow `outputLanguage`; `label` and `header` stay English. If `outputLanguage == tr`, the user sees Turkish question text; do not emit the English literal inside the `<localized:>` marker.
|
|
94
|
-
|
|
95
|
-
#### Step 1 - Analysis name
|
|
96
|
-
|
|
97
|
-
If `$ARGUMENTS` is empty, ask via AskUserQuestion (single question, user types via Other).
|
|
98
|
-
Result: `state.analysisSpec.featureName` (state key kept for backward compatibility; user-facing label is "analysis name").
|
|
99
|
-
|
|
100
|
-
#### Step 2 - Account picker
|
|
101
|
-
|
|
102
|
-
Reuse `_account-picker.md`. Skipped if the resolved flow is local-only.
|
|
103
|
-
|
|
104
|
-
#### Step 3 - Platform multi-select
|
|
105
|
-
|
|
106
|
-
AskUserQuestion (multiSelect=true):
|
|
107
|
-
```
|
|
108
|
-
header: "Platforms"
|
|
109
|
-
question: <localized: "Which platforms is this analysis for?">
|
|
110
|
-
options:
|
|
111
|
-
- label: "iOS"
|
|
112
|
-
- label: "Android"
|
|
113
|
-
- label: "Backend"
|
|
114
|
-
- label: "Frontend"
|
|
115
|
-
```
|
|
116
|
-
Empty submit → re-ask. Result: `state.analysisSpec.platforms[]`.
|
|
117
|
-
|
|
118
|
-
**Platform coverage = provided platforms.** The analysis renders exactly one per-platform file (Locked 9) for each platform selected here and given a repo in Step 4: select iOS only -> a single iOS document; select iOS + Android -> one iOS and one Android document, each projected through that repo's own conventions (Phase 1c) and its own Code Connect index (Phase 1b.1, discovered from that repo's `*.figma.swift` / `*.figma.kt`). Do not analyze a platform the user did not select, and do not drop a selected platform that has a repo.
|
|
119
|
-
|
|
120
|
-
#### Step 4 - Repo multi-select per platform
|
|
121
|
-
|
|
122
|
-
For each selected platform, run one AskUserQuestion round. Reuse `_dev-context.md` logic:
|
|
123
|
-
- Run `~/.claude/lib/submodule-detector.sh "$REPO_PATH"` to enumerate submodules + `canPush`
|
|
124
|
-
- Augment with `prefs.projects[<key>].editableRelatedRepos[]` for iOS / Android / Backend
|
|
125
|
-
- For `Frontend`, read `prefs.projects[<key>].frontendRepos[]` as the primary source (since Frontend is rarely in the iOS submodule tree); fall back to Other input
|
|
126
|
-
- If no repos are detectable for a platform, present a single Other input asking for `<owner>/<repo>`
|
|
127
|
-
|
|
128
|
-
Result: `state.analysisSpec.repos[]` (each entry has `platform`, `name`, `path`, `canPush`).
|
|
129
|
-
|
|
130
|
-
#### Step 5 - Input URLs (single 6-question batch)
|
|
131
|
-
|
|
132
|
-
One AskUserQuestion call with **6 parallel questions**, one per source type. Each question shows a `Skip` option plus auto-available `Other` for free-text input. Empty / `Skip` selections yield no entry in `state.analysisSpec.contextLinks[]`.
|
|
133
|
-
|
|
134
|
-
```
|
|
135
|
-
Q1: header="Figma URL"
|
|
136
|
-
question: <localized: "Do you have a Figma URL for this feature?">
|
|
137
|
-
options:
|
|
138
|
-
- label: "No Figma input"
|
|
139
|
-
- label: "Use repo Code Connect only"
|
|
140
|
-
(Other: paste URL - comma-separated for multiple frames)
|
|
141
|
-
|
|
142
|
-
Q2: header="Swagger URL"
|
|
143
|
-
question: <localized: "Do you have a Swagger / OpenAPI URL?">
|
|
144
|
-
options:
|
|
145
|
-
- label: "No Swagger input"
|
|
146
|
-
- label: "Extract from Confluence instead"
|
|
147
|
-
(Other: paste URL)
|
|
148
|
-
|
|
149
|
-
Q3: header="Confluence"
|
|
150
|
-
question: <localized: "Do you have a Confluence page URL for the feature spec?">
|
|
151
|
-
options:
|
|
152
|
-
- label: "No Confluence input"
|
|
153
|
-
(Other: paste URL - comma-separated for multiple pages)
|
|
154
|
-
|
|
155
|
-
Q4: header="Jira"
|
|
156
|
-
question: <localized: "Do you have a related Jira ID?">
|
|
157
|
-
options:
|
|
158
|
-
- label: "No Jira input"
|
|
159
|
-
(Other: type Jira ID like {JIRA_KEY}-12345 - comma-separated for multiple)
|
|
160
|
-
|
|
161
|
-
Q5: header="Standards"
|
|
162
|
-
question: <localized: "Do you have coding documentation or standards to bind the development plan? Confluence URL, GitHub wiki URL, or local file path.">
|
|
163
|
-
options:
|
|
164
|
-
- label: "No standards input"
|
|
165
|
-
- label: "Auto-detect from repo"
|
|
166
|
-
description: "Searches the auto-detect probe list below (canonical home-dir Standards file, repo CLAUDE.md / CONTRIBUTING.md, docs/architecture/*.md, and the wiki Home.md / Navigation.md if a GitHub wiki is configured)"
|
|
167
|
-
(Other: comma-separated mix of Confluence URLs, GitHub wiki URLs, and absolute / tilde-expanded local file paths)
|
|
168
|
-
|
|
169
|
-
Q6: header="Firebase"
|
|
170
|
-
question: <localized: "Do you have Firebase Analytics events for this feature? Comma-separated event-name list, a JSON schema file path, or a Firebase Console URL.">
|
|
171
|
-
options:
|
|
172
|
-
- label: "No Firebase input"
|
|
173
|
-
- label: "Auto-detect from repo"
|
|
174
|
-
description: "Greps Analytics.logEvent / firebaseAnalytics.logEvent / logEvent(analytics, ...) call sites in the selected repos and extracts event names"
|
|
175
|
-
(Other: comma-separated mix of event names like 'profile.view,profile.opened', a /path/to/events.json, or a console.firebase.google.com URL)
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
After submit, run `~/.claude/lib/context-link-extractor.sh` on each Other-provided string. Results are typed and written to `state.analysisSpec.contextLinks[]`. Q5 entries are additionally tagged `binding: true` so Phase 2 Section 7 treats them as hard constraints (see the Phase 1 type table and the Phase 2 Section 7 row).
|
|
179
|
-
|
|
180
|
-
**Q5 + Q6 type detection rules** (also documented in `~/.claude/lib/context-link-extractor.sh`):
|
|
181
|
-
|
|
182
|
-
| Input shape | Detected type | Phase 1 strategy |
|
|
183
|
-
|---|---|---|
|
|
184
|
-
| Starts with `/` or `~` and ends with `.md` / `.markdown` / `.txt` | `local-file` | `Read` tool on the absolute path (tilde-expanded) |
|
|
185
|
-
| Host = `github.com` AND path matches `/<owner>/<repo>/wiki/<PageName>` (no `.md`) | `wiki` | `git clone --depth 1 https://github.com/<owner>/<repo>.wiki.git /tmp/<repo>-wiki && Read /tmp/<repo>-wiki/<PageName>.md` (URL `-` to ` ` decoding) |
|
|
186
|
-
| Host matches `confluence*.<tld>` AND path contains `/display/` or `/pages/viewpage.action?pageId=` | `standards-confluence` | Same fetcher as `confluence` but bucket goes to `evidence.standards[]` |
|
|
187
|
-
| Comma-separated lowercase tokens with `.` or `_` (e.g. `profile.view,screen_view`) and no slash / no scheme | `firebase-events:names` | Scaffold rows from names alone |
|
|
188
|
-
| Starts with `/` or `~`, ends with `.json`, path contains `events` or `analytics` | `firebase-events:schema` | `Read` + JSON parse `events[]` |
|
|
189
|
-
| Host `console.firebase.google.com` with `/analytics/` in path | `firebase-events:console` | Reference-only; INFO warning printed, no fetch |
|
|
190
|
-
| Any other `http(s)://` URL | `generic-doc` | `WebFetch` |
|
|
191
|
-
|
|
192
|
-
Q5 Auto-detect mode probe order (option 2):
|
|
193
|
-
1. `~/<project>-Standards.md` - canonical home-dir reference file; the exact filename comes from `prefs.projects[<project>].standardsFile` (no hardcoded project name in this command)
|
|
194
|
-
2. `<repo>/CLAUDE.md`, `<repo>/CONTRIBUTING.md`
|
|
195
|
-
3. `<repo>/docs/architecture/*.md`
|
|
196
|
-
4. If a `*.wiki.git` mirror is reachable for the primary repo, clone and ingest `Home.md` + any page named `Navigation*.md`
|
|
197
|
-
|
|
198
|
-
Q6 Auto-detect mode probe order (option 2):
|
|
199
|
-
1. Per-repo grep for `Analytics\.logEvent\(`, `firebaseAnalytics\.logEvent\(`, `logEvent\(analytics,` and harvest the first string literal in each call as the event name
|
|
200
|
-
2. Generated `AnalyticsEvents/*.swift` / `AnalyticsEvents/*.kt` if present (treat each public struct conforming to `AnalyticsEvent` as one event)
|
|
201
|
-
3. Repo-level `firebase-events.json` / `analytics/events.json` files
|
|
202
|
-
|
|
203
|
-
#### Step 5a - Coverage options (opt-in, 2 questions)
|
|
204
|
-
|
|
205
|
-
One `AskUserQuestion` call with 2 parallel yes/no questions. These are opt-INs, not source intake: an empty answer is NOT consent (per `feedback_no-inferred-defaults-from-empty-answer`) - re-ask on empty rather than defaulting silently once the picker is shown.
|
|
206
|
-
|
|
207
|
-
```
|
|
208
|
-
Q1: header="UI Tests"
|
|
209
|
-
question: <localized: "Should the analysis include UI test scenarios (XCUITest / Compose UI test)? Optional; unit + snapshot coverage is always included.">
|
|
210
|
-
options:
|
|
211
|
-
- label: "No UI tests" -> state.analysisSpec.options.uiTests = false (default)
|
|
212
|
-
- label: "Write UI test scenarios" -> state.analysisSpec.options.uiTests = true
|
|
213
|
-
|
|
214
|
-
Q2: header="A11y depth"
|
|
215
|
-
question: <localized: "How detailed should accessibility be? Basic checklist always ships; full adds a VoiceOver / TalkBack reading-order walkthrough.">
|
|
216
|
-
options:
|
|
217
|
-
- label: "Basic checklist" -> state.analysisSpec.options.a11yDepth = "basic" (default)
|
|
218
|
-
- label: "Full walkthrough" -> state.analysisSpec.options.a11yDepth = "full"
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
`options.uiTests` gates Section 15.6 (UI test flows); `options.a11yDepth` gates the Section 16 VoiceOver / TalkBack walkthrough. Both default to the lighter choice so the doc stays lean unless the user opts in.
|
|
222
|
-
|
|
223
|
-
#### Step 5b - Repo-evidence collector (automatic, no prompt)
|
|
224
|
-
|
|
225
|
-
Runs after Step 5a submits and before Phase 1 begins. Reads from `state.analysisSpec.repos[]`. For each repo, walks the platform whitelist and produces a 13-bucket evidence catalogue. No user interaction. Output: `state.analysisSpec.evidence.repoEvidence[<repo>]`. See Phase 1b for the bucket list and tagging rules.
|
|
226
|
-
|
|
227
|
-
#### Step 6 - REMOVED in v8.10.0
|
|
228
|
-
|
|
229
|
-
The output-destination picker moved to **Phase 3.5**, which runs after Phase 3 finishes the per-platform draft buffers. See Phase 3.5 below for the picker definition.
|
|
230
|
-
|
|
231
|
-
### Phase 1 - Fetch & extract (parallel)
|
|
232
|
-
|
|
233
|
-
For each entry in `state.analysisSpec.contextLinks[]`, fan out by `type`. Entries tagged `binding: true` (Q5 inputs) land in `evidence.standards[]` regardless of underlying source type so Section 7 can iterate them as one set.
|
|
234
|
-
|
|
235
|
-
| type | Command | Output bucket |
|
|
236
|
-
|------|---------|---------------|
|
|
237
|
-
| swagger | `~/.claude/lib/fetch-swagger.sh <url>` | `state.analysisSpec.evidence.swagger[]` |
|
|
238
|
-
| confluence | `~/.claude/lib/fetch-confluence.sh <url>` | `state.analysisSpec.evidence.confluence[]` |
|
|
239
|
-
| figma | **MUST** establish the Figma access tier per Locked decision #12. Tier 1 (preferred): call `mcp__claude_ai_Figma__get_design_context` (primary), `mcp__claude_ai_Figma__get_screenshot`, `mcp__claude_ai_Figma__get_metadata` for every node ID; auth failure runs `authenticate` + `complete_authentication` then retries. Tier 2 (fallback): `GET https://api.figma.com/v1/files/{fileKey}/nodes?ids={nodeId}` for design context and `GET /v1/images/{fileKey}?ids={nodeId}&format=png&scale=2` for screenshots, with PAT from `~/.claude/lib/credential-store.sh get <logical-key>` (logical key = `prefs.global.keychainMapping.figma`); canonical component resolves via repo `*.figma.swift` / `*.figma.kt` mapping. Tier 3 (last resort): user-attached screenshot, `codeConnectSnippets: []`, forced Open Question. Capture each `CodeConnectSnippet` block verbatim when on Tier 1 (component name + modifier chain). **Annotation capture (when the project `figma-config` has `annotations.enabled`):** on Tier 1, walk the `annotations[]` the `get_design_context` payload returns for each node (read `label` / `labelMarkdown`); on Tier 2, run `~/.claude/lib/fetch-figma-annotations.sh --file-key <fileKey> --node-id <ids> --lang-prefixes <config.annotations.langPrefixes>`. Parse each annotation by the configured language prefixes (prefixed `TR:/EN:` wins, else line1/line2, else single) and persist to `annotations[]`. The annotation is the authoritative copy for its node (Locked 3); the visible text layer is a placeholder. Persist `state.figmaAccess.tier`. See Locked decision #12 and `$HOME/.claude/rules/figma-pipeline.md` "MUST: Figma access - 3-tier fallback chain". | `state.analysisSpec.evidence.figma[]` (records: `nodeId`, `screenshotUrl`, `codeConnectSnippets[]`, `tokens[]`, `textLayers[]`, `annotations[]`, `tier`; see `analysis-spec.schema.json`) |
|
|
240
|
-
| jira | `gh api` or Jira REST API for issue summary | `state.analysisSpec.evidence.jira[]` |
|
|
241
|
-
| generic-doc | WebFetch on demand | `state.analysisSpec.evidence.confluence[]` (generic bucket) unless `binding: true` -> `evidence.standards[]` |
|
|
242
|
-
| `local-file` | `Read` (no fetch) on tilde-expanded absolute path | `state.analysisSpec.evidence.standards[]` |
|
|
243
|
-
| `wiki` | `git clone --depth 1 https://github.com/<owner>/<repo>.wiki.git /tmp/<repo>-wiki`, then `Read /tmp/<repo>-wiki/<PageName>.md` (`-` decoded back to space in PageName). Fallback chain: `gh api repos/<owner>/<repo>/contents/<file>.md` for repo-hosted docs if wiki repo is 404. | `state.analysisSpec.evidence.standards[]` |
|
|
244
|
-
| `standards-confluence` | `~/.claude/lib/fetch-confluence.sh <url>` (same fetcher as `confluence`) | `state.analysisSpec.evidence.standards[]` |
|
|
245
|
-
| `firebase-events:names` | Scaffold rows directly from `metadata.names[]`; one row per name with empty params (filled later by repo grep cross-check) | `state.analysisSpec.evidence.firebase[]` |
|
|
246
|
-
| `firebase-events:schema` | `Read` the JSON path; parse `events[]` with `python3 -c json.load`; each entry yields `{name, params: [{name, type, required}]}` | `state.analysisSpec.evidence.firebase[]` |
|
|
247
|
-
| `firebase-events:console` | Reference-only; print INFO warning `INFO: Firebase Console URL captured for reference; provide JSON schema or event-name list for structured ingestion.`; no fetch attempt | `state.analysisSpec.evidence.firebase[]` (URL stored as reference link only) |
|
|
248
|
-
|
|
249
|
-
**Auth / access failure handling** (applies to `confluence`, `standards-confluence`, `generic-doc` when WebFetch returns a login page, 401, 403, or HTML containing `<form action="/login.action"`):
|
|
250
|
-
|
|
251
|
-
1. Do **not** silently drop the entry. Record `state.analysisSpec.evidence.fetchErrors[]` with `{url, type, reason: "auth_required"}`.
|
|
252
|
-
2. Surface a one-line warning to the user during Phase 1 progress output: `WARN: Confluence requires browser auth for <url>. Falling back to repo evidence; add the page text manually to /tmp/analysis-paste.md and re-run if needed.`
|
|
253
|
-
3. Continue Phase 1 with remaining evidence sources rather than aborting.
|
|
254
|
-
|
|
255
|
-
For each repo in `state.analysisSpec.repos[]`, run parallel greps (lightweight surface scan; the deeper 13-bucket extraction happens in Phase 1b):
|
|
256
|
-
|
|
257
|
-
```bash
|
|
258
|
-
# Localization
|
|
259
|
-
grep -rEl '(Localizable\.strings|strings\.xml|i18n|locale)' "$REPO_PATH"
|
|
260
|
-
|
|
261
|
-
# Deeplink handlers
|
|
262
|
-
grep -rEl '(UniversalLink|DeeplinkRouter|getDeeplink|onNewIntent|intent-filter)' "$REPO_PATH"
|
|
263
|
-
|
|
264
|
-
# Push handlers
|
|
265
|
-
grep -rEl '(UNUserNotificationCenter|didReceiveRemoteNotification|FirebaseMessaging|FCM)' "$REPO_PATH"
|
|
266
|
-
|
|
267
|
-
# Firebase Analytics call sites (Phase 1 auto-detect + Phase 1b cross-check)
|
|
268
|
-
grep -rEln '(Analytics\.logEvent|firebaseAnalytics\.logEvent|logEvent\(analytics,)' "$REPO_PATH"
|
|
269
|
-
|
|
270
|
-
# Code Connect
|
|
271
|
-
find "$REPO_PATH" -name '*.figma.swift' -o -name '*.figma.kt'
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
Results go to `state.analysisSpec.evidence.repo[]` (presence flags only).
|
|
275
|
-
|
|
276
|
-
**Confluence-embedded API table detection**: if a Confluence page body contains `Request Path` / `Service Name` / `Response Body` table columns, set `embeddedApiTable=true` and parse the endpoints from those columns (a project may supply its own parser for this). Do not also trigger a separate Swagger fetch.
|
|
277
|
-
|
|
278
|
-
### Phase 1b - Repo-evidence collector (parallel, per repo)
|
|
279
|
-
|
|
280
|
-
After Phase 1 finishes, run a deeper scan per repo to enable Section 7's reuse-first rule (Locked decision 11). Output: `state.analysisSpec.evidence.repoEvidence[<repo>]`.
|
|
281
|
-
|
|
282
|
-
**Whitelist roots per platform** (subset of repo paths scanned to keep the catalogue bounded):
|
|
283
|
-
|
|
284
|
-
| Platform | Roots |
|
|
285
|
-
|---|---|
|
|
286
|
-
| iOS | `Domains/`, `Common/`, `Core/`, `App/` |
|
|
287
|
-
| Android | `app/src/`, `feature/`, `core/`, `common/` |
|
|
288
|
-
| Backend | `src/`, `api/`, `services/` |
|
|
289
|
-
| Frontend | `src/`, `app/`, `components/`, `features/`, `lib/` (override with `prefs.projects[<key>].frontendRoots[]`) |
|
|
290
|
-
|
|
291
|
-
Skip dirs (always): `.build`, `DerivedData`, `Pods`, `node_modules`, `.next`, `build/`, `.gradle`, `vendor/`.
|
|
292
|
-
|
|
293
|
-
**Candidate set**: build a feature-name slug bundle:
|
|
294
|
-
|
|
295
|
-
```bash
|
|
296
|
-
slugs=$(echo "$featureName" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/ /g')
|
|
297
|
-
# e.g. UserProfile -> "user profile userprofile"
|
|
298
|
-
grep -rilE "$slugs" $WHITELIST --include="*.swift" --include="*.kt" --include="*.ts" --include="*.tsx" --include="*.py" --include="*.go" | head -200 > $CANDIDATES
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
If `wc -l < $CANDIDATES` exceeds 200, record `fetchWarnings += "feature-name too generic; candidate cap hit"` in `repoEvidence[<repo>]`.
|
|
302
|
-
|
|
303
|
-
**13 buckets** (each scanned in parallel with a 30 s timeout per bucket; timeout marks the bucket as `partial`, never blocks the others):
|
|
304
|
-
|
|
305
|
-
| Bucket | Detection (iOS Swift sketch) | Cross-platform variant |
|
|
306
|
-
|---|---|---|
|
|
307
|
-
| services | `class .*Service\b`, `protocol .*Service\b`, generated `InfoEndpoint<...>` | `class *Service` / `interface *Service` / `def *_service` |
|
|
308
|
-
| dtos | `struct .*(Request|Response|DTO)\b` | `data class *Dto` / `interface *DTO` / Pydantic `BaseModel` |
|
|
309
|
-
| useCases | `protocol .*UseCase\b`, `class .*UseCase\b` | `class *UseCase` / `def *_use_case` |
|
|
310
|
-
| validationRules | `*Rule.swift`, `*Validator.swift`, Validation/ dir | `*Validator.kt` / `*.ts` zod schemas / pydantic validators |
|
|
311
|
-
| domainEntities | `Domain/Entities/*.swift` | `domain/entities/*.kt` / `entities/*.py` |
|
|
312
|
-
| routes | Public `enum *Route` matching `DomainRoute` | `*Route` sealed / NavRoute / `routes.*` modules |
|
|
313
|
-
| coordinators | `*Coordinator.swift` + `CoordinatorProtocol`/`DomainRouter` | Navigator / NavController helpers |
|
|
314
|
-
| diConfigurators | `*DependencyConfigurator.swift`, `Module.kt` (Hilt) | DI container registrations |
|
|
315
|
-
| uiComponents | `Common/UIComponents/.../Components/**/*.swift` triplet (Configuration + View + +Modifiers) | Compose @Composable functions / React components |
|
|
316
|
-
| tokens | `*Token` enums under `UIAssetTokens/Generated/` | `Theme.kt` / `tokens.ts` / `tailwind.config.*` |
|
|
317
|
-
| localizationKeys | `LocalizationStringKeys.swift` public enum + cases | `strings.xml` keys / `i18n/*.json` keys |
|
|
318
|
-
| testingIdentifiers | `ui-testing-identifiers.json` | `testTag` strings / `data-testid` constants |
|
|
319
|
-
| analyticsEvents | Generated `AnalyticsEvents/*.swift` + `Analytics.logEvent\(` call sites | Equivalent Android / Frontend / Backend telemetry |
|
|
320
|
-
|
|
321
|
-
**Tagging rule** for each row:
|
|
322
|
-
|
|
323
|
-
| Tag | Match condition |
|
|
324
|
-
|---|---|
|
|
325
|
-
| `direct-match` | The item name contains a feature-name slug fragment |
|
|
326
|
-
| `same-domain` | Item lives under `Domains/<feature>/` or `feature/<feature>/` |
|
|
327
|
-
| `cross-cutting` | Item lives under `Common/` / `core/` / shared roots (not under any single feature) |
|
|
328
|
-
|
|
329
|
-
**Output JSON shape** (per repo):
|
|
330
|
-
|
|
331
|
-
```json
|
|
332
|
-
{
|
|
333
|
-
"buckets": {
|
|
334
|
-
"services": [
|
|
335
|
-
{"name": "UserProfileService", "file": "Domains/UserProfile/Services/UserProfileService.swift", "line": 12, "tag": "direct-match"},
|
|
336
|
-
{"name": "LoggingService", "file": "Common/Logging/LoggingService.swift", "line": 8, "tag": "cross-cutting"}
|
|
337
|
-
]
|
|
338
|
-
},
|
|
339
|
-
"fetchWarnings": []
|
|
340
|
-
}
|
|
341
|
-
```
|
|
342
|
-
|
|
343
|
-
### Phase 1b.1 - Code Connect index (after Phase 1b)
|
|
344
|
-
|
|
345
|
-
figma-to-swiftui (and the Android equivalent) already produced the feature's components and bound them to Figma via Code Connect. The analysis treats those bindings as the ground truth for "what already exists" - it does not re-derive components from the design. Build an index from the `*.figma.swift` / `*.figma.kt` files found in Phase 1:
|
|
346
|
-
|
|
347
|
-
```bash
|
|
348
|
-
# Code Connect figma(...) calls carry the Figma URL (fileKey + node-id)
|
|
349
|
-
grep -rEn 'figma\("https://www\.figma\.com/[^"]+"' "$REPO_PATH" \
|
|
350
|
-
--include='*.figma.swift' --include='*.figma.kt'
|
|
351
|
-
```
|
|
352
|
-
|
|
353
|
-
For each binding, parse `{ fileKey, nodeId, component, path }` where `component` is the registered component type and `path` is the binding file. Decode the URL `node-id` form (`-` to `:`). Output: `state.analysisSpec.evidence.codeConnect[]`.
|
|
354
|
-
|
|
355
|
-
Phase 2 fills the design->code link deterministically from this index:
|
|
356
|
-
- Section 5.1 `Code Connect` column: the matched component name for that frame's `nodeId` (blank when the frame has no existing binding).
|
|
357
|
-
- Section 6 `Mevcut / Existing`: `yes` + `reuse <component> at <path>` when the design `nodeId` (or its `fileKey`) matches an index entry; `no` + `new component` (added to Section 14) when it does not.
|
|
358
|
-
|
|
359
|
-
When no Code Connect file exists in any selected repo, the index is empty and Section 6 falls back to the Phase 1b `uiComponents` heuristic (the prior behavior).
|
|
360
|
-
|
|
361
|
-
### Phase 1c - Convention extraction (parallel, per repo)
|
|
362
|
-
|
|
363
|
-
Per Locked decision 23. After Phase 1b finishes, run `~/.claude/lib/extract-conventions.sh <repo-path> <platform>` for each selected repo. The script returns a JSON document with seven pattern groups:
|
|
364
|
-
|
|
365
|
-
| Group | Keys |
|
|
366
|
-
|---|---|
|
|
367
|
-
| C1 folder structure | `folderStructure` |
|
|
368
|
-
| C2 class naming | `stateHolderNaming`, `viewNaming`, `navigatorNaming`, `useCaseNaming`, `repositoryNaming`, `dtoNaming` |
|
|
369
|
-
| C3 UI state model | `uiStateModel` |
|
|
370
|
-
| C4 test method naming | `testMethodNaming` |
|
|
371
|
-
| C5 accessibility identifier | `accessibilityIdentifier` |
|
|
372
|
-
| C6 localization key | `localizationKey` |
|
|
373
|
-
| C7 DI registration | `diRegistration` |
|
|
374
|
-
|
|
375
|
-
Each field has shape `{ pattern, example, confidence, evidenceFiles, alternativeCandidates }` where `confidence` is one of `high` (5+ examples, dominant), `medium` (3-4 examples, majority), `low` (2 examples or mixed), `none` (no evidence).
|
|
376
|
-
|
|
377
|
-
**Output**: `state.analysisSpec.evidence.conventions[<repo>]`.
|
|
378
|
-
|
|
379
|
-
**Risk auto-population (Locked 23)**: when any field returns `confidence: "low"` or `"none"`, push a row onto `state.analysisSpec.evidence.conventionRisks[]`:
|
|
380
|
-
|
|
381
|
-
```json
|
|
382
|
-
{
|
|
383
|
-
"repo": "<repo>",
|
|
384
|
-
"field": "<pattern key>",
|
|
385
|
-
"confidence": "<low | none>",
|
|
386
|
-
"fallback": "conventions-defaults.md:C<n>-<platform>",
|
|
387
|
-
"question": "<convention-key> evidence is insufficient. Apply default <pattern> or override?"
|
|
388
|
-
}
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
Phase 2 Section 20 Risks reads this list and emits one open question per entry.
|
|
392
|
-
|
|
393
|
-
**Fallback source**: when `confidence == "none"` AND `evidence.standards[]` does not contain an explicit rule for that field, the renderer reads `$HOME/.claude/multi-agent-refs/conventions-defaults.md` and applies the platform default.
|
|
394
|
-
|
|
395
|
-
**Caching (Locked 27)**: compute `evidence_digest = sha256(featureName || sorted(platforms) || hash(evidence.repoEvidence) || hash(evidence.conventions))`. Cache key on disk: `/tmp/multi-agent-analysis-cache/<digest>.json` with mtime <= 24h. Cache hit skips Phase 1b and Phase 1c. `--no-cache` flag forces re-run.
|
|
396
|
-
|
|
397
|
-
**Lite mode auto-detection (Locked 25, v9.1.0 scoring)**: at the end of Phase 1c, evaluate three signals and score each:
|
|
41
|
+
Full picker chain: `$HOME/.claude/multi-agent-refs/analysis/intake.md`. Sequential `AskUserQuestion` steps filling `state.analysisSpec.*`: analysis name, account, platform multi-select, repos per platform, the six-question source batch (Figma / Swagger / Confluence / Jira / Standards / Firebase) and the two coverage opt-ins. Step narration is required - the chain length is known up front, so every step prints its breadcrumb.
|
|
398
42
|
|
|
399
|
-
|
|
400
|
-
|---|---|---|
|
|
401
|
-
| Confluence spec body lines | < 100 | 1 |
|
|
402
|
-
| Figma frames count | <= 1 | 1 |
|
|
403
|
-
| Repo evidence direct-match count | >= 8 | 1 |
|
|
43
|
+
### Phases 1, 1b, 1b.1, 1c - Evidence gathering
|
|
404
44
|
|
|
405
|
-
|
|
45
|
+
Full contract: `$HOME/.claude/multi-agent-refs/analysis/evidence.md`. Fetches every declared source in parallel (Figma / Swagger / Confluence / Jira / Standards / Firebase), collects the 13-bucket repo evidence, builds the Code Connect index, and extracts the seven convention groups. Output: `state.analysisSpec.evidence.*`. Nothing here writes a document.
|
|
406
46
|
|
|
407
|
-
### Phase 2 - Two-pass synthesis
|
|
47
|
+
### Phase 2, 2a, 2b - Two-pass synthesis
|
|
408
48
|
|
|
409
|
-
|
|
49
|
+
Full contract: `$HOME/.claude/multi-agent-refs/analysis/synthesis.md`. Pass A builds the platform-agnostic concept layer; Phase 2a previews the resolved conventions for approval (Locked 26); Pass B projects each concept onto the selected platform with a footnote per filled cell (Locked 24).
|
|
410
50
|
|
|
411
|
-
|
|
51
|
+
### Phases 3, 3.5, 4, 5 - Render, publish, report
|
|
412
52
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
```
|
|
416
|
-
synthesizedSections = {
|
|
417
|
-
scope: { ... shared block ... },
|
|
418
|
-
design: { shared: {frameGallery, codeConnect}, byPlatform: {ios, android, frontend} },
|
|
419
|
-
localization: { keys: [...], byPlatform: {ios: {source: "Localizable.strings", rows}, android: {source: "strings.xml", rows}, frontend: {source: "i18n/*.json", rows}} },
|
|
420
|
-
apiContracts: { ... shared verbatim ... },
|
|
421
|
-
deeplinkPush: { byPlatform: {ios, android, frontend, backend: null} },
|
|
422
|
-
business: { rules: [...], useCases: [...], firebaseEvents: [...], byPlatform: {ios: {testFramework: "Swift Testing", skeletons}, android: {testFramework: "JUnit5 + Turbine"}, frontend: {testFramework: "Vitest + RTL"}, backend: {testFramework: "pytest"}} },
|
|
423
|
-
devPlan: { byPlatform: {ios: {tasks, standards}, android: {...}, ...} }
|
|
424
|
-
}
|
|
425
|
-
```
|
|
426
|
-
|
|
427
|
-
| Section | Production logic |
|
|
428
|
-
|---------|------------------|
|
|
429
|
-
| 1. Scope | Always present. Derive in-scope / out-of-scope, audience from Jira summary + Confluence title + feature name. LLM inference allowed. Shared across all per-platform files verbatim. |
|
|
430
|
-
| 2. Design | If `evidence.figma[]` is empty AND no `evidence.repoEvidence[*].buckets.uiComponents` direct-match → `byPlatform[*]` = null. Otherwise produce frame gallery (shared) + per-platform component inventory (rows from `evidence.repoEvidence[<repo>].buckets.uiComponents`). |
|
|
431
|
-
| 3. Localization | If both Figma annotations/text layers and `evidence.repoEvidence[*].buckets.localizationKeys` are empty → `byPlatform[*]` = null. Otherwise produce the key table per the project `localization.ownership` mode (Locked 20): `in-repo` fills the configured locale set (default `ar, de, en, es, fr, it, ru, tr`, RTL for ar); `externally-owned` lists key + status + copy source + base value and defers per-locale values. Base copy is sourced from the Figma annotation when present (Locked 3). |
|
|
432
|
-
| 4. API Contracts | If `evidence.swagger[]` is empty AND no Confluence embedded API table AND no `evidence.repoEvidence[*].buckets.services` direct-match → null. Otherwise produce endpoint summary + per-endpoint tables (shared verbatim across files). |
|
|
433
|
-
| 5. Deeplink / Push | Per-platform: iOS uses Universal Links / `UNUserNotificationCenter`; Android uses `intent-filter` / FCM; Frontend uses web URL routing; Backend file omits this section entirely. |
|
|
434
|
-
| 6. Business + Tests | If sections 2 and 4 are both `null` AND `evidence.firebase[]` is empty → null. Otherwise produce use-case + mock stubs + per-platform test skeletons + shared Firebase events table. Reuse Red-Green-Refactor naming from `$HOME/.claude/rules/tdd.md`. |
|
|
435
|
-
| 7. Development Plan | Always present. Tasks for the current platform only. Architecture standards come from `evidence.standards[]` filtered by platform (see Pass B step 1). **Reuse-first rule (Locked 11)**: when an item has `direct-match` in `evidence.repoEvidence[<repo>].buckets.<X>`, emit `Reuse existing <FQN> (<file>:<line>)` instead of `Add new <FQN>`. New-write task with a `direct-match` competitor becomes a Risk row. |
|
|
436
|
-
|
|
437
|
-
#### Phase 2a - Pass B preview (Locked 26)
|
|
438
|
-
|
|
439
|
-
Before Pass B renders any file, present the resolved convention table to the user via `AskUserQuestion`. The table is one row per concept, one column per selected platform.
|
|
440
|
-
|
|
441
|
-
Example (iOS + Android selected):
|
|
442
|
-
|
|
443
|
-
```
|
|
444
|
-
Convention preview - Pass B will render with:
|
|
445
|
-
|
|
446
|
-
| Concept | iOS | Android |
|
|
447
|
-
|---|---|---|
|
|
448
|
-
| Module folder | Domains/Profile/.../Screens/ProfileEditor/ ^[C1 high] | feature/profile/.../userprofile/ ^[C1 high] |
|
|
449
|
-
| State holder | UserProfileViewModel ^[C2 high: 8 examples] | UserProfileViewModel ^[C2 high: 5 examples] |
|
|
450
|
-
| State model | sealed enum UserProfileUIState ^[C3 high] | sealed interface UserProfileUiState ^[C3 high] |
|
|
451
|
-
| Test naming | @Test func scenario_expected() ^[C4 medium: 4 examples] | fun scenario_expectedBehavior() ^[C4 high] |
|
|
452
|
-
| Identifier | userProfile.continueButton ^[C5 high] | userProfileContinueButton ^[C5 medium] |
|
|
453
|
-
| Localization key | UserProfile.ContinueButton ^[C6 high] | user_profile_continue_button ^[C6 high] |
|
|
454
|
-
| DI | UserProfileDependencyConfigurator ^[C7 high] | UserProfileModule (Hilt) ^[C7 fallback: defaults] |
|
|
455
|
-
|
|
456
|
-
Confidence summary:
|
|
457
|
-
iOS: 7/7 high, 0 medium, 0 low, 0 fallback
|
|
458
|
-
Android: 5/7 high, 1 medium, 0 low, 1 fallback
|
|
459
|
-
```
|
|
460
|
-
|
|
461
|
-
AskUserQuestion shape:
|
|
462
|
-
|
|
463
|
-
```
|
|
464
|
-
header: "Conventions"
|
|
465
|
-
question: <localized: "Pass B will render with the above conventions. Approve, override, or cancel?">
|
|
466
|
-
options:
|
|
467
|
-
- label: "Approve, render"
|
|
468
|
-
description: "Proceed to Phase 2b with these conventions"
|
|
469
|
-
- label: "Override individual cells"
|
|
470
|
-
description: "Open follow-up questions for cells you want to change"
|
|
471
|
-
- label: "Cancel"
|
|
472
|
-
```
|
|
473
|
-
|
|
474
|
-
On `Approve`: proceed to Phase 2b directly.
|
|
475
|
-
On `Override`: for each cell the user wants to change, surface one follow-up AskUserQuestion with the current value and an `Other` for the new value. Persist overrides into `state.analysisSpec.conventionOverrides[<repo>][<field>] = <new pattern>`. Pass B reads overrides before defaults.
|
|
476
|
-
On `Cancel`: halt and write `state.analysisSpec.phase = "cancelled_at_pass_b_preview"`. Drafts in `/tmp/` are kept for inspection.
|
|
477
|
-
|
|
478
|
-
Empty submit (`feedback_no-inferred-defaults-from-empty-answer`): re-ask the same question. Do not infer consent.
|
|
479
|
-
|
|
480
|
-
Skip condition: Phase 2a is skipped only when every `evidence.conventions[<repo>].*.confidence` is `high` AND `state.analysisSpec.conventionRisks[]` is empty AND the user did not pass `--preview-conventions` flag. Otherwise it always runs.
|
|
481
|
-
|
|
482
|
-
#### Phase 2b - Per-platform render (Pass B)
|
|
483
|
-
|
|
484
|
-
For each `platform` in `state.analysisSpec.platforms[]`:
|
|
485
|
-
|
|
486
|
-
1. **Resolve standards binding source** (one canonical source per platform):
|
|
487
|
-
- `ios` → `prefs.projects[<key>].standardsFile` if present → glob `~/<project>-iOS-Standards.md` → `~/.claude/rules/swiftui-qa.md`
|
|
488
|
-
- `android` → `~/.claude/rules/kotlin-android.md` first → `evidence.standards[]` entries whose path contains `android` or `kotlin`
|
|
489
|
-
- `backend` → `evidence.standards[]` entries matching language hints (`python`, `go`, `node`, `fastapi`) → fall back to `~/.claude/rules/security.md` + `code-style.md`
|
|
490
|
-
- `frontend` → `evidence.standards[]` entries matching `react`, `vue`, `next`, `sveltekit` → `~/.claude/rules/code-style.md`
|
|
491
|
-
2. **Apply per-platform omission rules.** Backend-only file drops Sections 5, 6, 7, 8, 16. Frontend with no UI inventory still keeps 5 (UI exists in code). Sections 1, 2, 4, 9, 13, 14, 20, 21 always present per Locked decision 2 + 13.
|
|
492
|
-
3. **Resolve mode.** If user passed `--lite` → Lite. If user passed `--full` → Full. Otherwise use `state.analysisSpec.liteModeAuto`. Lite mode renders only Sections 1, 2, 4, 9, 13, 14, 21 plus optional 23.
|
|
493
|
-
4. **Produce YAML front-matter header** (see `$HOME/.claude/multi-agent-refs/analysis-template.md`). Include `mode: full | lite`, plus `ui_tests: <state.analysisSpec.options.uiTests | false>` and `a11y_depth: <state.analysisSpec.options.a11yDepth | basic>` so the pre-dispatch validator can enforce the opt-in coverage (15.6 present when ui_tests, 16.2 walkthrough present when a11y_depth is full).
|
|
494
|
-
5. **Read conventions for this platform's repo.** For each cell Pass B fills in Section 13 and in any per-platform projection (Sections 5, 6, 7, 8, 10, 11, 13, 14, 15, 16, 17), read `state.analysisSpec.evidence.conventions[<repo>].<field>` and emit the value with a footnote (Locked 24). If `conventionOverrides` has an entry for that field, use the override and footnote with `^[user-override: <reason>]` instead of evidence path.
|
|
495
|
-
6. **Concatenate non-null sections in canonical order.** Numbering stays sequential `1..N` over the rendered set (omitted sections do not create gaps).
|
|
496
|
-
7. **Schema validation** on the per-platform spec object:
|
|
497
|
-
```bash
|
|
498
|
-
python3 -c "import json,jsonschema; jsonschema.validate(json.load(open('state/<feature>-<platform>.json')), json.load(open('$HOME/.claude/schemas/analysis-spec.schema.json')))"
|
|
499
|
-
```
|
|
500
|
-
On failure for any platform, surface the error and stop before Phase 3 (do not draft partial outputs).
|
|
501
|
-
|
|
502
|
-
### Phase 3 - Humanize & buffer drafts (no side effects)
|
|
503
|
-
|
|
504
|
-
1. **Language resolution**: read `prefs.global.outputLanguage` (`tr` or `en`, default `tr`). Use the `Output language matrix` table in `$HOME/.claude/multi-agent-refs/analysis-template.md` to swap headings and system strings.
|
|
505
|
-
|
|
506
|
-
2. **Per-platform markdown render**: for each platform in `state.analysisSpec.platforms[]`, concatenate the per-platform spec into one markdown file. Tables in pipe-syntax. Numbering uses plain `## 1.`, `## 2.`, ... - omitted sections do **not** create gaps. Visible numbering is sequential 1..N over the rendered set.
|
|
507
|
-
|
|
508
|
-
3. **Humanizer pass (MANDATORY: actually invoke the `ai-common-toolkit:humanizer` skill on the rendered markdown - the punctuation grep alone does NOT satisfy this step)** (`technical-explanatory` tone for the scratch buffer; per-channel re-humanize happens in Phase 4 when actually emitting):
|
|
509
|
-
```
|
|
510
|
-
ai-common-toolkit:humanizer skill input:
|
|
511
|
-
language: <tr|en>
|
|
512
|
-
tone: technical-explanatory
|
|
513
|
-
stripFancyPunctuation: true
|
|
514
|
-
content: <markdown>
|
|
515
|
-
```
|
|
516
|
-
|
|
517
|
-
**Explicit punctuation policy** (enforced by `stripFancyPunctuation: true`): no em-dash (U+2014), no en-dash (U+2013), no horizontal ellipsis (U+2026), no curly quotes (U+2018, U+2019, U+201C, U+201D), no section sign (U+00A7). The humanizer replaces these with ASCII equivalents (`-`, `:`, `,`, `...`, `'`, `"`, and `bölüm` / `section` for the section sign per `outputLanguage`) before emit. Tables, code blocks, URLs, and front-matter YAML are exempt. Post-emit verification: `grep -P '[\x{2013}\x{2014}\x{2026}\x{201C}\x{201D}\x{2018}\x{2019}\x{00A7}]' /tmp/analysis-<feature-slug>-<ts>/*.md` returns zero matches. **Diacritics are PRESERVED, not stripped: this policy targets ONLY the listed fancy-punctuation codepoints. Turkish letters (ş/Ş, ç/Ç, ğ/Ğ, ı/I, İ, ö/Ö, ü/Ü) and all other `outputLanguage` letters MUST stay verbatim. Never ASCII-fold the prose - emit `Geliştirme Özeti`, `için`, `Kullanıcı Hikayeleri`, NOT `Gelistirme Ozeti`, `icin`, `Kullanici`. ASCII-folded Turkish is a humanizer-skipped smell and fails review.**
|
|
518
|
-
|
|
519
|
-
4. **Write scratch drafts**: create `/tmp/analysis-<feature-slug>-<UTC-iso8601>/` and write `<feature>-<platform>.md` for each selected platform. Update `state.analysisSpec.outputs.draftDir` with the path.
|
|
520
|
-
|
|
521
|
-
5. **Surface the draft tree to the user**:
|
|
522
|
-
```
|
|
523
|
-
Drafts ready (3 files, 6.4 KB):
|
|
524
|
-
/tmp/analysis-UserProfile-20260514T1015/UserProfile-ios.md
|
|
525
|
-
/tmp/analysis-UserProfile-20260514T1015/UserProfile-android.md
|
|
526
|
-
/tmp/analysis-UserProfile-20260514T1015/UserProfile-backend.md
|
|
527
|
-
```
|
|
528
|
-
User can inspect drafts before choosing output destinations in Phase 3.5.
|
|
529
|
-
|
|
530
|
-
### Phase 3.5 - Output destination picker
|
|
531
|
-
|
|
532
|
-
AskUserQuestion (multiSelect=true), at least one selection required. `Local file` pre-selected per Locked decision 5.
|
|
533
|
-
|
|
534
|
-
```
|
|
535
|
-
header: "Output"
|
|
536
|
-
question: <localized: "Where should the per-platform analyses be written?">
|
|
537
|
-
options:
|
|
538
|
-
- label: "Local file"
|
|
539
|
-
description: "analysis/<feature>-<platform>.md in each selected repo's working tree"
|
|
540
|
-
- label: "Confluence page"
|
|
541
|
-
- label: "Jira description"
|
|
542
|
-
```
|
|
543
|
-
|
|
544
|
-
Conditional follow-ups:
|
|
545
|
-
- If `Confluence` selected: ask `header="Parent page"`, free-text via Other for the parent page key or URL. One Confluence page per platform is created under this parent, each titled `<Feature> - <Platform>`.
|
|
546
|
-
- If `Jira` selected: if Step 5 Q4 produced Jira IDs, AskUserQuestion (single-select) to pick which one; otherwise ask via Other. Per Locked decision 9 + design choice "single description with platform separators", the chosen issue receives one combined description body holding all per-platform sections under `h2. Platform: <X>` separators (wiki markup - the description field does not render Markdown; conversion happens at dispatch, see Phase 4).
|
|
547
|
-
|
|
548
|
-
Result: `state.analysisSpec.outputs.requested[]`.
|
|
549
|
-
|
|
550
|
-
### Phase 4 - Dispatch & report
|
|
551
|
-
|
|
552
|
-
**Pre-dispatch gate (BLOCKING).** Before writing to any destination, run the deterministic doc validator on every per-platform draft:
|
|
553
|
-
|
|
554
|
-
```bash
|
|
555
|
-
for f in /tmp/analysis-<feature-slug>-<ts>/*.md; do
|
|
556
|
-
node "$HOME/.claude/scripts/validate-analysis-doc.mjs" "$f" || GATE_FAILED=1
|
|
557
|
-
done
|
|
558
|
-
```
|
|
559
|
-
|
|
560
|
-
`validate-analysis-doc.mjs` enforces the mechanically-checkable Locked decisions on the emitted markdown itself (front-matter completeness, never-omitted sections per Locked 2, humanizer punctuation per Locked 7, and Full-mode business-rule traceability per Locked 31). Any ERROR blocks dispatch: fix the draft and re-validate. Warnings are advisory (run with `--strict` to treat them as blocking). This turns the "fails the dispatch gate" prose into a real, model-independent check.
|
|
561
|
-
|
|
562
|
-
Iterate `state.analysisSpec.outputs.requested`. For each target:
|
|
563
|
-
|
|
564
|
-
| Target | Action |
|
|
565
|
-
|--------|--------|
|
|
566
|
-
| Local | For each per-platform draft, `cp /tmp/analysis-<feature-slug>-<ts>/<feature>-<platform>.md` into `analysis/<feature>-<platform>.md` in the matching repo's working tree. When multiple repos exist for the same platform, the file is duplicated into each and the dispatch report lists every destination. **No commit.** |
|
|
567
|
-
| Confluence | Re-humanize each per-platform draft with `formal-stakeholder` tone. One Confluence page per platform under the chosen parent, titled `<Feature> - <Platform>`. Cross-link siblings inside each page via `<ac:link><ri:page ri:content-title="<Feature> - <OtherPlatform>"/></ac:link>`. Markdown -> storage XML via `$HOME/.claude/multi-agent-refs/channels/confluence.md`. Re-emit on existing pages uses PUT with version bump. |
|
|
568
|
-
| Jira | Re-humanize the combined body with `informal-technical` tone. Concatenate per-platform drafts under `h2. Platform: iOS`, `h2. Platform: Android`, `h2. Platform: Backend`, `h2. Platform: Frontend` separators (in the order platforms were selected), then run the whole body through the markdown → Jira wiki conversion table in `$HOME/.claude/multi-agent-refs/channels/jira.md` - the `description` field renders wiki markup, so raw `##`/`**`/backticks arrive as literal text. Write with `PUT /rest/api/2/issue/{key}` body `{"fields": {"description": <converted body>}}` (`channels/jira.md` documents only the comment POST; the description update is this PUT). Same rawfile + `--data-binary` transport rules. |
|
|
569
|
-
|
|
570
|
-
**Output capture**: fill `state.analysisSpec.outputs.localPaths[]` (one entry per per-platform-per-repo write), `outputs.confluencePageUrls[]` (one entry per platform), `outputs.jiraIssueKey` (single string).
|
|
571
|
-
|
|
572
|
-
### Phase 5 - Report & stop
|
|
573
|
-
|
|
574
|
-
After dispatch, print a summary to the user (in `outputLanguage`). Example shape:
|
|
575
|
-
|
|
576
|
-
```
|
|
577
|
-
Feature: <featureName>
|
|
578
|
-
Language: <tr|en>
|
|
579
|
-
Platforms: iOS, Android, Backend
|
|
580
|
-
Repos: my-ios-app (write), my-android-app (write), my-backend-api (write)
|
|
581
|
-
|
|
582
|
-
Sources used:
|
|
583
|
-
Figma: 2 frames
|
|
584
|
-
Swagger: 1 file
|
|
585
|
-
Confluence: 1 page (1 fetch error: auth_required)
|
|
586
|
-
Jira: 1 issue
|
|
587
|
-
Firebase: 3 events from schema, 1 from auto-detect
|
|
588
|
-
Standards: 2 local files + 1 wiki page
|
|
589
|
-
- /Users/.../<project>-Standards.md
|
|
590
|
-
- /tmp/<repo>-wiki/Navigation.md
|
|
591
|
-
- ~/.claude/rules/<framework>-qa.md (auto-detected)
|
|
592
|
-
|
|
593
|
-
Repo evidence (reuse vs new):
|
|
594
|
-
iOS my-ios-app: 4 direct-match, 6 same-domain, 11 cross-cutting
|
|
595
|
-
Android my-android-app: 2 direct-match, 8 same-domain, 14 cross-cutting
|
|
596
|
-
Backend my-backend-api: 1 direct-match, 3 same-domain, 7 cross-cutting
|
|
597
|
-
|
|
598
|
-
Sections (per platform):
|
|
599
|
-
iOS: [1 Scope, 2 Design, 3 Localization, 4 API, 5 Deeplink/Push, 6 Business+Tests, 7 Dev Plan]
|
|
600
|
-
Android: [1 Scope, 2 Design, 3 Localization, 4 API, 5 Deeplink/Push, 6 Business+Tests, 7 Dev Plan]
|
|
601
|
-
Backend: [1 Scope, 4 API, 6 Business+Tests, 7 Dev Plan] (Sections 2/3/5 omitted - no UI)
|
|
602
|
-
|
|
603
|
-
Outputs:
|
|
604
|
-
- analysis/UserProfile-ios.md (my-ios-app)
|
|
605
|
-
- analysis/UserProfile-android.md (my-android-app)
|
|
606
|
-
- analysis/UserProfile-backend.md (my-backend-api)
|
|
607
|
-
- Confluence (3 pages):
|
|
608
|
-
https://{CONFLUENCE_HOST}/pages/viewpage.action?pageId=... (iOS)
|
|
609
|
-
https://{CONFLUENCE_HOST}/pages/viewpage.action?pageId=... (Android)
|
|
610
|
-
https://{CONFLUENCE_HOST}/pages/viewpage.action?pageId=... (Backend)
|
|
611
|
-
- Jira: {JIRA_KEY}-12345 (description updated with 3 platform sections)
|
|
612
|
-
```
|
|
613
|
-
|
|
614
|
-
**Stop. Do not chain into `/multi-agent:dev`. Do not open a worktree. Do not create a branch.**
|
|
615
|
-
|
|
616
|
-
**Open-question follow-up**: when any rendered file's Section 20 (Risks and Open Questions) has rows with status `Acik / Open`, append one line to the report: `<localized: "Section 20 has <N> open rows. Run /multi-agent:analysis-resolve to resolve them interactively before dispatching to dev.">`. This is a suggestion line only - never auto-invoke the resolver.
|
|
53
|
+
Full contract: `$HOME/.claude/multi-agent-refs/analysis/render.md`. Renders one markdown file per platform, runs the **required** `ai-common-toolkit:humanizer` pass, gates on `validate-analysis-doc.mjs`, asks for the output destination, dispatches to Local / Confluence / Jira, then reports and stops. The humanizer pass and the validator are required in every mode; a document that skipped either is not shippable.
|
|
617
54
|
|
|
618
55
|
### Resume contract
|
|
619
56
|
|
|
@@ -674,19 +111,6 @@ When `phase == "cancelled_at_pass_b_preview"`:
|
|
|
674
111
|
| `~/<project>-Standards.md` | Canonical home-dir standards reference (auto-detected at Q5 option 2; exact filename from `prefs.projects[<project>].standardsFile`) |
|
|
675
112
|
| `~/.claude/rules/*.md` | Fallback rules when `evidence.standards[]` is empty |
|
|
676
113
|
|
|
677
|
-
## Confluence write (on-request only)
|
|
678
|
-
|
|
679
|
-
Per the `analysis-output-confluence-on-request` memory, Confluence post is NEVER default-selected at Phase 3.5 (the output destination picker). Only when the user explicitly asks ("post this to Confluence", "create a page under the Coding Documentation parent", etc.) does the command:
|
|
680
|
-
|
|
681
|
-
1. Resolve the token via `~/.claude/lib/credential-store.sh get <key>`, where `<key>` is read from `prefs.global.keychainMapping.confluence` (per-user mapping; never hardcode the service name in this doc - see channel adapter doc `$HOME/.claude/multi-agent-refs/channels/confluence.md` for the lookup contract).
|
|
682
|
-
2. Use parent page URL from user input. No default parent is hardcoded here; the user picks one at the prompt (LRU recents come from `prefs.projects[<project>].confluenceUrls`).
|
|
683
|
-
3. Convert markdown to storage XML using the table in `$HOME/.claude/multi-agent-refs/channels/confluence.md`.
|
|
684
|
-
4. Upload Figma frame screenshots as page attachments via `POST /rest/api/content/{pageId}/child/attachment` (cache the MCP asset locally first because the upstream URLs expire after 7 days).
|
|
685
|
-
5. Reference attachments inside the page body via `<ac:image><ri:attachment ri:filename="frame-<nodeId>.png"/></ac:image>`.
|
|
686
|
-
6. POST `/rest/api/content` to create the page (or PUT with version bump when updating). Surface the resulting page URL in the Phase 4 report.
|
|
687
|
-
|
|
688
|
-
Token miss handling: surface a single line `WARN: Confluence token not configured (prefs.global.keychainMapping.confluence). Run /multi-agent:setup or skip Confluence output.` and continue with local-only output.
|
|
689
|
-
|
|
690
114
|
## Notes
|
|
691
115
|
|
|
692
116
|
- Default `prefs.global.outputLanguage` is `tr` for this user.
|
|
@@ -702,3 +126,68 @@ Token miss handling: surface a single line `WARN: Confluence token not configure
|
|
|
702
126
|
- **Workspace coding documentation default**: when Q5 option 2 (Auto-detect) is selected, the probe also reads `prefs.projects[<project>].confluenceStandardsParent` (if set) and looks for child pages whose title starts with `Coding`, `Standards`, `Architecture`, or `Navigation`. If that fetch fails with auth, log a hint that the user should host an offline mirror at `prefs.projects[<project>].standardsFile` (canonical local fallback).
|
|
703
127
|
- **Mixed paste handling**: Q5 / Q6 Other inputs accept comma-separated mixed entries. Whitespace is trimmed; entries are de-duplicated by canonicalised string (lowercase scheme + host + path for URLs; `realpath` for local files; lowercase exact match for event names).
|
|
704
128
|
- **Repo-evidence reuse policy**: Phase 1b's catalogue is consulted by Pass B Section 7 rendering. The `direct-match` tag is the strongest signal; a `same-domain` row becomes an advisory note ("consider adapting existing X in the same feature directory"); `cross-cutting` items become a sentence in the section preamble ("reuse the cross-feature X from Common/"). See Locked decision 11.
|
|
129
|
+
|
|
130
|
+
## Required: Phase Tracker Contract
|
|
131
|
+
|
|
132
|
+
**The phase tracker is mandatory** - the agent cannot skip it. Full spec: [`$HOME/.claude/multi-agent-refs/tracker-contract.md`]($HOME/.claude/multi-agent-refs/tracker-contract.md).
|
|
133
|
+
|
|
134
|
+
Two channels run in parallel at every phase boundary:
|
|
135
|
+
|
|
136
|
+
1. **State channel** (every CLI, identical): `phase-tracker.sh` writes to `tracker-state.json`. Drives `:resume`, `:log`, `:status`.
|
|
137
|
+
2. **Visual channel** (CLI-specific): native widget on Claude Code, ANSI render on every other CLI. Without it the user sees no phase progress.
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
# Phase 0, very first shell call (every CLI):
|
|
141
|
+
bash $HOME/.claude/scripts/phase-tracker.sh init "$TASK_ID"
|
|
142
|
+
for p in "0:Init" "1:Analysis" "2:Planning" "4:Review" "6:Commit" "7:Report"; do
|
|
143
|
+
bash $HOME/.claude/scripts/phase-tracker.sh add "${p%%:*}" "${p#*:}"
|
|
144
|
+
done
|
|
145
|
+
bash $HOME/.claude/scripts/phase-tracker.sh update 0 in_progress
|
|
146
|
+
|
|
147
|
+
# Every phase boundary (every CLI):
|
|
148
|
+
bash $HOME/.claude/scripts/phase-tracker.sh update <N> in_progress|completed|failed|skipped
|
|
149
|
+
|
|
150
|
+
# After every LLM call (every CLI):
|
|
151
|
+
bash $HOME/.claude/scripts/phase-tracker.sh tokens <N> <in> <out> [cached]
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Visual channel - Claude Code (native TaskList widget, required)
|
|
155
|
+
|
|
156
|
+
In Claude Code the agent MUST also drive the native TaskList widget so the user sees a sticky phase tile stack - this is the only progress signal Claude Code surfaces. Skipping these calls is the #1 source of "I don't see any phases" complaints.
|
|
157
|
+
|
|
158
|
+
**TaskCreate ordering (strict)**: All TaskCreate calls fire in strict phase-number order BEFORE any TaskUpdate is applied. The native widget renders by creation order, not by phase number - out-of-order calls produce visually scrambled tile stacks (e.g. `1 ✓ · 2 ✓ · 4 ✓ · 0 ▶ · 3 ☐`) even when the underlying state is correct. Pre-marking phases as completed/skipped before Phase 0 starts is FORBIDDEN - register the tile in order, then flip status via TaskUpdate when the phase actually short-circuits. Full contract in `$HOME/.claude/multi-agent-refs/tracker-contract.md` section "TaskCreate ordering (strict)".
|
|
159
|
+
|
|
160
|
+
```text
|
|
161
|
+
# Phase 0 startup - register one tile per phase (0..N), capture the taskId, persist it:
|
|
162
|
+
for each phase in 0:Init, 1:Analysis, 2:Planning, 4:Review, 6:Commit, 7:Report:
|
|
163
|
+
TaskCreate({ subject: "Phase <N>: <Name>", activeForm: "<doing-form>" })
|
|
164
|
+
-> returns taskId
|
|
165
|
+
bash $HOME/.claude/scripts/phase-tracker.sh meta <N> tasklist_id "<taskId>"
|
|
166
|
+
|
|
167
|
+
# Phase entry - flip the tile to in_progress alongside the state update:
|
|
168
|
+
TaskUpdate({ taskId: <saved>, status: "in_progress" })
|
|
169
|
+
bash $HOME/.claude/scripts/phase-tracker.sh update <N> in_progress
|
|
170
|
+
|
|
171
|
+
# Active sub-step inside a phase - update activeForm so the spinner header reflects what's happening now:
|
|
172
|
+
TaskUpdate({ taskId: <saved>, activeForm: "Editing TopBarView.swift" })
|
|
173
|
+
|
|
174
|
+
# Phase exit - flip to completed/failed/skipped on both channels:
|
|
175
|
+
TaskUpdate({ taskId: <saved>, status: "completed" })
|
|
176
|
+
bash $HOME/.claude/scripts/phase-tracker.sh update <N> completed
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
`analysis` mode does NOT TaskCreate phases 3/5 - those are not part of the `analysis` phase set (`0:Init 1:Analysis 2:Planning 4:Review 6:Commit 7:Report`). Only register tiles for the active set.
|
|
180
|
+
|
|
181
|
+
#### TaskCreate ordering (strict)
|
|
182
|
+
|
|
183
|
+
**All TaskCreate calls fire in strict phase-number order BEFORE any TaskUpdate is applied.** For `analysis` that means: Phase 0 → Phase 1 → Phase 2 → Phase 4 → Phase 6 → Phase 7. The native widget renders by creation order, not by phase number - out-of-order calls produce visually scrambled tile stacks. Full ordering contract in `$HOME/.claude/multi-agent-refs/tracker-contract.md` section "TaskCreate ordering (strict)".
|
|
184
|
+
|
|
185
|
+
### Visual channel - Copilot CLI / plain shell
|
|
186
|
+
|
|
187
|
+
These CLIs have no TaskList widget. After every state change the agent calls render, which prints a bordered ANSI card as the last tool result so the user sees an updated phase table:
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
bash $HOME/.claude/scripts/phase-tracker.sh render
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Do NOT call TaskCreate on these CLIs - the tool does not exist and the call fails.
|