@mmerterden/multi-agent-pipeline 20.33.0 → 20.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/README.md +2 -1
  3. package/README.tr.md +2 -1
  4. package/docs/adr/0018-cross-repo-links-not-a-global-graph.md +43 -0
  5. package/docs/adr/README.md +2 -1
  6. package/docs/facts.json +5 -4
  7. package/docs/features.md +1 -1
  8. package/install/_dev-only-files.mjs +1 -0
  9. package/install/catalog-history.json +1 -1
  10. package/install/claude.mjs +9 -2
  11. package/install/templates/claude-hooks.json +12 -1
  12. package/manifest.json +98 -75
  13. package/package.json +3 -1
  14. package/pipeline/agents/code-reviewer.md +9 -0
  15. package/pipeline/agents/explorer.md +4 -0
  16. package/pipeline/agents/plan-critic.md +4 -2
  17. package/pipeline/commands/multi-agent/SKILL.md +17 -136
  18. package/pipeline/commands/multi-agent/channels/SKILL.md +15 -297
  19. package/pipeline/commands/multi-agent/graph/SKILL.md +5 -2
  20. package/pipeline/commands/multi-agent/language/SKILL.md +3 -3
  21. package/pipeline/commands/multi-agent/resume/SKILL.md +8 -22
  22. package/pipeline/commands/multi-agent/review/SKILL.md +7 -131
  23. package/pipeline/commands/multi-agent/setup/SKILL.md +19 -224
  24. package/pipeline/contract/README.md +5 -2
  25. package/pipeline/multi-agent-refs/channels/generator.md +146 -0
  26. package/pipeline/multi-agent-refs/channels/menu.md +55 -0
  27. package/pipeline/multi-agent-refs/channels/multi-repo.md +6 -0
  28. package/pipeline/multi-agent-refs/channels/preview.md +25 -0
  29. package/pipeline/multi-agent-refs/channels/reference.md +98 -0
  30. package/pipeline/multi-agent-refs/features/autopilot-circuit-breaker.md +1 -1
  31. package/pipeline/multi-agent-refs/features/code-graph.md +27 -0
  32. package/pipeline/multi-agent-refs/features/office-threat-model.md +1 -1
  33. package/pipeline/multi-agent-refs/features/plan-critic.md +5 -2
  34. package/pipeline/multi-agent-refs/features/review-delta.md +4 -1
  35. package/pipeline/multi-agent-refs/features/scope-check.md +10 -1
  36. package/pipeline/multi-agent-refs/knowledge.md +9 -0
  37. package/pipeline/multi-agent-refs/orchestrator/dispatcher.md +163 -0
  38. package/pipeline/multi-agent-refs/phases/phase-1-plan.md +4 -4
  39. package/pipeline/multi-agent-refs/phases/phase-2-dev.md +9 -8
  40. package/pipeline/multi-agent-refs/phases/phase-3-review.md +12 -7
  41. package/pipeline/multi-agent-refs/phases/phase-4-commit.md +7 -3
  42. package/pipeline/multi-agent-refs/phases/phase-5-report.md +6 -3
  43. package/pipeline/multi-agent-refs/picker-contract.md +1 -1
  44. package/pipeline/multi-agent-refs/resume/details.md +35 -0
  45. package/pipeline/multi-agent-refs/review/inputs.md +87 -0
  46. package/pipeline/multi-agent-refs/review/module-guides.md +25 -0
  47. package/pipeline/multi-agent-refs/review/valven.md +42 -0
  48. package/pipeline/multi-agent-refs/setup/accounts.md +27 -0
  49. package/pipeline/multi-agent-refs/setup/app-store-connect.md +5 -0
  50. package/pipeline/multi-agent-refs/setup/firebase.md +5 -0
  51. package/pipeline/multi-agent-refs/setup/google-play.md +4 -0
  52. package/pipeline/multi-agent-refs/setup/hooks-and-plugins.md +21 -0
  53. package/pipeline/multi-agent-refs/setup/language.md +46 -0
  54. package/pipeline/multi-agent-refs/setup/multi-repo-group.md +51 -0
  55. package/pipeline/multi-agent-refs/setup/summaries.md +63 -0
  56. package/pipeline/multi-agent-refs/setup/token-save-flow.md +51 -0
  57. package/pipeline/office/index.html +12 -7
  58. package/pipeline/office/toolkit.json +1 -1
  59. package/pipeline/rules/response-shape.md +6 -7
  60. package/pipeline/schemas/agent-state.schema.json +18 -0
  61. package/pipeline/schemas/phases.json +4 -4
  62. package/pipeline/schemas/plan-critique.schema.json +9 -2
  63. package/pipeline/schemas/planning-output.schema.json +25 -2
  64. package/pipeline/schemas/prefs.schema.json +24 -1
  65. package/pipeline/schemas/reviewer-output.schema.json +20 -2
  66. package/pipeline/schemas/token-budget.json +4 -4
  67. package/pipeline/schemas/triage-output.schema.json +20 -2
  68. package/pipeline/scripts/_graph-analysis.mjs +270 -0
  69. package/pipeline/scripts/_memory-policy.mjs +165 -0
  70. package/pipeline/scripts/_secret-scan.mjs +105 -0
  71. package/pipeline/scripts/_unified-diff.mjs +2 -2
  72. package/pipeline/scripts/capture-flush.sh +12 -2
  73. package/pipeline/scripts/check-read-size.sh +9 -0
  74. package/pipeline/scripts/code-graph-rules/android.json +8 -3
  75. package/pipeline/scripts/contract-server.mjs +36 -15
  76. package/pipeline/scripts/debt-ledger.mjs +323 -0
  77. package/pipeline/scripts/file-context.mjs +261 -0
  78. package/pipeline/scripts/file-context.sh +20 -0
  79. package/pipeline/scripts/graph-links.mjs +230 -0
  80. package/pipeline/scripts/graph-query.mjs +133 -1
  81. package/pipeline/scripts/graph-report.mjs +65 -0
  82. package/pipeline/scripts/learn-from-transcripts.mjs +12 -48
  83. package/pipeline/scripts/learnings-ledger.mjs +143 -24
  84. package/pipeline/scripts/plan-critique-gate.mjs +11 -2
  85. package/pipeline/scripts/rework-rulings.mjs +106 -0
  86. package/pipeline/scripts/scope-check-gate.mjs +149 -2
  87. package/pipeline/scripts/triage-memory.mjs +64 -37
  88. package/pipeline/scripts/validate-planning.mjs +68 -4
  89. package/pipeline/scripts/validate-reviewer.mjs +20 -0
  90. package/pipeline/scripts/validate-triage.mjs +107 -2
  91. package/pipeline/skills/.skill-manifest.json +5 -5
  92. package/pipeline/skills/shared/core/multi-agent-graph/SKILL.md +5 -2
  93. package/pipeline/skills/shared/core/multi-agent-language/SKILL.md +4 -4
  94. package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +2 -0
  95. package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +4 -4
