@hanzlaa/rcode 4.0.0 → 4.1.1
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/AGENTS.md +1 -1
- package/README.md +2 -2
- package/cli/doctor.js +17 -0
- package/cli/github-sync.js +3 -2
- package/cli/index.js +16 -0
- package/cli/install.js +1 -0
- package/cli/lib/manifest.cjs +13 -0
- package/cli/set-mode.js +10 -0
- package/cli/set-profile.js +10 -0
- package/cli/uninstall.js +100 -39
- package/cli/workflow.js +97 -0
- package/dist/rcode.js +249 -229
- package/package.json +1 -1
- package/rcode/bin/lib/config.cjs +3 -2
- package/rcode/bin/rcode-tools.cjs +8 -3
- package/rcode/skills/SKILLS_INDEX.md +4 -3
- package/rcode/skills/actions/1-analysis/rcode-document-project/SKILL.md +6 -0
- package/rcode/skills/actions/3-solutioning/rcode-check-implementation-readiness/SKILL.md +6 -0
- package/rcode/skills/actions/3-solutioning/rcode-create-architecture/steps/step-01-init.md +1 -1
- package/rcode/skills/actions/3-solutioning/rcode-create-architecture/workflow.md +13 -1
- package/rcode/skills/actions/4-implementation/rcode-herdr-orchestration/SKILL.md +166 -0
- package/rcode/skills/actions/4-implementation/rcode-herdr-orchestration/references.md +136 -0
- package/rcode/skills/actions/4-implementation/rcode-herdr-orchestration/rules/backlog-building.md +113 -0
- package/rcode/skills/actions/4-implementation/rcode-herdr-orchestration/rules/composition-with-herdr.md +85 -0
- package/rcode/skills/actions/4-implementation/rcode-herdr-orchestration/rules/integration-branch.md +191 -0
- package/rcode/skills/actions/4-implementation/rcode-herdr-orchestration/rules/merge-strategy.md +113 -0
- package/rcode/skills/actions/4-implementation/rcode-herdr-orchestration/rules/orchestrator-rhythm.md +119 -0
- package/rcode/skills/actions/4-implementation/rcode-herdr-orchestration/rules/wave-design.md +100 -0
- package/rcode/skills/actions/4-implementation/rcode-herdr-orchestration/templates/BACKLOG-template.md +34 -0
- package/rcode/skills/actions/4-implementation/rcode-herdr-orchestration/templates/STATE-template.md +40 -0
- package/rcode/skills/actions/4-implementation/rcode-herdr-orchestration/templates/heartbeat.sh +29 -0
- package/rcode/skills/actions/4-implementation/rcode-herdr-orchestration/templates/wave-prompt.md +69 -0
- package/rcode/skills/actions/4-implementation/rcode-retrospective/workflow.md +61 -246
- package/rcode/templates/sprint.md +16 -0
- package/rcode/workflows/audit.md +3 -0
- package/rcode/workflows/brainstorm.md +1 -1
- package/rcode/workflows/council.md +8 -1
- package/rcode/workflows/create-architecture.md +5 -1
- package/rcode/workflows/create-prd.md +5 -1
- package/rcode/workflows/dashboard.md +5 -2
- package/rcode/workflows/discuss-phase.md +3 -15
- package/rcode/workflows/execute-sprint.md +3 -1
- package/rcode/workflows/plan-spawn-planner.md +96 -0
- package/rcode/workflows/plan.md +67 -0
- package/rcode/workflows/retrospective.md +5 -1
- package/rcode/workflows/sprint-planning.md +9 -5
- package/server/dashboard.js +2 -2
package/rcode/skills/actions/4-implementation/rcode-herdr-orchestration/rules/integration-branch.md
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# Campaign Integration Branch
|
|
2
|
+
|
|
3
|
+
The orchestrator maintains its own long-lived parent branch for the campaign. Sub-agents fork from it, merges land on it, master stays untouched until the user explicitly lands the whole campaign.
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
A prior campaign session (2026-05-26) revealed the failure mode this rule prevents:
|
|
8
|
+
|
|
9
|
+
- Sub-agents in Wave-1 forked directly from `master`. They committed.
|
|
10
|
+
- Wave-1 merges landed on `master`.
|
|
11
|
+
- Wave-2 sub-agents forked from `master` again — at a HEAD that already had Wave-1's merges.
|
|
12
|
+
- **But the worktrees were created with `git worktree add ... master` at slightly different times, and some Wave-1 work was still in flight on its own branches.**
|
|
13
|
+
- Wave-2 branches overlapped with Wave-1 branches' files → cross-wave merge conflicts.
|
|
14
|
+
- The orchestrator spent multiple ticks resolving those conflicts instead of shipping new work.
|
|
15
|
+
- Some branches couldn't be auto-merged at all and got queued for a rebase agent, who introduced TSC regressions of its own.
|
|
16
|
+
|
|
17
|
+
The fix: **one campaign integration branch**, serially advanced. Sub-agents always fork from the integration branch's CURRENT TIP (not a snapshot, not master). When a wave's merges land on the integration branch, the next wave's sub-agents inherit them automatically.
|
|
18
|
+
|
|
19
|
+
## Rules
|
|
20
|
+
|
|
21
|
+
### Naming
|
|
22
|
+
|
|
23
|
+
| Branch | When to use |
|
|
24
|
+
|---|---|
|
|
25
|
+
| `campaign-integration` | Default for unnamed campaigns. |
|
|
26
|
+
| `campaign-<topic>` | When the campaign has a coherent theme (e.g. `campaign-crm-cleanup`, `campaign-q2-tech-debt`). |
|
|
27
|
+
| `campaign-<topic>-<wave>` | Don't use. The integration branch is one branch across all waves. Per-wave naming defeats the purpose. |
|
|
28
|
+
|
|
29
|
+
Sub-agent branches stay named `campaign-<area>` and live as short-lived feature branches that merge into the integration branch.
|
|
30
|
+
|
|
31
|
+
### Lifecycle
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
master ┐
|
|
35
|
+
├─ campaign-integration (branch) │ <-- orchestrator stays here
|
|
36
|
+
│ ├─ campaign-area-1 │ <-- sub-agent Wave 1
|
|
37
|
+
│ ├─ campaign-area-2 │
|
|
38
|
+
│ ├─ campaign-area-3 │
|
|
39
|
+
│ │
|
|
40
|
+
│ │ <-- Wave 1 merged into campaign-integration
|
|
41
|
+
│ │
|
|
42
|
+
│ ├─ campaign-area-4 │ <-- Wave 2 forks from updated integration
|
|
43
|
+
│ ├─ campaign-area-5 │
|
|
44
|
+
│ │
|
|
45
|
+
│ │ <-- Wave 2 merged
|
|
46
|
+
│ │
|
|
47
|
+
│ └─ (continues...) │
|
|
48
|
+
│ │
|
|
49
|
+
└─ (Phase 3: integration → master)│
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Pre-flight (Phase 0)
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
git checkout master && git pull origin master # start fresh
|
|
56
|
+
git checkout -b campaign-integration master
|
|
57
|
+
git push -u origin campaign-integration # OPTIONAL — only the integration branch may be auto-pushed
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The integration branch can be auto-pushed because:
|
|
61
|
+
- It is **not master** — pushing it does not affect production.
|
|
62
|
+
- It enables PR-style review via GitHub.
|
|
63
|
+
- It survives orchestrator crashes (work lives on origin).
|
|
64
|
+
|
|
65
|
+
If the user says "no push of anything ever" — respect that. Don't push the integration branch either.
|
|
66
|
+
|
|
67
|
+
### Sub-agent worktree creation
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# WRONG — direct fork from master, cross-wave conflict risk
|
|
71
|
+
git worktree add ../sm-worktrees/camp-<area> -b campaign-<area> master
|
|
72
|
+
|
|
73
|
+
# RIGHT — fork from integration branch
|
|
74
|
+
git worktree add ../sm-worktrees/camp-<area> -b campaign-<area> campaign-integration
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Merging during a wave (Phase 2)
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# orchestrator's main worktree is checked out on campaign-integration
|
|
81
|
+
git merge campaign-<area> --no-edit
|
|
82
|
+
NEW_TSC=$(pnpm tsc --noEmit 2>&1 | grep -c "error TS")
|
|
83
|
+
if [ "$NEW_TSC" -gt "$INTEGRATION_BASELINE_TSC" ]; then
|
|
84
|
+
git reset --hard HEAD~1 # back out of integration branch, NOT master
|
|
85
|
+
fi
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Master never enters the picture during merges. The TSC gate compares against the integration branch's recorded baseline, not master's.
|
|
89
|
+
|
|
90
|
+
### Sync from master during long campaigns
|
|
91
|
+
|
|
92
|
+
If the campaign runs for hours and other work lands on master from outside, periodically pull master into the integration branch:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# orchestrator on campaign-integration
|
|
96
|
+
git fetch origin
|
|
97
|
+
git merge origin/master --no-edit # fast-forward when possible, conflict-resolve when not
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Do this between waves, NEVER mid-wave (would disrupt in-flight sub-agents whose branches were forked from the older integration tip).
|
|
101
|
+
|
|
102
|
+
### Landing (Phase 3)
|
|
103
|
+
|
|
104
|
+
When BACKLOG.md is empty and all sub-agent branches have merged into the integration branch:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
git checkout campaign-integration
|
|
108
|
+
git diff master..campaign-integration --stat # show user the change set
|
|
109
|
+
git log master..campaign-integration --oneline # show user the commit list
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Then **ask the user**:
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
Campaign-integration is N commits ahead of master.
|
|
116
|
+
How do you want to land it?
|
|
117
|
+
(a) Open a PR: gh pr create --base master --head campaign-integration
|
|
118
|
+
(b) Merge to master locally (--no-ff for a clean merge commit)
|
|
119
|
+
(c) Squash-merge to master (one tidy commit, history compressed)
|
|
120
|
+
(d) Leave campaign-integration as-is — I'll review later
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Do NOT default to any of these. Wait for the user's answer.
|
|
124
|
+
|
|
125
|
+
## Examples
|
|
126
|
+
|
|
127
|
+
### Three-wave campaign with integration branch
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
T+0: git checkout -b campaign-integration master # Phase 0
|
|
131
|
+
T+1: wave 1: 4 sub-agents fork from campaign-integration
|
|
132
|
+
T+15m: wave 1 merges land on campaign-integration (NOT master)
|
|
133
|
+
T+15m: wave 2: 4 sub-agents fork from updated campaign-integration
|
|
134
|
+
↑ inherits wave 1's work automatically
|
|
135
|
+
T+30m: wave 2 merges land on campaign-integration
|
|
136
|
+
T+30m: wave 3: 4 sub-agents fork from updated campaign-integration
|
|
137
|
+
T+45m: wave 3 merges land
|
|
138
|
+
T+45m: BACKLOG empty. Ask user how to land. (PR / merge / squash / leave)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Cross-wave conflicts disappear because every sub-agent sees the previous waves' merged work.
|
|
142
|
+
|
|
143
|
+
### Sync from master mid-campaign (rare)
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
T+0h: Start campaign-integration from master.
|
|
147
|
+
T+2h: Wave 1, 2 done on integration branch.
|
|
148
|
+
T+2h: Notice another team merged "fix(auth): X" to master.
|
|
149
|
+
T+2h: Between waves: orchestrator on campaign-integration runs
|
|
150
|
+
`git merge origin/master --no-edit` → fast-forward succeeds.
|
|
151
|
+
T+2h: Wave 3 forks from now-up-to-date integration branch.
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Anti-Patterns
|
|
155
|
+
|
|
156
|
+
### Forking sub-agents from master directly
|
|
157
|
+
|
|
158
|
+
**Problem**: Cross-wave conflicts pile up — sibling branches stomp on the same files because they both fork from the same parent without seeing each other's work.
|
|
159
|
+
**Instead**: Sub-agents always fork from `campaign-integration`.
|
|
160
|
+
|
|
161
|
+
### Treating the integration branch as just-another-branch and merging it to master mid-campaign
|
|
162
|
+
|
|
163
|
+
**Problem**: Defeats the isolation. If you ship integration → master on every wave, you're back to the old direct-on-master pattern.
|
|
164
|
+
**Instead**: Merge integration → master only once, at Phase 3, with explicit user consent.
|
|
165
|
+
|
|
166
|
+
### Per-wave integration branches (`campaign-wave1-integration`, `campaign-wave2-integration`)
|
|
167
|
+
|
|
168
|
+
**Problem**: Now you have to merge the wave integrations together at the end — adds a layer of merge work for no benefit. The whole point of integration is one durable line.
|
|
169
|
+
**Instead**: One integration branch, serially advanced across all waves.
|
|
170
|
+
|
|
171
|
+
### Skipping the Phase-3 "how do you want to land it" question
|
|
172
|
+
|
|
173
|
+
**Problem**: Auto-merging integration → master at campaign end repeats the no-consent-push mistake at the local level.
|
|
174
|
+
**Instead**: Always ask. Present PR / merge / squash / leave as explicit options.
|
|
175
|
+
|
|
176
|
+
### Pushing campaign-integration without checking first
|
|
177
|
+
|
|
178
|
+
**Problem**: User may have a "no push" preference that covers ALL refs, not just master.
|
|
179
|
+
**Instead**: For the very first push of the integration branch, ask once. Subsequent pushes of the same branch can use that answer.
|
|
180
|
+
|
|
181
|
+
## Related
|
|
182
|
+
|
|
183
|
+
- `orchestrator-rhythm.md` — heartbeat continues while integration branch has open waves
|
|
184
|
+
- `wave-design.md` — wave size still 3-5; integration branch doesn't change wave structure
|
|
185
|
+
- `merge-strategy.md` — TSC gate is now against integration baseline, not master
|
|
186
|
+
- `backlog-building.md` — BACKLOG and STATE files live on the integration branch
|
|
187
|
+
- `composition-with-herdr.md` — herdr panes still own per-sub-agent worktrees; orchestrator owns the integration branch's main worktree
|
|
188
|
+
|
|
189
|
+
## Changelog
|
|
190
|
+
|
|
191
|
+
- 2026-05-26: Initial. Codified from the session that revealed cross-wave conflict explosions — the orchestrator was merging sub-agent branches into master directly, which forced parallel waves to fight over the same files. The integration-branch pattern eliminates that.
|
package/rcode/skills/actions/4-implementation/rcode-herdr-orchestration/rules/merge-strategy.md
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Merge Strategy + TSC Gate
|
|
2
|
+
|
|
3
|
+
How to merge wave output **into the campaign integration branch** without regressing. Master is never touched during the campaign — see `integration-branch.md`.
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
Parallel branches stomp on shared files. Merging requires a discipline: smallest first, TSC at every step, abort on first sign of trouble.
|
|
7
|
+
|
|
8
|
+
## Rules
|
|
9
|
+
|
|
10
|
+
### Order: smallest first
|
|
11
|
+
Sort campaign branches by `git rev-list --count campaign-integration..<branch>` ascending. Merge the smallest one first.
|
|
12
|
+
- Validates the merge flow on low-risk content.
|
|
13
|
+
- Lets big branches rebase on top of small ones (less conflict per merge step).
|
|
14
|
+
|
|
15
|
+
### TSC baseline gate
|
|
16
|
+
Before any wave:
|
|
17
|
+
```bash
|
|
18
|
+
TSC_BASELINE=$(pnpm tsc --noEmit 2>&1 | grep -c "error TS")
|
|
19
|
+
```
|
|
20
|
+
After every merge:
|
|
21
|
+
```bash
|
|
22
|
+
TSC_NEW=$(pnpm tsc --noEmit 2>&1 | grep -c "error TS")
|
|
23
|
+
if [ "$TSC_NEW" -gt "$TSC_BASELINE" ]; then
|
|
24
|
+
echo "Regression on this merge — reverting"
|
|
25
|
+
git reset --hard HEAD~1
|
|
26
|
+
fi
|
|
27
|
+
```
|
|
28
|
+
**Never compound regressions across waves.**
|
|
29
|
+
|
|
30
|
+
### Conflict resolution (delegates to herdr-orchestration)
|
|
31
|
+
- Content conflicts: read both sides, keep the **more-complete superset side**, remove markers, syntax-check, stage, commit. (See herdr-orchestration rules.)
|
|
32
|
+
- AA conflicts (add/add): peek both versions; if nearly identical, keep the canonical owner's version. The "owner" is the branch whose audit doc claimed the feature.
|
|
33
|
+
- Unable to resolve safely: `git merge --abort`, mark the branch as `[needs-rebase]` in STATE.md, queue for next wave's resolution pass.
|
|
34
|
+
|
|
35
|
+
### Push policy
|
|
36
|
+
**During the campaign**: NEVER `git push origin campaign-integration`. The orchestrator is on the integration branch, not master.
|
|
37
|
+
|
|
38
|
+
Pushing the integration branch itself is permitted (it's not master, it's isolated), but ASK ONCE at Phase 0:
|
|
39
|
+
```bash
|
|
40
|
+
git push -u origin campaign-integration 2>&1 | tail -3
|
|
41
|
+
```
|
|
42
|
+
Once that question is answered yes, the orchestrator may push the integration branch silently after each wave merge (helpful for PR previews and survival across restarts).
|
|
43
|
+
|
|
44
|
+
**At Phase 3 only**: ask the user how to land the campaign. Options: PR, local merge to master, squash, or leave. Push master ONLY if they say "yes, merge and push to master" — explicit, never inferred. Never rely on `git push 2>/dev/null || true` patterns (they swallow auth failures and diverge silently).
|
|
45
|
+
|
|
46
|
+
### Worktree cleanup
|
|
47
|
+
After a branch is merged AND pushed:
|
|
48
|
+
```bash
|
|
49
|
+
git worktree remove --force ../sm-worktrees/camp-<area>
|
|
50
|
+
git branch -d campaign-<area>
|
|
51
|
+
```
|
|
52
|
+
Frees space and keeps `git worktree list` readable.
|
|
53
|
+
|
|
54
|
+
## Examples
|
|
55
|
+
|
|
56
|
+
### Single-wave merge sweep
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
for B in $(git branch --format="%(refname:short)" | grep "^campaign-"); do
|
|
60
|
+
C=$(git rev-list --count master..$B 2>/dev/null)
|
|
61
|
+
[ "$C" = "0" ] && continue
|
|
62
|
+
echo "=== merging $B ($C commits) ==="
|
|
63
|
+
if git merge "$B" --no-edit 2>&1 | tail -5 | grep -q "CONFLICT"; then
|
|
64
|
+
echo "CONFLICT — aborting and queueing $B for resolution"
|
|
65
|
+
git merge --abort
|
|
66
|
+
echo "$B" >> .planning/campaign/NEEDS-REBASE.md
|
|
67
|
+
else
|
|
68
|
+
NEW=$(pnpm tsc --noEmit 2>&1 | grep -c "error TS")
|
|
69
|
+
if [ "$NEW" -gt "$TSC_BASELINE" ]; then
|
|
70
|
+
echo "TSC regressed ($TSC_BASELINE → $NEW) — reverting $B"
|
|
71
|
+
git reset --hard HEAD~1
|
|
72
|
+
fi
|
|
73
|
+
fi
|
|
74
|
+
done
|
|
75
|
+
git push origin campaign-integration
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Aborted merge handling
|
|
79
|
+
|
|
80
|
+
When a conflict aborts:
|
|
81
|
+
1. The branch stays alive — work isn't lost.
|
|
82
|
+
2. The orchestrator's next turn dispatches a single rebase agent specifically for `NEEDS-REBASE.md` items.
|
|
83
|
+
3. After rebase, retry merge.
|
|
84
|
+
|
|
85
|
+
## Anti-Patterns
|
|
86
|
+
|
|
87
|
+
### Auto-resolving conflicts with `-X theirs` or `-X ours`
|
|
88
|
+
|
|
89
|
+
**Problem**: Strategy options pick a whole side, discarding the other branch's work without inspection.
|
|
90
|
+
**Instead**: Read both sides; superset rule; if uncertain, abort and queue.
|
|
91
|
+
|
|
92
|
+
### Merging while sub-agents are still active on overlapping files
|
|
93
|
+
|
|
94
|
+
**Problem**: Sub-agent's later commit invalidates the merge you just made.
|
|
95
|
+
**Instead**: Only merge branches whose status is `idle`/`done`. `working` branches stay queued.
|
|
96
|
+
|
|
97
|
+
### Skipping the TSC check
|
|
98
|
+
|
|
99
|
+
**Problem**: A type error silently lands on master, next wave forks from broken master, regression compounds.
|
|
100
|
+
**Instead**: TSC after every merge. Revert immediately on regression.
|
|
101
|
+
|
|
102
|
+
### Force-pushing master to "fix" a regression
|
|
103
|
+
|
|
104
|
+
**Problem**: Destroys local work, can lose unpushed wave output.
|
|
105
|
+
**Instead**: `git reset --hard HEAD~1` (no force-push) to undo a bad local merge before pushing.
|
|
106
|
+
|
|
107
|
+
## Related
|
|
108
|
+
- `orchestrator-rhythm.md` — merges happen during heartbeat ticks, not in the middle of dispatch
|
|
109
|
+
- `wave-design.md` — wave composition determines conflict surface area
|
|
110
|
+
- `composition-with-herdr.md` — herdr conflict-resolution superset rule
|
|
111
|
+
|
|
112
|
+
## Changelog
|
|
113
|
+
- 2026-05-26: Initial.
|
package/rcode/skills/actions/4-implementation/rcode-herdr-orchestration/rules/orchestrator-rhythm.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Orchestrator Rhythm + Heartbeat
|
|
2
|
+
|
|
3
|
+
The orchestrator must never go silent while sub-agents are still working.
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
A long-running campaign hits two failure modes that this rule prevents:
|
|
7
|
+
1. **Silent assistant**: orchestrator answers a question, then never wakes back up — sub-agents finish, their commits sit unmerged.
|
|
8
|
+
2. **Polling waste**: orchestrator wakes too often (every 60s), burning cache misses and tokens.
|
|
9
|
+
|
|
10
|
+
## Rules
|
|
11
|
+
|
|
12
|
+
### Heartbeat sources — IMPORTANT distinctions
|
|
13
|
+
|
|
14
|
+
**`ScheduleWakeup` only fires when `/loop` mode is active.** Outside `/loop`, it is effectively a no-op — the harness will NOT re-invoke the assistant after the delay. The assistant must verify this before relying on it.
|
|
15
|
+
|
|
16
|
+
**To actually auto-wake the orchestrator during a campaign, pick ONE of these:**
|
|
17
|
+
|
|
18
|
+
1. **`/loop` mode (RECOMMENDED for long campaigns)** — User invokes `/loop` at the start of the campaign. After that, the assistant's `ScheduleWakeup` calls actually fire and re-invoke autonomously. The user can ctrl-c the loop at any time. This is the only built-in path to true autonomous re-invocation.
|
|
19
|
+
|
|
20
|
+
2. **`/schedule` (cron-based)** — User creates a scheduled routine that pings the assistant at fixed intervals (e.g. every 15 min). Survives session restarts. Requires Anthropic's scheduled-agents feature. Best for multi-hour campaigns where the user closes the terminal.
|
|
21
|
+
|
|
22
|
+
3. **Manual pinging** — User types `<<autonomous-loop-dynamic>>` (or just "check status") each time they want progress. Most honest default if `/loop` and `/schedule` aren't available. The orchestrator should be honest with the user that nothing auto-fires.
|
|
23
|
+
|
|
24
|
+
4. **Bash heartbeat file** — Only an EXTERNAL liveness signal. `touch .planning/campaign/HEARTBEAT` every 30s in a background bash loop. **This does NOT wake the assistant** — it only tells an external watcher (you, a monitor script) that the campaign hasn't crashed. Useful as a secondary check, never as the primary heartbeat.
|
|
25
|
+
|
|
26
|
+
### Be honest at campaign start
|
|
27
|
+
|
|
28
|
+
At Phase 0, the orchestrator MUST clarify with the user which heartbeat path is in effect:
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
Heartbeat options for this campaign:
|
|
32
|
+
(a) Wrap the campaign in /loop so auto-wakeup actually fires (recommended for >1h work)
|
|
33
|
+
(b) Use /schedule to ping every N minutes (best for multi-hour, can-close-terminal campaigns)
|
|
34
|
+
(c) Manual mode — you ping me with "check status" whenever you want progress
|
|
35
|
+
|
|
36
|
+
Which would you like? (a/b/c)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
If the user picks (c) or skips: NEVER claim "Scheduling 20-min wakeup" in chat — that's a lie. Say instead: "12 agents detached and running. Ping me back with 'check status' when you want me to merge results."
|
|
40
|
+
|
|
41
|
+
### Cadence by phase (only relevant under /loop or /schedule)
|
|
42
|
+
|
|
43
|
+
| Phase | Heartbeat interval | Rationale |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| Phase 1 (wave just dispatched) | 720s | Sub-agents need 10-15 min to produce a commit |
|
|
46
|
+
| Phase 2 (multiple waves running) | 540-720s | Slightly tighter — more chances to merge |
|
|
47
|
+
| Phase 3 (draining last waves) | 270s | Sub-agents finishing close to each other; don't miss the last |
|
|
48
|
+
| Idle (waiting on stuck pane) | 1200s | Sub-agent stuck — give it room or surface it |
|
|
49
|
+
|
|
50
|
+
### Cadence by phase
|
|
51
|
+
|
|
52
|
+
| Phase | Heartbeat interval | Rationale |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| Phase 1 (wave just dispatched) | 720s | Sub-agents need 10-15 min to produce a commit |
|
|
55
|
+
| Phase 2 (multiple waves running) | 540-720s | Slightly tighter — more chances to merge |
|
|
56
|
+
| Phase 3 (draining last waves) | 270s | Sub-agents finishing close to each other; don't miss the last |
|
|
57
|
+
| Idle (waiting on stuck pane) | 1200s | Sub-agent stuck — give it room or surface it |
|
|
58
|
+
|
|
59
|
+
### Stop conditions
|
|
60
|
+
The heartbeat should stop ONLY when ALL three are true:
|
|
61
|
+
- Every herdr pane is `idle` or `done`
|
|
62
|
+
- Every campaign branch has been merged or marked rejected
|
|
63
|
+
- `.planning/campaign/BACKLOG.md` is empty (or only contains items marked `[skip]`)
|
|
64
|
+
|
|
65
|
+
## Examples
|
|
66
|
+
|
|
67
|
+
### End-of-turn pattern (every campaign turn)
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
ScheduleWakeup(
|
|
71
|
+
delaySeconds=720,
|
|
72
|
+
reason="Wave-3 in flight; expect commits within 10 min then merge + dispatch wave-4",
|
|
73
|
+
prompt="<<autonomous-loop-dynamic>>"
|
|
74
|
+
)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Heartbeat bash template
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
#!/bin/bash
|
|
81
|
+
# Run with: bash heartbeat.sh & echo $! > .planning/campaign/HEARTBEAT.pid
|
|
82
|
+
HEARTBEAT=.planning/campaign/HEARTBEAT
|
|
83
|
+
while true; do
|
|
84
|
+
date -u +%FT%TZ > "$HEARTBEAT"
|
|
85
|
+
sleep 30
|
|
86
|
+
done
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Resuming after auto-compact
|
|
90
|
+
|
|
91
|
+
If the orchestrator hits auto-compact mid-campaign, the first turn after must:
|
|
92
|
+
1. Read `.planning/campaign/STATE.md` — figure out which wave is in flight.
|
|
93
|
+
2. Run `herdr pane list` — find which panes are still working.
|
|
94
|
+
3. Run `git branch | grep campaign-` + `git rev-list --count master..<each>` — find unmerged commits.
|
|
95
|
+
4. Resume from Phase 2 of the workflow. Do not redispatch waves that are already in flight.
|
|
96
|
+
|
|
97
|
+
## Anti-Patterns
|
|
98
|
+
|
|
99
|
+
### Polling every 60s
|
|
100
|
+
|
|
101
|
+
**Problem**: Wakeup interval shorter than 270s burns the Anthropic prompt cache repeatedly without any real work happening (sub-agents need minutes between commits).
|
|
102
|
+
**Instead**: 540-720s default. Drop to 270s only when wrapping the last wave.
|
|
103
|
+
|
|
104
|
+
### Bash `sleep && check` loop instead of ScheduleWakeup
|
|
105
|
+
|
|
106
|
+
**Problem**: A blocking `sleep` in the assistant's own session ties up the conversation slot. The harness blocks long leading sleeps anyway.
|
|
107
|
+
**Instead**: Use ScheduleWakeup. The bash heartbeat is for a SEPARATE background process, not for sleeping in the assistant's bash.
|
|
108
|
+
|
|
109
|
+
### Ending a turn without scheduling wakeup while sub-agents are working
|
|
110
|
+
|
|
111
|
+
**Problem**: Orchestrator returns control to user, user doesn't reply, sub-agents complete, no one merges, work rots.
|
|
112
|
+
**Instead**: Last action of every campaign turn = `ScheduleWakeup`. Non-negotiable.
|
|
113
|
+
|
|
114
|
+
## Related
|
|
115
|
+
- `wave-design.md` — how wave size affects cadence
|
|
116
|
+
- `composition-with-herdr.md` — herdr pane status states (`working`/`idle`/`done`) drive the loop exit
|
|
117
|
+
|
|
118
|
+
## Changelog
|
|
119
|
+
- 2026-05-26: Initial. Codified from session that shipped 200+ commits across ~12 waves.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Wave Design
|
|
2
|
+
|
|
3
|
+
How to size, split, and sequence campaign waves.
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
A campaign with too few agents underuses parallelism; too many causes merge conflicts and stalls. This rule encodes the sizing + sequencing that worked across long sessions.
|
|
7
|
+
|
|
8
|
+
## Rules
|
|
9
|
+
|
|
10
|
+
### Wave size
|
|
11
|
+
- **Default: 4 agents per wave.** 2x2 herdr grid, easy to monitor visually.
|
|
12
|
+
- **Minimum: 3.** Below 3 the orchestrator overhead isn't justified — just do the work directly.
|
|
13
|
+
- **Maximum: 5.** Above 5 the merge stage becomes painful and TSC regressions compound across simultaneous changes.
|
|
14
|
+
- **Sequential or concurrent waves?** Concurrent only if you have >8 distinct unrelated areas AND the merge bookkeeping is automated. Default is sequential: dispatch wave → merge → dispatch wave.
|
|
15
|
+
|
|
16
|
+
### Wave scope rules
|
|
17
|
+
Each agent in a wave must:
|
|
18
|
+
- Own a **distinct audit area** (no two agents touching the same file domain).
|
|
19
|
+
- Have a **clear stop signal** — fix 3-5 items, then return. No "keep going until I say stop".
|
|
20
|
+
- Be **diagnose-then-fix**, not "rewrite this area".
|
|
21
|
+
|
|
22
|
+
Cross-agent overlap risks (use these to vet wave composition):
|
|
23
|
+
|
|
24
|
+
| If wave includes both… | Conflict risk | Mitigation |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| `lead-types` + `call-update-flow` | Both touch `leadService.js`/`callService.js` | Run sequentially, not concurrent |
|
|
27
|
+
| `crm-pipeline` + `deals-pipeline-forecast` | Both touch deal stage logic | Split: one schema, one UI |
|
|
28
|
+
| `email-system` + `email-sequences` | Both touch templating | Run sequentially |
|
|
29
|
+
| `oauth-callbacks` + `integrations-developer` | Both touch OAuth handlers | Different providers per agent |
|
|
30
|
+
|
|
31
|
+
### Item picking heuristics
|
|
32
|
+
|
|
33
|
+
For each backlog item, score before assigning to a wave:
|
|
34
|
+
|
|
35
|
+
| Criterion | Good for wave | Bad for wave |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| Blast radius | 1-5 files | 20+ files |
|
|
38
|
+
| Has Prisma schema change | OK with migration | Not OK without migration |
|
|
39
|
+
| Cross-cuts auth/RBAC | Solo agent | Avoid |
|
|
40
|
+
| Touches WebSocket/realtime | Solo agent | Avoid |
|
|
41
|
+
| Pure UI/CSS | Great parallel target | — |
|
|
42
|
+
| Pure backend logic in one service | Great parallel target | — |
|
|
43
|
+
|
|
44
|
+
### Wave duration
|
|
45
|
+
- Target: 10-15 min per wave.
|
|
46
|
+
- Past 25 min: peek at all panes, identify stuck agents, decide kill-or-wait.
|
|
47
|
+
- Hard stop: 45 min. If a wave hasn't produced commits in 45 min, something is wrong — abort and re-dispatch.
|
|
48
|
+
|
|
49
|
+
## Examples
|
|
50
|
+
|
|
51
|
+
### Good wave-1 composition (from real session)
|
|
52
|
+
```
|
|
53
|
+
camp-crm-pipeline ← AUDIT-CRM-pipeline P1/P2
|
|
54
|
+
camp-crm-reporting ← AUDIT-CRM-reporting P1/P2
|
|
55
|
+
camp-deals-forecast ← AUDIT-deals-pipeline-forecast P1
|
|
56
|
+
camp-crm-activity ← AUDIT-CRM-activity P1
|
|
57
|
+
```
|
|
58
|
+
Distinct services, distinct schema tables, no overlap.
|
|
59
|
+
|
|
60
|
+
### Bad wave composition
|
|
61
|
+
```
|
|
62
|
+
camp-leads-A ← leadService refactor
|
|
63
|
+
camp-leads-B ← leadService bug fixes
|
|
64
|
+
camp-leads-C ← leadService new feature
|
|
65
|
+
camp-leads-D ← leadService perf
|
|
66
|
+
```
|
|
67
|
+
All four touch `leadService.js` — merge will be a conflict bloodbath.
|
|
68
|
+
|
|
69
|
+
### Phased waves (when items naturally depend on each other)
|
|
70
|
+
```
|
|
71
|
+
Wave 1: schema additions (lead-types schema, conversation schema)
|
|
72
|
+
Wave 2: backend wiring on top of Wave 1's schema
|
|
73
|
+
Wave 3: UI on top of Wave 2's API
|
|
74
|
+
```
|
|
75
|
+
Each phase merges before the next dispatches.
|
|
76
|
+
|
|
77
|
+
## Anti-Patterns
|
|
78
|
+
|
|
79
|
+
### Dispatching all backlog items at once
|
|
80
|
+
|
|
81
|
+
**Problem**: 17 audit docs × 4 items = 68 simultaneous agents. Herdr can't manage that; merge stage becomes O(N²).
|
|
82
|
+
**Instead**: 4 agents at a time, 17 waves over the campaign.
|
|
83
|
+
|
|
84
|
+
### Reusing a worktree across waves
|
|
85
|
+
|
|
86
|
+
**Problem**: Worktree state lingers — uncommitted files, stale `node_modules` symlink, half-merged branch.
|
|
87
|
+
**Instead**: Fresh worktree per wave-agent. Tear down after merge.
|
|
88
|
+
|
|
89
|
+
### Wave with no audit doc backing
|
|
90
|
+
|
|
91
|
+
**Problem**: Agent invents work that wasn't asked for; commits get rejected.
|
|
92
|
+
**Instead**: Every wave-agent prompt must reference a specific audit doc with specific item numbers.
|
|
93
|
+
|
|
94
|
+
## Related
|
|
95
|
+
- `backlog-building.md` — what feeds wave selection
|
|
96
|
+
- `merge-strategy.md` — what happens after a wave completes
|
|
97
|
+
- `composition-with-herdr.md` — herdr 2x2 pane grid
|
|
98
|
+
|
|
99
|
+
## Changelog
|
|
100
|
+
- 2026-05-26: Initial.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# CAMPAIGN BACKLOG
|
|
2
|
+
|
|
3
|
+
Generated: <ISO-TIMESTAMP>
|
|
4
|
+
Repo: <REPO-NAME>
|
|
5
|
+
Baseline TSC errors: <COUNT>
|
|
6
|
+
Source: `<AUDIT-DOC-DIRECTORY>` + `grep TODO/FIXME/HACK` in `<SCAN-DIRS>`
|
|
7
|
+
|
|
8
|
+
## Open items
|
|
9
|
+
|
|
10
|
+
<!-- One bullet per atomic, mergeable unit of work. Order = priority. -->
|
|
11
|
+
|
|
12
|
+
- [ ] **<area-1>** (P1): <short description>. Source: `<audit-doc>:<line>`
|
|
13
|
+
- [ ] **<area-1>** (P2): <short description>. Source: `<audit-doc>:<line>`
|
|
14
|
+
- [ ] **<area-2>** (P1): <short description>. Source: `<audit-doc>:<line>`
|
|
15
|
+
- [ ] **<area-2>** (P2): <short description>. Source: `<audit-doc>:<line>`
|
|
16
|
+
- …
|
|
17
|
+
|
|
18
|
+
## In flight
|
|
19
|
+
|
|
20
|
+
<!-- Updated by orchestrator at every wave dispatch. -->
|
|
21
|
+
|
|
22
|
+
- [~] **<area>**: assigned to pane <pane-id>, branch `<branch>`, started <iso-time>, wave <N>
|
|
23
|
+
|
|
24
|
+
## Shipped
|
|
25
|
+
|
|
26
|
+
<!-- Updated by orchestrator at every merge. -->
|
|
27
|
+
|
|
28
|
+
- [x] **<area>**: commit `<sha>`, wave <N>, merged <iso-time>, push <iso-time>
|
|
29
|
+
|
|
30
|
+
## Skipped / blocked
|
|
31
|
+
|
|
32
|
+
<!-- Items the campaign deliberately did NOT do. Always include reason. -->
|
|
33
|
+
|
|
34
|
+
- [skip] **<area>**: <reason>. Re-evaluate after <blocker> is resolved.
|
package/rcode/skills/actions/4-implementation/rcode-herdr-orchestration/templates/STATE-template.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# CAMPAIGN STATE
|
|
2
|
+
|
|
3
|
+
Last update: <ISO-TIMESTAMP>
|
|
4
|
+
Heartbeat: `.planning/campaign/HEARTBEAT` (file mtime should be < 60s old while campaign is live)
|
|
5
|
+
Heartbeat PID: see `.planning/campaign/HEARTBEAT.pid`
|
|
6
|
+
|
|
7
|
+
## TSC drift over time
|
|
8
|
+
|
|
9
|
+
| Time (UTC) | Wave | TSC errors | Delta vs baseline |
|
|
10
|
+
|---|---|---|---|
|
|
11
|
+
| <iso> (campaign start) | 0 (baseline) | <count> | 0 |
|
|
12
|
+
| <iso> | 1 | <count> | +/-N |
|
|
13
|
+
| <iso> | 2 | <count> | +/-N |
|
|
14
|
+
|
|
15
|
+
## Wave history
|
|
16
|
+
|
|
17
|
+
### Wave 1 — <one-line theme>
|
|
18
|
+
- Dispatched: <iso>
|
|
19
|
+
- Agents: 4 (pane labels: <Pane1, Pane2, Pane3, Pane4>)
|
|
20
|
+
- Branches: `<branch-1>`, `<branch-2>`, `<branch-3>`, `<branch-4>`
|
|
21
|
+
- Outcome:
|
|
22
|
+
- merged: `<branch-1>` (3 commits), `<branch-2>` (5 commits), `<branch-3>` (2 commits)
|
|
23
|
+
- rebase needed: `<branch-4>` (conflict on shared file)
|
|
24
|
+
- Pushed to origin: <iso>
|
|
25
|
+
- Cumulative commits: <count>
|
|
26
|
+
|
|
27
|
+
### Wave 2 — <one-line theme>
|
|
28
|
+
- …
|
|
29
|
+
|
|
30
|
+
## Active panes
|
|
31
|
+
|
|
32
|
+
| Pane | Label | Branch | Status | Last commit at |
|
|
33
|
+
|---|---|---|---|---|
|
|
34
|
+
| `<pane-id>` | <label> | `<branch>` | working/idle/done | <iso> |
|
|
35
|
+
|
|
36
|
+
## Open questions / blockers
|
|
37
|
+
|
|
38
|
+
<!-- Things the orchestrator surfaces to the human at next opportunity. -->
|
|
39
|
+
|
|
40
|
+
- <blocker description>
|
package/rcode/skills/actions/4-implementation/rcode-herdr-orchestration/templates/heartbeat.sh
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Background heartbeat for the autonomous fix campaign.
|
|
3
|
+
#
|
|
4
|
+
# Run: bash heartbeat.sh & echo $! > .planning/campaign/HEARTBEAT.pid
|
|
5
|
+
# Kill: kill $(cat .planning/campaign/HEARTBEAT.pid) && rm .planning/campaign/HEARTBEAT.pid
|
|
6
|
+
#
|
|
7
|
+
# Touches .planning/campaign/HEARTBEAT every 30s with an ISO-8601 UTC timestamp.
|
|
8
|
+
# External watchers can monitor mtime to see the campaign is alive.
|
|
9
|
+
#
|
|
10
|
+
# This is the SECONDARY heartbeat. The PRIMARY heartbeat is ScheduleWakeup inside
|
|
11
|
+
# the assistant session — without ScheduleWakeup the assistant goes silent regardless
|
|
12
|
+
# of this bash loop.
|
|
13
|
+
|
|
14
|
+
set -euo pipefail
|
|
15
|
+
|
|
16
|
+
HEARTBEAT_DIR="${HEARTBEAT_DIR:-.planning/campaign}"
|
|
17
|
+
mkdir -p "$HEARTBEAT_DIR"
|
|
18
|
+
|
|
19
|
+
HEARTBEAT_FILE="$HEARTBEAT_DIR/HEARTBEAT"
|
|
20
|
+
INTERVAL="${HEARTBEAT_INTERVAL:-30}"
|
|
21
|
+
|
|
22
|
+
echo "[heartbeat] starting — writes to $HEARTBEAT_FILE every ${INTERVAL}s" >&2
|
|
23
|
+
|
|
24
|
+
trap 'echo "[heartbeat] received SIGTERM, exiting" >&2; exit 0' TERM INT
|
|
25
|
+
|
|
26
|
+
while true; do
|
|
27
|
+
date -u +%FT%TZ > "$HEARTBEAT_FILE"
|
|
28
|
+
sleep "$INTERVAL"
|
|
29
|
+
done
|