@mmerterden/multi-agent-pipeline 17.0.0 → 17.3.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 (88) hide show
  1. package/CHANGELOG.md +159 -0
  2. package/README.md +56 -4
  3. package/README.tr.md +57 -4
  4. package/docs/architecture.md +3 -3
  5. package/docs/ecosystem.md +5 -5
  6. package/docs/token-budget-history.md +22 -0
  7. package/install/_dev-only-files.mjs +1 -0
  8. package/install/codex.mjs +18 -1
  9. package/install/copilot.mjs +17 -1
  10. package/install/templates/multi-agent-autopilot.plist.template +79 -0
  11. package/package.json +1 -1
  12. package/pipeline/commands/multi-agent/autopilot-off/SKILL.md +64 -0
  13. package/pipeline/commands/multi-agent/autopilot-on/SKILL.md +181 -0
  14. package/pipeline/commands/multi-agent/autopilot-status/SKILL.md +74 -0
  15. package/pipeline/commands/multi-agent/channels/SKILL.md +41 -12
  16. package/pipeline/commands/multi-agent/help/SKILL.md +41 -35
  17. package/pipeline/commands/multi-agent/manual-test/SKILL.md +1 -1
  18. package/pipeline/commands/multi-agent/sync/SKILL.md +10 -9
  19. package/pipeline/commands/multi-agent/update/SKILL.md +1 -1
  20. package/pipeline/lib/autopilot-activation.sh +117 -0
  21. package/pipeline/lib/autopilot-state.sh +184 -0
  22. package/pipeline/lib/issue-fetcher.sh +18 -1
  23. package/pipeline/lib/plan-todos.sh +18 -0
  24. package/pipeline/multi-agent-refs/_dev-context.md +10 -0
  25. package/pipeline/multi-agent-refs/analysis/redesign.md +8 -0
  26. package/pipeline/multi-agent-refs/analysis/review.md +9 -0
  27. package/pipeline/multi-agent-refs/android-guide.md +14 -0
  28. package/pipeline/multi-agent-refs/audit-guide.md +12 -0
  29. package/pipeline/multi-agent-refs/backend-guide.md +10 -0
  30. package/pipeline/multi-agent-refs/channels/confluence.md +11 -0
  31. package/pipeline/multi-agent-refs/channels/issue-comment.md +12 -0
  32. package/pipeline/multi-agent-refs/channels/jira.md +90 -20
  33. package/pipeline/multi-agent-refs/channels/pr-review-actions.md +13 -0
  34. package/pipeline/multi-agent-refs/channels/pr.md +76 -19
  35. package/pipeline/multi-agent-refs/component-dispatch.md +11 -0
  36. package/pipeline/multi-agent-refs/component-generation.md +11 -0
  37. package/pipeline/multi-agent-refs/conventions-defaults.md +15 -0
  38. package/pipeline/multi-agent-refs/cross-cli-contract.md +49 -5
  39. package/pipeline/multi-agent-refs/features/analysis-jira.md +11 -0
  40. package/pipeline/multi-agent-refs/features/design-conformance.md +10 -0
  41. package/pipeline/multi-agent-refs/features/doctor.md +10 -0
  42. package/pipeline/multi-agent-refs/features/external-context-injection.md +7 -0
  43. package/pipeline/multi-agent-refs/features/jira-context.md +9 -0
  44. package/pipeline/multi-agent-refs/features/model-fallback.md +10 -0
  45. package/pipeline/multi-agent-refs/features/skill-conformance.md +13 -0
  46. package/pipeline/multi-agent-refs/features/url-enrichment.md +9 -0
  47. package/pipeline/multi-agent-refs/features/visual-evidence.md +61 -7
  48. package/pipeline/multi-agent-refs/generate-issue.md +7 -0
  49. package/pipeline/multi-agent-refs/issue-jira-triad.md +9 -0
  50. package/pipeline/multi-agent-refs/knowledge.md +6 -0
  51. package/pipeline/multi-agent-refs/multi-repo-integration-build.md +13 -0
  52. package/pipeline/multi-agent-refs/phases/modes.md +7 -0
  53. package/pipeline/multi-agent-refs/phases/operations.md +9 -0
  54. package/pipeline/multi-agent-refs/phases/phase-0-init.md +2 -2
  55. package/pipeline/multi-agent-refs/phases/phase-2-planning.md +17 -15
  56. package/pipeline/multi-agent-refs/phases/phase-3-dev.md +1 -1
  57. package/pipeline/multi-agent-refs/phases/phase-6-commit.md +1 -1
  58. package/pipeline/multi-agent-refs/phases.md +11 -0
  59. package/pipeline/multi-agent-refs/picker-contract.md +12 -0
  60. package/pipeline/multi-agent-refs/platform-parity.md +10 -0
  61. package/pipeline/multi-agent-refs/progress-contract.md +10 -0
  62. package/pipeline/multi-agent-refs/readiness-review.md +7 -1
  63. package/pipeline/multi-agent-refs/rules.md +3 -11
  64. package/pipeline/multi-agent-refs/setup/firebase.md +9 -0
  65. package/pipeline/multi-agent-refs/swiftui-guide.md +17 -0
  66. package/pipeline/multi-agent-refs/tracker-contract.md +44 -0
  67. package/pipeline/multi-agent-refs/web-guide.md +10 -0
  68. package/pipeline/multi-agent-refs/wiki-capture.md +11 -0
  69. package/pipeline/schemas/autopilot-config.schema.json +149 -0
  70. package/pipeline/schemas/prefs.schema.json +4 -0
  71. package/pipeline/schemas/token-budget.json +10 -19
  72. package/pipeline/scripts/autopilot-arming.mjs +147 -0
  73. package/pipeline/scripts/autopilot-intake.mjs +387 -0
  74. package/pipeline/scripts/autopilot-menubar.swift +361 -0
  75. package/pipeline/scripts/autopilot-runner.mjs +354 -0
  76. package/pipeline/scripts/autopilot-status.sh +213 -0
  77. package/pipeline/scripts/capture-evidence.sh +79 -11
  78. package/pipeline/scripts/gen-ref-toc.mjs +279 -0
  79. package/pipeline/scripts/jira-search.sh +70 -0
  80. package/pipeline/scripts/phase-tracker.sh +134 -12
  81. package/pipeline/scripts/probe-evidence-capability.sh +27 -3
  82. package/pipeline/scripts/run-ui-tests.sh +113 -4
  83. package/pipeline/skills/.skill-manifest.json +16 -4
  84. package/pipeline/skills/shared/core/multi-agent-autopilot-off/SKILL.md +67 -0
  85. package/pipeline/skills/shared/core/multi-agent-autopilot-on/SKILL.md +146 -0
  86. package/pipeline/skills/shared/core/multi-agent-autopilot-status/SKILL.md +64 -0
  87. package/pipeline/skills/shared/core/multi-agent-channels/SKILL.md +62 -11
  88. package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +9 -8
