@open-tomato/rafa 0.33.0 → 0.34.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/README.md CHANGED
@@ -66,6 +66,27 @@ your accounts.
66
66
  nobody). `rafa loop resume` starts no session itself, but it lets a
67
67
  paused run go on spending. rafa calls no model API directly: all of
68
68
  it goes through the `claude` command.
69
+ - **Your machine may go to sleep in the middle of a run.** rafa does not
70
+ keep it awake, so the operating system's power settings can suspend a
71
+ loop mid-task. The task carries on when the machine wakes, if its
72
+ session survived, and its recorded time includes the time asleep, which
73
+ then reads as an outlier in `rafa effort report --trend`. On a machine
74
+ you leave running loops, turn sleep off in its power settings, or run
75
+ the loop under the operating system's own sleep lock, which lasts as
76
+ long as the command it wraps:
77
+
78
+ ```bash
79
+ systemd-inhibit --what=sleep:idle --why="rafa loop" rafa loop start --plan=<plan>
80
+ ```
81
+
82
+ ```bash
83
+ caffeinate -i rafa loop start --plan=<plan>
84
+ ```
85
+
86
+ The first is Linux's, the second macOS's. **On a managed device, check
87
+ its power policy before you do either:** some organisations report, or
88
+ block, software that keeps a device awake. An opt-in `--keep-awake`
89
+ flag is planned (#641).
69
90
  - So run it in a repository, on a branch and on a machine where all of
70
91
  that is acceptable: a container or a disposable checkout is a good
71
92
  first home. Nothing here is a sandbox.
@@ -497,6 +518,10 @@ project's file outranks the same one in yours. `rafa init` writes both
497
518
  with every setting commented out at its default, so uncomment a line,
498
519
  with its section line, to change it.
499
520
 
521
+ Tab indentation in `.rafa/config.yaml` is refused with rafa's own error
522
+ on every Bun version, before the parser sees the file. The error names
523
+ the line that carries a tab; use spaces only.
524
+
500
525
  ### `effort`
501
526
 
502
527
  One setting says how long a command waits for another rafa process that
@@ -795,6 +820,20 @@ is the old one removed, so no reader meets a half-replaced runtime. The
795
820
  link lands by a rename too, so a shell meets the old link or the new one
796
821
  and never none.
797
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
+
798
837
  ## Runtime
799
838
 
800
839
  The build targets bun, and `engines` names `bun` alone: there is no
@@ -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.
@@ -31,6 +31,11 @@ steps: a helper, never a hinderer. Hold every step you take to it:
31
31
  written; a flag you always add is a flag rafa may not need. Note both
32
32
  in the report.
33
33
  - Stop and ask only where there is a risk. Everything else is yours.
34
+ - Move an issue between epics with `rafa epic move <issue> --to=<epic>`,
35
+ never by adding a second `epic:` label: where the project installs the
36
+ epic guard, a second label added beside the first is removed, and its
37
+ comment lands on the issue. Turning the guard on or off is the
38
+ person's, never yours.
34
39
 
35
40
  ## Two stops, everything else unattended
36
41
 
@@ -123,10 +128,14 @@ One loop at a time; never two at once inside a stretch.
123
128
  `setsid` is Linux's; on macOS start it with `nohup` alone and log the
124
129
  difference as a gap. Detached loops are a gap of their own.
125
130
  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.
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.
134
+ 4. Merge its pull request:
135
+ - Into `stretch/<n>`: `rafa pr merge <pr> --skip-checks`. The merge push
136
+ runs `verify` asynchronously; read the result at the pit stop.
137
+ - Into `main`: `rafa pr wait <pr>` then `rafa pr merge <pr>` once
138
+ the checks pass.
130
139
  5. Clean up: `rafa cleanup`.
131
140
 
132
141
  ### 3. Pit stop
@@ -144,7 +153,8 @@ it is never a change of course.
144
153
  gh pr create --base main --head stretch/<n> --title "Stretch <n>" --body-file .rafa/stretch/<n>/report.md
145
154
  ```
146
155
 
147
- 2. Stop for the person's merge.
156
+ 2. Merge the stretch's pull request into `main` once `verify` is green on
157
+ it: `rafa pr wait <pr>` then `rafa pr merge <pr>`.
148
158
  3. After it, point `pr.base` back at `main`, then
149
159
  `rafa release settle --dry-run`, check the base it names, and
150
160
  `rafa release settle`. Tagging and publishing stay with the person.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: rafa-stretch-pit-stop
3
- description: "Use after each stretch item: check effort, bugs, delivery and conflicts, then go on, insert one fix, or halt."
3
+ description: "Use after each stretch item: check effort, bugs, delivery, conflicts and CI, then go on, insert one fix, or halt."
4
4
  provenance: first-party
5
5
  source: rafa
6
6
  stage: alpha
@@ -23,7 +23,7 @@ A pit stop is the check between two items. It fixes the one thing that
23
23
  would stop the next item, then rejoins the bucket: it is never a change
24
24
  of course, and never a reason to chase one issue down a rabbit hole.
25
25
 
26
- ## The four checks
26
+ ## The five checks
27
27
 
28
28
  | Check | Line | What is wrong |
29
29
  |---|---|---|
@@ -31,6 +31,11 @@ of course, and never a reason to chase one issue down a rabbit hole.
31
31
  | Bugs | `rafa issue list --type=bug --limit=200` | the open count rising, or bugs filed during this loop that repeat an open one |
32
32
  | Delivery | `rafa loop status`, `rafa pr list` | the run is done with no pull request, or its pull request did not merge |
33
33
  | Conflicts | `rafa pr show <pr>` | the pull request conflicts with the integration branch |
34
+ | CI | `gh run list --branch stretch/<n> --workflow verify.yml --limit 1` | the run failed (use `gh run view <id> --log-failed` to see why), or is still running |
35
+
36
+ A CI failure already red in the local runs is inherited and noted in the pit-stop entry.
37
+ A new failure is filed as one bug after a search for an existing one. A run still in progress
38
+ is read at the next pit stop.
34
39
 
35
40
  A conflict goes to the resolve plans first:
36
41
 
@@ -67,5 +72,6 @@ Append one entry to `.rafa/stretch/<n>/pit-stops.md`:
67
72
  - Bugs: 61 open, 64 at the start; none filed during the loop.
68
73
  - Delivery: pull request #612 merged into stretch/3.
69
74
  - Conflicts: none.
75
+ - CI: verify.yml passed.
70
76
  - Decision: next item, #486.
71
77
  ```
@@ -28,7 +28,7 @@ This file is the single source of that format. `rafa plan` inlines it, without i
28
28
  | `<plan.dir>/PLAN-<stub>.md` | Full task checklist with structured blocks and technical context |
29
29
  | `<plan.dir>/PREREQUISITES-<stub>.md` | Non-automatable setup steps required before the plan can run (only when any exist) |
30
30
 
31
- `plan.dir` is `.rafa/plans` unless the project's `.rafa/config.yaml` names another directory. `rafa plan --spec=<spec>.md` generates both files (optionally `--stub=<name>`; the stub defaults to the spec's basename) and writes them into `plan.dir`, creating the directory when it is missing. It reads the spec from the project root, or from `specs.dir` (`.rafa/specs` by default) when the root holds no such file, and refuses to run when `<plan.dir>/PLAN-<stub>.md` already exists.
31
+ `plan.dir` is `.rafa/plans` unless the project's `config.yaml` under `.rafa/` names another directory. `rafa plan --spec=<spec>.md` generates both files (optionally `--stub=<name>`; the stub defaults to the spec's basename) and writes them into `plan.dir`, creating the directory when it is missing. It reads the spec from the project root, or from `specs.dir` (`.rafa/specs` by default) when the root holds no such file, and refuses to run when `<plan.dir>/PLAN-<stub>.md` already exists.
32
32
 
