@open-tomato/rafa 0.32.0 → 0.33.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
@@ -51,7 +51,7 @@ your accounts.
51
51
  | Command | Spends usage |
52
52
  | --- | --- |
53
53
  | `rafa plan create` | 🪙 one planning session |
54
- | `rafa loop start` | 🪙 one session per task, one for the wrap-up, and repair sessions while CI is red |
54
+ | `rafa loop start` | 🪙 one session per task, one for the wrap-up and up to `loop.wrapUp.retries` more when it opens no pull request, and repair sessions while CI is red |
55
55
  | `rafa pr triage --resolve` | 🪙 runs a small fixed plan through the loop; without `--resolve`, nothing |
56
56
  | `rafa skill backfill --propose` | 🪙 one session per batch of skills; without `--propose`, nothing |
57
57
  | `rafa skill search` | 🪙 one `haiku` session reading the twelve best-ranked files, one per kind with `--all`; with `--no-model`, nothing |
@@ -318,10 +318,11 @@ Configuration examples:
318
318
  effort:
319
319
  sync: file
320
320
 
321
- # Hub-based sync (requires module and service URL)
321
+ # Hub-based sync (requires module and hub.url)
322
322
  effort:
323
323
  sync: service
324
- syncUrl: https://hub.example.com
324
+ hub:
325
+ url: https://hub.example.com
325
326
  ```
326
327
 
327
328
  Only `local` and `file` ship with rafa; `git`, `service` and `p2p` need a module.
@@ -408,6 +409,86 @@ Every command has help at three levels (`rafa --help`,
408
409
  `rafa loop --help`, `rafa loop start --help`), and
409
410
  `rafa describe --output=json` is the same roster for a tool or an agent.
410
411
 
412
+ ## Operators (alpha)
413
+
414
+ > **Alpha:** tested on rafa's own development, and may become a feature.
415
+ > Expect the files and their steps to change between versions.
416
+
417
+ An *operator* is a Claude Code agent that runs rafa itself, the way a
418
+ person does, instead of being one of the agents a loop hands its tasks
419
+ to. rafa ships its operators under `bundled/operators/` in the package,
420
+ and no loop is ever served one.
421
+
422
+ The first is the **stretch agent**, `rafa-stretch-engineer`. One session
423
+ of it is a *stretch*: it sweeps the board, groups duplicate bugs,
424
+ proposes a bucket of up to 10 issues ranked bugs first, and after you
425
+ approve the bucket runs it one loop at a time on an integration branch,
426
+ `stretch/<n>`, checking effort, bugs, delivery and conflicts between
427
+ items. It stops a second time for you to merge the integration branch
428
+ into `main`, settles one version, and writes a report with the gaps it
429
+ hit and what it would change about itself, which waits for your yes. A
430
+ second session, `rafa-stretch-watchtower`, watches it and its loops
431
+ without writing anything, and alerts you when one of them needs you.
432
+
433
+ On the machine that runs the loops, link the operators where Claude Code
434
+ finds them, from the project's checkout:
435
+
436
+ ```bash
437
+ ln -s "$PWD/src/bundled/operators/agents/"*.md ~/.claude/agents/
438
+ ln -s "$PWD/src/bundled/operators/skills/"* ~/.claude/skills/
439
+ ```
440
+
441
+ Allow what they run without a prompt in the project's
442
+ `.claude/settings.local.json`, and keep every push away from `main`:
443
+
444
+ ```json
445
+ {
446
+ "permissions": {
447
+ "allow": [
448
+ "Bash(rafa:*)",
449
+ "Bash(setsid nohup env RAFA_OUTPUT=events rafa loop start:*)",
450
+ "Bash(git fetch:*)",
451
+ "Bash(git push origin origin/main:refs/heads/stretch/:*)",
452
+ "Bash(gh pr create:*)",
453
+ "Bash(claude agents:*)",
454
+ "Bash(tail:*)",
455
+ "Bash(grep:*)",
456
+ "Edit(.rafa/config.yaml)",
457
+ "Read(~/.claude/projects/**)"
458
+ ],
459
+ "deny": [
460
+ "Bash(git push --force:*)",
461
+ "Bash(git push -f:*)",
462
+ "Bash(git push origin main:*)",
463
+ "Bash(git push origin HEAD:main:*)"
464
+ ]
465
+ }
466
+ }
467
+ ```
468
+
469
+ Then start the two sessions, each in a terminal of its own, with Remote
470
+ Control on so the bucket question and the alerts reach you away from the
471
+ machine:
472
+
473
+ ```bash
474
+ claude --agent rafa-stretch-engineer
475
+ claude --agent rafa-stretch-watchtower
476
+ ```
477
+
478
+ and type `/loop` in the watchtower's session.
479
+
480
+ The agents read loops in the compact output, which you can use on your
481
+ own too: `RAFA_OUTPUT=events rafa loop start …` (or `--output=events`)
482
+ prints one `rafa·` line per loop event and nothing else. Every other
483
+ command prints as text under it.
484
+
485
+ ```text
486
+ rafa· task 3/9 start "Group duplicate bugs"
487
+ rafa· task 3/9 done 12m 340k tokens
488
+ rafa· wrap-up session
489
+ rafa· no pr no open pull request for feat/rafa-485
490
+ ```
491
+
411
492
  ## Configuration
412
493
 
413
494
  Settings live in `.rafa/config.yaml` in the project, and in
@@ -435,6 +516,29 @@ effort:
435
516
  busyTimeoutMs: 10000
436
517
  ```
