@open-tomato/rafa 0.34.1 → 0.36.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/README.md CHANGED
@@ -61,10 +61,9 @@ your accounts.
61
61
 
62
62
  The same 🪙 marks appear in `rafa --help` at all levels and in `rafa describe` output.
63
63
 
64
- Everything else reads files, git and GitHub and spends nothing,
65
- `rafa usage` included (it reads `CLAUDE_USAGE_PERCENT` and asks
66
- nobody). `rafa loop resume` starts no session itself, but it lets a
67
- paused run go on spending. rafa calls no model API directly: all of
64
+ Everything else reads files, git and GitHub and spends nothing.
65
+ `rafa loop resume` starts no session itself, but it lets a paused run
66
+ go on spending. rafa calls no model API directly: all of
68
67
  it goes through the `claude` command.
69
68
  - **Your machine may go to sleep in the middle of a run.** rafa does not
70
69
  keep it awake, so the operating system's power settings can suspend a
@@ -451,13 +450,10 @@ hit and what it would change about itself, which waits for your yes. A
451
450
  second session, `rafa-stretch-watchtower`, watches it and its loops
452
451
  without writing anything, and alerts you when one of them needs you.
453
452
 
454
- On the machine that runs the loops, link the operators where Claude Code
455
- finds them, from the project's checkout:
456
-
457
- ```bash
458
- ln -s "$PWD/src/bundled/operators/agents/"*.md ~/.claude/agents/
459
- ln -s "$PWD/src/bundled/operators/skills/"* ~/.claude/skills/
460
- ```
453
+ Nothing is linked into `~/.claude`. Each stretch runs on its own copy of
454
+ the operators, made under `.rafa/stretch/<n>/operators/` when it starts
455
+ and loaded with `claude --plugin-dir`, so a stretch already running is
456
+ never changed by a pull or an update of rafa.
461
457
 
462
458
  Allow what they run without a prompt in the project's
463
459
  `.claude/settings.local.json`, and keep every push away from `main`:
@@ -487,17 +483,15 @@ Allow what they run without a prompt in the project's
487
483
  }
488
484
  ```
489
485
 
490
- Then start the two sessions, each in a terminal of its own, with Remote
491
- Control on so the bucket question and the alerts reach you away from the
492
- machine:
486
+ Then start the engineer, the watchtower and the analyst in one tmux
487
+ session, `stretch-<project>-<n>`, from the project's main checkout, with
488
+ Remote Control on so the bucket question and the alerts reach you away
489
+ from the machine. From a rafa checkout beside the project:
493
490
 
494
491
  ```bash
495
- claude --agent rafa-stretch-engineer
496
- claude --agent rafa-stretch-watchtower
492
+ bash ../rafa/scripts/stretch/stretch.sh start --remote-control
497
493
  ```
498
494
 
499
- and type `/loop` in the watchtower's session.
500
-
501
495
  The agents read loops in the compact output, which you can use on your
502
496
  own too: `RAFA_OUTPUT=events rafa loop start …` (or `--output=events`)
503
497
  prints one `rafa·` line per loop event and nothing else. Every other
@@ -576,6 +570,12 @@ Three settings shape what `rafa cleanup` lists.
576
570
 
577
571
  Both day counts take a whole number above zero.
578
572
 
573
+ Besides the `cleanup.keep` matches, `rafa cleanup` never lists the
574
+ branch checked out, the base branch (`pr.base`, else the branch
575
+ `origin/HEAD` names, else `main`), and the branch `origin/HEAD` names
576
+ even when `pr.base` names another, so a repository that merges into an
577
+ integration branch never sees its default branch offered for deletion.
578
+
579
579
  ```yaml
580
580
  cleanup:
581
581
  staleDays: 30
@@ -80,7 +80,7 @@ derive which one you have rather than assuming it:
80
80
  - Every `context/` pointer in a map stays a PLAIN backticked path. The
81
81
  `@` import form is reserved for `CLAUDE.md` itself; an `@`-prefixed
82
82
  pointer pulls that page into every turn and undoes the whole saving of
83
- the split. `src/tests/context-page-imports.test.ts` reads the live
83
+ the split. `src/tests/context-page-imports.sweep.test.ts` reads the live
84
84
  maps and is the guard.
85
85
  - The root `AGENTS.md` map is capped at 80 lines and nothing enforces
86
86
  the cap, so count before you finish. A promoted finding goes to the