@@ -0,0 +1,79 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!--
3
+ multi-agent autopilot - the schedule for continuous mode.
4
+
5
+ Rendered and installed ONLY by /multi-agent:autopilot-on, after an explicit
6
+ confirmation that names this file's path. A clean install writes nothing here;
7
+ smoke-autopilot-default-off.sh fails if it ever does.
8
+
9
+ A user agent, not a daemon, and that is the correct choice rather than a
10
+ limitation: it loads at LOGIN. Before login the keychain is locked, so a tick
11
+ that fired at boot could not read a single token - it would take items it could
12
+ not work on and burn them. Automatic login means nothing to do after a restart.
13
+
14
+ StartInterval does NOT wake a sleeping Mac; it fires on the next wake. The mode
15
+ therefore holds its own sleep assertion while on AC and releases it on battery,
16
+ so an overnight queue keeps moving without flattening a laptop off the charger.
17
+
18
+ {{PLACEHOLDERS}} are substituted by autopilot-on: NODE, TICK, LABEL, ROOT,
19
+ INTERVAL.
20
+ -->
21
+ <plist version="1.0">
22
+ <dict>
23
+ <key>Label</key>
24
+ <string>{{LABEL}}</string>
25
+
26
+ <key>ProgramArguments</key>
27
+ <array>
28
+ <string>{{NODE}}</string>
29
+ <string>{{TICK}}</string>
30
+ </array>
31
+
32
+ <!-- Load at login and run one tick immediately, so turning the mode on does
33
+ something visible rather than waiting out the first interval. -->
34
+ <key>RunAtLoad</key>
35
+ <true/>
36
+
37
+ <key>StartInterval</key>
38
+ <integer>{{INTERVAL}}</integer>
39
+
40
+ <!-- One tick at a time. Overlapping ticks would each claim the queue head;
41
+ the runner's own pid+sessionId check is the real mutual exclusion, and
42
+ this keeps the common case from ever reaching it. -->
43
+ <key>AbandonProcessGroup</key>
44
+ <false/>
45
+
46
+ <key>ProcessType</key>
47
+ <string>Background</string>
48
+
49
+ <!-- Nice to the interactive session. The point of this mode is work that
50
+ happens while you do something else, so it must never be what makes the
51
+ machine feel slow. -->
52
+ <key>LowPriorityIO</key>
53
+ <true/>
54
+ <key>Nice</key>
55
+ <integer>5</integer>
56
+
57
+ <!-- Both streams go to the runner's own log, inside the 0700 state directory.
58
+ Not /tmp: a tick's output names tickets, repos and branches, and on a
59
+ shared machine that is somebody's roadmap. Every file the runner writes
60
+ is scanned for credentials before it is kept. -->
61
+ <key>StandardOutPath</key>
62
+ <string>{{ROOT}}/runner.log</string>
63
+ <key>StandardErrorPath</key>
64
+ <string>{{ROOT}}/runner.log</string>
65
+
66
+ <key>EnvironmentVariables</key>
67
+ <dict>
68
+ <key>PATH</key>
69
+ <string>/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
70
+ <!-- No token is set here, deliberately. launchd plists are world-readable
71
+ and get backed up; credentials are read from the keychain at tick time
72
+ through credential-store.sh, which streams them over stdin so they never
73
+ reach argv either. -->
74
+ </dict>
75
+
76
+ <key>WorkingDirectory</key>
77
+ <string>{{ROOT}}</string>
78
+ </dict>
79
+ </plist>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmerterden/multi-agent-pipeline",
3
- "version": "17.0.0",
3
+ "version": "17.3.0",
4
4
  "description": "8-phase AI development pipeline with full orchestration on Claude Code, Copilot CLI and Codex CLI. Analysis, planning, TDD, CLI-aware parallel review with consensus surfacing + Fable triage, default-FAIL evidence gates, secret + intent guards, per-phase cost ledger, persistent learnings memory, wiki generation, commit automation. Token-preserving uninstall.",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -0,0 +1,64 @@
