@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.
- package/CHANGELOG.md +159 -0
- package/README.md +56 -4
- package/README.tr.md +57 -4
- package/docs/architecture.md +3 -3
- package/docs/ecosystem.md +5 -5
- package/docs/token-budget-history.md +22 -0
- package/install/_dev-only-files.mjs +1 -0
- package/install/codex.mjs +18 -1
- package/install/copilot.mjs +17 -1
- package/install/templates/multi-agent-autopilot.plist.template +79 -0
- package/package.json +1 -1
- package/pipeline/commands/multi-agent/autopilot-off/SKILL.md +64 -0
- package/pipeline/commands/multi-agent/autopilot-on/SKILL.md +181 -0
- package/pipeline/commands/multi-agent/autopilot-status/SKILL.md +74 -0
- package/pipeline/commands/multi-agent/channels/SKILL.md +41 -12
- package/pipeline/commands/multi-agent/help/SKILL.md +41 -35
- package/pipeline/commands/multi-agent/manual-test/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/sync/SKILL.md +10 -9
- package/pipeline/commands/multi-agent/update/SKILL.md +1 -1
- package/pipeline/lib/autopilot-activation.sh +117 -0
- package/pipeline/lib/autopilot-state.sh +184 -0
- package/pipeline/lib/issue-fetcher.sh +18 -1
- package/pipeline/lib/plan-todos.sh +18 -0
- package/pipeline/multi-agent-refs/_dev-context.md +10 -0
- package/pipeline/multi-agent-refs/analysis/redesign.md +8 -0
- package/pipeline/multi-agent-refs/analysis/review.md +9 -0
- package/pipeline/multi-agent-refs/android-guide.md +14 -0
- package/pipeline/multi-agent-refs/audit-guide.md +12 -0
- package/pipeline/multi-agent-refs/backend-guide.md +10 -0
- package/pipeline/multi-agent-refs/channels/confluence.md +11 -0
- package/pipeline/multi-agent-refs/channels/issue-comment.md +12 -0
- package/pipeline/multi-agent-refs/channels/jira.md +90 -20
- package/pipeline/multi-agent-refs/channels/pr-review-actions.md +13 -0
- package/pipeline/multi-agent-refs/channels/pr.md +76 -19
- package/pipeline/multi-agent-refs/component-dispatch.md +11 -0
- package/pipeline/multi-agent-refs/component-generation.md +11 -0
- package/pipeline/multi-agent-refs/conventions-defaults.md +15 -0
- package/pipeline/multi-agent-refs/cross-cli-contract.md +49 -5
- package/pipeline/multi-agent-refs/features/analysis-jira.md +11 -0
- package/pipeline/multi-agent-refs/features/design-conformance.md +10 -0
- package/pipeline/multi-agent-refs/features/doctor.md +10 -0
- package/pipeline/multi-agent-refs/features/external-context-injection.md +7 -0
- package/pipeline/multi-agent-refs/features/jira-context.md +9 -0
- package/pipeline/multi-agent-refs/features/model-fallback.md +10 -0
- package/pipeline/multi-agent-refs/features/skill-conformance.md +13 -0
- package/pipeline/multi-agent-refs/features/url-enrichment.md +9 -0
- package/pipeline/multi-agent-refs/features/visual-evidence.md +61 -7
- package/pipeline/multi-agent-refs/generate-issue.md +7 -0
- package/pipeline/multi-agent-refs/issue-jira-triad.md +9 -0
- package/pipeline/multi-agent-refs/knowledge.md +6 -0
- package/pipeline/multi-agent-refs/multi-repo-integration-build.md +13 -0
- package/pipeline/multi-agent-refs/phases/modes.md +7 -0
- package/pipeline/multi-agent-refs/phases/operations.md +9 -0
- package/pipeline/multi-agent-refs/phases/phase-0-init.md +2 -2
- package/pipeline/multi-agent-refs/phases/phase-2-planning.md +17 -15
- package/pipeline/multi-agent-refs/phases/phase-3-dev.md +1 -1
- package/pipeline/multi-agent-refs/phases/phase-6-commit.md +1 -1
- package/pipeline/multi-agent-refs/phases.md +11 -0
- package/pipeline/multi-agent-refs/picker-contract.md +12 -0
- package/pipeline/multi-agent-refs/platform-parity.md +10 -0
- package/pipeline/multi-agent-refs/progress-contract.md +10 -0
- package/pipeline/multi-agent-refs/readiness-review.md +7 -1
- package/pipeline/multi-agent-refs/rules.md +3 -11
- package/pipeline/multi-agent-refs/setup/firebase.md +9 -0
- package/pipeline/multi-agent-refs/swiftui-guide.md +17 -0
- package/pipeline/multi-agent-refs/tracker-contract.md +44 -0
- package/pipeline/multi-agent-refs/web-guide.md +10 -0
- package/pipeline/multi-agent-refs/wiki-capture.md +11 -0
- package/pipeline/schemas/autopilot-config.schema.json +149 -0
- package/pipeline/schemas/prefs.schema.json +4 -0
- package/pipeline/schemas/token-budget.json +10 -19
- package/pipeline/scripts/autopilot-arming.mjs +147 -0
- package/pipeline/scripts/autopilot-intake.mjs +387 -0
- package/pipeline/scripts/autopilot-menubar.swift +361 -0
- package/pipeline/scripts/autopilot-runner.mjs +354 -0
- package/pipeline/scripts/autopilot-status.sh +213 -0
- package/pipeline/scripts/capture-evidence.sh +79 -11
- package/pipeline/scripts/gen-ref-toc.mjs +279 -0
- package/pipeline/scripts/jira-search.sh +70 -0
- package/pipeline/scripts/phase-tracker.sh +134 -12
- package/pipeline/scripts/probe-evidence-capability.sh +27 -3
- package/pipeline/scripts/run-ui-tests.sh +113 -4
- package/pipeline/skills/.skill-manifest.json +16 -4
- package/pipeline/skills/shared/core/multi-agent-autopilot-off/SKILL.md +67 -0
- package/pipeline/skills/shared/core/multi-agent-autopilot-on/SKILL.md +146 -0
- package/pipeline/skills/shared/core/multi-agent-autopilot-status/SKILL.md +64 -0
- package/pipeline/skills/shared/core/multi-agent-channels/SKILL.md +62 -11
- 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.
|
|
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`.
|
|
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
|
-
|
|
201
|
-
|
|
202
|
-
|
|
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
|
-
|
|
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
|
|