@@ -0,0 +1,5 @@
1
+ {
2
+ "name": "rafa-operators",
3
+ "description": "Alpha: rafa's stretch operators, loaded per session with --plugin-dir by scripts/stretch/stretch.sh. Never a loop task executor.",
4
+ "author": { "name": "open-tomato" }
5
+ }
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: rafa-stretch-engineer
3
- description: Operator agent, never a loop task executor. Runs one stabilisation stretch on the machine that runs the loops — sweeps the board, proposes a bucket of up to 10 issues, runs it one loop at a time on an integration branch, checks between items, and reports what to improve. Start it with `claude --agent rafa-stretch-engineer` in the project's main checkout.
4
- tools: Read, Write, Edit, Bash, Grep, Glob
3
+ description: Operator agent, never a loop task executor. Runs one stabilisation stretch on the machine that runs the loops — sweeps the board, proposes a bucket of up to 10 issues, runs it one loop at a time on an integration branch, checks between items, and reports what to improve. Start it with `scripts/stretch/stretch.sh` from rafa, in the project's main checkout.
4
+ tools: Read, Write, Edit, Bash, Grep, Glob, Skill
5
5
  model: opus
6
6
  provenance: first-party
7
7
  source: rafa
@@ -26,7 +26,8 @@ rafa is a shortener of commands, a simplifier of tasks, a reminder of
26
26
  steps: a helper, never a hinderer. Hold every step you take to it:
27
27
 
28
28
  - Prefer the rafa line. When a step needs a raw `gh`, `git` or shell line
29
- because no rafa line does it, load `rafa-stretch-gap-log` and log it.
29
+ because no rafa line does it, load `rafa-operators:rafa-stretch-gap-log`
30
+ and log it.
30
31
  - A step you repeat the same way every time is a pipeline waiting to be
31
32
  written; a flag you always add is a flag rafa may not need. Note both
32
33
  in the report.
@@ -51,7 +52,9 @@ with its reason.
51
52
  ## The stretch folder
52
53
 
53
54
  Everything you write for a stretch goes under `.rafa/stretch/<n>/`, where
54
- `<n>` is one more than the highest number already there:
55
+ `<n>` is the stretch your opening message names. The launcher has made
56
+ that folder and copied the operators into its `operators/`, the copy
57
+ this session and your skills load from; leave it as it is.
55
58
 
56
59
  | File | What it holds |
57
60
  |---|---|
@@ -60,6 +63,7 @@ Everything you write for a stretch goes under `.rafa/stretch/<n>/`, where
60
63
  | `loop-<issue>.log` | each loop's output |
61
64
  | `pit-stops.md` | one entry per pit stop: what was checked, what was found, what was decided |
62
65
  | `report.md` | the stretch report |
66
+ | `../engineer-prompt.md` | the next stretch's opening message, written at the wrap-up |
63
67
 
64
68
  The watchtower writes `watch.md` there; read it before the report.
65
69
 
@@ -85,7 +89,6 @@ rafa doctor
85
89
  rafa loop list
86
90
  rafa status
87
91
  rafa release status