1
+ ---
2
+ description: "Turn off continuous mode on this machine: the schedule is removed, work already running finishes, the repo selection is kept. Use when the machine should stop picking work up."
3
+ description-tr: "Bu makinede sürekli modu kapatır: zamanlama kaldırılır, koşan iş biter, repo seçimi saklanır."
4
+ argument-hint: "[--now] - --now also stops the item currently running"
5
+ ---
6
+
7
+ # multi-agent autopilot-off - stop picking work up
8
+
9
+ Removes the schedule. **Work already in flight finishes** unless you pass
10
+ `--now`: an item stopped mid-development leaves a worktree and a half-written
11
+ branch, which is the exact state this release spent its time cleaning up.
12
+
13
+ ## Steps
14
+
15
+ ### 1. Say what is in flight before stopping anything
16
+
17
+ ```bash
18
+ bash "$HOME/.claude/scripts/autopilot-status.sh" --short
19
+ ```
20
+
21
+ When something is running, name it and how long it has been going. "Stopped"
22
+ means something different when an item is 2 minutes from a PR than when the queue
23
+ is idle, and the user is the one who knows which.
24
+
25
+ ### 2. Remove the schedule
26
+
27
+ ```bash
28
+ L="com.multi-agent.autopilot"
29
+ launchctl bootout "gui/$(id -u)/$L" 2>/dev/null || launchctl unload "$HOME/Library/LaunchAgents/$L.plist" 2>/dev/null
30
+ rm -f "$HOME/Library/LaunchAgents/$L.plist"
31
+ ```
32
+
33
+ The plist is removed rather than left disabled, because its presence is the
34
+ definition of on: a disabled-but-present job is a third state nobody can read
35
+ from the outside.
36
+
37
+ ### 3. Release the sleep assertion and the indicator
38
+
39
+ ```bash
40
+ pkill -f 'caffeinate -i -w' 2>/dev/null || true # only the one this mode holds
41
+ pkill -f "$HOME/.claude/autopilot/bin/menubar" 2>/dev/null || true
42
+ ```
43
+
44
+ ### 4. `--now` only: end the in-flight item deliberately
45
+
46
+ Without `--now` nothing here runs. With it, the child session is stopped and the
47
+ run is marked `abandoned`, its worktree is removed **unless it holds uncommitted
48
+ work**, in which case the work is stashed to `autopilot/abandoned/<task-id>` and
49
+ the worktree is kept. Same contract as `gc-abandoned.sh`; losing a day of edits
50
+ is worse than 750 MB.
51
+
52
+ ### 5. Keep the selection
53
+
54
+ `~/.claude/autopilot/config.json`, `queue.json` and `attempted.jsonl` all stay.
55
+ Turning the mode back on must not re-ask which repos, and the attempt history is
56
+ what stops an item that already failed twice from being retried forever.
57
+
58
+ To forget the selection as well: `rm -rf ~/.claude/autopilot`. Say that rather
59
+ than doing it - "off" and "forget everything" are different requests.
60
+
61
+ ### 6. Report
62
+
63
+ State that it is off, what was left running or finishing, and that the repo
64
+ selection is kept. If an item was stashed, name the branch.
@@ -0,0 +1,181 @@
1
+ ---
2
+ description: "Turn on continuous mode on THIS machine: pick the repos it watches; labelled GitHub issues and assigned+labelled Jira items then run in a worktree and stop at an open PR. Use when the machine should pick work up unattended."
3
+ description-tr: "Bu makinede sürekli modu açar: izlenecek repoları seçersin, etiketli GitHub issue'ları ve sana atanmış + etiketli Jira maddeleri worktree'de geliştirilip PR'da durur. Repo listesini değiştirmek için aynı komutu tekrar çalıştır."
4
+ argument-hint: "(no arguments - opens the repo picker)"
5
+ ---
6
+
7
+ # multi-agent autopilot-on - continuous mode, on this machine
8
+
9
+ Turns on the mode that picks work up without being asked. **No repo is included
10
+ by default and none is ever added implicitly** - you choose, here, every time.
11
+
12
+ Why a picker rather than a label alone: measured on one machine, 66 repos grant
13
+ push and a good half belong to other people. A label is a filter; anyone who can
14
+ open an issue in a repo you happen to have push on could add one. The gate is
15
+ this selection, and it is per machine.
16
+
17
+ ## Steps
18
+
19
+ ### 1. Prerequisites, stated before anything is written
20
+
21
+ ```bash
22
+ gh auth status >/dev/null 2>&1 || echo "BLOCKED: gh is not authenticated - run 'gh auth login'"
23
+ command -v jq >/dev/null 2>&1 || echo "BLOCKED: jq is required"
24
+ node "$HOME/.claude/scripts/doctor.mjs" >/dev/null 2>&1; [ "$?" -ge 2 ] && echo "BLOCKED: doctor reports a blocking problem - fix it first"
25
+ ```
26
+
27
+ Any BLOCKED line stops here and is reported. Arming unattended work on an install
28
+ that `doctor` calls broken produces a queue of failures, one per item.
29
+
30
+ ### 2. The repo list, both halves of it
31
+
32
+ ```bash
33
+ bash "$HOME/.claude/lib/autopilot-activation.sh" list
34
+ ```
35
+
36
+ Two states come back and **both are shown**:
37
+
38
+ - `eligible` - push rights and a checkout on this machine
39
+ - `unavailable` - push rights, no local checkout, listed WITH that reason
40
+
41
+ Never hide the second list. Dropping 51 of 66 rows silently looks exactly like a
42
+ permissions problem, and the user goes hunting for a token fault that does not
43
+ exist.
44
+
45
+ ### 3. Pick, with the current selection already checked
46
+
47
+ Read `~/.claude/autopilot/config.json` if it exists, then one `AskUserQuestion`
48
+ (`multiSelect: true`) over the **eligible** rows:
49
+
50
+ - `question` (in `outputLanguage`): which repos this machine should pick work up from
51
+ - `header`: "Repos" (English, UI contract)
52
+ - `options`: one per eligible repo, currently-selected ones marked "(seçili)" / "(selected)"
53
+
54
+ **This is how repos are added and removed.** Checking a new one adds it;
55
+ unchecking an existing one removes it. There is no `add-repo` / `remove-repo`
56
+ command, because two entry points to one list is two lists.
57
+
58
+ Unavailable repos are printed above the question as a plain list with their
59
+ reason, not offered as options.
60
+
61
+ ### 4. Sources and label, per selected repo
62
+
63
+ One `AskUserQuestion` per newly added repo (already-configured ones keep their
64
+ answers - re-running must not re-ask what was already settled):
65
+
66
+ - Sources: `GitHub issues` / `Jira` / both
67
+ - Label: default **`agent-queue`** on both sides, editable
68
+
69
+ The same name works on both sides and both mechanisms already exist:
70
+
71
+ | Source | Query | Extra condition |
72
+ |---|---|---|
73
+ | GitHub | `gh issue list --repo <r> --label <label> --state open` | none - the label is the whole gate |
74
+ | Jira | `assignee = currentUser() AND labels = "<label>" AND resolution = EMPTY AND status not in (Done, Closed, Cancelled)` | **assigned to you**, so a label somebody else adds is not enough |
75
+
76
+ Two Jira caveats worth saying out loud when Jira is selected: labels are one
77
+ global namespace across the whole instance and anyone can write them, so on a
78
+ shared instance prefer a qualified name (`agent-queue-<team>`); and the Labels
79
+ field has to be on the edit screen for the issue types in play. An instance where
80
+ neither holds is a `jiraJql` config change - a saved filter, a component - not a
81
+ redesign.
82
+
83
+ Run the query before saving it, and show the count:
84
+
85
+ ```bash
86
+ bash "$HOME/.claude/scripts/jira-search.sh" --jql "$JQL" --max 5 | jq '.total, [.issues[].key]'
87
+ ```
88
+
89
+ A JQL that returns nothing is not an error and is usually correct on day one
90
+ (nothing is labelled yet), but a JQL that errors is a config that will be silent
91
+ forever - the Labels field missing from an edit screen looks exactly like an
92
+ empty queue from the outside. Saying "0 items, query valid" and "query rejected"
93
+ differently here is the difference between a two-minute fix and a week of
94
+ wondering why nothing happens.
95
+
96
+ ### 5. Write the config
97
+
98
+ Validate against `schemas/autopilot-config.schema.json`, then write
99
+ `~/.claude/autopilot/config.json` (0600, in a 0700 directory) via
100
+ `ma_ap_write` in `lib/autopilot-state.sh`. Defaults that are not asked:
101
+ `slots: 1`, `scanIntervalSeconds: 120`, `maxAttempts: 2`,
102
+ `askOnLowMaturity: true`, `costCeilingUsd: 25`, `depthRouter: "off"`.
103
+
104
+ ### 6. Build the menu bar indicator (best effort)
105
+
106
+ ```bash
107
+ SRC="$HOME/.claude/scripts/autopilot-menubar.swift"
108
+ OUT="$HOME/.claude/autopilot/bin/menubar"
109
+ if command -v swiftc >/dev/null 2>&1; then
110
+ swiftc -O "$SRC" -o "$OUT" 2>/dev/null && chmod 700 "$OUT"
111
+ fi
112
+ ```
113
+
114
+ Built from source on demand, never shipped as a binary: the package contains only
115
+ text today, and a compiled artifact in it would need signing and notarization to
116
+ be distributable. No `swiftc` means no indicator and nothing else changes - say
117
+ so in one line rather than failing. `autopilot-status` works either way.
118
+
119
+ ### 7. Confirm the schedule, naming the file
120
+
121
+ Render `templates/multi-agent-autopilot.plist.template` by substituting its five
122
+ placeholders, then show the resolved **path** and interval and `AskUserQuestion`:
123
+
124
+ ```bash
125
+ . "$HOME/.claude/lib/autopilot-state.sh"
126
+ TPL=$(ma_ap_asset templates/multi-agent-autopilot.plist.template) || {
127
+ echo "BLOCKED: the plist template is not installed on this host - re-run the installer"; exit 1; }
128
+ DEST="$HOME/Library/LaunchAgents/com.multi-agent.autopilot.plist"
129
+ INTERVAL=$(bash "$HOME/.claude/scripts/autopilot-status.sh" --json | jq -r '.scanIntervalSeconds // 120')
130
+ sed -e "s|{{NODE}}|$(command -v node)|g" \
131
+ -e "s|{{TICK}}|$HOME/.claude/scripts/autopilot-runner.mjs|g" \
132
+ -e "s|{{LABEL}}|com.multi-agent.autopilot|g" \
133
+ -e "s|{{ROOT}}|$HOME/.claude/autopilot|g" \
134
+ -e "s|{{INTERVAL}}|$INTERVAL|g" \
135
+ "$TPL" > "$DEST"
136
+ ```
137
+
138
+ `ma_ap_asset` rather than a literal `$HOME/.claude/templates/...`: only
139
+ `install/claude.mjs` used to lay that tree down, so on a Copilot-only or
140
+ Codex-only machine the mode would have written a launchd job from a template
141
+ the host does not have. The state root stays shared on purpose - two CLIs on one
142
+ machine must see one queue, not two.
143
+
144
+ `command -v node` rather than the bare word: launchd does not read a login
145
+ shell, so its `PATH` is the short one in the plist's own `EnvironmentVariables`,
146
+ and a Homebrew or nvm node that is not on that path would make every tick fail
147
+ with a message nobody is watching for.
148
+
149
+ - `question`: install the schedule at `~/Library/LaunchAgents/com.multi-agent.autopilot.plist` and start picking work up?
150
+ - options: `{ label: "Start" }` / `{ label: "Configure only", description: "Save the repo selection, do not schedule anything yet" }`
151
+
152
+ "Configure only" is a real answer and the safe default to offer first: the queue
153
+ can be watched with `autopilot-status` for a while before anything runs.
154
+
155
+ On **Start**:
156
+
157
+ ```bash
158
+ launchctl bootstrap "gui/$(id -u)" "$HOME/Library/LaunchAgents/com.multi-agent.autopilot.plist" 2>/dev/null \
159
+ || launchctl load "$HOME/Library/LaunchAgents/com.multi-agent.autopilot.plist"
160
+ ```
161
+
162
+ ### 8. Report what is now true
163
+
164
+ Say all five, because each one is something a user has asked about after the
165
+ fact: which repos and which labels; that it survives a restart with no command to
166
+ run (launchd loads at **login** - not boot, and that is correct, because the login
167
+ keychain is what unlocks the tokens, so a run before login could not reach Jira or
168
+ GitHub anyway); that the machine will be kept awake **only on AC**; the slot count
169
+ and the ceiling this machine would allow (`ma_ap_slot_ceiling`); and that
170
+ `/multi-agent:autopilot-off` is the only way to stop it.
171
+
172
+ ## What this does not do
173
+
174
+ - **No cap on PRs.** As many items as carry the label become as many PRs. The
175
+ bounds are `costCeilingUsd` over a rolling 24 hours and what the machine can
176
+ hold - never a daily count.
177
+ - **Does not merge.** The runner stops at an open PR; the merge decision stays
178
+ yours.
179
+ - **Does not touch an attended run.** Both are worktrees and per-repo concurrency
180
+ is 1, so the queue skips a repo you are working in rather than competing for
181
+ `.git/index.lock`.
@@ -0,0 +1,74 @@
1
+ ---
2
+ description: "Show what continuous mode is doing here: what runs at which phase, what is queued, what waits for an answer, what PRs it opened today. Use when asked whether autopilot is on."
3
+ description-tr: "Sürekli modun ne yaptığını gösterir: ne koşuyor hangi fazda, sırada ne var, ne cevap bekliyor, bugün hangi PR'lar açıldı."
4
+ argument-hint: "[--subjects] - --subjects prints one widget line per in-flight item"
5
+ ---
6
+
7
+ # multi-agent autopilot-status - what is it doing
8
+
9
+ ```bash
10
+ bash "$HOME/.claude/scripts/autopilot-status.sh" ${ARGUMENTS}
11
+ ```
12
+
13
+ That script is the **only** producer. The menu bar indicator, this command and
14
+ the session-start hook all render the same `status.json` it writes, because the
15
+ moment each computes its own answer they start disagreeing - which is the failure
16
+ this whole area was built around: a run reading `in_progress` while its PR was
17
+ already open.
18
+
19
+ ## What the output means
20
+
21
+ | Line | Meaning |
22
+ |---|---|
23
+ | `KAPALI` with repos selected | the selection is kept, launchd holds no job. `autopilot-on` starts it again without re-asking |
24
+ | `kurulu değil` | never configured on this machine; nothing has been written |
25
+ | `Koşuyor` | in flight now. Phase and elapsed come from the run's own state, not from a guess |
26
+ | `Cevap bekliyor` | the item was not mature enough, the open questions were posted as a comment, and it resumes on its own once answered |
27
+ | `config açık ama launchd'de iş yok` | the failure a `resume` command would have hidden: an OS update dropped the plist, or it was booted out. Re-run `autopilot-on` |
28
+
29
+ An empty queue is reported with the reason - no item carries the label yet - and
30
+ not as an error. That is the most common "why is nothing happening", and it is
31
+ not a fault.
32
+
33
+ ## The menu bar indicator
34
+
35
+ When `swiftc` was available at `autopilot-on` time, `~/.claude/autopilot/bin/menubar`
36
+ shows the same thing in the top right, refreshing on its own: one row per item
37
+ with its id, whether it is running Full or Short, the phase as a fraction, the
38
+ elapsed time and the stack, then the queue, then what is waiting, then the PRs of
39
+ the last day - each one clickable.
40
+
41
+ The indicator only **draws**. It cannot start, stop or change a run: control
42
+ stays here, where it is confirmed. It disappears from the list the moment an item
43
+ finishes, and the item reappears under `Raporlar` with its PR.
44
+
45
+ No `swiftc` means no indicator and nothing else changes.
46
+
47
+ ## Watching the queue before anything runs
48
+
49
+ The queue can be read dry, with no scheduling and nothing dispatched:
50
+
51
+ ```bash
52
+ node "$HOME/.claude/scripts/autopilot-intake.mjs" --dry-run | jq '{queued: [.queued[].id], awaiting: [.awaiting[].id], dropped: [.dropped[] | {id, reason}]}'
53
+ ```
54
+
55
+ This is the honest way to decide whether to arm the runner: it queries the same
56
+ sources, applies the same ordering and the same attempt history, and writes
57
+ nothing at all. `dropped` is the part worth reading - it is where "why is my
58
+ issue not being picked up" is answered, one reason per item.
59
+
60
+ ## `--subjects`
61
+
62
+ One line per in-flight item, shaped for the native task widget, with the numbers
63
+ travelling **inside** the subject string because the widget takes exactly one
64
+ string per row:
65
+
66
+ ```
67
+ PROJ-1234 · Full · Faz 3/8 Dev · ios
68
+ PROJ-1199 · cevap bekliyor
69
+ ```
70
+
71
+ Honest limit, worth saying rather than discovering: that widget belongs to the
72
+ session that calls `TaskUpdate`, and it refreshes when that session takes a turn -
73
+ when you type, or when a hook fires. It is a view, not a live counter. The menu
74
+ bar indicator is the one that updates on its own.
@@ -159,16 +159,39 @@ Non-interactive in three cases - menu skipped entirely, flag values or prefs u
159
159
 