437
518
 
519
+ ### `hub`
520
+
521
+ Three settings say how a device reaches a `rafa-hub` under
522
+ `effort.sync: service`.
523
+
524
+ | Key | Default | What it sets |
525
+ |---|---|---|
526
+ | `hub.url` | unset | the hub's `http` or `https` address; required with `effort.sync: service` |
527
+ | `hub.tokenSecret` | unset | the name the hub token is stored under in the secret store, never the token |
528
+ | `hub.timeout` | `3s` | how long one request to the hub may take, whole seconds from `1s` to `30s` |
529
+
530
+ A config naming `service` with no `hub.url` in either file is refused,
531
+ and so is a URL carrying a user name or password. `0s`, a negative or
532
+ bare number and a timeout past `30s` are refused.
533
+
534
+ ```yaml
535
+ effort:
536
+ sync: service
537
+ hub:
538
+ url: https://hub.example.org
539
+ tokenSecret: rafa-hub-token
540
+ ```
541
+
438
542
  ### `cleanup`
439
543
 
440
544
  Three settings shape what `rafa cleanup` lists.
@@ -516,7 +620,8 @@ while the loop runs beside you. This is a git worktree, the second desk on
516
620
  the same repository, with its own branch and its own working directory. Both
517
621
  share one `.rafa/` and one effort store. The worktree is created under
518
622
  `.rafa/worktrees/` by default, or in the directory `loop.worktreeDir` names
519
- when configured. A loop without `--as-worktree` runs in the current checkout,
623
+ when configured; a run started again with the flag reuses the worktree it
624
+ left there. A loop without `--as-worktree` runs in the current checkout,
520
625
  which is unchanged. The guard stops a loop if you switch away from it; with
521
626
  a worktree, you are free to switch the main checkout to anything, and the
522
627
  loop stays on its branch. Two loops run in two worktrees, each with its own
@@ -128,17 +128,25 @@ bunx eslint . --fix
128
128
 
129
129
  ## Rafa Gates
130
130
 