88
- rafa usage
89
92
  ```
90
93
 
91
94
  Then:
@@ -104,14 +107,14 @@ Then:
104
107
  any command is denied by a hook, stop and alert the person. Never read
105
108
  a permission denial as a hook denial, and never install a hook.
106
109
 
107
- Stop before phase 1 when `rafa doctor` fails, another loop of the project
108
- is live, or usage is too low for a stretch.
110
+ Stop before phase 1 when `rafa doctor` fails, or another loop of the
111
+ project is live.
109
112
 
110
113
  ### 1. Sweep and bucket
111
114
 
112
- Load `rafa-stretch-sweep` and follow it. It ends with `bucket.md` written
113
- and the stretch stopped for approval. After the approval, close the
114
- duplicate groups as the skill says.
115
+ Load `rafa-operators:rafa-stretch-sweep` and follow it. It ends with
116
+ `bucket.md` written and the stretch stopped for approval. After the
117
+ approval, close the duplicate groups as the skill says.
115
118
 
116
119
  ### 2. Run one item
117
120
 
@@ -127,10 +130,10 @@ One loop at a time; never two at once inside a stretch.
127
130
 
128
131
  `setsid` is Linux's; on macOS start it with `nohup` alone and log the
129
132
  difference as a gap. Detached loops are a gap of their own.
130
- 3. Watch it: read the log's `rafa·` lines and `rafa loop status`. Wait
131
- with a background check on the log, never a tight loop of reads. No
132
- foreground command waits longer than 60 seconds; longer waits run in
133
- the background.
133
+ 3. Watch it: `rafa loop wait --until=pr,no-pr,halt,error,exit` reads the
134
+ `.rafa/runs/<session-id>.events.ndjson` file your loop wrote, not the
135
+ log. No foreground command waits longer than 60 seconds; longer waits
136
+ run in the background.
134
137
  4. Merge its pull request:
135
138
  - Into `stretch/<n>`: `rafa pr merge <pr> --skip-checks`. The merge push
136
139
  runs `verify` asynchronously; read the result at the pit stop.
@@ -140,9 +143,9 @@ One loop at a time; never two at once inside a stretch.
140
143
 
141
144
  ### 3. Pit stop
142
145
 
143
- After every item, load `rafa-stretch-pit-stop` and follow it. A pit stop
144
- fixes the one thing that stops the stretch and goes back to the bucket;
145
- it is never a change of course.
146
+ After every item, load `rafa-operators:rafa-stretch-pit-stop` and follow
147
+ it. A pit stop fixes the one thing that stops the stretch and goes back
148
+ to the bucket; it is never a change of course.
146
149
 
147
150
  ### 4. Wrap-up
148
151
 
@@ -159,6 +162,20 @@ it is never a change of course.
159
162
  `rafa release settle --dry-run`, check the base it names, and
160
163
  `rafa release settle`. Tagging and publishing stay with the person.
161
164
  4. Finish `report.md`.
165
+ 5. Write the next stretch's opening message to
166
+ `.rafa/stretch/engineer-prompt.md`, which the launcher reads before any
167
+ other prompt. Write `{{STRETCH}}` and `{{PREVIOUS}}` where the numbers
168
+ go, and keep it to what the next engineer needs on top of this report:
169
+ - which report to read first, and which of its sections;
170
+ - which of the report's "Steps for the person" are already done, so the
171
+ next engineer does not chase them;
172
+ - the carried work, in the person's order, each issue with a few words
173
+ on its subject;
174
+ - what the board gained since the bucket that the next sweep should
175
+ weigh;
176
+ - a line saying the self-improvement proposals wait for the person's
177
+ yes, so the person adds the ones they approve before the next start.
178
+ Add reviewing it to "Steps for the person" in the report.
162
179
 
163
180
  ## Halts
164
181
 
@@ -166,9 +183,13 @@ Stop and alert the person when:
166
183
 
167
184
  - one failure happens twice;
168
185
  - the hook rule fires;
169
- - usage runs low;
170
186
  - an action would touch anything outside the integration branch, `main`
171
- included.
187
+ included;
188
+ - a `rafa self-update` while another project's stretch runs on this
189
+ machine: rafa is installed once per machine, so the update changes the
190
+ rafa that stretch's next loop runs. Another project's stretch shows as
191
+ a tmux session named `stretch-<project>-<n>` or `rafa-stretch-<n>` that
192
+ is not yours.
172
193
 
173
194
  ## The stretch report
174
195
 
@@ -55,17 +55,17 @@ Four sources, all on this machine:
55
55
 
56
56
  ## How you wait
57
57
 
58
- - **A Monitor on the loop log**, so each `rafa·` line, a `blocked` line, an
59
- `error` line or a `halt` line reaches you as it is written. Match every
60
- ending, not only the good ones:
58
+ Watch the running loop's events from `.rafa/runs/<session-id>.events.ndjson`:
61
59
 
62
- ```bash
63
- tail -F .rafa/stretch/<n>/loop-<issue>.log | grep --line-buffered -E 'rafa· (task|wrap-up|pr|no pr|halt|error)'
64
- ```
60
+ ```bash
61
+ rafa loop wait --until=blocked,quiet:<minutes>,exit
62
+ ```
65
63
 
66
- A Monitor stops after 30 minutes at most; restart it at every wake.
67
- - **`/loop`**, self-paced, every 10 to 30 minutes, for the slower checks:
68
- the agent's status and the quiet-loop timing.
64
+ The `<minutes>` is 2× the p90 task time from `rafa effort dashboard`. With
65
+ no baseline yet, use 30 minutes and say so in the alert. The wait exits
66
+ when a task blocks, when the loop is quiet for that long, or when the loop
67
+ ends. Between waits, read the agent's session status and check the hook
68
+ rule at every wake: `/loop`, self-paced, every 10 to 30 minutes.
69
69
 
70
70
  ## How you alert
71
71
 
@@ -55,8 +55,8 @@ only after reading the run's last `rafa·` lines.
55
55
  When the bucket is full, the lowest-ranked preparation item leaves it.
56
56
  Add a line to `bucket.md` saying so.
57
57
  3. **A halt.** Stop the stretch and alert the person when one failure
58
- happens twice, when the hook rule fires, when usage runs low, or when
59
- the fix would touch anything outside the integration branch.
58
+ happens twice, when the hook rule fires, or when the fix would touch
59
+ anything outside the integration branch.
60
60
 
61
61
  Anything else you find is filed, not fixed: one issue, after a search for
62
62
  an existing one, and the stretch goes on.