160
160
  For each selected **content** source, produce one section body. Each section runs through the `humanizer` skill separately (Jira / Confluence / PR tones differ).
161
161
 
162
+ **The Jira body is not the PR body.** Jira is read by the person who filed the
163
+ ticket and by whoever tests it, so its comment carries the four sections
164
+ `channels/jira.md` fixes - `summary` (`Geliştirme Özeti`), `test_scenarios`
165
+ (`Test Senaryoları`), `impact` (`Etki Analizi`) and `context_refs`
166
+ (`Bağlantılar`) - and nothing else. Technical sections go to the PR and to
167
+ Confluence, where the reader is a code reviewer. A shipped Jira comment once
168
+ explained a hash-table mutation across three paragraphs of class names; it was
169
+ correct, and it was the wrong document. When `jira` is a selected channel, drop
170
+ the technical sections from its body rather than converting them: the PR link on
171
+ line 1 is how a Jira reader reaches the detail.
172
+
173
+ `impact` is not a technical section in disguise. It answers four questions -
174
+ what was wrong, what was changed, which areas must be tested, what else is
175
+ affected - in the same plain register as the summary, and it is the part a test
176
+ lead reads before deciding how wide to test.
177
+
162
178
  | Content option | Generated section |
163
179
  |---|---|
164
180
  | Normal analiz | `### Analysis` - impact summary from Phase 1, risks from Phase 4 (pipeline-log source, high-level only) |
