@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.
Files changed (90) hide show
  1. package/CHANGELOG.md +124 -0
  2. package/README.md +2 -2
  3. package/README.tr.md +1 -2
  4. package/docs/architecture.md +2 -2
  5. package/docs/ecosystem.md +9 -6
  6. package/docs/features.md +2 -3
  7. package/install/_plugin-skills.mjs +28 -2
  8. package/install/templates/copilot-instructions.md +8 -7
  9. package/package.json +1 -1
  10. package/pipeline/commands/multi-agent/SKILL.md +5 -6
  11. package/pipeline/commands/multi-agent/analysis/SKILL.md +77 -588
  12. package/pipeline/commands/multi-agent/analysis-resolve/SKILL.md +5 -69
  13. package/pipeline/commands/multi-agent/channels/SKILL.md +1 -1
  14. package/pipeline/commands/multi-agent/complaint-analysis/SKILL.md +5 -4
  15. package/pipeline/commands/multi-agent/dev/SKILL.md +8 -280
  16. package/pipeline/commands/multi-agent/dev-autopilot/SKILL.md +12 -124
  17. package/pipeline/commands/multi-agent/dev-local/SKILL.md +8 -111
  18. package/pipeline/commands/multi-agent/dev-local-autopilot/SKILL.md +11 -113
  19. package/pipeline/commands/multi-agent/help/SKILL.md +61 -56
  20. package/pipeline/commands/multi-agent/ios-coding-standard/SKILL.md +4 -2
  21. package/pipeline/commands/multi-agent/local-autopilot/SKILL.md +2 -4
  22. package/pipeline/commands/multi-agent/refactor/SKILL.md +1 -1
  23. package/pipeline/commands/multi-agent/resume-local/SKILL.md +3 -3
  24. package/pipeline/commands/multi-agent/setup/SKILL.md +2 -2
  25. package/pipeline/commands/multi-agent/stack/SKILL.md +10 -9
  26. package/pipeline/commands/multi-agent/store-ready/SKILL.md +1 -1
  27. package/pipeline/commands/multi-agent/sync/SKILL.md +2 -2
  28. package/pipeline/commands/multi-agent/update/SKILL.md +1 -1
  29. package/pipeline/lib/context-link-extractor.sh +38 -0
  30. package/pipeline/lib/fetch-document.sh +190 -0
  31. package/pipeline/multi-agent-refs/_dev-context.md +4 -0
  32. package/pipeline/multi-agent-refs/analysis/evidence.md +213 -0
  33. package/pipeline/multi-agent-refs/analysis/intake.md +167 -0
  34. package/pipeline/multi-agent-refs/analysis/locked.md +53 -0
  35. package/pipeline/multi-agent-refs/analysis/render.md +133 -0
  36. package/pipeline/multi-agent-refs/analysis/resolve.md +76 -0
  37. package/pipeline/multi-agent-refs/analysis/synthesis.md +98 -0
  38. package/pipeline/multi-agent-refs/analysis-template.md +58 -11
  39. package/pipeline/multi-agent-refs/complaint-analysis-template.md +1 -1
  40. package/pipeline/multi-agent-refs/component-dispatch.md +5 -5
  41. package/pipeline/multi-agent-refs/cross-cli-contract.md +9 -7
  42. package/pipeline/multi-agent-refs/features/skill-conformance.md +1 -1
  43. package/pipeline/multi-agent-refs/features/url-enrichment.md +13 -3
  44. package/pipeline/multi-agent-refs/knowledge.md +2 -2
  45. package/pipeline/multi-agent-refs/payload-contracts.md +1 -1
  46. package/pipeline/multi-agent-refs/phases/modes.md +73 -53
  47. package/pipeline/multi-agent-refs/phases/phase-0-init.md +21 -2
  48. package/pipeline/multi-agent-refs/phases/phase-1-analysis.md +26 -0
  49. package/pipeline/multi-agent-refs/phases/phase-2-planning.md +26 -12
  50. package/pipeline/multi-agent-refs/phases/phase-3-dev.md +17 -18
  51. package/pipeline/multi-agent-refs/phases/phase-4-review.md +29 -7
  52. package/pipeline/multi-agent-refs/phases/phase-5-test.md +1 -1
  53. package/pipeline/multi-agent-refs/phases/phase-6-commit.md +8 -0
  54. package/pipeline/multi-agent-refs/phases/phase-7-report.md +1 -1
  55. package/pipeline/multi-agent-refs/phases.md +9 -7
  56. package/pipeline/multi-agent-refs/progress-contract.md +1 -1
  57. package/pipeline/multi-agent-refs/readiness-review.md +2 -0
  58. package/pipeline/multi-agent-refs/rules.md +2 -2
  59. package/pipeline/multi-agent-refs/tracker-contract.md +32 -13
  60. package/pipeline/multi-agent-refs/wiki-capture.md +2 -2
  61. package/pipeline/schemas/agent-state.schema.json +3 -3
  62. package/pipeline/schemas/analysis-output.schema.json +17 -0
  63. package/pipeline/schemas/analysis-spec.schema.json +69 -1
  64. package/pipeline/schemas/complaint-analysis-spec.schema.json +1 -1
  65. package/pipeline/schemas/prefs.schema.json +47 -0
  66. package/pipeline/schemas/token-budget.json +2 -2
  67. package/pipeline/scripts/_stack-routing.mjs +17 -12
  68. package/pipeline/scripts/build-stack-plugins.mjs +16 -6
  69. package/pipeline/scripts/cost-table.json +1 -1
  70. package/pipeline/scripts/gen-mode-dispatch.mjs +20 -30
  71. package/pipeline/scripts/run-aggregator.mjs +1 -1
  72. package/pipeline/scripts/validate-analysis-doc.mjs +36 -3
  73. package/pipeline/skills/.skills-index.json +40 -7
  74. package/pipeline/skills/shared/README.md +12 -9
  75. package/pipeline/skills/shared/core/multi-agent/SKILL.md +9 -5
  76. package/pipeline/skills/shared/core/multi-agent-dev/SKILL.md +7 -61
  77. package/pipeline/skills/shared/core/multi-agent-dev-autopilot/SKILL.md +11 -51
  78. package/pipeline/skills/shared/core/multi-agent-dev-local/SKILL.md +7 -33
  79. package/pipeline/skills/shared/core/multi-agent-dev-local-autopilot/SKILL.md +10 -38
  80. package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +28 -18
  81. package/pipeline/skills/shared/core/multi-agent-ios-coding-standard/SKILL.md +4 -2
  82. package/pipeline/skills/shared/core/multi-agent-local-autopilot/SKILL.md +2 -4
  83. package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +1 -1
  84. package/pipeline/skills/shared/core/multi-agent-resume-local/SKILL.md +2 -2
  85. package/pipeline/skills/shared/core/multi-agent-stack/SKILL.md +10 -9
  86. package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +2 -2
  87. package/pipeline/skills/shared/external/evidence-github/SKILL.md +45 -0
  88. package/pipeline/skills/shared/external/evidence-registry/SKILL.md +33 -0
  89. package/pipeline/skills/shared/external/signal-community/SKILL.md +44 -0
  90. package/pipeline/skills/skills-index.md +10 -7