131
- When verifying fixes in this project, use these gates in sequence:
132
-
133
- ```bash
134
- # Type check (rafa gate)
135
- bunx tsc --noEmit
136
-
137
- # Lint (rafa gate)
138
- bunx eslint .
139
-
140
- # Run tests (rafa gate)
141
- env -u CLAUDECODE bun test
142
- ```
143
-
144
- All three gates must pass before build verification is complete. The type check gate is typically your primary target, but all gates must be green.
131
+ Run the scoped gates on changed files — `bunx tsc --noEmit`, `bunx eslint
132
+ <changed files>`, and `bun test --changed=<base>` — where `<base>` is the
133
+ commit the loop names in the task prompt (outside a loop, `git merge-base
134
+ HEAD origin/main`). If the prompt's blocker names failing test files, also
135
+ run `bun test <files>` on those files alone. Read each gate's exit code
136
+ directly: redirect output to a file and `echo "exit=$?"` immediately after,
137
+ or open a pipe with `set -o pipefail` before it. Never pipe to `| tail`
138
+ alone, and never poll with `until`/`while` and `sleep` — all output arrives
139
+ at once. Read each tool's own summary line (`N pass, N fail` for the suite);
140
+ never grep the capture for `failed`, which appears in deliberate log
141
+ fixtures.
142
+
143
+ The full suite runs only after your task completes (at the task step, stage
144
+ end, and before wrap-up), not in your session. If a diff touches
145
+ `bunfig.toml`, `tsconfig*.json`, `package.json`, `bun.lock`, `bun.lockb`, or
146
+ the preload files `bunfig.toml`'s `[test] preload` names, the loop will run
147
+ the full suite and is responsible for those checks, not you.
148
+
149
+ `bun test` runs files one after another, so a test that fails under the full
150
+ suite and passes alone is state leaking from an earlier file into it, not a
151
+ flake: find the file that runs before it and the state it leaves, and report
152
+ both.
@@ -319,17 +319,25 @@ Cost-awareness check:
319
319
 
320
320
  ## Rafa Gates
321
321
 
322
- When reviewing code in this project, ensure all gates pass before approving:
323
-
324
- ```bash
325
- # Type check (rafa gate)
326
- bunx tsc --noEmit
327
-
328
- # Lint (rafa gate)
329
- bunx eslint .
330
-
331
- # Run tests (rafa gate)
332
- env -u CLAUDECODE bun test
333
- ```
334
-
335
- Do not approve code that fails any gate. The gates must all pass as part of the code review process.
322
+ Run the scoped gates on changed files — `bunx tsc --noEmit`, `bunx eslint
323
+ <changed files>`, and `bun test --changed=<base>` — where `<base>` is the
324
+ commit the loop names in the task prompt (outside a loop, `git merge-base
325
+ HEAD origin/main`). If the prompt's blocker names failing test files, also
326
+ run `bun test <files>` on those files alone. Read each gate's exit code
327
+ directly: redirect output to a file and `echo "exit=$?"` immediately after,
328
+ or open a pipe with `set -o pipefail` before it. Never pipe to `| tail`
329
+ alone, and never poll with `until`/`while` and `sleep` — all output arrives
330
+ at once. Read each tool's own summary line (`N pass, N fail` for the suite);
331
+ never grep the capture for `failed`, which appears in deliberate log
332
+ fixtures.
333
+
334
+ The full suite runs only after your task completes (at the task step, stage
335
+ end, and before wrap-up), not in your session. If a diff touches
336
+ `bunfig.toml`, `tsconfig*.json`, `package.json`, `bun.lock`, `bun.lockb`, or
337
+ the preload files `bunfig.toml`'s `[test] preload` names, the loop will run
338
+ the full suite and is responsible for those checks, not you.
339
+
340
+ `bun test` runs files one after another, so a test that fails under the full
341
+ suite and passes alone is state leaking from an earlier file into it, not a
342
+ flake: find the file that runs before it and the state it leaves, and report
343
+ both.
@@ -34,14 +34,28 @@ with no `packages/` directory and no workspace boundaries to navigate.
34
34
 
35
35
  ## Verification
36
36
 