165
- | Teknik analiz | `### Technical Details` - Changes (what/why per file group), Architecture (structural decisions, pattern changes), Dependencies (new imports/frameworks/packages). Source: Phase 2 planning + Phase 3 dev log + `git diff --stat`. Same shape as PR body's Technical Details - gives Jira/Confluence readers the code-reviewer view without making them click into the PR. |
181
+ | Teknik analiz | `### Technical Details` - Changes (what/why per file group), Architecture (structural decisions, pattern changes), Dependencies (new imports/frameworks/packages). Source: Phase 2 planning + Phase 3 dev log + `git diff --stat`. **PR and Confluence only** - never rendered into a Jira comment. |
166
182
  | Test senaryoları | `### Test Scenarios` - precondition / steps / expected table (4-8 rows), user perspective |
167
183
  | Auto-diff | Old enrich Output Template verbatim - Root Cause / Solution / Changed Files / Test Scenarios |
168
184
  | Manuel not | `### Notes` - user-provided paragraph, or LLM-split into subsections if `--message` is plain text and long |
169
185
  | 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. |
170
186
  | 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. |
171
187
 
188
+ **The content options are sources, not the body's shape.** Which sections a PR
189
+ body carries and in what order is fixed by `channels/pr.md` (`summary` →
190
+ `technical` → `architecture` → `impact` → `test_scenarios` → `visuals` → `risk`
191
+ → `dependencies` → `build` → `related`); the options below choose what gets
192
+ gathered to fill them. A content option left unselected means a section has no
193
+ source, not that the section may be reordered or renamed.
194
+
172
195
  **Output template (aggregated across selected content options):**