@@ -0,0 +1,167 @@
1
+ # Intake (analysis Phase 0)
2
+
3
+ > The picker chain that fills `state.analysisSpec.*` before any fetch runs. Loaded by `/multi-agent:analysis`. Pipeline Phase 1 does NOT load this file: in a pipeline run the account, project, repos and task already came from the orchestrator's own Phase 0, and only the source and coverage batches below are asked (see `phase-1-analysis.md` Step 4).
4
+
5
+ ### Phase 0 - Intake
6
+
7
+ Sequential `AskUserQuestion` chain. Each answer is written to state under `state.analysisSpec.*`.
8
+
9
+ **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.
10
+
11
+ #### Step 0 - Language resolution (BLOCKING, runs before any picker)
12
+
13
+ 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.
14
+
15
+ #### Step 1 - Analysis name
16
+
17
+ If `$ARGUMENTS` is empty, ask via AskUserQuestion (single question, user types via Other).
18
+ Result: `state.analysisSpec.featureName` (state key kept for backward compatibility; user-facing label is "analysis name").
19
+
20
+ #### Step 2 - Account picker
21
+
22
+ Reuse `_account-picker.md`. Skipped if the resolved flow is local-only.
23
+
24
+ #### Step 3 - Platform (derived; asked only when it cannot be)
25
+
26
+ **Derive first.** Every repo selected in Step 2 already carries a stack tag from the orchestrator's project scan (`[iOS]`, `[Android]`, ...), so the platform set is the distinct tags of the selected repos. Print the breadcrumb with the resolution noted and move on - a question whose answer is already on screen is a question not worth asking.
27
+
28
+ Ask only when the derivation is ambiguous (a repo whose stack the scan could not tag) or when the user wants **fewer** platforms than the repos imply (one repo carrying both an app and its backend). The question below is that fallback.
29
+
30
+ #### Step 3 (fallback) - Platform multi-select
31
+
32
+ AskUserQuestion (multiSelect=true):
33
+ ```
34
+ header: "Platforms"
35
+ question: <localized: "Which platforms is this analysis for?">
36
+ options:
37
+ - label: "iOS"
38
+ - label: "Android"
39
+ - label: "Backend"
40
+ - label: "Frontend"
41
+ ```
42
+ Empty submit → re-ask. Result: `state.analysisSpec.platforms[]`.
43
+
44
+ **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.
45
+
46
+ #### Step 4 - Repos (from Phase 0, not re-asked)
47
+
48
+ Repos come from the orchestrator's Step 2 project selection plus `_dev-context.md`; both already handle multi-select, `canPush`, submodules and `frontendRepos[]`. Analysis does **not** ask its own repo question - that was a third place asking the same thing, and the platform-to-repo mapping falls straight out of the stack tags anyway.
49
+
50
+ Map `state.analysisSpec.repos[]` from the Phase 0 selection: one entry per repo with `platform` (its stack tag), `name`, `path`, `canPush`. If a selected platform has no repo, ask for that one platform only.
51
+
52
+ #### Step 4 (fallback) - Repo multi-select per platform
53
+
54
+ For each selected platform, run one AskUserQuestion round. Reuse `_dev-context.md` logic:
55
+ - Run `~/.claude/lib/submodule-detector.sh "$REPO_PATH"` to enumerate submodules + `canPush`
56
+ - Augment with `prefs.projects[<key>].editableRelatedRepos[]` for iOS / Android / Backend
57
+ - 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
58
+ - If no repos are detectable for a platform, present a single Other input asking for `<owner>/<repo>`
59
+
60
+ Result: `state.analysisSpec.repos[]` (each entry has `platform`, `name`, `path`, `canPush`).
61
+
62
+ #### Step 5 - Input URLs (single 6-question batch)
63
+
64
+ One AskUserQuestion call with **7 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[]`.
65
+
66
+ ```
67
+ Q1: header="Figma URL"
68
+ question: <localized: "Do you have a Figma URL for this feature?">
69
+ options:
70
+ - label: "No Figma input"
71
+ - label: "Use repo Code Connect only"
72
+ (Other: paste URL - comma-separated for multiple frames)
73
+
74
+ Q2: header="Swagger URL"
75
+ question: <localized: "Do you have a Swagger / OpenAPI URL?">
76
+ options:
77
+ - label: "No Swagger input"
78
+ - label: "Extract from Confluence instead"
79
+ (Other: paste URL)
80
+
81
+ Q3: header="Confluence"
82
+ question: <localized: "Do you have a Confluence page URL for the feature spec?">
83
+ options:
84
+ - label: "No Confluence input"
85
+ (Other: paste URL - comma-separated for multiple pages)
86
+
87
+ Q4: header="Jira"
88
+ question: <localized: "Do you have a related Jira ID?">
89
+ options:
90
+ - label: "No Jira input"
91
+ (Other: type Jira ID like {JIRA_KEY}-12345 - comma-separated for multiple)
92
+
93
+ Q4b: header="Document"
94
+ question: <localized: "Do you have a spec document? A .docx, .pdf, .md or .txt file, as a local path or a URL.">
95
+ options:
96
+ - label: "No document input"
97
+ (Other: absolute or tilde path, or a URL - comma-separated for multiple)
98
+
99
+ Q5: header="Standards"
100
+ question: <localized: "Do you have coding documentation or standards to bind the development plan? Confluence URL, GitHub wiki URL, or local file path.">
101
+ options:
102
+ - label: "No standards input"
103
+ - label: "Auto-detect from repo"
104
+ 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)"
105
+ (Other: comma-separated mix of Confluence URLs, GitHub wiki URLs, and absolute / tilde-expanded local file paths)
106
+
107
+ Q6: header="Firebase"
108
+ 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.">
109
+ options:
110
+ - label: "No Firebase input"
111
+ - label: "Auto-detect from repo"
112
+ description: "Greps Analytics.logEvent / firebaseAnalytics.logEvent / logEvent(analytics, ...) call sites in the selected repos and extracts event names"
113
+ (Other: comma-separated mix of event names like 'profile.view,profile.opened', a /path/to/events.json, or a console.firebase.google.com URL)
114
+ ```
115
+
116
+ 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).
117
+
118
+ **Q5 + Q6 type detection rules** (also documented in `~/.claude/lib/context-link-extractor.sh`):
119
+
120
+ | Input shape | Detected type | Phase 1 strategy |
121
+ |---|---|---|
122
+ | Starts with `/` or `~` and ends with `.md` / `.markdown` / `.txt` | `local-file` | `Read` tool on the absolute path (tilde-expanded) |
123
+ | 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) |
124
+ | 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[]` |
125
+ | 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 |
126
+ | Starts with `/` or `~`, ends with `.json`, path contains `events` or `analytics` | `firebase-events:schema` | `Read` + JSON parse `events[]` |
127
+ | Host `console.firebase.google.com` with `/analytics/` in path | `firebase-events:console` | Reference-only; INFO warning printed, no fetch |
128
+ | Any other `http(s)://` URL | `generic-doc` | `WebFetch` |
129
+
130
+ Q5 Auto-detect mode probe order (option 2):
131
+ 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)
132
+ 2. `<repo>/CLAUDE.md`, `<repo>/CONTRIBUTING.md`
133
+ 3. `<repo>/docs/architecture/*.md`
134
+ 4. If a `*.wiki.git` mirror is reachable for the primary repo, clone and ingest `Home.md` + any page named `Navigation*.md`
135
+
136
+ Q6 Auto-detect mode probe order (option 2):
137
+ 1. Per-repo grep for `Analytics\.logEvent\(`, `firebaseAnalytics\.logEvent\(`, `logEvent\(analytics,` and harvest the first string literal in each call as the event name
138
+ 2. Generated `AnalyticsEvents/*.swift` / `AnalyticsEvents/*.kt` if present (treat each public struct conforming to `AnalyticsEvent` as one event)
139
+ 3. Repo-level `firebase-events.json` / `analytics/events.json` files
140
+
141
+ #### Step 5a - Coverage options (opt-in, 2 questions)
142
+
143
+ 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.
144
+
145
+ ```
146
+ Q1: header="UI Tests"
147
+ question: <localized: "Should the analysis include UI test scenarios (XCUITest / Compose UI test)? Optional; unit + snapshot coverage is always included.">
148
+ options:
149
+ - label: "No UI tests" -> state.analysisSpec.options.uiTests = false (default)
150
+ - label: "Write UI test scenarios" -> state.analysisSpec.options.uiTests = true
151
+
152
+ Q2: header="A11y depth"
153
+ question: <localized: "How detailed should accessibility be? Basic checklist always ships; full adds a VoiceOver / TalkBack reading-order walkthrough.">
154
+ options:
155
+ - label: "Basic checklist" -> state.analysisSpec.options.a11yDepth = "basic" (default)
156
+ - label: "Full walkthrough" -> state.analysisSpec.options.a11yDepth = "full"
157
+ ```
158
+
159
+ `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.
160
+
161
+ #### Step 5b - Repo-evidence collector (automatic, no prompt)
162
+
163
+ 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.
164
+
165
+ #### Step 6 - REMOVED in v8.10.0
166
+
167
+ 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.
@@ -0,0 +1,53 @@
1
+ # Locked decisions (31)
2
+
3
+ > The 31 Locked decisions of the analysis flow. Loaded by `/multi-agent:analysis`, by `/multi-agent:analysis-resolve` (which inherits them) and by pipeline Phase 1 when it runs the analysis engine. Numbering is canonical: cite as `Locked <n> (<short label>)`.
4
+
5
+ ### Index by category (v9.1.0+)
6
+
7
+ Browse-friendly grouping of the 31 Locked decisions. Numbering stays canonical (matches the list below); the index is read-only navigation.
8
+
9
+ | Category | Decisions | Concern |
10
+ |---|---|---|
11
+ | **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 |
12
+ | **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) |
13
+ | **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 |
14
+ | **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) |
15
+ | **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 |
16
+
17
+ 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)`).
18
+
19
+ ### Full list
20
+
21
+ 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.
22
+ 2. **Section omission rule.** Sections with zero evidence are dropped entirely; no `TBD` placeholder section. Numbering remains sequential `1..N` over the rendered set.
23
+ 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.
24
+ 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?".
25
+ 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).
26
+ 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.
27
+ 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.
28
+ 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.
29
+ 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.
30
+ 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`.
31
+ 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").
32
+ 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]]`.
33
+ 13. **Gherkin user stories.** Section 4 scenarios use Given / When / Then. Plain-prose user stories are rejected at render time.
34
+ 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.
35
+ 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.
36
+ 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.
37
+ 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.
38
+ 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.
39
+ 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.
40
+ 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.
41
+ - **`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.
42
+ - **`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.
43
+ 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.
44
+ 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.
45
+ 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.
46
+ 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.
47
+ 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.
48
+ 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.
49
+ 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.
50
+ 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.
51
+ 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.
52
+ 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`, at either depth. 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".
53
+ 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 by a dev run. The rule-to-acceptance-criterion half always holds, in both modes.
@@ -0,0 +1,133 @@
1
+ # Render, publish, report (Phases 3, 3.5, 4, 5)
2
+
3
+ > Render, humanize, validate, publish and report. Loaded on demand by `/multi-agent:analysis` and by pipeline Phase 1. The humanizer pass and `validate-analysis-doc.mjs` are required here in every mode: a document that skipped either is not shippable.
4
+
5
+ ### Phase 3 - Humanize & buffer drafts (no side effects)
6
+
7
+ 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.
8
+
9
+ 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.
10
+
11
+ 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):
12
+ ```
13
+ ai-common-toolkit:humanizer skill input:
14
+ language: <tr|en>
15
+ tone: technical-explanatory
16
+ stripFancyPunctuation: true
17
+ content: <markdown>
18
+ ```
19
+
20
+ **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 runs through `node $HOME/.claude/scripts/validate-analysis-doc.mjs <file>`, which checks this policy deterministically in Node on all three operating systems. Do NOT verify with `grep -P`: BSD grep (macOS, the pipeline's primary platform) has no `-P`, so that command never runs and "zero matches" is trivially true. **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.**
21
+
22
+ 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.
23
+
24
+ 5. **Surface the draft tree to the user**:
25
+ ```
26
+ Drafts ready (3 files, 6.4 KB):
27
+ /tmp/analysis-UserProfile-20260514T1015/UserProfile-ios.md
28
+ /tmp/analysis-UserProfile-20260514T1015/UserProfile-android.md
29
+ /tmp/analysis-UserProfile-20260514T1015/UserProfile-backend.md
30
+ ```
31
+ User can inspect drafts before choosing output destinations in Phase 3.5.
32
+
33
+ ### Phase 3.5 - Output destination picker
34
+
35
+ AskUserQuestion (multiSelect=true), at least one selection required. `Local file` pre-selected per Locked decision 5.
36
+
37
+ ```
38
+ header: "Output"
39
+ question: <localized: "Where should the per-platform analyses be written?">
40
+ options:
41
+ - label: "Local file"
42
+ description: "analysis/<feature>-<platform>.md in each selected repo's working tree"
43
+ - label: "Confluence page"
44
+ - label: "Jira description"
45
+ ```
46
+
47
+ Conditional follow-ups:
48
+ - 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>`.
49
+ - 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).
50
+
51
+ Result: `state.analysisSpec.outputs.requested[]`.
52
+
53
+ ### Phase 4 - Dispatch & report
54
+
55
+ **Pre-dispatch gate (BLOCKING).** Before writing to any destination, run the deterministic doc validator on every per-platform draft:
56
+
57
+ ```bash
58
+ for f in /tmp/analysis-<feature-slug>-<ts>/*.md; do
59
+ node "$HOME/.claude/scripts/validate-analysis-doc.mjs" "$f" || GATE_FAILED=1
60
+ done
61
+ ```
62
+
63
+ `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.
64
+
65
+ Iterate `state.analysisSpec.outputs.requested`. For each target:
66
+
67
+ | Target | Action |
68
+ |--------|--------|
69
+ | 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.** |
70
+ | 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. |
71
+ | 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. |
72
+
73
+ **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).
74
+
75
+ ### Phase 5 - Report & stop
76
+
77
+ After dispatch, print a summary to the user (in `outputLanguage`). Example shape:
78
+
79
+ ```
80
+ Feature: <featureName>
81
+ Language: <tr|en>
82
+ Platforms: iOS, Android, Backend
83
+ Repos: my-ios-app (write), my-android-app (write), my-backend-api (write)
84
+
85
+ Sources used:
86
+ Figma: 2 frames
87
+ Swagger: 1 file
88
+ Confluence: 1 page (1 fetch error: auth_required)
89
+ Jira: 1 issue
90
+ Firebase: 3 events from schema, 1 from auto-detect
91
+ Standards: 2 local files + 1 wiki page
92
+ - /Users/.../<project>-Standards.md
93
+ - /tmp/<repo>-wiki/Navigation.md
94
+ - ~/.claude/rules/<framework>-qa.md (auto-detected)
95
+
96
+ Repo evidence (reuse vs new):
97
+ iOS my-ios-app: 4 direct-match, 6 same-domain, 11 cross-cutting
98
+ Android my-android-app: 2 direct-match, 8 same-domain, 14 cross-cutting
99
+ Backend my-backend-api: 1 direct-match, 3 same-domain, 7 cross-cutting
100
+
101
+ Sections (per platform):
102
+ iOS: [1 Scope, 2 Design, 3 Localization, 4 API, 5 Deeplink/Push, 6 Business+Tests, 7 Dev Plan]
103
+ Android: [1 Scope, 2 Design, 3 Localization, 4 API, 5 Deeplink/Push, 6 Business+Tests, 7 Dev Plan]
104
+ Backend: [1 Scope, 4 API, 6 Business+Tests, 7 Dev Plan] (Sections 2/3/5 omitted - no UI)
105
+
106
+ Outputs:
107
+ - analysis/UserProfile-ios.md (my-ios-app)
108
+ - analysis/UserProfile-android.md (my-android-app)
109
+ - analysis/UserProfile-backend.md (my-backend-api)
110
+ - Confluence (3 pages):
111
+ https://{CONFLUENCE_HOST}/pages/viewpage.action?pageId=... (iOS)
112
+ https://{CONFLUENCE_HOST}/pages/viewpage.action?pageId=... (Android)
113
+ https://{CONFLUENCE_HOST}/pages/viewpage.action?pageId=... (Backend)
114
+ - Jira: {JIRA_KEY}-12345 (description updated with 3 platform sections)
115
+ ```
116
+
117
+ **Stop. Do not chain into a dev run. Do not open a worktree. Do not create a branch.**
118
+
119
+ **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.
120
+
121
+
122
+ ## Confluence write (on-request only)
123
+
124
+ 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:
125
+
126
+ 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).
127
+ 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`).
128
+ 3. Convert markdown to storage XML using the table in `$HOME/.claude/multi-agent-refs/channels/confluence.md`.
129
+ 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).
130
+ 5. Reference attachments inside the page body via `<ac:image><ri:attachment ri:filename="frame-<nodeId>.png"/></ac:image>`.
131
+ 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.
132
+
133
+ 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.
@@ -0,0 +1,76 @@
1
+ # Open-question resolution engine
2
+
3
+ > Walks the Section 20 rows of an analysis v3 document one at a time, proposing source-labeled answer candidates and merging the chosen answer into the proper body section. Two mount points share this file: `/multi-agent:analysis-resolve` (standalone, for a document produced earlier) and pipeline Phase 4 in analysis mode. In the full pipeline the same walk runs at the end of Phase 2, before the Plan Approval Gate, because Phase 4 comes after development and a question answered then is answered too late.
4
+ >
5
+ > The 31 inherited decisions are in `locked.md`; the ones below are this engine's own. Core invariant: the document is authoritative and forward-looking. The engine never invents an answer - when no source produces a credible candidate the only options are Defer and Other.
6
+
7
+ ## New Locked decisions (this command)
8
+
9
+ 1. **One question per `AskUserQuestion` call.** Never batch Section 20 rows. Sequential resolution keeps each decision explicit and traceable.
10
+ 2. **Up to 3 source-labeled candidates plus Defer = 4 options max.** Each candidate's `description` carries its source label: `From evidence - <doc section / citation>`, `From repo - <file:line>`, `AI reasoned - <one-line rationale>`. The auto-provided Other accepts free text and stop tokens.
11
+ 3. **Three sources, never blended.**
12
+ - **From evidence**: the answer is already derivable from the doc's own sections and their citations (Sections 5, 6, 9, 13, 21) or from cached `state.analysisSpec.evidence.*` when the session still holds it. Cite the section or evidence bucket.
13
+ - **From repo**: the batched Phase 1 repo lookup (one Explore subagent) returned an answer with a `file:line` citation.
14
+ - **AI reasoned**: contextual reasoning grounded in the loaded doc (feature scope, platform, surrounding sections). Requires a one-line rationale; skip if the basis is no stronger than guessing.
15
+ 4. **Never invent.** If no source produces a credible candidate, offer only Defer and Other.
16
+ 5. **Stop tokens** (case-insensitive, typed into Other): `stop`, `pause`, `dur`, `kes`. Halt immediately, save current state, jump to the Finalize phase.
17
+ 6. **Follow-up questions surface immediately.** If an answer creates a new question ("use a new endpoint" leads to "endpoint name?"), insert a new `Acik / Open` row into Section 20 directly after the current row and process it next, not at queue end.
18
+ 7. **Save after every answer.** Each resolution writes the full doc to disk atomically before the next question. Interruption loses nothing.
19
+ 8. **Status enum is fixed:** `Acik / Open`, `Girdi bekleniyor / Pending input`, `Karar verildi / Decided` (render the side matching the doc's `language`). Only the Status cell and a trailing `[Cozum: <value> - <source>]` / `[Resolved: <value> - <source>]` fragment on the question cell are edited in Section 20; Owner is never synthesized or changed.
20
+ 9. **Sibling propagation is explicit, never silent.** Per-platform sibling files (front-matter `siblings:`) are touched only in the Finalize phase, only for rows whose question text matches verbatim, and only after the user approves one summary question. Platform-specific rows (convention fallbacks, per-platform reuse rows) never propagate.
21
+ 10. **`evidence_digest` stays untouched.** Resolving questions does not change the evidence inputs; the front-matter digest and `generated` timestamp are preserved. Only the Section 23 changelog records the revision.
22
+
23
+
24
+ ### Phase 1 - Parse and batched repo lookup
25
+
26
+ 1. Read the doc end-to-end. Capture:
27
+ - Front-matter: `feature`, `platform`, `language`, `mode`, `siblings[]`.
28
+ - The Risks and Open Questions table: ordered rows `{index, question, owner, status}`.
29
+ - Context for reasoning: Summary, Goals, API Contracts, Architecture Plan (concept table + footnotes), Files to Add, References.
30
+ 2. Filter to rows whose status is `Acik / Open` or `Girdi bekleniyor / Pending input`. If zero remain, report `Section 20 has no open rows.` and stop.
31
+ 3. **Classify each row** by its auto-population fingerprint:
32
+
33
+ | Class | Fingerprint (from analysis.md auto-population rules) | Extra candidate source |
34
+ |---|---|---|
35
+ | `convention-fallback` | row text contains `convention fallback applied` or cites `conventions-defaults.md:C<n>-` (Locked 23) | re-run `~/.claude/lib/extract-conventions.sh <repo> <platform>` for that one field; offer the default vs the fresh extraction |
36
+ | `reuse-vs-new` | row text matches `existing <X> candidate found; reuse or document why a new one is needed` (Locked 11) | repo lookup reads the candidate `file:line` and summarizes its fit |
37
+ | `citation-tbd` | row originated from a `[label TBD - see Open Questions]` downgrade (Locked 3) | repo localization keys / Figma evidence already cited elsewhere in the doc |
38
+ | `legacy-decision` | row phrased `current code does X; should the new feature keep, change, or drop this?` (Locked 4) | repo lookup confirms current behavior with `file:line` |
39
+ | `standards-conflict` | row cites a binding standards source (Locked 8) | quote the binding section verbatim from References |
40
+ | `design-gap` | row needs new Figma/design information (tier-3 forced questions, missing variants per Locked 12/19) | NONE - Locked 30; offer only Defer + the re-run recommendation |
41
+ | `generic` | anything else | all three standard sources |
42
+
43
+ 4. **Batched repo lookup** (single Explore subagent, one call regardless of row count; skip if every row classified `design-gap`):
44
+ > "For the feature `<feature>` on platform `<platform>`, answer the following questions from the repo at `<repo-root>`. Return one entry per question ID with either an answer plus `file:line` citation OR `not-found`. Scope reading to paths the questions name plus their direct dependencies; do not roam, do not propose changes.
45
+ > Q1: <row 1 text> ..."
46
+ 5. Cache per-question answers keyed by row index. These feed the `From repo` candidate in Phase 2.
47
+
48
+ ### Phase 2 - Sequential resolution loop
49
+
50
+ For each open row in source order:
51
+
52
+ 1. **Generate candidates** per the row's class (max 3). Skip any source with no credible output. For `design-gap` rows, skip candidate generation entirely.
53
+ 2. **Ask** (interactive mode) - single AskUserQuestion:
54
+ - `header`: the target section anchor, max 12 chars (e.g. `S13 Arch`, `S9 API`, `S10 L10n`, `Conventions`)
55
+ - `question`: the row text verbatim, prefixed `[R-<index>]` (follows the doc, so it may be Turkish; that is correct here - the row IS the doc content)
56
+ - `options`: up to 3 candidates + `Defer - keep open`. Candidate descriptions carry the source label per New Locked 2.
57
+ - Autonomous mode: pick the single credible candidate if exactly one source produced one; otherwise Defer. Log each auto-decision as one line.
58
+ 3. **Apply**:
59
+ - **Concrete answer**: locate the target body section from the row's anchor or content (convention rows target the Architecture Plan concept table; reuse rows target Files to Add + Architecture Plan; API rows target API Contracts; etc.).
60
+ - `From evidence` / `AI reasoned` / user Other: write as primary content in the doc's `language`, ASCII punctuation, citations preserved.
61
+ - `From repo` describing current behavior: write as `> Legacy reference: <text> (file:line)` under the target entry (Locked 4). A repo answer that the user adopts as the forward decision is primary content WITH its `file:line` citation.
62
+ - `convention-fallback`: update the convention cell, rewrite its footnote to `^[user-override: resolved via analysis-resolve <YYYY-MM-DD>]` (Locked 24).
63
+ - Update the Section 20 row: Status to `Karar verildi / Decided`, append ` [Cozum: <one-line> - <source>]` (tr) / ` [Resolved: <one-line> - <source>]` (en) to the question cell. Do not delete the row; the table stays a decision log.
64
+ - **Defer**: Status to `Girdi bekleniyor / Pending input`. Row otherwise untouched.
65
+ - **Stop token**: save, jump to Phase 3.
66
+ - **Follow-up**: insert the new `Acik / Open` row right after the current one (New Locked 6) and process it next.
67
+ 4. **Save the full doc to disk** before the next iteration (New Locked 7).
68
+
69
+ ### Phase 3 - Finalize
70
+
71
+ 1. **Sibling propagation** (only if front-matter `siblings[]` is non-empty AND at least one resolved row's question text appears verbatim with an open status in a sibling file on disk): one AskUserQuestion, `header: "Siblings"`, question `<localized: "N resolved rows also appear open in sibling file(s) <list>. Apply the same resolutions there?">`, options `Apply to all listed` / `Skip siblings`. On apply: repeat the Phase 2 apply step per matching row per sibling, then give each touched sibling its own changelog row. Platform-specific classes (`convention-fallback`, `reuse-vs-new`) are excluded from matching (New Locked 9).
72
+ 2. **Changelog**: append one row to the Changelog section of every touched file: next version (integer scheme `v1 -> v2`; dotted scheme bumps the minor), today's date, author `analysis-resolve`, change `Resolved <N> of <M> Section 20 rows; <K> deferred`.
73
+ 3. **Punctuation gate**: run the Locked 7 verification grep over every touched file; fix any hit before reporting.
74
+ 4. **Report** (in `outputLanguage`, max 12 lines): doc path(s) + new version, counts (resolved / deferred / follow-ups created / still open), `design-gap` rows that need a `/multi-agent:analysis` re-run (list inputs to re-supply), and - if open rows remain - a reminder that re-running this command resumes where it left off (state is the doc itself; no separate state file).
75
+
76
+ **Stop. No commit, no branch, no dispatch.** The user reviews the diff and commits manually (Locked 6).
@@ -0,0 +1,98 @@
1
+ # Two-pass synthesis (Phase 2, 2a, 2b)
2
+
3
+ > Two-pass synthesis: the platform-agnostic concept pass and the per-platform Pass B projection, plus the convention preview that gates it. Loaded on demand by `/multi-agent:analysis` and by pipeline Phase 1.
4
+
5
+ ### Phase 2 - Two-pass synthesis (per-platform)
6
+
7
+ Synthesis runs in two passes: Pass A computes the shared logical content once, Pass B projects it onto each selected platform.
8
+
9
+ #### Pass A - Shared synthesis (sequential, fail-soft)
10
+
11
+ Build one in-memory `synthesizedSections` object from all evidence. Apply the omission rule per section (zero-evidence → `null`). The object holds both shared content (Sections 1, 4) and `byPlatform` projections (Sections 2, 3, 5, 6, 7).
12
+
13
+ ```
14
+ synthesizedSections = {
15
+ scope: { ... shared block ... },
16
+ design: { shared: {frameGallery, codeConnect}, byPlatform: {ios, android, frontend} },
17
+ localization: { keys: [...], byPlatform: {ios: {source: "Localizable.strings", rows}, android: {source: "strings.xml", rows}, frontend: {source: "i18n/*.json", rows}} },
18
+ apiContracts: { ... shared verbatim ... },
19
+ deeplinkPush: { byPlatform: {ios, android, frontend, backend: null} },
20
+ business: { rules: [...], useCases: [...], firebaseEvents: [...], byPlatform: {ios: {testFramework: "Swift Testing", skeletons}, android: {testFramework: "JUnit5 + Turbine"}, frontend: {testFramework: "Vitest + RTL"}, backend: {testFramework: "pytest"}} },
21
+ devPlan: { byPlatform: {ios: {tasks, standards}, android: {...}, ...} }
22
+ }
23
+ ```
24
+
25
+ | Section | Production logic |
26
+ |---------|------------------|
27
+ | 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. |
28
+ | 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`). |
29
+ | 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). |
30
+ | 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). |
31
+ | 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. |
32
+ | 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`. |
33
+ | 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. |
34
+
35
+ #### Phase 2a - Pass B preview (Locked 26)
36
+
37
+ 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.
38
+
39
+ Example (iOS + Android selected):
40
+
41
+ ```
42
+ Convention preview - Pass B will render with:
43
+
44
+ | Concept | iOS | Android |
45
+ |---|---|---|
46
+ | Module folder | Domains/Profile/.../Screens/ProfileEditor/ ^[C1 high] | feature/profile/.../userprofile/ ^[C1 high] |
47
+ | State holder | UserProfileViewModel ^[C2 high: 8 examples] | UserProfileViewModel ^[C2 high: 5 examples] |
48
+ | State model | sealed enum UserProfileUIState ^[C3 high] | sealed interface UserProfileUiState ^[C3 high] |
49
+ | Test naming | @Test func scenario_expected() ^[C4 medium: 4 examples] | fun scenario_expectedBehavior() ^[C4 high] |
50
+ | Identifier | userProfile.continueButton ^[C5 high] | userProfileContinueButton ^[C5 medium] |
51
+ | Localization key | UserProfile.ContinueButton ^[C6 high] | user_profile_continue_button ^[C6 high] |
52
+ | DI | UserProfileDependencyConfigurator ^[C7 high] | UserProfileModule (Hilt) ^[C7 fallback: defaults] |
53
+
54
+ Confidence summary:
55
+ iOS: 7/7 high, 0 medium, 0 low, 0 fallback
56
+ Android: 5/7 high, 1 medium, 0 low, 1 fallback
57
+ ```
58
+
59
+ AskUserQuestion shape:
60
+
61
+ ```
62
+ header: "Conventions"
63
+ question: <localized: "Pass B will render with the above conventions. Approve, override, or cancel?">
64
+ options:
65
+ - label: "Approve, render"
66
+ description: "Proceed to Phase 2b with these conventions"
67
+ - label: "Override individual cells"
68
+ description: "Open follow-up questions for cells you want to change"
69
+ - label: "Cancel"
70
+ ```
71
+
72
+ On `Approve`: proceed to Phase 2b directly.
73
+ 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.
74
+ On `Cancel`: halt and write `state.analysisSpec.phase = "cancelled_at_pass_b_preview"`. Drafts in `/tmp/` are kept for inspection.
75
+
76
+ Empty submit (`feedback_no-inferred-defaults-from-empty-answer`): re-ask the same question. Do not infer consent.
77
+
78
+ 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.
79
+
80
+ #### Phase 2b - Per-platform render (Pass B)
81
+
82
+ For each `platform` in `state.analysisSpec.platforms[]`:
83
+
84
+ 1. **Resolve standards binding source** (one canonical source per platform):
85
+ - `ios` → `prefs.projects[<key>].standardsFile` if present → glob `~/<project>-iOS-Standards.md` → `~/.claude/rules/swiftui-qa.md`
86
+ - `android` → `~/.claude/rules/kotlin-android.md` first → `evidence.standards[]` entries whose path contains `android` or `kotlin`
87
+ - `backend` → `evidence.standards[]` entries matching language hints (`python`, `go`, `node`, `fastapi`) → fall back to `~/.claude/rules/security.md` + `code-style.md`
88
+ - `frontend` → `evidence.standards[]` entries matching `react`, `vue`, `next`, `sveltekit` → `~/.claude/rules/code-style.md`
89
+ 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.
90
+ 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.
91
+ 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).
92
+ 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.
93
+ 6. **Concatenate non-null sections in canonical order.** Numbering stays sequential `1..N` over the rendered set (omitted sections do not create gaps).
94
+ 7. **Schema validation** on the per-platform spec object:
95
+ ```bash
96
+ python3 -c "import json,jsonschema; jsonschema.validate(json.load(open('state/<feature>-<platform>.json')), json.load(open('$HOME/.claude/schemas/analysis-spec.schema.json')))"
97
+ ```
98
+ On failure for any platform, surface the error and stop before Phase 3 (do not draft partial outputs).