@@ -0,0 +1,146 @@
1
+ # Channels - Generator (Step 5 section bodies)
2
+
3
+ > Loaded by `channels/SKILL.md` Step 5. The SKILL keeps the Jira-vs-PR body rule, the section-order rule and the target length rule; this file carries the content-option table, the aggregated output template, the store-compliance augmentation, and the work-summary and cost-summary generators. Read it before generating any section body.
4
+
5
+ ## Content options
6
+
7
+ | Content option | Generated section |
8
+ |---|---|
9
+ | Normal analiz | `### Analysis` - impact summary from Phase 1, risks from Phase 4 (pipeline-log source, high-level only) |
10
+ | Teknik analiz | `### Technical Details` - Changes (what/why per file group), Architecture (structural decisions, pattern changes), Dependencies (new imports/frameworks/packages). Source: Phase 1 planning + Phase 2 dev log + `git diff --stat`. **PR and Confluence only** - never rendered into a Jira comment. |
11
+ | Test senaryoları | `### Test Scenarios` - precondition / steps / expected table (4-8 rows), user perspective |
12
+ | Test Koşumu (Xray) | `### Test Koşumu` - Xray Test Execution of the task's UI scenario run (`channels/test-run.md`) |
13
+ | Auto-diff | Old enrich Output Template verbatim - Root Cause / Solution / Changed Files / Test Scenarios |
14
+ | Manuel not | `### Notes` - user-provided paragraph, or LLM-split into subsections if `--message` is plain text and long |
15
+ | Cost özeti | `### Cost Summary` - per-phase token tally + est. USD table. Source: `phase-tracker.sh` phase status + optional OTel spans. See "Cost summary generation" below. |
16
+ | Yapılan iş özeti | `### Work Summary` - executive one-screen summary: task + branch + base + PR, scope delivered (done/[pending] per Phase 2 task), changed files with +/- counts (capped at 20 rows), review outcome (accepted/deferred/rejected + approved), phase tick strip. Source: `agent-state.json` + `phase-tracker.json` + `git diff --numstat base...HEAD`. See "Work summary generation" below. |
17
+
18
+ ## Output template
19
+
20
+ **Output template (aggregated across selected content options):**
21
+
22
+ ```markdown
23
+ ### Analysis ← if "Normal analiz" selected
24
+ {impact summary, risks - from pipeline log, high-level}
25
+
26
+ ### Technical Details ← if "Teknik analiz" selected
27
+ #### Changes
28
+ {Per changed-file-group, what changed + why - from Phase 2 dev log}
29
+ #### Architecture
30
+ {Structural decisions, pattern changes, new file layouts - from Phase 1 plan}
31
+ #### Dependencies
32
+ {New imports / frameworks / packages - from git diff --stat, or "None"}
33
+
34
+ ### Root Cause ← if "Auto-diff" selected
35
+ {single paragraph - from diff}
36
+
37
+ - `path/to/File.ext → funcName`: {why it broke}
38
+
39
+ ### Solution ← if "Auto-diff" selected
40
+ - `path/to/File.ext:LINE-LINE` - {change, one line}
41
+
42
+ ### Changed Files ← if "Auto-diff" selected
43
+ | File | +/- |
44
+ |------|-----|
45
+ | `path/to/File.ext` | +N / -M |
46
+
47
+ ### Test Scenarios ← if "Test senaryoları" OR "Auto-diff" selected
48
+ **1. {what this scenario exercises}**
49
+ 1. {step the tester performs}
50
+ 2. **Expected:** {what they should see}
51
+
52
+ **2. {regression scenario}**
53
+ 1. {step}
54
+ 2. **Expected:** {what should still behave as before}
55
+
56
+ ### Test Koşumu ← if "Test Koşumu (Xray)" selected
57
+
58
+ ### Notes ← if "Manuel not" selected
59
+ {user message}
60
+
61
+ ### Work Summary ← if "Yapılan iş özeti" selected
62
+ {executive scope + files + review + phases block - see "Work summary generation" below}
63
+
64
+ ### Cost Summary ← if "Cost özeti" selected
65
+ {per-phase token + USD table - see "Cost summary generation" below}
66
+
67
+ ### Store compliance ← auto-appended if cached compliance report exists
68
+ {summary line - see below}
69
+
70
+ Ref: {jiraId}
71
+ ```
72
+
73
+ **Store compliance auto-augmentation:**
74
+
75
+ After the content-selected sections are generated, check for a recent compliance report cached from `/multi-agent:test "store-ready"`:
76
+
77
+ ```bash
78
+ # Cache locations (newest wins; expire after 6h to avoid stale cross-branch reports)
79
+ find /tmp -maxdepth 1 -name 'archiveguard-*.json' -o -name 'play-compliance-*.json' \
80
+ -newermt "-6 hours" -print 2>/dev/null | head -1
81
+ ```
82
+
83
+ If a cached report exists AND any of the selected channels is PR / Jira / Confluence, append an auto-summary section:
84
+
85
+ | Blocker count | Appended line |
86
+ |---|---|
87
+ | `errors > 0` | `### Store compliance` + `{N} blocker(s), {M} warning(s) - run /multi-agent:test "store-ready" for the full report.` - per-blocker: `- \`{ruleID}\` - {Apple ITMS / Play ref}: {message}` (capped at 5 rows, rest collapsed to `+N more`) |
88
+ | `errors == 0, warnings > 0` | `### Store compliance` + `[done] No blockers. {M} warning(s) - see /multi-agent:test "store-ready" for detail.` |
89
+ | `errors == 0, warnings == 0` | Skip section entirely - don't pollute PR body |
90
+
91
+ The section references `ruleID` + policy ref from the compliance skill catalogs (`apple-archive-compliance` / `google-play-compliance`) verbatim. No translation - global identifiers stay as-is.
92
+
93
+ If no cached report exists, skip silently - this is augmentation, not a gate.
94
+
95
+ **Work summary generation:**
96
+
97
+ Emitted only when `reportContent.workSummary === true` and at least one of (`agent-state.json`, `--branch` flag) is available. The shell adapter is `$HOME/.claude/scripts/render-work-summary.sh <taskId>`, and that script's own header is the spec for what it emits - task header, scope delivered, changed files, review outcome, phase strip - including the caps and the hidden-when-empty rules. Exit 2 means the state was unreadable: skip the section, do not substitute a hand-written one.
98
+
99
+ **Output template:**
100
+
101
+ ```markdown
102
+ ### Work Summary
103
+ **Task**: `PROJ-1099` | **Branch**: `bugfix/PROJ-1099-dark-mode` | **Base**: `develop` | **PR**: #104
104
+
105
+ #### Scope delivered
106
+ - [done] T1 Add failing dark-mode snapshot test
107
+ - [done] T2 Replace Color.white with design token
108
+
109
+ #### Changed files (3 files · +48 / -12)
110
+ - `Sources/Auth/LoginView.swift` (+24 / -8)
111
+ - `Sources/Auth/LoginViewTests.swift` (+22 / -4)
112
+ - `Sources/DesignSystem/Color+Tokens.swift` (+2 / -0)
113
+
114
+ #### Review outcome
115
+ - 1 accepted · 0 deferred · 0 rejected · approved=true
116
+
117
+ #### Phases
118
+ - 0 Init [done] · 1 Plan [done] · 2 Dev [done] · 3 Review [done] · 4 Commit [done] · 5 Report active
119
+ ```
120
+
121
+ **Post-hoc invocation** (task already finished, agent-state.json may be archived): pass `--branch` + `--base-branch` explicitly - the script still emits task header + changed-files + phases sections (scope + review outcome are state-dependent and will be absent if state is gone).
122
+
123
+ **Cost summary generation:**
124
+
125
+ Emitted only when `reportContent.costSummary === true` and tracker data is available. Source of truth is `phase-tracker.sh`:
126
+
127
+ 1. **Token tallies per phase** - `render-cost-summary.sh <taskId>` resolves the tracker JSON itself: worktree candidates (`.worktrees/{taskPath}/phase-tracker.json`) first, then the standard location `$HOME/.claude/logs/multi-agent/{taskId}/tracker-state.json` that `phase-tracker.sh` actually writes. Each phase row carries `{tokens_in, tokens_out}`.
128
+ 2. **Fallback to OTel spans** - if tracker JSON has no token columns but `otel-spans.jsonl` exists (set `MULTI_AGENT_OTEL_SPANS=1` beforehand), aggregate `phase.tokens` spans by phase ID.
129
+ 3. **USD estimate** - uses a static price table in `$HOME/.claude/scripts/cost-table.json` (model → $/Mtok_in, $/Mtok_out). Missing model → show ` - ` for USD, never block.
130
+
131
+ **Output template:**
132
+
133
+ ```markdown
134
+ ### Cost Summary
135
+ | Phase | Model | Tokens in | Tokens out | Est. USD |
136
+ |-------|-------|-----------|------------|----------|
137
+ | 1. Analysis | opus | 12,480 | 3,210 | $0.42 |
138
+ | 2. Planning | opus | 18,904 | 5,120 | $0.66 |
139
+ | 3. Dev | sonnet | 42,310 | 9,880 | $0.27 |
140
+ | 4. Review | opus | 21,050 | 4,720 | $0.66 |
141
+ | **Total** | | **94,744** | **22,930** | **$2.04** |
142
+ ```
143
+
144
+ Generated by `$HOME/.claude/scripts/render-cost-summary.sh <task-id>` using prices from `$HOME/.claude/scripts/cost-table.json`. The channels adapter shells out to this renderer - doc table is illustrative only, runtime is authoritative.
145
+
146
+ **Precision rules:** tokens as thousand-separated integers. USD rounded to 2 dp (`printf '$%.2f'`). Rows with zero tokens dropped. If total USD is ` - ` (no price for any model), replace the total row USD cell with ` - ` and add a one-line footnote: `*USD unavailable - add model to cost-table.json*`.
@@ -0,0 +1,55 @@
1
+ # Channels - Menu (Step 2 sources, Step 3a preview, Step 3b picker rules)
2
+
3
+ > Loaded by `channels/SKILL.md` Step 2. The SKILL keeps the step order and the autopilot rule; this file carries the context-source table, the summary-first preview logic, the greyed-out rules and the first-run defaults. Read it before Step 2.
4
+
5
+ ## Step 2 - Context sources
6
+
7
+ Automatic. The generator picks the best-available source:
8
+
9
+ | Source | Available when | Used for |
10
+ |---|---|---|
11
+ | **Pipeline log** | `$HOME/.claude/logs/multi-agent/<project>/<task-id>/agent-log.md` exists AND matches `jiraId` | "Normal analiz" + "Test senaryoları" content options - uses Phase 1/2/4 output verbatim |
12
+ | **PR diff** | PR exists, diff fetchable (`gh pr diff` or Bitbucket `/diff?contextLines=5`) | "Auto-diff summary" content option - old enrich behavior |
13
+ | **Manual message** | `--message` / `--message-file` provided | Replaces both sources - user text is canonical |
14
+
15
+ ## Step 3a - Work Summary preview (summary-first flow)
16
+
17
+ **Runs only when** (a) `agent-state.json` exists for the task AND (b) a Work Summary can be generated (same availability rule as the "Yapılan iş özeti" content row). Purpose: give the user an instant "what did this ship?" answer BEFORE they pick channels. They see the outcome first, then decide where to route it - instead of the reverse.
18
+
19
+ ```bash
20
+ preview=$(bash $HOME/.claude/scripts/render-work-summary.sh "$TASK_ID" 2>/dev/null || true)
21
+ [ -n "$preview" ] && {
22
+ printf '%s\n\n' "$preview"
23
+ # Auto-tick workSummary content row when preview was shown.
24
+ # Users can still untick it in 3b if they don't want to re-send the same
25
+ # block to remote channels (useful when preview was enough for a look).
26
+ content_defaults.workSummary=true
27
+ }
28
+ ```
29
+
30
+ When the preview renders:
31
+ - **workSummary** row in 3b is **auto-ticked** (user can still uncheck).
32
+ - Previous `prefs.global.reportContent.workSummary` value is respected - if the user had explicitly unticked in a prior run, the auto-tick is **suppressed** and the ticked state matches the pref.
33
+
34
+ When the preview does NOT render (no state, or pref explicitly off at global level with no override):
35
+ - Skip 3a silently, go straight to the channels picker. The workSummary row in 3b stays at its pref default (`false`).
36
+
37
+ After the preview prints, 3b renders the two pickers: **Channels** (PR description, Jira comment, Confluence page, Wiki, Board; each unavailable one greyed with its reason) and **Content** (normal analysis, technical analysis, test scenarios, test run, PR auto-diff, manual note, cost summary, work summary).
38
+
39
+ **Why auto-tick:** the user just saw the summary and is most likely sending it; the explicit pref still wins.
40
+
41
+ ## Step 3b - Channel + content picker
42
+
43
+ **Greyed-out rules:**
44
+ - "Wiki" unselectable unless `state.taskType === "component"` AND `figmaConfig.wiki.enabled === true`. If greyed, show reason: `"(no figma-config or taskType != component)"`.
45
+ - "Board" unselectable unless `figmaConfig.board.enabled === true` AND `figmaConfig.board.provider === "github-projects-v2"` AND `figmaConfig.github.projectV2Id` set. If greyed, show reason: `"(no figma-config.board or projectV2Id missing)"`. Default target column: `inReview`.
46
+ - "Normal analiz" + "Test senaryoları" unselectable if no pipeline log found. Reason: `"(no pipeline log for PROJ-12345)"`.
47
+ - "Teknik analiz" unselectable if no Phase 1 planning log AND no PR diff available. Reason: `"(no technical source - need Phase 1 plan or PR diff)"`.
48
+ - "Auto-diff" unselectable if no PR found. Reason: `"(no PR linked to this target)"`.
49
+ - "Manuel not" always available. "Test Koşumu (Xray)": `channels/test-run.md`.
50
+ - "Cost özeti" unselectable if `phase-tracker.sh cost total` prints `-` (no priced token tallies; there is no `status` action) AND no `otel-spans.jsonl` exists for the task. Reason: `"(no tracker data - set MULTI_AGENT_OTEL_SPANS=1 or enable token tracking)"`.
51
+ - "Yapılan iş özeti" unselectable if no `agent-state.json` exists for the task (post-hoc call with `--branch` + `--base-branch` flags restores partial availability). Reason: `"(no agent-state.json for {taskId})"`. **Auto-ticked** when Step 3a preview was shown - user can still uncheck before confirming the menu.
52
+
53
+ **Defaults (first run):** PR + Jira ticked, Confluence + Wiki unticked. Content: auto-diff if pipeline log missing; otherwise normal-analiz + test-senaryoları.
54
+
55
+ Saved to `prefs.global.reportChannels` and `prefs.global.reportContent` - next run uses these as defaults.
@@ -13,3 +13,9 @@
13
13
  **Target enumeration:** `channels-multi-repo.sh targets <state>` returns a JSON array `[{repoName, prUrl, prNumber, isPrimary, crossLinks}]` for the dispatch loop. Single-repo tasks return one entry with empty `crossLinks` - every render-* call falls through to the body unchanged, so the loop is uniform across single-repo and multi-repo paths.