173
196
 
174
197
  ```markdown
@@ -197,9 +220,13 @@ For each selected **content** source, produce one section body. Each section run
197
220
  | `path/to/File.ext` | +N / -M |
198
221
 
199
222
  ### Test Scenarios ← if "Test senaryoları" OR "Auto-diff" selected
200
- | # | Precondition | Steps | Expected | Status |
201
- |---|--------------|-------|----------|--------|
202
- | 1 | ... | ... | ... | To Test|
223
+ **1. {what this scenario exercises}**
224
+ 1. {step the tester performs}
225
+ 2. **Expected:** {what they should see}
226
+
227
+ **2. {regression scenario}**
228
+ 1. {step}
229
+ 2. **Expected:** {what should still behave as before}
203
230
 
204
231
  ### Notes ← if "Manuel not" selected
205
232
  {user message}
@@ -240,13 +267,7 @@ If no cached report exists, skip silently - this is augmentation, not a gate.
240
267
 
241
268
  **Work summary generation:**
242
269
 
243
- 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>`:
244
-
245
- 1. **Task header** - `taskId`, `branch`, `baseBranch`, `prNumber` from `agent-state.json` (or explicit flags for post-hoc invocation).
246
- 2. **Scope delivered** - Phase 2 `planTodos[]` / `tasks[]` rendered as `done` (status=done) or `pending` (anything else) rows. Task id + title shown; `(deferred - rationale)` appended if the task's `status` is `"deferred"`.
247
- 3. **Changed files** - `git -C $WORKTREE diff --numstat $baseBranch...HEAD`. Shows `` `path` (+add / -del) `` per row, capped at 20 with a `_... +N more files not shown_` footer when exceeded. Total adds/dels + file count in section header.
248
- 4. **Review outcome** - from `reviewConsensus` (pre-v6.1) or `phases["4"].triage`: `{accepted} accepted · {deferred} deferred · {rejected} rejected · approved={bool}`. Hidden entirely when all three buckets are empty (normal for a run that never reached Phase 4).
249
- 5. **Phase tick strip** - single line from the tracker state (`render-work-summary.sh` resolves worktree/artifacts copies, then `$HOME/.claude/logs/multi-agent/{taskId}/tracker-state.json`): `0 Init [done] · 1 Analysis [done] · 2 Planning [done] · 3 Dev [done] · 4 Review [done] · 5 Test skipped · 6 Commit [done] · 7 Report active`. Marks: `done` completed · `active` in_progress · `failed` failed · `skipped` skipped · `·` pending.
270
+ 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. Re-stating those five steps here gave the pipeline two specifications of one script, and the prose one is the copy that rots. Exit 2 means the state was unreadable: skip the section, do not substitute a hand-written one.
250
271
 