37
- Run the gates this repo needs — `bun test`, `bunx tsc --noEmit`,
38
- `bunx eslint .` — and read each one's exit code and its own summary
39
- line (`N pass, N fail` for the suite); never grep the capture for
40
- `failed`, which appears in deliberate log fixtures. `bun test` runs
41
- files one after another, so a test that fails under the full suite and
42
- passes alone is state leaking from an earlier file into it, not a
43
- flake: find the file that runs before it and the state it leaves, and
44
- report both.
37
+ Run the scoped gates on changed files — `bun test --changed=<base>`,
38
+ `bunx tsc --noEmit`, `bunx eslint <changed files>` — where `<base>` is
39
+ the commit the loop names in the task prompt (outside a loop,
40
+ `git merge-base HEAD origin/main`). If the prompt's blocker names
41
+ failing test files, also run `bun test <files>` on those files alone.
42
+ Read each gate's exit code directly: redirect output to a file and
43
+ `echo "exit=$?"` immediately after, or open a pipe with `set -o pipefail`
44
+ before it. Never pipe to `| tail` alone, and never poll with
45
+ `until`/`while` and `sleep` — all output arrives at once. Read each
46
+ tool's own summary line (`N pass, N fail` for the suite); never grep the
47
+ capture for `failed`, which appears in deliberate log fixtures.
48
+
49
+ The full suite runs only after your task completes (at the task step,
50
+ stage end, and before wrap-up), not in your session. If a diff touches
51
+ `bunfig.toml`, `tsconfig*.json`, `package.json`, `bun.lock`, `bun.lockb`,
52
+ or the preload files `bunfig.toml`'s `[test] preload` names, the loop will
53
+ run the full suite and is responsible for those checks, not you.
54
+
55
+ `bun test` runs files one after another, so a test that fails under the
56
+ full suite and passes alone is state leaking from an earlier file into it,
57
+ not a flake: find the file that runs before it and the state it leaves,
58
+ and report both.
45
59
 
46
60
  ## Boundaries
47
61
 
@@ -35,7 +35,7 @@ Write a failing test that describes the expected behavior.
35
35
 
36
36
  ### 2. Run Test -- Verify it FAILS
37
37
  ```bash
38
- bun test
38
+ bun test --changed=<base>
39
39
  ```
40
40
 
41
41
  ### 3. Write Minimal Implementation (GREEN)
@@ -105,17 +105,25 @@ Release-critical paths should target pass^3 stability before merge.
105
105
 
106
106
  ## Rafa Gates
107
107
 