14
14
 
15
15
  **Logging hint:** `channels-multi-repo.sh summary <state>` produces a one-line autopilot log entry (`1 primary (foo) + 2 extras: <url> <url>` or `single-repo task`).
16
+
17
+ ## Target resolution (Step 1)
18
+
19
+ **Multi-repo:** when `agent-state.json` `projects[].length > 1`, Step 1 builds **one target per project**. Each project's PR is resolved via `pr` field in its projects[] entry; if missing, the Jira/Issue link query returns multiple PRs (one per repo) - all are added to `targets[]`. The project at `projects[0]` (or whose name matches `state.project`) is marked `isPrimary: true`; others are `isPrimary: false`.
20
+
21
+ For single-repo tasks, `targets` has exactly one entry. The rest of the flow is target-aware: Step 5 generates one body, Step 7 dispatches to each target, with cross-links (see the dispatch table above).
@@ -0,0 +1,25 @@
1
+ # Channels - Preview render (Step 6)
2
+
3
+ > Loaded by `channels/SKILL.md` Step 6. The SKILL keeps the approval gate, its skip cases, its options and the byte-identical rule; this file carries the per-channel markup conversion, the preview block layout and the secondary-artifact intents. Read it before rendering the Step 6 preview.
4
+
5
+ Conversion is per-channel; two channels have none:
6
+
7
+ | Channel | Conversion after approval | Table |
8
+ |---|---|---|
9
+ | PR description | **none** - posted as Markdown, verbatim | GitHub / Bitbucket / GitLab all render Markdown; see `channels/pr.md` "Markup dialect" |
10
+ | GitHub issue comment | **none** - posted as Markdown, verbatim | - |
11
+ | Jira comment | markdown → Jira wiki markup | `channels/jira.md` "Wiki markup conversion" |
12
+ | Confluence page | markdown → storage format | `channels/confluence.md` "Body conversion" |
13
+
14
+ The Jira table is the only *text* markup table in the doc set and never applies to the PR body: `h2.`, `{{code}}` or `#`-numbered lists render there as raw wiki markup.
15
+
16
+ ```
17
+ ── PR description ({repoName} #{prNumber}, replace) ─────────
18
+ {body}
19
+ ── Jira comment ({jiraId}) ──────────────────────────────────
20
+ {body}
21
+ ── Confluence page ("{title}" under {parentUrl}) ────────────
22
+ {body}
23
+ ```
24
+
25
+ Secondary artifacts ride along as one-line intents at the bottom of the preview: Wiki page list, wiki → Jira triad comment (when Wiki is selected and the triad is active per `$HOME/.claude/multi-agent-refs/issue-jira-triad.md`), Board status move (`{from} → {to}`), GitHub issue comment + Progress-flag sync (Phase 5 Step 1.5 - same gate, see `$HOME/.claude/multi-agent-refs/phases/phase-5-report.md`), test-run candidates to untick (`channels/test-run.md`), the Jira body's `--measure` (`render-jira-evidence.mjs`).
@@ -0,0 +1,98 @@
1
+ # Channels - Input forms, flags, summary format, error handling, cross-CLI parity, examples
2
+
3
+ > Loaded by `channels/SKILL.md`. Read the flag table and the error-handling table before Step 1 and whenever a target, a token or a precondition fails; the parity notes and examples are for orientation.
4
+
5
+ ## Input forms
6
+
7
+ ```
8
+ /multi-agent:channels # cwd + current branch
9
+ /multi-agent:channels PROJ-12345 # Jira ID
10
+ /multi-agent:channels #42 # GitHub issue/PR number
11
+ /multi-agent:channels https://github.com/<org>/<repo>/pull/N
12
+ /multi-agent:channels https://<bitbucket-host>/projects/.../pull-requests/N
13
+ /multi-agent:channels https://<jira-host>/browse/PROJ-12345
14
+
15
+ /multi-agent:channels PROJ-12345 --channels jira,confluence # non-interactive channel
16
+ /multi-agent:channels PROJ-12345 --content auto-diff # non-interactive content
17
+ /multi-agent:channels PROJ-12345 --message "root: ..." # manual source
18
+ /multi-agent:channels PROJ-12345 --message-file notes.md # manual, long
19
+ /multi-agent:channels PROJ-12345 --dry-run # preview, no POST
20
+ ```
21
+
22
+ ## Flags
23
+
24
+ | Flag | Effect |
25
+ |------|--------|
26
+ | `--channels pr,jira,confluence,wiki` | Non-interactive channel selection (comma list). Skips channel menu. |
27
+ | `--content normal,technical,test,auto-diff,note,test-run` | Non-interactive content selection. Skips content menu. |
28
+ | `--flow-run <runId>[,<runId>...]` | Runs for the test run block (`channels/test-run.md`). |
29
+ | `--message "..."` | Manual mode - use user text as source, no diff read. Forces `content=note`. |
30
+ | `--message-file path` | Manual mode, long message from file. |
31
+ | `--append` | PR description: append instead of replace. |
32
+ | `--dry-run` | Generate, print to stdout, do not POST. |
33
+ | `--lang=tr\|en\|both` | Output language override (default: `en`; `promptLanguage` is locked to `en`). |
34
+ | `--ready` | If PR draft, promote to READY after channels dispatch. |
35
+
36
+ ## Step 8 summary format
37
+
38
+ ```
39
+ channels dispatch complete
40
+ PR description ✓ version 3→4, reviewers 23 preserved
41
+ Jira comment ✓ posted → <jira-url>?focusedCommentId=2484780
42
+ Confluence - skipped: user declined
43
+ Wiki ✓ 3 files via github-wiki adapter
44
+ Board ✓ In Develop → In Review (project #4)
45
+ ```
46
+
47
+ ## Error handling
48
+
49
+ | Condition | Behavior |
50
+ |-----------|----------|
51
+ | No target resolvable | Error, exit 1 |
52
+ | PR not found + Jira selected | Proceed Jira-only, log reason |
53
+ | PR merged/closed | Warn, confirm continue |
54
+ | Author bot / dependabot | Skip entire run |
55
+ | Diff > 2 MB | Ask: skip / top-20-files / cancel |
56
+ | No pipeline log + "Normal analiz" selected | Greyed out at menu; if forced via `--content`, error |
57
+ | Bitbucket PR version mismatch | Refetch once, retry; fail on second mismatch |
58
+ | Jira token missing/expired | Token Save Flow inline; skip on user-skip |
59
+ | Wiki preconditions not met | Case B menu per `$HOME/.claude/multi-agent-refs/wiki-capture.md` |
60
+
61
+ ## Cross-CLI parity
62
+
63
+ | CLI | Command name | Invocation |
64
+ |---|---|---|
65
+ | Claude Code | `/multi-agent:channels` | Slash namespace (colon) |
66
+ | Copilot CLI | `multi-agent-channels` | Top-level command (dash-separated, no namespace support) |
67
+
68
+ Both installations read the same source file (`$HOME/.claude/commands/multi-agent/channels/SKILL.md`) - `install.js --all` copies to:
69
+ - `~/.claude/commands/multi-agent/channels/SKILL.md`
70
+ - `~/.copilot/commands/multi-agent-channels.md`
71
+
72
+ Prompts MUST be byte-identical. `smoke-cross-cli-behavior.sh` asserts this - spacing, brackets, numbering, log-line format.
73
+
74
+ Progress emission on Copilot (no native TaskCreate UI): `bash ~/.copilot/scripts/phase-tracker.sh sub 5 <N> "<step>" <status>` - same shape as Phase 5.
75
+
76
+ ## Examples
77
+
78
+ ```
79
+ /multi-agent:channels
80
+ → resolves from cwd+branch → PROJ-12345 + PR #3433
81
+ → menu: PR ✓ Jira ✓ / Normal analiz ✓ Test senaryoları ✓
82
+ → PR description replaced (v3→4, 23 reviewers preserved)
83
+ → Jira comment posted (id 2484780)
84
+ → Confluence - Wiki -
85
+
86
+ /multi-agent:channels PROJ-12345 --channels confluence --content note --message-file notes.md
87
+ → non-interactive: only Confluence, content from notes.md
88
+ → asks: parent page URL (or recent [1] / [2])
89
+ → page created → https://<host>/pages/12345
90
+
91
+ /multi-agent:channels https://<bitbucket>/.../pull-requests/42 --dry-run
92
+ → resolves → PROJ-67890
93
+ → prints Jira + PR body preview to stdout, no POST
94
+
95
+ /multi-agent:channels --message "root: order id empty, UI silent. fix: length>0 guard in HomeVC.m"
96
+ → auto-diff from cwd+branch PR + user note combined
97
+ → posts to default channels (PR + Jira)
98
+ ```
@@ -32,7 +32,7 @@ Trigger 2 is the key addition over the plain build-retry cap: a build can "fail
32
32
  | Trigger | Evaluated by | Status |
