@mmerterden/multi-agent-pipeline 20.11.1 → 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 +51 -0
- package/README.md +1 -1
- package/README.tr.md +1 -1
- package/docs/facts.json +2 -2
- package/install/_common.mjs +1 -1
- package/install/_plugin-skills.mjs +13 -9
- package/install/catalog-history.json +1 -1
- package/install/claude.mjs +9 -0
- package/install/codex.mjs +12 -12
- package/manifest.json +74 -67
- package/package.json +5 -5
- package/pipeline/agents/code-reviewer.md +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/model/SKILL.md +7 -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/commands/multi-agent/sync/SKILL.md +5 -6
- package/pipeline/lib/agent-model-sync.mjs +95 -0
- 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/lib/model-rung.sh +7 -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/multi-agent-refs/features/doctor.md +10 -0
- package/pipeline/multi-agent-refs/features/model-fallback.md +10 -0
- package/pipeline/multi-agent-refs/features/phone-api.md +1 -1
- package/pipeline/multi-agent-refs/features/unattended-security.md +2 -2
- package/pipeline/multi-agent-refs/features/usage-reporting.md +13 -0
- 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/doctor.mjs +48 -0
- package/pipeline/scripts/jira-wiki-escape.mjs +40 -0
- package/pipeline/scripts/migrate-prefs.mjs +14 -0
- package/pipeline/scripts/unattended_policy.py +12 -5
- package/pipeline/scripts/usage-report.mjs +84 -9
- 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
|
@@ -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.
|
|
@@ -293,6 +293,16 @@ readiness, not correctness: a machine that fails all four still runs the
|
|
|
293
293
|
pipeline perfectly well with someone watching it. What they catch is the
|
|
294
294
|
failure mode of an unwatched run - stopping without saying so.
|
|
295
295
|
|
|
296
|
+
|
|
297
|
+
### usage-report
|
|
298
|
+
|
|
299
|
+
The outcome `usage-report.mjs` recorded for its last send attempt, read from
|
|
300
|
+
`logs/multi-agent/usage-last-send.json`. SKIP when `usageLog.enabled` is off or
|
|
301
|
+
nothing has been sent yet; OK when the last send was accepted; WARN for every
|
|
302
|
+
other outcome (`redirected`, `rejected`, `not-accepted`, `failed`, `skipped`),
|
|
303
|
+
with the status code or reason and the step that fixes it. The emitter runs
|
|
304
|
+
detached from phase-tracker with its output discarded, so this record is the
|
|
305
|
+
only surface on which a reporting path that stopped working shows up.
|
|
296
306
|
### unattended-contract
|
|
297
307
|
|
|
298
308
|
Is `multi-agent-refs/unattended-contract.md` installed. It is the only place
|
|
@@ -132,6 +132,16 @@ evidence, and there is now one fewer of them. Triage also runs on `opus`, which
|
|
|
132
132
|
makes it the same model as Reviewer 1; the Step 3 anonymisation requirement
|
|
133
133
|
already covers that case and is not optional here.
|
|
134
134
|
|
|
135
|
+
**Installed agents follow the switch.** Five personas declare
|
|
136
|
+
`preferredModel: fable` (code-reviewer, plan-critic, and the iOS, Android and
|
|
137
|
+
backend architects). A dispatch the router resolves passes its model explicitly,
|
|
138
|
+
but an agent spawned without one runs on its frontmatter `model:`. So the
|
|
139
|
+
installed copies are written from `fableEnabled`: `fable` while it is on, `opus`
|
|
140
|
+
while it is off. `model-rung.sh` re-applies them on every flip and the installer
|
|
141
|
+
on every install; sources keep `model: fable`, so `lint-personas.mjs` still holds
|
|
142
|
+
`model === preferredModel` there. A `--symlink` install links the source tree and
|
|
143
|
+
is left alone.
|
|
144
|
+
|
|
135
145
|
**Commands without Phase 0 resolve it themselves.** `/multi-agent:review`,
|
|
136
146
|
`/multi-agent:review-analysis` and the untracked-branch tail of
|
|
137
147
|
`/multi-agent:resume` dispatch reviewers and triage without a Phase 0 Step 0, so
|
|
@@ -303,4 +303,4 @@ Scripts: `contract-server.mjs` (phone branch, `isPhonePath`), `_phone-auth.mjs`
|
|
|
303
303
|
`unattended-policy.json` (`publisherScripts`). Tests:
|
|
304
304
|
`test/phone-api.test.mjs`, `test/contract-server.test.mjs`,
|
|
305
305
|
`test/launch-request.test.mjs`, `test/redact.test.mjs`,
|
|
306
|
-
`test/contract-kit.test.mjs`, `test/unattended-guard.
|
|
306
|
+
`test/contract-kit.test.mjs`, `test/unattended-guard.serial.mjs`.
|
|
@@ -35,7 +35,7 @@ the variable the same way.
|
|
|
35
35
|
|
|
36
36
|
With the variable unset every hook behaves as it did without this feature:
|
|
37
37
|
`smoke-unattended-redteam.sh` runs the same inputs both ways, and
|
|
38
|
-
`test/unattended-guard.
|
|
38
|
+
`test/unattended-guard.serial.mjs` holds the attended verdicts.
|
|
39
39
|
|
|
40
40
|
## The guard
|
|
41
41
|
|
|
@@ -722,7 +722,7 @@ Scripts: `agent-guard.sh`, `agent-guard.py`, `unattended_policy.py`,
|
|
|
722
722
|
`lib/outbound-gate.mjs`, `lib/unattended-settings-location.mjs`,
|
|
723
723
|
`install/_unattended-profile.mjs`. Data:
|
|
724
724
|
`schemas/unattended-policy.json`, `schemas/unattended-profile.json`,
|
|
725
|
-
`schemas/pr-request.schema.json`. Tests: `test/unattended-guard.
|
|
725
|
+
`schemas/pr-request.schema.json`. Tests: `test/unattended-guard.serial.mjs`,
|
|
726
726
|
`test/pr-request.test.mjs`, `test/autopilot-publish.test.mjs`,
|
|
727
727
|
the runner's tests, `test/outbound-gate.test.mjs`,
|
|
728
728
|
`test/unattended-profile.test.mjs`, `test/agent-guard.test.mjs`; smokes
|
|
@@ -147,6 +147,19 @@ reason, `unavailable` with the cause, `declined`, `registered`, `enabled`, `dry-
|
|
|
147
147
|
"you turned it off" and "we could not reach the endpoint" are different facts
|
|
148
148
|
about the same empty panel.
|
|
149
149
|
|
|
150
|
+
Every send attempt past the on-switch overwrites
|
|
151
|
+
`~/.claude/logs/multi-agent/usage-last-send.json` with its outcome: `accepted`,
|
|
152
|
+
`not-accepted` (the server answered but did not keep the record), `rejected`
|
|
153
|
+
(with the status code), `redirected` (with the host it pointed to; a redirect is
|
|
154
|
+
never followed, because the token would ride along), `failed` (network or
|
|
155
|
+
timeout), or `skipped` (`no-token`, `no-login`, `endpoint-not-allowed`). It
|
|
156
|
+
carries the run id, the event and the endpoint host, never the token. The
|
|
157
|
+
phase-tracker ping discards the emitter's output, so `/multi-agent:doctor`
|
|
158
|
+
reads this file (check `usage-report`) and turns anything but `accepted` into a
|
|
159
|
+
WARN with one step. `migrate-prefs.mjs` rewrites an endpoint on the platform
|
|
160
|
+
host to the site's domain, so a stored redirecting endpoint does not outlive an
|
|
161
|
+
update.
|
|
162
|
+
|
|
150
163
|
`prefs.global.usageLog.endpoint` overrides where both calls go - the register URL
|
|
151
164
|
is derived from it, so a self-hosted ingest gets its own registration rather than
|
|
152
165
|
this one's. Absent means the shipped default, and every shipped default names the
|
|
@@ -57,6 +57,28 @@
|
|
|
57
57
|
"default": "global",
|
|
58
58
|
"description": "Analysis profile chosen at Phase 0 Step 1b (Locked 31). 'global' renders analysis-template.md (23-section development handoff); 'corporate' renders analysis-template-corporate.md (IG/UC/FG requirements document). Both read the same evidence; only the projection differs."
|
|
59
59
|
},
|
|
60
|
+
"edgeCandidates": {
|
|
61
|
+
"type": "array",
|
|
62
|
+
"description": "Failure paths proposed from the evidence (refusals, error codes, timeouts, empty or expired states), shown at the Pass B preview. Only accepted ones enter the document; a candidate needs a source.",
|
|
63
|
+
"items": {
|
|
64
|
+
"type": "object",
|
|
65
|
+
"additionalProperties": false,
|
|
66
|
+
"required": ["target", "candidate", "source"],
|
|
67
|
+
"properties": {
|
|
68
|
+
"target": {
|
|
69
|
+
"type": "string",
|
|
70
|
+
"description": "Use case or rule group the candidate belongs to, e.g. UC-001 or BR-login."
|
|
71
|
+
},
|
|
72
|
+
"candidate": { "type": "string", "minLength": 1 },
|
|
73
|
+
"source": {
|
|
74
|
+
"type": "string",
|
|
75
|
+
"minLength": 1,
|
|
76
|
+
"description": "Where the evidence states it: a spec path, a page, a file:line."
|
|
77
|
+
},
|
|
78
|
+
"accepted": { "type": "boolean" }
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
},
|
|
60
82
|
"options": {
|
|
61
83
|
"type": "object",
|
|
62
84
|
"additionalProperties": false,
|
|
@@ -948,7 +948,7 @@
|
|
|
948
948
|
},
|
|
949
949
|
"titleFormat": {
|
|
950
950
|
"type": "string",
|
|
951
|
-
"description": "Page-title pattern, e.g. \"{prefix}{module}_{flow}_{suffix}\". Placeholders are resolved at emit time."
|
|
951
|
+
"description": "Page-title pattern, e.g. \"{status}{prefix}{module}_{flow}_{suffix}\". Placeholders are resolved at emit time; {status} is the draft marker while the document is not final, and empty once it is. Without {status} the marker is prepended."
|
|
952
952
|
},
|
|
953
953
|
"titlePrefix": {
|
|
954
954
|
"type": "string",
|
|
@@ -2107,6 +2107,27 @@
|
|
|
2107
2107
|
"type": "string",
|
|
2108
2108
|
"default": "ma-analysis",
|
|
2109
2109
|
"description": "Prefix of the identity label a created issue carries. The label is how a second run, on a second machine or by a second analyst, finds the tree it already made instead of opening a duplicate."
|
|
2110
|
+
},
|
|
2111
|
+
"epicLinkMode": {
|
|
2112
|
+
"type": "string",
|
|
2113
|
+
"enum": ["auto", "parent", "epicLinkField", "none"],
|
|
2114
|
+
"default": "auto",
|
|
2115
|
+
"description": "How a story joins an existing epic. auto: parent on Cloud, the epic-link field (found by its schema type) on Server and Data Center, nothing when neither exists."
|
|
2116
|
+
},
|
|
2117
|
+
"epicLinkFieldId": {
|
|
2118
|
+
"type": ["string", "null"],
|
|
2119
|
+
"default": null,
|
|
2120
|
+
"description": "The epic-link custom field id, for epicLinkField mode or to skip discovery. Null means discover."
|
|
2121
|
+
},
|
|
2122
|
+
"cloneByChannel": {
|
|
2123
|
+
"type": "boolean",
|
|
2124
|
+
"default": false,
|
|
2125
|
+
"description": "Create one linked story per channel in channelComponents, each carrying that channel's component."
|
|
2126
|
+
},
|
|
2127
|
+
"cloneLinkType": {
|
|
2128
|
+
"type": "string",
|
|
2129
|
+
"default": "Relates",
|
|
2130
|
+
"description": "The link type between a story and its channel clones, by this site's name."
|
|
2110
2131
|
}
|
|
2111
2132
|
}
|
|
2112
2133
|
},
|