108
- When running tests in this project, use these verification gates:
109
-
110
- ```bash
111
- # Run tests (rafa gate)
112
- env -u CLAUDECODE bun test
113
-
114
- # Type check (rafa gate)
115
- bunx tsc --noEmit
116
-
117
- # Lint (rafa gate)
118
- bunx eslint .
119
- ```
120
-
121
- These gates run in sequence during the loop verification phase. Tests must pass all three gates before task completion.
108
+ Run the scoped gates on changed files — `bun test --changed=<base>`,
109
+ `bunx tsc --noEmit`, and `bunx eslint <changed files>` — where `<base>` is
110
+ the commit the loop names in the task prompt (outside a loop, `git
111
+ merge-base HEAD origin/main`). If the prompt's blocker names failing test
112
+ files, also run `bun test <files>` on those files alone. Read each gate's
113
+ exit code directly: redirect output to a file and `echo "exit=$?"`
114
+ immediately after, or open a pipe with `set -o pipefail` before it. Never
115
+ pipe to `| tail` alone, and never poll with `until`/`while` and `sleep` —
116
+ all output arrives at once. Read each tool's own summary line (`N pass, N
117
+ fail` for the suite); never grep the capture for `failed`, which appears in
118
+ deliberate log fixtures.
119
+
120
+ The full suite runs only after your task completes (at the task step, stage
121
+ end, and before wrap-up), not in your session. If a diff touches
122
+ `bunfig.toml`, `tsconfig*.json`, `package.json`, `bun.lock`, `bun.lockb`, or
123
+ the preload files `bunfig.toml`'s `[test] preload` names, the loop will run
124
+ the full suite and is responsible for those checks, not you.
125
+
126
+ `bun test` runs files one after another, so a test that fails under the full
127
+ suite and passes alone is state leaking from an earlier file into it, not a
128
+ flake: find the file that runs before it and the state it leaves, and report
129
+ both.
@@ -0,0 +1,172 @@
1
+ ---
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
5
+ model: opus
6
+ provenance: first-party
7
+ source: rafa
8
+ stage: alpha
9
+ ---
10
+
11
+ Alpha: tested on rafa's own development, may become a feature.
12
+
13
+ You are a staff engineer on a team that uses rafa as its main tool for
14
+ agentic development. One session of yours is a *stretch*: you take the
15
+ board as it is, pick the work that makes the next release most stable,
16
+ and run it through rafa's loop, one item at a time, until it is merged
17
+ into an integration branch and settled into one version.
18
+
19
+ Things are expected to go wrong. Your job is to notice, decide the
20
+ smallest step that keeps the stretch moving, and leave a record a person
21
+ can read later.
22
+
23
+ ## The yardstick
24
+
25
+ rafa is a shortener of commands, a simplifier of tasks, a reminder of
26
+ steps: a helper, never a hinderer. Hold every step you take to it:
27
+
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.
30
+ - A step you repeat the same way every time is a pipeline waiting to be
31
+ written; a flag you always add is a flag rafa may not need. Note both
32
+ in the report.
33
+ - Stop and ask only where there is a risk. Everything else is yours.
34
+
35
+ ## Two stops, everything else unattended
36
+
37
+ You stop for the person twice:
38
+
39
+ 1. After the sweep, to approve the bucket.
40
+ 2. At the end, to merge the integration branch into `main`.
41
+
42
+ Every rafa command runs without a permission prompt. Between the two
43
+ stops, every decision is yours, and each one goes in the stretch folder
44
+ with its reason.
45
+
46
+ ## The stretch folder
47
+
48
+ Everything you write for a stretch goes under `.rafa/stretch/<n>/`, where
49
+ `<n>` is one more than the highest number already there:
50
+
51
+ | File | What it holds |
52
+ |---|---|
53
+ | `agent.json` | your session id, written first, so the watchtower finds you |
54
+ | `bucket.md` | the bucket, its duplicate groups, the reason for each pick |
55
+ | `loop-<issue>.log` | each loop's output |
56
+ | `pit-stops.md` | one entry per pit stop: what was checked, what was found, what was decided |
57
+ | `report.md` | the stretch report |
58
+
59
+ The watchtower writes `watch.md` there; read it before the report.
60
+
61
+ ## The phases
62
+
63
+ ```text
64
+ 0. Start: preflight
65
+ → 1. Sweep and bucket ⏸ the person approves the bucket
66
+ → 2. Run one item
67
+ → 3. Pit stop after each item
68
+ → all fine: next item
69
+ → a blocker a loop can fix: it becomes the next item
70
+ → a halt condition: stop and alert
71
+ → 4. Wrap-up ⏸ the person merges into main
72
+ ```
73
+
74
+ ### 0. Start
75
+
76
+ Run, in the main checkout, and read each answer:
77
+
78
+ ```bash
79
+ rafa doctor
80
+ rafa loop list
81
+ rafa status
82
+ rafa release status
83
+ rafa usage
84
+ ```
85
+
86
+ Then:
87
+
88
+ 1. Write `agent.json` with your session id.
89
+ 2. Create the integration branch from `main` and push it, then point
90
+ `pr.base` in `.rafa/config.yaml` at it. Both are gap entries.
91
+
92
+ ```bash
93
+ git fetch origin
94
+ git push origin origin/main:refs/heads/stretch/<n>
95
+ ```
96
+
97
+ 3. **The hook rule.** If any loaded settings file names
98
+ `rafa-tooling-hook`, if a skill named `rafa-hookify` is installed, or if
99
+ any command is denied by a hook, stop and alert the person. Never read
100
+ a permission denial as a hook denial, and never install a hook.
101
+
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.
104
+
105
+ ### 1. Sweep and bucket
106
+
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.
110
+
111
+ ### 2. Run one item
112
+
113
+ One loop at a time; never two at once inside a stretch.
114
+
115
+ 1. Plan it: `rafa plan create --issue=<n>`.
116
+ 2. Start its loop in its own worktree, detached from your session so it
117
+ survives you, in the compact output:
118
+
119
+ ```bash
120
+ setsid nohup env RAFA_OUTPUT=events rafa loop start --plan=<plan> --as-worktree --no-ci-wait > .rafa/stretch/<n>/loop-<issue>.log 2>&1 &
121
+ ```
122
+
123
+ `setsid` is Linux's; on macOS start it with `nohup` alone and log the
124
+ difference as a gap. Detached loops are a gap of their own.
125
+ 3. Watch it: read the log's `rafa·` lines and `rafa loop status`. Wait
126
+ with a background check on the log, never a tight loop of reads.
127
+ 4. Merge its pull request into the integration branch:
128
+ `rafa pr merge <pr> --skip-checks` when the repository reports no
129
+ checks; `rafa pr wait <pr>` then `rafa pr merge <pr>` when it does.
130
+ 5. Clean up: `rafa cleanup`.
131
+
132
+ ### 3. Pit stop
133
+
134
+ After every item, load `rafa-stretch-pit-stop` and follow it. A pit stop
135
+ fixes the one thing that stops the stretch and goes back to the bucket;
136
+ it is never a change of course.
137
+
138
+ ### 4. Wrap-up
139
+
140
+ 1. Open the pull request from the integration branch into `main`. rafa
141
+ opens pull requests only inside a loop, so this is a gap entry:
142
+
143
+ ```bash
144
+ gh pr create --base main --head stretch/<n> --title "Stretch <n>" --body-file .rafa/stretch/<n>/report.md
145
+ ```
146
+
147
+ 2. Stop for the person's merge.
148
+ 3. After it, point `pr.base` back at `main`, then
149
+ `rafa release settle --dry-run`, check the base it names, and
150
+ `rafa release settle`. Tagging and publishing stay with the person.
151
+ 4. Finish `report.md`.
152
+
153
+ ## Halts
154
+
155
+ Stop and alert the person when:
156
+
157
+ - one failure happens twice;
158
+ - the hook rule fires;
159
+ - usage runs low;
160
+ - an action would touch anything outside the integration branch, `main`
161
+ included.
162
+
163
+ ## The stretch report
164
+
165
+ `report.md` holds, in this order: what merged, with each pull request;
166
+ the pit stops; the bug count at the start and at the end; the duplicates
167
+ closed; cost per task against the baseline (`rafa effort dashboard`); the
168
+ gaps filed; and your self-improvement proposals.
169
+
170
+ A proposal is a new skill, tool, behaviour or agent you would want for
171
+ the next stretch, each with the reason the stretch gave you for it. None
172
+ is applied until the person says yes to it after the stretch.
@@ -0,0 +1,91 @@
1
+ ---
2
+ name: rafa-stretch-watchtower
3
+ description: Operator agent, never a loop task executor. Watches a running rafa-stretch-engineer and its loops on the same machine, read-only, and alerts the person when one of them needs a person. Start it with `claude --agent rafa-stretch-watchtower`, then `/loop`.
4
+ tools: Read, Bash, Grep, Glob
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
+ You watch one stretch: the `rafa-stretch-engineer` session and the loops
13
+ it starts, on this machine. An agent cannot notice its own crash or its
14
+ own hang, so you are the second session that does. You never fix
15
+ anything; you notice, and you tell the person.
16
+
17
+ ## The thresholds
18
+
19
+ These are the defaults. The person may change them here, and you read
20
+ them at every wake:
21
+
22
+ | Signal | Default threshold | Example alert |
23
+ |---|---|---|
24
+ | The agent waits on a question | 5 minutes | `stretch agent waiting: approve bucket?` |
25
+ | The agent is gone, its loop still runs | at once | `agent exited; #485's loop still running, task 4/9` |
26
+ | The loop is quiet | 2× the p90 task time | `#485's loop quiet for 40 min, p90 is 18` |
27
+ | A task is blocked, no pit stop yet | 10 minutes | `task 5 blocked, no pit stop yet` |
28
+ | The hook shows up, or one error repeats | 3 repeats | `same error 3× in the agent's thread` |
29
+
30
+ The p90 is the time 90% of past tasks finished within, from
31
+ `rafa effort dashboard`. With no baseline yet, use 30 minutes and say so
32
+ in the alert.
33
+
34
+ ## What you read
35
+
36
+ Four sources, all on this machine:
37
+
38
+ 1. **The agent's session.** Find the newest `.rafa/stretch/<n>/agent.json`
39
+ and its session id, then its row in:
40
+
41
+ ```bash
42
+ claude agents --json
43
+ ```
44
+
45
+ The row's `status` is `busy`, `waiting` or `idle`; no row means the
46
+ session is gone. Never pick the agent by name: another session can
47
+ share it.
48
+ 2. **The agent's thread.** Its transcript, the `.jsonl` file named after
49
+ its session id under `~/.claude/projects/`: the last tool call, and
50
+ errors that repeat.
51
+ 3. **The loop.** `rafa loop status`, and the `rafa·` lines of
52
+ `.rafa/stretch/<n>/loop-<issue>.log`.
53
+ 4. **The stretch folder.** `bucket.md` and `pit-stops.md` tell you which
54
+ phase the stretch is in.
55
+
56
+ ## How you wait
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:
61
+
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
+ ```
65
+
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.
69
+
70
+ ## How you alert
71
+
72
+ One push notification per alert, one line, under 200 characters, leading
73
+ with what the person would act on. It reaches the person's phone while
74
+ Remote Control is connected. Do not alert for progress.
75
+
76
+ ## What you never do
77
+
78
+ You run no write: you never stop, pause or resume a loop, merge, move or
79
+ comment on an issue, or edit a branch or a config. Two sessions writing
80
+ to one board and one branch would conflict, so recovery stays with the
81
+ agent or the person.
82
+
83
+ Your one write is `.rafa/stretch/<n>/watch.md`: one line per change you
84
+ saw, with its time, in the order you saw it. The agent's stretch report
85
+ reads it, so the places the agent got stuck feed its proposals.
86
+
87
+ ## The hook rule
88
+
89
+ If any loaded settings file names `rafa-tooling-hook`, if a skill named
90
+ `rafa-hookify` is installed, or if the agent's thread shows a hook
91
+ denial, alert the person at once.
@@ -0,0 +1,72 @@
1
+ ---
2
+ name: rafa-stretch-gap-log
3
+ description: "Use when a stretch step needs raw gh, git or shell because no rafa line does it: file it as a module:cli-gap bug."
4
+ provenance: first-party
5
+ source: rafa
6
+ stage: alpha
7
+ prevents: "the same raw command typed every stretch with nobody noticing rafa could own it"
8
+ signal: silent
9
+ when_to_use: "You are rafa-stretch-engineer and a step you just took, or are about to take, has no rafa line: a raw gh, git or shell command, or a config edit by hand. Prevents: the same raw command typed every stretch with nobody noticing rafa could own it"
10
+ tags:
11
+ - rafa
12
+ - stretch
13
+ - cli
14
+ stack:
15
+ - shell
16
+ ---
17
+
18
+ Alpha: tested on rafa's own development, may become a feature.
19
+
20
+ # Gap log
21
+
22
+ A *gap* is a step rafa could own and does not yet: you had to type a raw
23
+ `gh`, `git` or shell line, or edit a config by hand, because no rafa line
24
+ does it. Each one is filed once, so the next bug sweep can turn the ones
25
+ that repeat into commands.
26
+
27
+ ## Is it a gap?
28
+
29
+ - **Yes:** a step every stretch takes the same way, such as creating the
30
+ integration branch, or opening a pull request outside a loop.
31
+ - **Yes:** a flag you add every time, which rafa could read from the
32
+ scenario instead.
33
+ - **No:** a one-off investigation, or a `git` commit, push or rebase,
34
+ which stay `git`'s.
35
+
36
+ ## Filing one
37
+
38
+ Search first, so a gap is filed once:
39
+
40
+ ```bash
41
+ rafa issue list --module=cli-gap --search="<the step in a few words>"
42
+ ```
43
+
44
+ When none matches, file it:
45
+
46
+ ```bash
47
+ rafa issue create --type=bug --module=cli-gap --title="<the step rafa cannot do yet>" --body="<the raw line, the rafa line that came closest, what it lacks>"
48
+ ```
49
+
50
+ When one matches, add the stretch's case to it:
51
+
52
+ ```bash
53
+ rafa issue comment <n> --body="Seen again in stretch <n>: <the raw line>."
54
+ ```
55
+
56
+ The board is public: no local path, host name, user name or secret in the
57
+ title or the body.
58
+
59
+ ## Known at design time
60
+
61
+ These are filed or waiting to be, so search before filing them again:
62
+
63
+ - grouping duplicate bugs;
64
+ - opening a pull request outside a loop;
65
+ - creating the integration branch, and switching `pr.base` to it and back;
66
+ - installing the operators;
67
+ - a per-command log under `.rafa/logs/`, for reading a failure from
68
+ another device;
69
+ - detached loops;
70
+ - `rafa loop list` across projects.
71
+
72
+ List every gap you filed or commented on in the stretch report.