33
33
  |---|---|---|
34
34
  | 2, finding half | `review-delta.mjs` exit 3 at Phase 3 Step 3.8: a blocking/important finding whose `fingerprint` (finding-fingerprint.mjs) stays in the accepted set for `identicalFindingCycles` consecutive rounds | **code** (v16.20.0) |
35
- | 3 | Phase 3 re-entry item 6: the `retryCount === 3` hard-kill records the trip | **code** (v16.20.0) |
35
+ | 3 | Phase 3 re-entry item 6: at `retryCount === 3`, `rework-rulings.mjs` rules on every open finding; the hard-kill, and the trip, happen only when a ruling is `escalate`. All parked: no trip, the run continues to Phase 4 with them as follow-ups | **code** (v16.20.0, rulings 20.34.0) |
36
36
  | 2, build-error half | needs a build-log signature normaliser | documented behaviour, no script yet |
37
37
  | 1 | needs checkpoint-to-checkpoint artifact diffing | documented behaviour, no script yet |
38
38
  | 4 | belongs to `cost-budget-check.mjs` | documented behaviour, no script yet |
@@ -4,6 +4,7 @@
4
4
  - [Phase 1 Step 2.6 - query before dispatching Explore](#phase-1-step-26---query-before-dispatching-explore)
5
5
  - [Impact of a change, not of a name](#impact-of-a-change-not-of-a-name)
6
6
  - [Who implements this](#who-implements-this)
7
+ - [How two symbols connect](#how-two-symbols-connect)
7
8
  - [Confirming with a language server](#confirming-with-a-language-server)
8
9
  - [Phase 5 Step 3 - refresh after the branch changed code](#phase-5-step-3---refresh-after-the-branch-changed-code)
9
10
  - [What the report answers that a file-level view cannot](#what-the-report-answers-that-a-file-level-view-cannot)
@@ -93,6 +94,17 @@ them with every other dependency. Production code never gains an edge to a
93
94
  type a test file declares, so a fake named after a framework type cannot turn
94
95
  into a hub.
95
96
 
97
+ ### How two symbols connect
98
+
99
+ `graph-query.mjs --path <from> <to>` answers with the shortest chain of edges
100
+ between two symbols or files, given by id or by name. An ambiguous name is
101
+ refused with its candidate ids and an unknown one gets its nearest names (exit
102
+ 3), so the answer is never a guess. A module node (an import the repository
103
+ does not declare) can end a path but is never walked through, since it joins
104
+ every file that imports it. On Android, a capitalised `fun` (in practice a
105
+ Compose UI function) is a symbol of kind `composable`, so screens and
106
+ components take part like types.
107
+
96
108
  ### Confirming with a language server
97
109
 
98
110
  The graph joins by name, so a direct dependent can be a file that only uses
@@ -134,6 +146,21 @@ node $HOME/.claude/scripts/validate-code-graph.mjs "$GRAPH_PATH"
134
146
  node $HOME/.claude/scripts/graph-report.mjs --graph "$GRAPH_PATH"
135
147
  ```
136
148
 
149
+ The report adds three whole-graph views (`_graph-analysis.mjs`): import cycles
150
+ (files that import each other, directly or around a loop), clusters of files
151
+ more connected to each other than to the rest (label propagation over imports
152
+ and references, with cohesion = the share of a cluster's edges that stay
153
+ inside), and a short list of questions worth asking before a change, drawn
154
+ from the hubs, the cycles and the strongest links between clusters. All three
155
+ are deterministic, so a changed report means changed code. `graph-report.mjs
156
+ --diff <older graph>` lists what changed between two builds.
157
+
158
+ A run across several repositories (dev-context extras, submodules) joins their
159
+ graphs with `graph-links.mjs build --projects <a,b,...>`: an import of a name
160
+ one repository does not declare is matched against what the others export,
161
+ and `graph-links.mjs affected --project <b>` lists the files elsewhere that
162
+ import b. The graphs are not merged (ADR-0018).
163
+
137
164
  The rebuild costs no API tokens, so it runs every task rather than on a staleness
138
165
  heuristic. A non-zero validator exit keeps the previous graph and logs
139
166
  `knowledge.graph_invalid`; it never fails the run - a stale graph is a degraded
@@ -50,7 +50,7 @@ not mitigated here.
50
50
  | T4 | Secret exposure through a response | Transcripts are read through `_transcript-tail.mjs`, which never parses api-request records and drops thinking blocks; every string passes the credential redactor and the scrubber; the finished office and chat documents are checked by the outbound gate; seat labels come from allow-listed fields (tool name, file basename, sidecar description), never a command line; credentials are read only by the service scripts and never returned | `smoke-office-privacy.sh`, `smoke-office-security.sh` T4, `test/office-activity.test.mjs` "carries no credential" |
51
51
  | T5 | Path traversal into arbitrary files | Session, agent, run, routine, tool and evidence ids are matched against safe character sets after decoding; transcripts are looked up by name under the projects root only; a screenshot must resolve (real path) inside the run's evidence directory; an analysis document named in run state is read only when its real path is inside the run's log directory, its artifacts or a worktree git lists under the state's projectRoot, and only when it is Markdown or HTML | `smoke-office-security.sh` T5, `test/office-work.test.mjs` "nothing outside its directory", "analysis documents are read only inside the run's roots", "a worktreePath counts only when git lists it" |
52
52
  | T6 | Oversized or malformed input | Bodies are capped at 64 KiB and validated against the route's schema; tool arguments are checked against the tool's inputSchema; launch input goes through `launch-request.mjs` validation only; chat paging is capped at 500 | `smoke-office-security.sh` T6, `office-work.test.mjs` "refuses an unknown tool, invalid arguments and an oversized body" |
53
- | T7 | Resource exhaustion | At most four event streams and 64 connections; a phone request has five seconds to send its body before any signature work; at most 256 confirm tokens, the oldest dropped first; service clients, the work list and autopilot control run as child processes, never blocking the event loop, one at a time per service (429 `busy` for a second one); one snapshot is computed per poll from bounded tail reads; the session list is cached for ten seconds; a server started on its own exits after its idle time and after 8 hours in any case, the one `office-on` starts runs until `office-off`, and both stop on SIGTERM | `smoke-office-security.sh` T7; `office-routes.test.mjs` "connections past the cap are dropped", "never sends its body", "confirm tokens are capped"; `office-work.test.mjs` "a slow service read neither blocks other routes nor runs twice at once" |
53
+ | T7 | Resource exhaustion | At most four event streams and 64 connections; a phone request has five seconds to send its body before any signature work; at most 256 confirm tokens, the oldest dropped first; service clients, the work list and autopilot control run as child processes, never blocking the event loop, one at a time per service (429 `busy` for a second write or service read; a second `GET /v1/prs`, `GET /v1/autopilot` or maturity read of the same issue shares the run in flight, and at most two maturity reads for different issues run at once); one snapshot is computed per poll from bounded tail reads; the session list is cached for ten seconds; a server started on its own exits after its idle time and after 8 hours in any case, the one `office-on` starts runs until `office-off`, and both stop on SIGTERM | `smoke-office-security.sh` T7; `office-routes.test.mjs` "connections past the cap are dropped", "never sends its body", "confirm tokens are capped"; `office-work.test.mjs` "a slow service read neither blocks other routes nor runs twice at once", "maturity checks for different issues run at most two at a time" |
54
54
  | T8 | XSS from hostile transcript or issue text | The panel renders every server string with `textContent` or canvas text; markdown is shown as plain text; server images only as `data:` URLs of image types; the office sprites are same-origin PNGs from `/office/assets/`, which answers only a plain file name (no separator or escape) whose real path is a PNG directly in the installed assets directory, and 404 otherwise; the page language the server stamps comes from a two-value set (`en`, `tr`), whatever the preferences file holds; the page's CSP allows only its per-response nonce for script and style, `connect-src 'self'`, no framing, no base URI, no form action | `smoke-office-page.sh`, `office-routes.test.mjs` "stamps the page language from outputLanguage", "serves a sprite and nothing else under /office/assets/", `office-build.test.mjs`, `smoke-office-runtime.sh` |
55
55
  | T9 | Clickjacking | `frame-ancestors 'none'` on the page and on every API response | `office-routes.test.mjs` "serves the page without a token, with a nonce CSP" |
56
56
  | T10 | An action nobody can account for | Every write leaves one line (who, route, step, status; never a body or token) in `office-actions.jsonl` | `office-routes.test.mjs` "every write leaves a line" |
@@ -53,8 +53,11 @@ CRITIC_RUNG=$(bash "$HOME/.claude/lib/model-dispatch.sh" subagent --persona plan
53
53
  ```
54
54
 
55
55
  It reads the plan, the analysis document(s), the constitution and the worktree,
56
- and writes objections under four lenses: `scope`, `feasibility`, `security`,
57
- `alternative` (a cheaper plan with the same result). Each objection has an id
56
+ and writes objections under six lenses: `scope`, `feasibility`, `security`,
57
+ `alternative` (a cheaper plan with the same result), `unstated-input` (an
58
+ input the spec implies that no task's tests exercise) and `underspecified` (a
59
+ decision a task leaves to its implementer that the analysis or the user should
60
+ make). Each objection has an id
58
61
  (`OBJ-NN`), a lens, a claim, at least one evidence anchor and, when the plan
59
62
  breaks one, a constitution rule id. The orchestrator writes the output to
60
63
  `$WORKTREE/.pipeline/plan-critique.json` (`schemas/plan-critique.schema.json`)
@@ -39,7 +39,8 @@ Phase 2 Step 3.7 wrote `$WORKTREE/.pipeline/scope-check.json` (contract: `featur
39
39
  ```bash
40
40
  SCOPE_JSON="$WORKTREE/.pipeline/scope-check.json"
41
41
  SCOPE_GATE=$(git -C "$WORKTREE" diff --name-only "origin/$BASE_BRANCH"...HEAD \
42
- | node $HOME/.claude/scripts/scope-check-gate.mjs --check "$SCOPE_JSON" --diff-files - --advisory 2>/dev/null)
42
+ | node $HOME/.claude/scripts/scope-check-gate.mjs --check "$SCOPE_JSON" --diff-files - --advisory \
43
+ --repo "$WORKTREE" --patch-range "origin/$BASE_BRANCH...HEAD" 2>/dev/null)
43
44
  ```
44
45
 
45
46
  ```
@@ -48,6 +49,8 @@ Files and the reason the dev gave for touching each:
48
49
  {jq -r '.files[] | "- \(.path): \(.reason)"' "$SCOPE_JSON"}
49
50
  Files in the diff with no stated reason (flag as scope drift if the change is not obviously required):
50
51
  {jq -r '.unjustified[]' <<< "$SCOPE_GATE"}
52
+ Layout-only hunks (whitespace the task did not need; a suggestion at most):
53
+ {jq -r '.formatOnly[]? | "- \(.file) \(.hunk)"' <<< "$SCOPE_GATE"}
51
54
  Deliberately not done (do not raise these as findings; they are known):
52
55
  {jq -r '.notDone[] | "- \(.what) (\(.why))"' "$SCOPE_JSON"}
53
56
  </scope-self-check>
@@ -29,7 +29,16 @@ git -C "$WORKTREE" diff --name-only "origin/$BASE_BRANCH"...HEAD \
29
29
  | node $HOME/.claude/scripts/scope-check-gate.mjs --check "$WORKTREE/.pipeline/scope-check.json" --diff-files -
30
30
  ```
31
31
 
32
- Output `{ok, justified, unjustified[], unlisted[], notDone}`. Exit 1 lists `unjustified[]` (in the diff, no reason or an empty one); `unlisted[]` (in the record, not in the diff) is reported and never fatal. Complete the record once and re-run. A second exit 1 does not block: log `dev.scope_check=incomplete unjustified=<n>` and hand off; Phase 4 receives the gate output inside `<scope-self-check>`, so reviewers see which files arrived without a stated reason. `--advisory` (used by Phase 4) always exits 0. Progress line: ` → checking scope self-check ({n} files, {m} not done)`.
32
+ Output `{ok, justified, unjustified[], unlisted[], notDone}`, plus `formatOnly[]` with `--patch` / `--patch-range` (`patchError` when the diff could not be read). With `--patch <unified diff>` (or `--repo <dir> --patch-range <a>...<b>`, which reads that diff itself), `formatOnly[]` lists hunks whose removed and added lines differ only in whitespace: a reformat of lines the task did not need to touch. It is reported, never fatal, and reviewers see it in `<scope-self-check>`. Exit 1 lists `unjustified[]` (in the diff, no reason or an empty one); `unlisted[]` (in the record, not in the diff) is reported and never fatal. Complete the record once and re-run. A second exit 1 does not block: log `dev.scope_check=incomplete unjustified=<n>` and hand off; Phase 4 receives the gate output inside `<scope-self-check>`, so reviewers see which files arrived without a stated reason. `--advisory` (used by Phase 4) always exits 0. Progress line: ` → checking scope self-check ({n} files, {m} not done)`.
33
+
34
+ ## Known limits in the code
35
+
36
+ A limit accepted on purpose is marked at the line, in the file's comment
37
+ style: `shortcut: <the limit>, <when to replace it>`. `notDone[]` says what the
38
+ change left out; the marker says what the code that shipped does not handle
39
+ yet. `debt-ledger.mjs` collects the markers a diff adds into the repo's debt
40
+ list, reviewers do not re-raise a marked limit unless it breaks a requirement
41
+ or a security rule, and the PR description lists them.
33
42
 
34
43
  ## Consumers
35
44
 
@@ -81,6 +81,8 @@ Knowledge files grow over time. Maintenance rules:
81
81
  and a rebuild is seconds, so age is the wrong question to ask of it.
82
82
  - `product-context.jsonl` is written by runs of OTHER repositories of the same product (`features/product-context.md`) and keyed by the remote sha it was read at; `product-context.mjs recall` returns a row only while that sha is current, so it needs no age rule
83
83
  - Stale entries are added to the prompt with a "STALE - verify before relying" tag
84
+ - A ledger entry earns or loses weight from the outcomes recorded against it: Phase 5 runs `learnings-ledger.mjs feedback --id <L:id> --outcome useful|dead_end|corrected` for each injected entry the run relied on or found wrong. Corrected, or a dead end at least twice and more often than useful, drops it from `brief` and `profile`; useful at least twice adds a strength that fades with age (`_memory-policy.mjs`). A new entry that repeats an existing one in other words (TF-IDF cosine 0.9 or more, same numbers, same negations) is not added
85
+ - `prefs.global.memory.excludeProjects` lists repo slugs whose ledger, triage corpus and debt list are never written
84
86
  - `prune-logs` does not touch knowledge - only deletes logs and state
85
87
  - `purge` does not touch knowledge either. Today the only removal path is `/multi-agent:uninstall --all-data`, which drops every project's knowledge at once; there is no per-project clear yet
86
88
 
@@ -113,6 +115,13 @@ node "$HOME/.claude/scripts/triage-memory.mjs" timeline --anchor T:<id> --bef
113
115
  node "$HOME/.claude/scripts/learnings-ledger.mjs" timeline --anchor L:<id> --before 3 --after 3
114
116
  ```
115
117
 
118
+ A store too large to rank in one pass (thousands of triage rows) goes through
119
+ the toolkit's full-text index instead of a whole-file read: `context_index` on
120
+ the store's path (`learnings-ledger.mjs path`, `triage-memory.mjs path`), then
121
+ `context_search` for ranked snippets and `context_get` for one passage. The
122
+ index is owner-only and re-indexing an unchanged file is a no-op, so this is
123
+ layer 1 and 3 again over the same rows, not a second copy to keep in step.
124
+
116
125
  ## Skill Injection Strategy
117
126
 
118
127
  When calling sub-agents, inject task-specific context from previous phases: