@mmerterden/multi-agent-pipeline 20.12.0 → 20.13.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 +36 -0
- package/README.md +1 -1
- package/README.tr.md +1 -1
- package/docs/facts.json +1 -1
- package/install/_common.mjs +1 -1
- package/install/_plugin-skills.mjs +13 -9
- package/install/catalog-history.json +1 -1
- package/install/codex.mjs +12 -12
- package/manifest.json +59 -53
- package/package.json +1 -1
- package/pipeline/commands/multi-agent/SKILL.md +1 -0
- package/pipeline/commands/multi-agent/analysis/SKILL.md +7 -3
- package/pipeline/commands/multi-agent/analysis-jira/SKILL.md +57 -7
- package/pipeline/commands/multi-agent/analysis-resolve/SKILL.md +2 -2
- package/pipeline/commands/multi-agent/autopilot/SKILL.md +6 -0
- package/pipeline/commands/multi-agent/autopilot-off/SKILL.md +1 -0
- package/pipeline/commands/multi-agent/doctor/SKILL.md +6 -0
- package/pipeline/commands/multi-agent/feedback/SKILL.md +2 -2
- package/pipeline/commands/multi-agent/forget/SKILL.md +1 -0
- package/pipeline/commands/multi-agent/garbage-collect/SKILL.md +1 -0
- package/pipeline/commands/multi-agent/kill/SKILL.md +1 -0
- package/pipeline/commands/multi-agent/prune-logs/SKILL.md +1 -0
- package/pipeline/commands/multi-agent/prune-prompts/SKILL.md +1 -0
- package/pipeline/commands/multi-agent/review/SKILL.md +5 -0
- package/pipeline/commands/multi-agent/review-analysis/SKILL.md +7 -2
- package/pipeline/lib/analysis-jira-write.sh +81 -27
- package/pipeline/lib/analysis-quality.mjs +261 -0
- package/pipeline/lib/analysis-sections.mjs +105 -0
- package/pipeline/lib/jira-epic-link.sh +54 -0
- package/pipeline/multi-agent-refs/analysis/locked.md +4 -4
- package/pipeline/multi-agent-refs/analysis/redesign.md +3 -1
- package/pipeline/multi-agent-refs/analysis/render.md +20 -21
- package/pipeline/multi-agent-refs/analysis/resolve.md +1 -1
- package/pipeline/multi-agent-refs/analysis/review.md +16 -3
- package/pipeline/multi-agent-refs/analysis/synthesis.md +10 -2
- package/pipeline/multi-agent-refs/analysis-template-corporate.md +44 -9
- package/pipeline/multi-agent-refs/analysis-template.md +21 -14
- package/pipeline/multi-agent-refs/cross-cli-contract.md +4 -0
- package/pipeline/multi-agent-refs/features/analysis-jira.md +69 -19
- package/pipeline/schemas/analysis-spec.schema.json +22 -0
- package/pipeline/schemas/prefs.schema.json +22 -1
- package/pipeline/scripts/analysis-story-body.mjs +210 -0
- package/pipeline/scripts/analysis-story-tree.mjs +73 -12
- package/pipeline/scripts/analysis-tickets-writeback.mjs +101 -0
- package/pipeline/scripts/build-references.mjs +14 -1
- package/pipeline/scripts/confluence-readback.mjs +148 -0
- package/pipeline/scripts/jira-wiki-escape.mjs +40 -0
- package/pipeline/scripts/validate-analysis-doc.mjs +120 -70
- package/pipeline/skills/.skill-manifest.json +8 -8
- package/pipeline/skills/shared/core/multi-agent-analysis/SKILL.md +6 -1
- package/pipeline/skills/shared/core/multi-agent-analysis-jira/SKILL.md +56 -6
- package/pipeline/skills/shared/core/multi-agent-autopilot/SKILL.md +6 -0
- package/pipeline/skills/shared/core/multi-agent-doctor/SKILL.md +6 -0
- package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +5 -0
- package/pipeline/skills/shared/core/multi-agent-review-analysis/SKILL.md +5 -0
- package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +1 -0
|
@@ -46,7 +46,7 @@ behind.
|
|
|
46
46
|
### Full list
|
|
47
47
|
|
|
48
48
|
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.
|
|
49
|
-
2. **Section omission rule.** Sections with zero evidence are dropped entirely; no `TBD` placeholder section. **A rendered section keeps its canonical template number**, so the set has gaps and that is correct: `1, 2, 4, 9, 13, 14, 21` is a valid rendered document.
|
|
49
|
+
2. **Section omission rule.** Sections with zero evidence are dropped entirely; no `TBD` placeholder section. **A rendered section keeps its canonical template number**, so the set has gaps and that is correct: `1, 2, 4, 9, 13, 14, 21` is a valid rendered document. Numbers are never rewritten into a sequential `1..N`, because Locked 30 threads ids across sections BY NUMBER (`Section 15.1 scenario`, `Section 4.4`, `Section 3/5 layout cells`) and renumbering would send every one of those cross-references to the wrong section or to nothing. What IS checked: every rendered number is a real template number, and the numbers ascend without repeating.
|
|
50
50
|
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.
|
|
51
51
|
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?".
|
|
52
52
|
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).
|
|
@@ -56,13 +56,13 @@ behind.
|
|
|
56
56
|
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.
|
|
57
57
|
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`.
|
|
58
58
|
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").
|
|
59
|
-
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]]`. **A channel's design may not be called missing until the file tree has been scanned.** Run `figma-screenshot.sh --discover-sections --file-key <k> --feature-slug <s>`; sibling sections it returns join `evidence.figma[]` as their own entries and are never re-asked (Locked 1). Only an empty `candidates` list lets a channel be recorded as having no design, and the record must cite the scan (`fileKey`, `pagesScanned`, `tokensTried`). Declaring a channel missing without scanning fails the dispatch gate
|
|
59
|
+
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]]`. **A channel's design may not be called missing until the file tree has been scanned.** Run `figma-screenshot.sh --discover-sections --file-key <k> --feature-slug <s>`; sibling sections it returns join `evidence.figma[]` as their own entries and are never re-asked (Locked 1). Only an empty `candidates` list lets a channel be recorded as having no design, and the record must cite the scan (`fileKey`, `pagesScanned`, `tokensTried`). Declaring a channel missing without scanning fails the dispatch gate, because a channel's frames often sit in a sibling section of the same file.
|
|
60
60
|
13. **Gherkin user stories.** Section 4 scenarios use Given / When / Then. Plain-prose user stories are rejected at render time.
|
|
61
61
|
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.
|
|
62
62
|
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.
|
|
63
63
|
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.
|
|
64
64
|
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.
|
|
65
|
-
18. **Screenshots embedded, not linked, and every inventory row gets one.** 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. The gallery is generated from the inventory, never hand-picked: one row, one embedded image, ordered by node id and titled `<nodeId> <frame name>`. A bare filename in a table cell is text to the reader, not a picture
|
|
65
|
+
18. **Screenshots embedded, not linked, and every inventory row gets one.** 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. The gallery is generated from the inventory, never hand-picked: one row, one embedded image, ordered by node id and titled `<nodeId> <frame name>`. A bare filename in a table cell is text to the reader, not a picture: an attachment that is uploaded but not embedded is invisible on the page. Narrowing to a canonical subset for page weight is not a call the run makes on its own; the display-width cap (`md2confluence-v3.py --image-width`, phone frames overriding to 320) already solves readability without dropping evidence. Dispatch reports the embedded-over-inventory ratio and warns below 1. URL-only Figma references in Section 5 are a review finding, not a validator ERROR: the check belongs to the Confluence dispatch step, which is the only place that knows whether an attachment upload succeeded.
|
|
66
66
|
19. **All Figma variants drilled, and drilled means read.** 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. Counting them is not drilling them: extract the visible `TEXT` layers inside each frame's own bounds, dropping hidden layers and component-instance boilerplate that overflows the frame (default card and widget filler can outnumber the real text several times over). A frame may be called out of scope only by quoting its own extracted text; "the name looked unrelated" is not a reason. Opening a Section 20 question about a frame requires that its text was extracted first, and asking about a frame nobody read fails the dispatch gate: a frame whose name looks ambiguous can spell out a whole step in its text.
|
|
67
67
|
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.
|
|
68
68
|
- **`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.
|
|
@@ -82,5 +82,5 @@ behind.
|
|
|
82
82
|
32. **Corporate backbone always renders.** In the `corporate` profile the Locked 2 omission rule is replaced for Part A and the footer: those sections render even with zero evidence, carrying `N/A` when the section is genuinely out of scope for the feature and `EKLENECEK` when evidence is expected but missing. This is the point of a requirements document - a reader has to be able to tell "we considered hardware needs and there are none" from "nobody looked". Every `EKLENECEK` emits a matching Section 20 Risks and Open Questions row naming what is missing and who can answer it; an `EKLENECEK` with no such row fails the dispatch gate, because an unanswered question nobody owns is how a placeholder reaches production. **Missing inputs never block the run**: the corporate source practice of halting until every input arrives is deliberately not adopted - the document is produced with `EKLENECEK` in the gaps and the gaps are raised in Section 20. Part B follows the global omission table unchanged. In the `global` profile Locked 2 applies as written, with no placeholder of any kind.
|
|
83
83
|
33. **References are built from the evidence record, not written.** Section 21 is emitted by `$HOME/.claude/scripts/build-references.mjs` from `state.analysisSpec.evidence.*` in both profiles. Each row carries a precision anchor in its `Sürüm / Ref` column - Figma node id, Confluence `pageId` plus page version, the commit SHA a repo was read at, the Swagger spec version - because a reference with no anchor points at a moving target. Each row carries an `Erişim / Access` cell: a declared source that could not be fetched still gets a row reading `erişilemedi (<reason>)`, since a silently dropped source reads to the next person as a source that never existed. User statements from the conversation that no fetched source contains are recorded as `Serbest metin` rows, quoted verbatim, with the decision they settled. **Coverage gate**: every entry in `evidence.figma[]`, `confluence[]`, `jira[]`, `swagger[]`, `repo[]`, `standards[]`, `firebase[]`, `documents[]`, `outside[]`, `freeText[]` and every entry in `evidence.fetchErrors[]` must appear as a row, and every row must map to an evidence entry. A source that shaped the document but is missing from References fails the dispatch gate; so does an invented row with no evidence behind it.
|
|
84
84
|
34. **Stack-optional render.** Platform and repo selection are optional. When `state.analysisSpec.platforms[]` is empty, the run still completes: the analysis layers that do not need a target repository render in full - Part A and Part B in the corporate profile, Sections 1-12 and 16-17 in the global profile - and only the development layer is dropped (corporate Part C; global Sections 13, 14, 15) along with the Pass B projection, since there are no conventions to project onto. A Section 20 row records that the development analysis awaits a repo selection. **The channel split survives the missing repo.** Channels are derived from the evidence instead of repo stack tags (`intake.md` Step 3 carries the signal table) and one document is emitted per derived channel - `mobile`, `web`, or both. A phone screen and a browser screen carry different requirements before anyone has picked a repository; the split (Locked 9) exists to carry that difference and only its *projection* half needs conventions. `mobile` stays one channel rather than iOS plus Android, since without conventions nothing tells the two apart. Evidence with no interface at all yields a single channel-agnostic `<feature>.md`. Files land under `~/Desktop/multiAgentAnalysis/<feature-name>/`, named `<feature>-<channel>.md` (or `<feature>.md` for the channel-agnostic case): the repo-relative `analysis/` path has nothing to be relative to without a repo, and the current working directory is never used, since for a repo-less run it is arbitrary. Desktop rather than a hidden directory because the document is a deliverable somebody is meant to open and hand over, and `multiAgentAnalysis` rather than a bare `Analysis` because a generic word collides with whatever else is on a desktop while the producer name groups every run this command ever writes. The Phase 3.5 picker shows the resolved path and takes an override through its Other input. A requirements document is useful before anyone has decided which repository will hold the code, and refusing to produce one until that decision exists inverts the order the work actually happens in.
|
|
85
|
-
35. **The document is reviewed before it is published.**
|
|
85
|
+
35. **The document is reviewed before it is published.** A deterministic validator checks structure, not content: a channel nobody searched for, an open question about a frame nobody opened, and an unowned `EKLENECEK` marker all pass it, and every one is what a reader catches on the first pass. Phase 3.2 runs `phases/phase-3-review.md` Step 0 (strict validator, the host's three-reviewer set, triage) on the draft before the destination is chosen: a finding is cheap while nothing is written. Reviewers are subagents holding `analysis/review.md`, never the context that wrote the document, which cannot notice a search it never thought to run. A blocking finding returns to Phase 2b with dispatch closed and never becomes an open question, since "the document is wrong" is not something to ask the reader; capped at two returns. Phase 3.3 sorts every remaining gap into searched-and-closed, asked-and-answered, or `AS-NN`; an unstamped gap fails the dispatch gate. Autopilot runs both; only the asking degrades, into rows stamped `autopilot: could not ask`.
|
|
86
86
|
36. **A redesign records v1 before it plans v2.** `options.redesign` is an opt-in on the `options.uiTests` axis, never a third `mode` value: `mode` says how many sections, `redesign` says which content, and a `mode: redesign` would switch off the Full-mode traceability, Test Plan and rule-to-test gates in exactly the documents that need them. It adds three sub-sections and no top-level section: current behaviour with `CB-<slug>-NN` ids and `repo/file:line` citations, the v1 to v2 endpoint mapping, and a difference list over a closed status vocabulary. Every `Missing` and `Partial` owes a Section 20 row by `AS-NN`, and a `CB-` id in one table but not the other fails in both directions - a behaviour that is in the code and on nobody's difference list is what a redesign loses and production finds. Evidence and certainty are derived from `repoEvidence`, never graded by the writer (Locked 24, same reason), and `options.redesign` is an `evidence_digest` input. Contract and the eight checks: `analysis/redesign.md`, loaded only on a redesign run.
|
|
@@ -41,7 +41,9 @@ intake opt-in, written into the front-matter, enforced by the validator's
|
|
|
41
41
|
## The three artefacts
|
|
42
42
|
|
|
43
43
|
Section numbers are per profile. The global profile uses sub-sections of existing
|
|
44
|
-
sections (4.5, 4.6, 9.5) and the corporate profile
|
|
44
|
+
sections (4.5, 4.6, 9.5) and the corporate profile nests them one level deeper in
|
|
45
|
+
its own spine (2.1.1 current behaviour, 2.3.1 difference list, 5.(N+4).1 endpoint
|
|
46
|
+
mapping); the validator looks each one up by profile. No
|
|
45
47
|
new top-level section is introduced in either, because section numbers are quoted
|
|
46
48
|
in 172 places and renumbering them to add a mode is a worse trade than nesting.
|
|
47
49
|
|
|
@@ -8,9 +8,11 @@
|
|
|
8
8
|
|
|
9
9
|
1b. **Template selection** (Locked 31): read `state.analysisSpec.profile`. `global` renders against `$HOME/.claude/multi-agent-refs/analysis-template.md`; `corporate` renders against `$HOME/.claude/multi-agent-refs/analysis-template-corporate.md`. The evidence is the same either way - this step chooses the projection, nothing else. In the corporate profile the Part A backbone and the footer render even with zero evidence, carrying `N/A` or `EKLENECEK`, and each `EKLENECEK` emits its Section 20 row (Locked 32).
|
|
10
10
|
|
|
11
|
-
2. **Markdown render**: for each platform in `state.analysisSpec.platforms[]`, concatenate the per-platform spec into one markdown file. Tables in pipe-syntax.
|
|
11
|
+
2. **Markdown render**: for each platform in `state.analysisSpec.platforms[]`, concatenate the per-platform spec into one markdown file. Tables in pipe-syntax. Each rendered section keeps its canonical number, so omitted sections leave gaps (Locked 2). Corporate Part A and footer never drop; Parts B and C follow the omission table.
|
|
12
12
|
|
|
13
|
-
**
|
|
13
|
+
**Missing inputs panel** above Section 1: `build-references.mjs "$STATE" --lang "$LANG" --missing-panel` (prints nothing when every source was read). "Not reachable" is never written as "does not exist".
|
|
14
|
+
|
|
15
|
+
**When `platforms[]` is empty** (Locked 34), the loop runs once per channel derived from the evidence (`mobile`, `web`, or one channel-agnostic pass). The development layer (corporate Part C, global Sections 13-15) and the Pass B projection are skipped, Section 20 records that they await a repo selection, and front-matter `platform` reads `none`. Everything else renders in full.
|
|
14
16
|
|
|
15
17
|
3. **Humanizer pass (required: 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):
|
|
16
18
|
```
|
|
@@ -21,7 +23,7 @@
|
|
|
21
23
|
content: <markdown>
|
|
22
24
|
```
|
|
23
25
|
|
|
24
|
-
**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.
|
|
26
|
+
**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. Verify with `node $HOME/.claude/scripts/validate-analysis-doc.mjs <file>`, not a Perl-regex grep (BSD grep lacks it, so "zero matches" is trivially true). Readability rules live in the humanizer skill; this paragraph owns only the punctuation policy. **Diacritics are PRESERVED: only the listed codepoints are replaced. Turkish letters (ş, ç, ğ, ı, İ, ö, ü) stay verbatim; never ASCII-fold (`Geliştirme Özeti`, not `Gelistirme Ozeti`). ASCII-folded Turkish fails review.**
|
|
25
27
|
|
|
26
28
|
3b. **Build Section 21 References** (Locked 33): emit the table with
|
|
27
29
|
|
|
@@ -207,36 +209,33 @@ Provenance:
|
|
|
207
209
|
|
|
208
210
|
## Confluence write (on-request only)
|
|
209
211
|
|
|
210
|
-
|
|
212
|
+
Confluence is NEVER default-selected at Phase 3.5. Only when the user explicitly asks to post does the command:
|
|
211
213
|
|
|
212
214
|
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).
|
|
213
215
|
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`).
|
|
214
216
|
|
|
215
|
-
**Corporate profile exception.**
|
|
217
|
+
**Corporate profile exception.** With the bindings configured, the prompt is skipped: space `prefs.global.analysisProfile.corporate.confluenceSpaceKey`, parent `prefs.global.analysisProfile.corporate.confluenceParentPageId`, title from `prefs.global.analysisProfile.corporate.titleFormat` with `prefs.global.analysisProfile.corporate.titlePrefix` filling `{prefix}`. Any of the four missing falls back to the prompt; a colliding title becomes an update (PUT with version bump), never a second page.
|
|
216
218
|
3. **Publish with `md2confluence-v3.py`, never a hand-rolled conversion + curl.** It
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
gallery render as pictures rather than filenames (Locked 18). It also warns when a
|
|
221
|
-
body references an image no attachment matched, which is how a missing screenshot
|
|
222
|
-
announces itself.
|
|
219
|
+
does the storage-XML conversion (`channels/confluence.md`), uploads every PNG in
|
|
220
|
+
`--attachments-dir`, injects `<ac:image><ri:attachment/>` so a frame gallery renders
|
|
221
|
+
as pictures (Locked 18), and warns on an image reference no attachment matched.
|
|
223
222
|
|
|
224
223
|
```bash
|
|
224
|
+
CONFLUENCE_BASE_URL="https://$(jq -r '.global.hosts.confluence // empty' "$HOME/.claude/multi-agent-preferences.json")"
|
|
225
|
+
export CONFLUENCE_BASE_URL
|
|
225
226
|
python3 "$HOME/.claude/lib/md2confluence-v3.py" create \
|
|
226
227
|
--space "$SPACE" --parent-page-id "$PARENT" --title "$TITLE" \
|
|
227
228
|
--markdown "$DRAFT" --attachments-dir "$(dirname "$DRAFT")"
|
|
228
229
|
# updating an existing page: `update --page-id <ID>` instead of `create --space ...`
|
|
229
230
|
```
|
|
230
231
|
|
|
231
|
-
Screenshots must already sit in `--attachments-dir
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
warning list means the page shipped with missing pictures; surface it rather than
|
|
240
|
-
reporting a clean publish. Surface the page URL in the Phase 4 report.
|
|
232
|
+
Screenshots must already sit in `--attachments-dir`: point `figma-screenshot.sh
|
|
233
|
+
--output-dir` at the draft directory during evidence collection, or the gallery
|
|
234
|
+
renders filenames. MCP asset URLs expire after 7 days; cells reference the local file.
|
|
235
|
+
**Draft title:** while `status` is not `final`, prefix `[TASLAK] ` / `[DRAFT] ` (or fill the corporate `titleFormat` `{status}`); the final publish drops it.
|
|
236
|
+
4. Read the script's JSON envelope (page id and URL, attachments, `image reference has
|
|
237
|
+
no matching attachment` warnings). A warning means missing pictures: surface it, not a
|
|
238
|
+
clean publish. Surface the page URL in the Phase 4 report.
|
|
239
|
+
5. **Read the page back:** `confluence-readback.mjs --page-id "$PAGE_ID" --markdown "$DRAFT"`. Exit 1 names missing headings and unattached images; report it, never republish automatically.
|
|
241
240
|
|
|
242
241
|
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.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
>
|
|
5
5
|
> The same three source labels drive `research/engine.md`, which generalises this walk to any gap list (maturity blockers, open questions) and adds a deterministic check of every cited source (`research-gate.mjs`) for runs nobody watches.
|
|
6
6
|
>
|
|
7
|
-
> The
|
|
7
|
+
> The 36 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.
|
|
8
8
|
|
|
9
9
|
## New Locked decisions (this command)
|
|
10
10
|
|
|
@@ -102,14 +102,27 @@ The verdict names the profile it judged against, the counts per severity, and wh
|
|
|
102
102
|
```
|
|
103
103
|
Verdict: 2 Blocker, 3 Important, 1 Suggestion (profile: global, mode: full)
|
|
104
104
|
|
|
105
|
-
A
|
|
106
|
-
B
|
|
107
|
-
C
|
|
105
|
+
A buildability 2 D altitude none
|
|
106
|
+
B evidence none E gaps 1
|
|
107
|
+
C spine none F contradiction 3
|
|
108
108
|
|
|
109
109
|
Not checked: references coverage (no state file passed)
|
|
110
110
|
Provenance: evidence_digest sha256:1f3a9c2 base_commit 4c1b2de
|
|
111
|
+
|
|
112
|
+
Publish ready: no
|
|
113
|
+
Fix first:
|
|
114
|
+
1. [A] 4.4 BR-login-03 has no acceptance criterion
|
|
115
|
+
2. [A] 13.2 names no file for the session store
|
|
116
|
+
3. [F] 9.1 and 4.2 disagree on the code lifetime (3 min vs 5 min)
|
|
117
|
+
Verified OK: front-matter, required sections, traceability, references (12 of 12)
|
|
111
118
|
```
|
|
112
119
|
|
|
120
|
+
**Publish ready** is `yes` only with zero Blocker findings and a clean
|
|
121
|
+
validator run. `Fix first` lists the Blocker and Important findings in the
|
|
122
|
+
order they should be fixed, each with its class and section, so the author has
|
|
123
|
+
a work list rather than a report. `Verified OK` names what was checked and
|
|
124
|
+
held, with counts, so a clean area is distinguishable from an unexamined one.
|
|
125
|
+
|
|
113
126
|
## Phase 4 - Output
|
|
114
127
|
|
|
115
128
|
Default is the chat report. Nothing is written anywhere without an explicit choice.
|
|
@@ -32,6 +32,14 @@ synthesizedSections = {
|
|
|
32
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
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
34
|
|
|
35
|
+
#### Pass A - content rules
|
|
36
|
+
|
|
37
|
+
- **Edge cases are proposals.** Failure paths the evidence states (refusal, error code, timeout, empty or expired state) go to `state.analysisSpec.edgeCandidates[]` (`{target, candidate, source}`) and the Pass B preview; only accepted ones enter the document. No source, no candidate.
|
|
38
|
+
- **Nothing invented:** no event name, sample value or threshold without a source. Show the type; a missing event name is a Section 20 question.
|
|
39
|
+
- **Unreadable is not absent.** A source that failed is listed in the missing-inputs panel and References; the body never infers absence from it.
|
|
40
|
+
- **One question, one Section 20 row**, listing every section it affects.
|
|
41
|
+
- Validator-enforced: an item is never both goal and non-goal (`scope-overlap`); every cited id is defined (`cited-undefined`); Part A carries no file path or endpoint outside `<details>` (`business-layer-technical`).
|
|
42
|
+
|
|
35
43
|
#### Phase 2a - Pass B preview (Locked 25)
|
|
36
44
|
|
|
37
45
|
Before Pass B renders any file, present the resolved convention table to the user via `AskUserQuestion` (`picker-contract.md`). The table is one row per concept, one column per selected platform.
|
|
@@ -86,7 +94,7 @@ For each `platform` in `state.analysisSpec.platforms[]`:
|
|
|
86
94
|
- `android` → `~/.claude/rules/kotlin-android.md` first → `evidence.standards[]` entries whose path contains `android` or `kotlin`
|
|
87
95
|
- `backend` → `evidence.standards[]` entries matching language hints (`python`, `go`, `node`, `fastapi`) → fall back to `~/.claude/rules/security.md` + `code-style.md`
|
|
88
96
|
- `web` → `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. Web 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; their numbers are canonical and never
|
|
97
|
+
2. **Apply per-platform omission rules.** Backend-only file drops Sections 5, 6, 7, 8, 16. Web 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; their numbers are canonical and never renumbered.
|
|
90
98
|
3. **Resolve the section set from evidence, not from a mode.** There is one
|
|
91
99
|
pipeline. A section renders when it has evidence and is dropped when it does
|
|
92
100
|
not, per Locked 2. A fixed section list chosen by a size score would fight
|
|
@@ -95,7 +103,7 @@ For each `platform` in `state.analysisSpec.platforms[]`:
|
|
|
95
103
|
would keep Section 9 for being on it.
|
|
96
104
|
4. **Produce YAML front-matter header** (see `$HOME/.claude/multi-agent-refs/analysis-template.md`). Include `profile: <state.analysisSpec.profile | global>` and `platform: <platform | none>` so the validator applies the right contract per profile (Locked 31) and recognises the stack-optional render (Locked 34), plus `ui_tests: <state.analysisSpec.options.uiTests | false>`, `a11y_depth: <state.analysisSpec.options.a11yDepth | basic>` and `redesign: <state.analysisSpec.options.redesign | false>` 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, 4.5 / 4.6 / 9.5 present when redesign). `status` is written only by `/multi-agent:analysis-resolve`; a rendered document is a draft.
|
|
97
105
|
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.
|
|
98
|
-
6. **Concatenate non-null sections in canonical order.** Each rendered section keeps its canonical template number, so omitted sections DO leave gaps - `1, 2, 4, 9, 13, 14, 21` is a correct rendered document. Locked 30 cites sections by number across the whole document;
|
|
106
|
+
6. **Concatenate non-null sections in canonical order.** Each rendered section keeps its canonical template number, so omitted sections DO leave gaps - `1, 2, 4, 9, 13, 14, 21` is a correct rendered document. Locked 30 cites sections by number across the whole document; renumbering them would break every one of those references.
|
|
99
107
|
7. **Schema validation** on the per-platform spec object:
|
|
100
108
|
```bash
|
|
101
109
|
python3 -c "import json,jsonschema; jsonschema.validate(json.load(open('state/<feature>-<platform>.json')), json.load(open('$HOME/.claude/schemas/analysis-spec.schema.json')))"
|
|
@@ -20,14 +20,14 @@ This is a sibling of `analysis-template.md` (the global profile), not a replacem
|
|
|
20
20
|
| Altitude | What to build and how | What is required and why; the how follows in Parts B and C |
|
|
21
21
|
| Current state | Legacy findings are blockquotes inside forward-looking sections (Locked 4) | Section 2.1 is a first-class current-state analysis, and 2.3 is the diff between 2.1 and 2.2 |
|
|
22
22
|
| Empty section | Dropped entirely (Locked 2) | Backbone sections always render, with `N/A` or `EKLENECEK` (Locked 32) |
|
|
23
|
-
| Version history | Section
|
|
23
|
+
| Version history | Section 23 Changelog at the bottom | `DOKÜMAN TARİHÇESİ` table at the top |
|
|
24
24
|
| Use cases | Gherkin scenarios in Section 4 | UC tables with Aktör / Ön Koşul / Ana Akış / Alternatif Akış |
|
|
25
25
|
|
|
26
26
|
Everything else is shared: citation discipline (Locked 3), forward-looking spec for Part B and C (Locked 4), the Figma 3-tier chain (Locked 12), Pass B footnotes (Locked 24), and References at the bottom (Locked 21).
|
|
27
27
|
|
|
28
28
|
## Section map
|
|
29
29
|
|
|
30
|
-
Numbering is fixed for Parts A and B
|
|
30
|
+
Numbering is fixed for Parts A and B, because the corporate backbone never drops (Locked 32). Section 5 sub-numbering shifts with the use-case count, exactly as the source documents do.
|
|
31
31
|
|
|
32
32
|
| Layer | Sections | Carries |
|
|
33
33
|
|---|---|---|
|
|
@@ -127,6 +127,16 @@ rather than a footnote.>
|
|
|
127
127
|
|---|---|---|---|
|
|
128
128
|
| 1 | <capability> | Var / Yok / Kısmi | <detail> |
|
|
129
129
|
|
|
130
|
+
#### 2.1.1 Mevcut Davranış / Current Behaviour
|
|
131
|
+
|
|
132
|
+
<Only when the front-matter carries `redesign: true` (Locked 36, `analysis/redesign.md`);
|
|
133
|
+
omitted otherwise. One `CB-<slug>-NN` row per v1 behaviour a reader could only find by
|
|
134
|
+
reading v1, each with the evidence that proves it.>
|
|
135
|
+
|
|
136
|
+
| Id | Davranış | Kanıt | Kesinlik |
|
|
137
|
+
|---|---|---|---|
|
|
138
|
+
| CB-<slug>-01 | <behaviour> | <path:line> | confirmed / uncertain |
|
|
139
|
+
|
|
130
140
|
### 2.2 Hedeflenen Durum Analizi
|
|
131
141
|
|
|
132
142
|
<What the product will do once this work ships. Sourced from the design and the
|
|
@@ -150,6 +160,16 @@ reason 2.1 and 2.2 are separate; if it is empty, one of them was not done.>
|
|
|
150
160
|
|---|---|---|---|
|
|
151
161
|
| <area> | <from 2.1> | <from 2.2> | <what has to change> |
|
|
152
162
|
|
|
163
|
+
#### 2.3.1 Fark Listesi / Difference List
|
|
164
|
+
|
|
165
|
+
<Only under `redesign: true`. Every `CB-` row from 2.1.1 appears here once with a status:
|
|
166
|
+
Moved / Taşındı, Partial / Kısmi, Missing / Yok, New / Yeni, Out of scope / Kapsam dışı.
|
|
167
|
+
Partial and Missing rows name the `AS-NN` that decides them.>
|
|
168
|
+
|
|
169
|
+
| Id | Durum | Nerede | AS-NN |
|
|
170
|
+
|---|---|---|---|
|
|
171
|
+
| CB-<slug>-01 | Moved / Taşındı | <section> | - |
|
|
172
|
+
|
|
153
173
|
### 2.4 Kısıtlar, Varsayımlar, Bağımlılıklar
|
|
154
174
|
|
|
155
175
|
| Tür | Madde | Kaynak |
|
|
@@ -230,6 +250,7 @@ Sub-numbering shifts with the use-case count. For `N` use cases:
|
|
|
230
250
|
| **Kullanım Sıklığı** | <how often> |
|
|
231
251
|
| **Ana Akış** | 1. <step> 2. <step> 3. <step> |
|
|
232
252
|
| **Alternatif Akış** | 2a. <alternative to step 2> 4a. <alternative to step 4> |
|
|
253
|
+
| **İstisna Akışı** | E1. <what happens when step N fails: refusal, error, timeout> |
|
|
233
254
|
| **İş Kuralları / Referans** | IG-01, IG-03 |
|
|
234
255
|
|
|
235
256
|
### Ekranlar
|
|
@@ -245,12 +266,14 @@ Rules the renderer enforces:
|
|
|
245
266
|
|
|
246
267
|
- **Ana Akış is numbered and single-directional.** A nested option takes a second-level number under its step.
|
|
247
268
|
- **Alternatif Akış always binds to a main-flow step**: `2a.`, `2b.`, `4a.`. A free-floating alternative sentence is rejected, because a reader cannot tell which step it replaces.
|
|
269
|
+
- **İstisna Akışı is never left out.** It is the failure path: what the user sees when the system refuses, errors or times out, and what state the flow is left in. A use case with genuinely no failure path writes `Yok: <reason>`. `validate-analysis-doc.mjs` (`exception-flow`) warns on a draft with no row or an empty one and fails a `status: final` document with no row. Edge-case candidates the synthesis proposes are written here only after the analyst accepts them.
|
|
270
|
+
- **Every screen belongs to a use case.** A design frame is listed in the `Ekranlar` block of the use case it serves; a frame linked anywhere else (outside Section 21) is a warning (`design-frame-unmapped`), because a screen no flow reaches is either missing a use case or out of scope.
|
|
248
271
|
- **Concrete limits appear only when a source states them.** A threshold nobody wrote down is invented (Locked 3), and an invented threshold in a requirements document reaches production as a bug.
|
|
249
272
|
- **FG references inside main-flow steps are optional but must be consistent.** Either every use case cites them or none does; half a document doing it reads as an omission.
|
|
250
273
|
|
|
251
274
|
### 5.(N+1) Kullanım Senaryosu Diyagramları
|
|
252
275
|
|
|
253
|
-
One mermaid diagram per use case, under a `### UC-00<i>: <name>` heading. The diagram shows the flow, including the alternative branches named in the table.
|
|
276
|
+
One mermaid diagram per use case, under a `### UC-00<i>: <name>` heading. The diagram shows the flow, including the alternative and exception branches named in the table. A use case that calls more than one service also gets a `sequenceDiagram`, so the call order and the failure point of each call are visible.
|
|
254
277
|
|
|
255
278
|
### 5.(N+2) Kullanım Senaryosu - İş Gereksinimi Eşleştirme
|
|
256
279
|
|
|
@@ -300,6 +323,14 @@ renders; when the whole contract is unknown, write one line instead of six `EKLE
|
|
|
300
323
|
cells: `Bu servisin sozlesmesi tanimli degil (AS-NN).` Render the table only once
|
|
301
324
|
`Name` and `Path` are both known.
|
|
302
325
|
|
|
326
|
+
#### 5.(N+4).1 Endpoint Eşlemesi / Endpoint Mapping
|
|
327
|
+
|
|
328
|
+
<Only under `redesign: true`. One row per v1 endpoint and the v2 endpoint that replaces it.>
|
|
329
|
+
|
|
330
|
+
| v1 | v2 | Değişiklik |
|
|
331
|
+
|---|---|---|
|
|
332
|
+
| <METHOD /v1/path> | <METHOD /v2/path> | unchanged / renamed / split / removed |
|
|
333
|
+
|
|
303
334
|
### 5.(N+5) Servis - Fonksiyonel Gereksinim Eşleştirmesi
|
|
304
335
|
|
|
305
336
|
```markdown
|
|
@@ -311,9 +342,9 @@ cells: `Bu servisin sozlesmesi tanimli degil (AS-NN).` Render the table only onc
|
|
|
311
342
|
### 5.(N+6) Gereksinim İzlenebilirlik Matrisi
|
|
312
343
|
|
|
313
344
|
```markdown
|
|
314
|
-
| İş Gereksinimi | Kullanım Senaryosu | Fonksiyonel Gereksinim | Servis |
|
|
315
|
-
|
|
316
|
-
| IG-01 | UC-001 | FG-01, FG-02 | <operation name> |
|
|
345
|
+
| İş Gereksinimi | Kullanım Senaryosu | Fonksiyonel Gereksinim | Servis | Ekran | Test |
|
|
346
|
+
|---|---|---|---|---|---|
|
|
347
|
+
| IG-01 | UC-001 | FG-01, FG-02 | <operation name> | <frame name> | <test row id> |
|
|
317
348
|
```
|
|
318
349
|
|
|
319
350
|
**This matrix is the most expensive thing in the document to get wrong**, because every downstream reader trusts it instead of re-deriving the chain.
|
|
@@ -325,6 +356,8 @@ The rest is the renderer's obligation, checked by reading rather than by a scrip
|
|
|
325
356
|
- every `IG` appears in at least one `UC`, and every `UC` cites at least one `IG`
|
|
326
357
|
- every `FG` names a source `UC` and a source `IG` that exist
|
|
327
358
|
- a struck-through requirement is struck through in all four places it appears
|
|
359
|
+
- `Ekran` names the frame from the use case's `Ekranlar` block; `Test` names the Section 19 row that proves the requirement, or `-` when Part C is not rendered
|
|
360
|
+
- tickets are not a matrix column: `/multi-agent:analysis-jira` writes them to a `## Tickets` table at the end of the document, keyed by the same ids
|
|
328
361
|
|
|
329
362
|
## 6. Donanım ve Altyapı / Hardware and Infrastructure
|
|
330
363
|
|
|
@@ -433,11 +466,13 @@ Never omitted.
|
|
|
433
466
|
## 20. Riskler ve Açık Sorular <!-- TR -->
|
|
434
467
|
## 20. Risks and Open Questions <!-- EN -->
|
|
435
468
|
|
|
436
|
-
| Id | Konu | Neden açık | Kime sorulacak | Etkilediği bölüm |
|
|
437
|
-
|
|
438
|
-
| AS-01 | <question> | <what evidence is missing> | <role or team> | 2.3 |
|
|
469
|
+
| Id | Konu | Neden açık | Kime sorulacak | Etkilediği bölüm | Kategori | Karar |
|
|
470
|
+
|---|---|---|---|---|---|---|
|
|
471
|
+
| AS-01 | <question> | <what evidence is missing> | <role or team> | 2.3, 5.2 | <business / design / service / content / legal> | <empty until answered> |
|
|
439
472
|
```
|
|
440
473
|
|
|
474
|
+
One question, one row: a question that affects several sections is written once and lists every section it affects, rather than repeated per section. `Karar` records the answer once it arrives, and `/multi-agent:analysis-resolve` folds it back into those sections.
|
|
475
|
+
|
|
441
476
|
The source corporate documents keep open questions out of the page and raise them in conversation instead. This profile keeps them in the document deliberately: an `EKLENECEK` with no matching `AS-NN` row here is an unanswered question nobody owns. Every `EKLENECEK` and every unverified assumption in 2.4 emits a row (Locked 32).
|
|
442
477
|
|
|
443
478
|
## 21. Referanslar / References
|
|
@@ -67,7 +67,7 @@ Phase 1 compares `evidence_digest` against an existing document to decide whethe
|
|
|
67
67
|
|
|
68
68
|
## Layer headings (A / B / C)
|
|
69
69
|
|
|
70
|
-
The 23 sections render under three named layers
|
|
70
|
+
The 23 sections render under three named layers, an **additive heading level** that never renumbers: layer headings are `#` (h1), sections stay `##`, and both the validator and `md2confluence-v3.py` read the extra level, which gives the Confluence page a two-level table of contents.
|
|
71
71
|
|
|
72
72
|
| Layer | Sections | What is lost if it is missing |
|
|
73
73
|
|---|---|---|
|
|
@@ -76,7 +76,9 @@ The 23 sections render under three named layers. This is an **additive heading l
|
|
|
76
76
|
| `# Bölüm C - Geliştirme Analizi` / `# Part C - Development Analysis` | 13, 14, 15 | **how** to build it: class name, file path, reuse, test row |
|
|
77
77
|
| (footer, no heading) | 21, 22, 23 | |
|
|
78
78
|
|
|
79
|
-
**Boundary rule.** Which layer a row belongs to is settled by one question: remove it, what becomes unclear? A row that is unclear in two layers at once is two rows. `A carries no technology name; C carries no business rationale.`
|
|
79
|
+
**Boundary rule.** Which layer a row belongs to is settled by one question: remove it, what becomes unclear? A row that is unclear in two layers at once is two rows. `A carries no technology name; C carries no business rationale.` Evidence that must stay in A goes in `<details>`.
|
|
80
|
+
|
|
81
|
+
**Document head**, above Section 1: the missing-inputs panel (if any), then one line of counts, e.g. `At a glance: 6 rules, 3 screens, 4 services, 2 open questions`.
|
|
80
82
|
|
|
81
83
|
A layer whose sections all drop for lack of evidence drops its heading too (Locked 2). Numbering still flows 1..N over the rendered set.
|
|
82
84
|
|
|
@@ -84,7 +86,7 @@ A layer whose sections all drop for lack of evidence drops its heading too (Lock
|
|
|
84
86
|
|
|
85
87
|
## Omission rules
|
|
86
88
|
|
|
87
|
-
Locked 2 - no `TBD` / `Not applicable` placeholder. Sections with zero evidence are omitted entirely.
|
|
89
|
+
Locked 2 - no `TBD` / `Not applicable` placeholder. Sections with zero evidence are omitted entirely. Each rendered section keeps its canonical number, so an omitted section leaves a gap (`1, 2, 4, 9, ...` is correct); section numbers are cited across the document and must not move. The dispatch report logs the omission list.
|
|
88
90
|
|
|
89
91
|
| Section | Omission condition |
|
|
90
92
|
|---|---|
|
|
@@ -472,15 +474,17 @@ Authorization: Bearer <token>
|
|
|
472
474
|
|
|
473
475
|
\`\`\`json
|
|
474
476
|
{
|
|
475
|
-
"field1": "
|
|
476
|
-
"field2":
|
|
477
|
+
"field1": "<string>",
|
|
478
|
+
"field2": "<integer>"
|
|
477
479
|
}
|
|
478
480
|
\`\`\`
|
|
479
481
|
|
|
480
|
-
| Alan / Field | Tip / Type | Zorunlu / Required | Validation |
|
|
481
|
-
|
|
482
|
-
| field1 | string | yes | <rule> |
|
|
483
|
-
| field2 | integer | no | <rule> |
|
|
482
|
+
| Alan / Field | Tip / Type | Zorunlu / Required | Validation | Kaynak / Source |
|
|
483
|
+
|---|---|---|---|---|
|
|
484
|
+
| field1 | string | yes | <rule> | <spec path or page that defines it> |
|
|
485
|
+
| field2 | integer | no | <rule> | <spec path or page that defines it> |
|
|
486
|
+
|
|
487
|
+
Types, never sample values; `Kaynak / Source` names where each field is defined.
|
|
484
488
|
|
|
485
489
|
### 9.3 Response varyantları / Response variants
|
|
486
490
|
|
|
@@ -933,13 +937,16 @@ Never omitted.
|
|
|
933
937
|
## 20. Riskler ve Açık Sorular <!-- TR -->
|
|
934
938
|
## 20. Risks and Open Questions <!-- EN -->
|
|
935
939
|
|
|
936
|
-
| Risk / Soru / Risk / Question | Sahibi / Owner | Durum / Status |
|
|
937
|
-
|
|
938
|
-
| <risk or question> | <name or role> | Açık / Open |
|
|
939
|
-
| <convention fallback applied> | Pass B (auto) | Açık / Open |
|
|
940
|
-
| <existing X candidate found; reuse or document why a new one is needed> | <name> | Açık / Open |
|
|
940
|
+
| ID | Risk / Soru / Risk / Question | Sahibi / Owner | Durum / Status |
|
|
941
|
+
|---|---|---|---|
|
|
942
|
+
| AS-01 | <risk or question> | <name or role> | Açık / Open |
|
|
943
|
+
| AS-02 | <convention fallback applied> | Pass B (auto) | Açık / Open |
|
|
944
|
+
| AS-03 | <existing X candidate found; reuse or document why a new one is needed> | <name> | Açık / Open |
|
|
941
945
|
```
|
|
942
946
|
|
|
947
|
+
Every row carries an `AS-NN` id: a gap marker elsewhere in the document names the row
|
|
948
|
+
it is answered by, and the closure gate pairs them by that id.
|
|
949
|
+
|
|
943
950
|
Auto-populated rows (Locked 11, 23): repo-evidence direct-match candidates that conflict with planned new-write; convention fallbacks where Phase 1c confidence was none.
|
|
944
951
|
|
|
945
952
|
## 21. Referanslar / References
|
|
@@ -288,6 +288,10 @@ argument-hint: "<input hint>"
|
|
|
288
288
|
|
|
289
289
|
**`not-for`** is optional and lists sibling commands this one must not be chosen for, as bare names (`not-for: jira, review-jira`). It is written for the model reading the routing surface, so it belongs beside the description rather than in prose further down. `lint-skills.mjs` also consumes it: a trigger-vocabulary collision either side has named drops off the warning list and is reported as settled instead, and a name that resolves to no sibling on the same surface is an error - a typo would otherwise leave the pair unanswered while the author believes it is handled. Both trees spell the value the same way and the lint reads it from either place; the `multi-agent-` prefix on the Copilot side is stripped before matching.
|
|
290
290
|
|
|
291
|
+
**Command-only keys stay top-level.** `parameters`, `gui`, `destructive`, `confirm` and `description-tr` sit at the top level of a command's frontmatter, not under `metadata:`. Claude Code ignores a key it does not recognize, command files are never packaged for claude.ai or the Skills API (where unknown keys are rejected), and these keys are read by the command contract, the GUI catalog and the installer's localizer, which all parse the top level. A shared skill keeps every key no host reads under `metadata:`, because shared skills are the files that do get packaged.
|
|
292
|
+
|
|
293
|
+
**`disable-model-invocation: true`** marks every command whose `destructive` is true: such a command runs only when the user types it. It is set on the Claude command only; the Copilot mirror does not carry it. Commands that only confirm (`confirm: required` without `destructive`), such as `sync`, stay model-invocable because they are routinely run on request and confirm inside their own flow. `test/command-contract.test.mjs` holds the rule.
|
|
294
|
+
|
|
291
295
|
**Invariant**: the English `description` must have the same meaning on both sides, and a `description-tr` line (when present) must be a faithful translation of it. Semantic drift is not allowed. `description-en` sidecars are an installed-tree artifact and must never appear in repo or Copilot files.
|
|
292
296
|
|
|
293
297
|
---
|
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
- [Identity is a label, not a title](#identity-is-a-label-not-a-title)
|
|
8
8
|
- [The write is ledgered](#the-write-is-ledgered)
|
|
9
9
|
- [An existing node is skipped, never updated](#an-existing-node-is-skipped-never-updated)
|
|
10
|
+
- [The story body is document text, escaped](#the-story-body-is-document-text-escaped)
|
|
11
|
+
- [An existing epic, linked the way the site links](#an-existing-epic-linked-the-way-the-site-links)
|
|
12
|
+
- [Channel clones are opt-in](#channel-clones-are-opt-in)
|
|
13
|
+
- [The document lists its tickets](#the-document-lists-its-tickets)
|
|
10
14
|
- [Every site-specific name is a VALUE, never a schema key](#every-site-specific-name-is-a-value-never-a-schema-key)
|
|
11
15
|
- [Auth](#auth)
|
|
12
16
|
<!-- /toc -->
|
|
@@ -17,16 +21,18 @@ Two files do it, and the split is the design:
|
|
|
17
21
|
| File | Does | Network |
|
|
18
22
|
|---|---|---|
|
|
19
23
|
| `scripts/analysis-story-tree.mjs` | decides WHAT to create, checks coverage, assigns identity | none |
|
|
24
|
+
| `scripts/analysis-story-body.mjs` | builds each story's description from the document | none |
|
|
20
25
|
| `lib/analysis-jira-write.sh` | creates it | yes |
|
|
26
|
+
| `lib/jira-epic-link.sh` | decides which field links a story to its epic | none (the writer passes the site's answers in) |
|
|
27
|
+
| `scripts/analysis-tickets-writeback.mjs` | writes the created keys back into the document | none |
|
|
21
28
|
|
|
22
29
|
Planning is deterministic and testable offline; creating issues is neither. Kept
|
|
23
30
|
apart, the file that can write to a tracker is small enough to read in one
|
|
24
31
|
sitting.
|
|
25
32
|
|
|
26
|
-
`jira-publish.sh`
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
replaces.
|
|
33
|
+
`jira-publish.sh` writes a comment or a description on an issue that already
|
|
34
|
+
exists; creating issues is a different contract, so it is a different file, and
|
|
35
|
+
the only one that creates issues.
|
|
30
36
|
|
|
31
37
|
## The marker gate runs first, before any network call
|
|
32
38
|
|
|
@@ -69,10 +75,9 @@ verdict is `unverifiable`, never `ok`. It appears:
|
|
|
69
75
|
- as a separate fourth approval option, not folded into `Approve`
|
|
70
76
|
- in the writer's own output, and beside every key in the ledger
|
|
71
77
|
|
|
72
|
-
Such a document still plans work, from its user-story sub-sections
|
|
73
|
-
|
|
74
|
-
"nothing to plan"
|
|
75
|
-
code claimed to handle and never could.
|
|
78
|
+
Such a document still plans work, from its user-story sub-sections, so a
|
|
79
|
+
document without atoms gets stories and an honest `unverifiable` verdict rather
|
|
80
|
+
than "nothing to plan".
|
|
76
81
|
|
|
77
82
|
## Identity is a label, not a title
|
|
78
83
|
|
|
@@ -99,8 +104,55 @@ answerable from the tree's own trail.
|
|
|
99
104
|
## An existing node is skipped, never updated
|
|
100
105
|
|
|
101
106
|
Jira has no backup path for fields other than description. Rewriting a body an
|
|
102
|
-
engineer has since edited would
|
|
103
|
-
|
|
107
|
+
engineer has since edited would lose that edit with no way back. A node found by
|
|
108
|
+
its label is recorded in the ledger as `exists`, beside its key.
|
|
109
|
+
|
|
110
|
+
## The story body is document text, escaped
|
|
111
|
+
|
|
112
|
+
`buildStoryBody()` assembles the description from the document alone:
|
|
113
|
+
|
|
114
|
+
| Part | Global profile | Corporate profile |
|
|
115
|
+
|---|---|---|
|
|
116
|
+
| User story | the "As a ..." line of the story's own section; the user-story section only when it holds exactly one | the use case's actor and short description |
|
|
117
|
+
| Acceptance criteria | the G/W/T column of each rule, else the rule | each functional requirement, plus the use case's alternative and exception flows |
|
|
118
|
+
| Current vs target | redesign rows that point at the story's section | the same, from the corporate redesign sub-sections |
|
|
119
|
+
| Links | the analysis page, Figma URLs in the story's sections, Swagger/OpenAPI URLs in References | same |
|
|
120
|
+
|
|
121
|
+
At most 8 criteria. What is missing stays missing and becomes a body warning
|
|
122
|
+
(no user story, fewer than 2 criteria, no negative criterion); nothing is filled
|
|
123
|
+
in. Every piece of document text passes `escapeJiraWiki()` before it is placed
|
|
124
|
+
in wiki markup, and links pass `wikiLink()`, which accepts http and https only,
|
|
125
|
+
so document text cannot become a macro, a mention, an image or a link.
|
|
126
|
+
|
|
127
|
+
## An existing epic, linked the way the site links
|
|
128
|
+
|
|
129
|
+
`--epic KEY` links every story to an epic that already exists; the tree never
|
|
130
|
+
creates one. Cloud links through the `parent` field. Server and Data Center use
|
|
131
|
+
an Epic Link custom field whose id differs per site, so `issueTree.epicLinkMode:
|
|
132
|
+
auto` reads `serverInfo` and discovers the field by its schema type
|
|
133
|
+
(`com.pyxis.greenhopper.jira:gh-epic-link`). No field found means the stories
|
|
134
|
+
are created unlinked, with a warning; a field id is never guessed. `parent`,
|
|
135
|
+
`epicLinkField` (with `epicLinkFieldId`) and `none` force one path. A story that
|
|
136
|
+
already exists is not relinked.
|
|
137
|
+
|
|
138
|
+
## Channel clones are opt-in
|
|
139
|
+
|
|
140
|
+
With `issueTree.cloneByChannel: true` and `channelComponents` filled, each story
|
|
141
|
+
gets one clone per channel: its own label (the story's identity plus
|
|
142
|
+
`ch:<channel>`), the channel's component, and an issue link of
|
|
143
|
+
`cloneLinkType` (default `Relates`) back to the story. Clone labels are part of
|
|
144
|
+
the label search, and a link is checked before it is sent, so a re-run doubles
|
|
145
|
+
neither.
|
|
146
|
+
|
|
147
|
+
## The document lists its tickets
|
|
148
|
+
|
|
149
|
+
After the write, `analysis-tickets-writeback.mjs` puts a `## Tickets` table at
|
|
150
|
+
the end of the local document, between `<!-- tickets:start -->` and
|
|
151
|
+
`<!-- tickets:end -->`: story, key, source ids and channel, keys taken from the
|
|
152
|
+
ledger. It carries no section number, so the canonical numbering is untouched,
|
|
153
|
+
and a re-run replaces the block. An unverifiable tree is titled
|
|
154
|
+
`## Tickets (coverage unverified)`. Publishing the updated document to its
|
|
155
|
+
Confluence page is a separate approval.
|
|
104
156
|
|
|
105
157
|
## Every site-specific name is a VALUE, never a schema key
|
|
106
158
|
|
|
@@ -113,6 +165,8 @@ are values the site fills in:
|
|
|
113
165
|
- `subtaskRoles` ships **empty**. An empty list is an instruction to look at how
|
|
114
166
|
this board actually splits work; a ready-made list would be the guess most
|
|
115
167
|
worth avoiding
|
|
168
|
+
- `epicLinkFieldId`, when set, is the site's own field id; otherwise it is
|
|
169
|
+
discovered
|
|
116
170
|
- `subtaskIssueType: null` means discover it - `createmeta` returns whichever
|
|
117
171
|
type carries `subtask: true`, under whatever name the site gave it. Same rule
|
|
118
172
|
as `features/jira-context.md`: the type travels as it comes from Jira and is
|
|
@@ -126,14 +180,10 @@ setting is visible before the writes rather than in Jira afterwards.
|
|
|
126
180
|
`lib/_jira-auth.sh` holds one host-and-token resolution and one curl idiom: the
|
|
127
181
|
token reaches curl through a `-K` config on process substitution and never
|
|
128
182
|
touches argv, a log, or `ps`. That idiom is the part most easily retyped badly,
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
a rename - `issue-fetcher.sh` resolves per-account token keys that this helper
|
|
135
|
-
does not model yet. So the file is the shared copy going forward, not a
|
|
136
|
-
consolidation that has already happened, and saying otherwise would describe a
|
|
137
|
-
cleanup nobody did. The leak property itself is asserted on all three callers
|
|
183
|
+
so it lives in one file.
|
|
184
|
+
|
|
185
|
+
**Only this writer consumes it.** `jira-publish.sh` and `issue-fetcher.sh`
|
|
186
|
+
carry their own resolution; `issue-fetcher.sh` resolves per-account token keys
|
|
187
|
+
that this helper does not model. The file is the shared copy for new callers. The leak property itself is asserted on all three callers
|
|
138
188
|
independently in `smoke-analysis-jira.sh`, which is the part that must hold
|
|
139
189
|
whether or not they ever share code.
|