251
272
  **Output template:**
252
273
 
@@ -369,7 +390,15 @@ Aggregated Markdown from Step 5 → PR description. GitHub uses `gh pr edit --bo
369
390
  Full contract: [`$HOME/.claude/multi-agent-refs/channels/pr.md`]($HOME/.claude/multi-agent-refs/channels/pr.md) - Bitbucket payload assembly snippet, version-mismatch retry, `--ready` promotion, multi-repo cross-link block.
370
391
 
371
392
  #### Adapter: Jira comment
372
- Body converted to Jira wiki markup (`### ...` → `*...*`, `- [ ] ...` → `# ...`, `` `x` `` → `{{x}}`, tables to `||h||h|| |c|c|`); first line is the PR URL. The converted body then goes through `node "$HOME/.claude/scripts/jira-wiki-escape.mjs"` (required, not optional - Jira renders `:)` `(x)` `(!)` `(/)` as emoticon images, and a Swift selector like `login(source:input:)` ends in `:)`). POST `/rest/api/2/issue/{id}/comment` via heredoc + `jq --rawfile` + `curl --data-binary @file`, from the escaped file. Token resolved from `keychainMapping.jira`.
393
+ Sections: `summary` + `test_scenarios` + `impact` + `context_refs` only - the technical ones go to the PR and Confluence (`channels/jira.md` fixes the order). The PR URL goes on line 1, above the first heading. The wiki-markup conversion table lives in that same ref and only there: the four-row summary that used to sit here mapped `### ...` to `*...*`, which is italic, not a heading - a shrunken copy of a table is a second answer, and it was the wrong one.
394
+
395
+ Then post it - do not assemble the request:
396
+
397
+ ```bash
398
+ bash "$HOME/.claude/lib/jira-publish.sh" --issue "$JIRA_ID" --body-file "$F" --target comment
399
+ ```
400
+
401
+ The publisher escapes every body (Jira renders `:)` `(x)` `(!)` `(/)` as emoticon images, and a Swift selector like `login(source:input:)` ends in `:)`) and resolves the token from `keychainMapping.jira` without putting it on argv. The hand-rolled `jq`+`curl` this replaced kept the escape as a separate step, and a shipped comment turned `hash(into:)` into a smiley.
373
402
 
374
403
  Full contract: [`$HOME/.claude/multi-agent-refs/channels/jira.md`]($HOME/.claude/multi-agent-refs/channels/jira.md) - full conversion table, multi-repo PR-list prepend, Wiki→Jira triad interaction.
375
404