33
33
  Execute a plan with `rafa start --plan=.rafa/plans/PLAN-<stub>.md`. With no `--plan`, `rafa start` runs `PLAN.md` in `plan.dir`, and falls back to a hand-written `PLAN.md` at the project root only when `plan.dir` holds no `PLAN.md`.
34
34
 
@@ -165,7 +165,7 @@ All rafa work follows a consistent naming scheme across specifications, plans, b
165
165
 
166
166
  | Artifact | Pattern | Example |
167
167
  | --- | --- | --- |
168
- | Specification file | `.rafa/specs/rafa-<n>-<slug>.md` | `.rafa/specs/rafa-20-pr-commands.md` |
168
+ | Specification file | `.rafa/specs/rafa-<n>-<slug>.md` | `rafa-20-pr-commands.md`, under `.rafa/specs/` |
169
169
  | Plan stub and directory | `rafa-<n>-<slug>` | `rafa-20-pr-commands` |
170
170
  | `issue:` field in `rafa:plan` | `<n>` (number only) | `issue: 20` |
171
171
  | Git branch | `feat/rafa-<n>-<slug>` | `feat/rafa-20-pr-commands` |
@@ -449,7 +449,7 @@ The second example above has no `skills=` and is still a valid task declaration.
449
449
 
450
450
  ## Three task-context injection modes
451
451
 
452
- The loop supports three modes of injecting task context, configured at plan start via `--inject=` or in `.rafa/config.yaml`:
452
+ The loop supports three modes of injecting task context, configured at plan start via `--inject=` or in the project's `config.yaml` under `.rafa/`:
453
453
 
454
454
  | Mode | Contents | Use case |
455
455
  | --- | --- | --- |
@@ -38,7 +38,7 @@ For the rafa project specifically, issue numbers are prefixed with `rafa-` and
38
38
  reflected throughout the spec and branch workflow:
39
39
 
40
40
  - **Issue reference** (in prose): `#rafa-<n>` — e.g., `#rafa-20`
41
- - **Spec file**: `.rafa/specs/rafa-<n>-<slug>.md` — e.g., `.rafa/specs/rafa-20-pr-commands.md`
41
+ - **Spec file**: `.rafa/specs/rafa-<n>-<slug>.md` — e.g., `rafa-20-pr-commands.md`, under `.rafa/specs/`
42
42
  - **Plan stub** (in prose): `rafa-<n>-<slug>` — e.g., `rafa-20-pr-commands`
43
43
  - **Branch name**: `feat/rafa-<n>-<slug>` — e.g., `feat/rafa-20-pr-commands`
44
44
  - **PR title**: `rafa-<n>: <title>` — e.g., `rafa-20: Add PR commands`