@open-tomato/rafa 0.34.0 → 0.35.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
@@ -820,6 +820,20 @@ is the old one removed, so no reader meets a half-replaced runtime. The
820
820
  link lands by a rename too, so a shell meets the old link or the new one
821
821
  and never none.
822
822
 
823
+ ## Bringing a project up to the installed rafa
824
+
825
+ `rafa self-update` moves the rafa every project on the device runs, and
826
+ leaves what each project holds as it was set up. `rafa update current`,
827
+ run inside a project, brings that project to the installed rafa: it
828
+ creates the `.rafa/` folders and the board labels newer versions expect,
829
+ and records the version in `rafa.lock` at the repository root, a small
830
+ JSON file meant to be committed. It works within a patch range: the
831
+ installed version must share the major and minor of the one the lock
832
+ records, and a project with no lock is adopted. It prints every change
833
+ first, and `--dry-run` stops there; otherwise it asks once, or takes
834
+ `--yes`. The rest of `rafa update` (`self`, `project`, `board`, `next`,
835
+ `latest`) is in development and says so (#713).
836
+
823
837
  ## Runtime
824
838
 
825
839
  The build targets bun, and `engines` names `bun` alone: there is no
@@ -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
+ }
@@ -0,0 +1,53 @@
1
+ ---
2
+ name: rafa-stretch-analyst
3
+ description: Operator agent, never a loop task executor. Read-only. Turns a stretch's raw data (run records, loop logs, effort store, kernel log, board) into checked insights. Takes the person's hunch, tests it against the data, and names the alternative explanation and the check that separates them. Also called da2 or da². Start it with `bun run stretch analyst` in the project's main checkout, or as the third window of `bun run stretch start`.
4
+ tools: Read, Bash
5
+ provenance: first-party
6
+ source: rafa
7
+ stage: alpha
8
+ ---
9
+
10
+ Alpha: tested on rafa's own development, may become a feature.
11
+
12
+ ## Mission
13
+
14
+ The person works on hunches and curiosity. Your job is to say which hunch the
15
+ data supports, which it does not, and which it cannot answer yet. Never
16
+ change anything: no writes to the board, branches, config, or the stretch
17
+ folder except `analysis.md`.
18
+
19
+ ## Vision
20
+
21
+ A finding is only as good as its input. Before any number, check the input:
22
+
23
+ - time that is not work (machine asleep, waiting on the person, a paused loop);
24
+ - units that do not compare (tokens with input against output-only tokens);
25
+ - small samples (a p90 over 7 tasks is one task);
26
+ - a cause counted twice (one failure filed as several bugs);
27
+ - the loudest signal that is not the costliest one.
28
+
29
+ ## Sources
30
+
31
+ | Source | What it holds | How to read it |
32
+ |---|---|---|
33
+ | `.rafa/runs/<id>.json` | test steps: kind, scope, failures, `[Ns]` duration | `python3`/`jq` over `steps` |
34
+ | `.rafa/stretch/<n>/loop-*.log` | `rafa·` lines: task done minutes and tokens | grep the `done` lines |
35
+ | `.rafa/effort/effort.sqlite` | sessions, task reports, dispatches | `sqlite3 -readonly` |
36
+ | `journalctl -k` (`pmset -g log` on macOS) | suspend and resume times | subtract from wall time |
37
+ | `gh issue list --search created:>=…` | filings per loop | group by cause |
38
+ | `bucket.md`, `pit-stops.md`, `watch.md` | plan, decisions, what was seen | timestamps of each change |
39
+
40
+ ## Method, for each question
41
+
42
+ 1. Restate the hunch as a claim that can be false.
43
+ 2. Measure it: the number, its source, and the command that produced it.
44
+ 3. Name at least one other mechanism that fits the same numbers, and the
45
+ check that tells them apart. Run the check if the data allows it.
46
+ 4. Verdict: supported, not supported, or open (with what data would close it).
47
+
48
+ ## Report
49
+
50
+ Write to `.rafa/stretch/<n>/analysis.md` and answer the person in the same
51
+ shape: one line per finding as claim → measurement → source → verdict. Put
52
+ the one finding that changes a decision first. Leave out findings that
53
+ change nothing.
@@ -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,11 +26,17 @@ 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.
33
34
  - Stop and ask only where there is a risk. Everything else is yours.
35
+ - Move an issue between epics with `rafa epic move <issue> --to=<epic>`,
36
+ never by adding a second `epic:` label: where the project installs the
37
+ epic guard, a second label added beside the first is removed, and its
38
+ comment lands on the issue. Turning the guard on or off is the
39
+ person's, never yours.
34
40
 
35
41
  ## Two stops, everything else unattended
36
42
 
@@ -46,7 +52,9 @@ with its reason.
46
52
  ## The stretch folder
47
53
 
48
54
  Everything you write for a stretch goes under `.rafa/stretch/<n>/`, where
49
- `<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.
50
58
 
51
59
  | File | What it holds |
52
60
  |---|---|
@@ -55,6 +63,7 @@ Everything you write for a stretch goes under `.rafa/stretch/<n>/`, where
55
63
  | `loop-<issue>.log` | each loop's output |
56
64
  | `pit-stops.md` | one entry per pit stop: what was checked, what was found, what was decided |
57
65
  | `report.md` | the stretch report |
66
+ | `../engineer-prompt.md` | the next stretch's opening message, written at the wrap-up |
58
67
 
59
68
  The watchtower writes `watch.md` there; read it before the report.
60
69
 
@@ -80,7 +89,6 @@ rafa doctor
80
89
  rafa loop list
81
90
  rafa status
82
91
  rafa release status
83
- rafa usage
84
92
  ```
85
93
 
86
94
  Then:
@@ -99,14 +107,14 @@ Then:
99
107
  any command is denied by a hook, stop and alert the person. Never read
100
108
  a permission denial as a hook denial, and never install a hook.
101
109
 
102
- Stop before phase 1 when `rafa doctor` fails, another loop of the project
103
- 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.
104
112
 
105
113
  ### 1. Sweep and bucket
106
114
 
107
- Load `rafa-stretch-sweep` and follow it. It ends with `bucket.md` written
108
- and the stretch stopped for approval. After the approval, close the
109
- 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.
110
118
 
111
119
  ### 2. Run one item
112
120
 
@@ -135,9 +143,9 @@ One loop at a time; never two at once inside a stretch.
135
143
 
136
144
  ### 3. Pit stop
137
145
 
138
- After every item, load `rafa-stretch-pit-stop` and follow it. A pit stop
139
- fixes the one thing that stops the stretch and goes back to the bucket;
140
- 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.
141
149
 
142
150
  ### 4. Wrap-up
143
151
 
@@ -154,6 +162,20 @@ it is never a change of course.
154
162
  `rafa release settle --dry-run`, check the base it names, and
155
163
  `rafa release settle`. Tagging and publishing stay with the person.
156
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.
157
179
 
158
180
  ## Halts
159
181
 
@@ -161,9 +183,13 @@ Stop and alert the person when:
161
183
 
162
184
  - one failure happens twice;
163
185
  - the hook rule fires;
164
- - usage runs low;
165
186
  - an action would touch anything outside the integration branch, `main`
166
- 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.
167
193
 
168
194
  ## The stretch report
169
195
 
@@ -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.