@open-tomato/rafa 0.43.0 → 0.45.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
@@ -182,9 +182,11 @@ the next one, so you rarely have to remember it.
182
182
  stored, one commit. A task that reports `blocked` is marked and the
183
183
  run stops with the reason; fix what it names and start again, and the
184
184
  blocked task goes first. After the last task a wrap-up session syncs
185
- with the base, commits a release fragment when the project has them
186
- (the plan's level and notes), pushes, opens the pull request and waits
187
- for CI, spending repair sessions on a red one.
185
+ with the base and rewrites the release fragment's notes into changelog
186
+ lines, when the project has fragments. The loop writes the fragment
187
+ (the plan's level and notes) and commits it, pushes, opens the pull
188
+ request and waits for CI, spending repair sessions on a red one. The
189
+ version and the changelog are left to `rafa release settle`.
188
190
 
189
191
  From another terminal: `rafa loop status`, `rafa loop pause` (after the
190
192
  running task), `rafa loop stop` (now).
@@ -205,12 +207,12 @@ the next one, so you rarely have to remember it.
205
207
 
206
208
  ### Release fragments and settling
207
209
 
208
- A branch no longer owns a version number. Instead, the wrap-up commits a
209
- release fragment (a small markdown file naming the plan, level and notes),
210
- and `rafa release settle` assigns the version on the base branch after
211
- merges. This lets several branches merge in any order without a version
212
- collision: whichever machine settles first releases all waiting fragments
213
- under one version.
210
+ A branch no longer owns a version number. Instead, the loop's wrap-up
211
+ writes and commits a release fragment (a small markdown file naming the
212
+ plan, level and notes), and `rafa release settle` assigns the version and
213
+ folds the changelog on the base branch after merges. This lets several
214
+ branches merge in any order without a version collision: whichever
215
+ machine settles first releases all waiting fragments under one version.
214
216
 
215
217
  The pull request shows a forecast of what version the branch would get if
216
218
  merged now. The fragment is stored under `release.fragments` (default
@@ -819,16 +821,20 @@ install the same way (`src/runtime/install.ts`). The bin is not in
819
821
  `~/.bun/bin`, where `bun link` in this checkout re-points `rafa` at the
820
822
  checkout's `dist/` with no message, so put `~/.rafa/bin` on `PATH` ahead
821
823
  of `~/.bun/bin`; both warn when it is not, and `rafa doctor` checks it.
822
- Both exit 1 before building anything while a plan tracker in `plan.dir`
823
- (`.rafa/plans` unless `.rafa/config.yaml` names another) still holds an
824
- open or blocked task, and name every such tracker. `rafa self-update`
825
- runs only inside a project, so `rafa init` the checkout first, and it
826
- also exits 1 while a loop of the project is live, naming each loop's
827
- branch and pid, unless `dangerous.selfUpdateDuringLoop` is true in the
828
- config; `--force` does not override that wait. They exit
829
- 2 when they could not run: a `package.json` that is not rafa's or cannot
830
- be read, a config or tracker they could not read, a loop record
831
- `rafa self-update` could not read, or a build, copy or link that failed.
824
+ A plan tracker in `plan.dir` (`.rafa/plans` unless `.rafa/config.yaml`
825
+ names another) that still holds an open or blocked task holds an install
826
+ back only while a loop of the checkout is live: both then exit 1 before
827
+ building anything and name every such tracker, unless `--force` is on
828
+ the line. With no loop live they install, one warning naming each such
829
+ tracker, so a plan stopped halfway no longer blocks an update.
830
+ `rafa self-update` runs only inside a project, so `rafa init` the
831
+ checkout first, and it also exits 1 while a loop of the project is live,
832
+ naming each loop's branch and pid, unless
833
+ `dangerous.selfUpdateDuringLoop` is true in the config; `--force` does
834
+ not override that wait. They exit 2 when they could not run: a
835
+ `package.json` that is not rafa's or cannot be read, a config, tracker
836
+ or loop record they could not read, or a build, copy or link that
837
+ failed.
832
838
 
833
839
  A version is installed once. Both also exit 1, before building, when
834
840
  `~/.rafa/runtime/<version>/` is already there, naming that directory and
@@ -311,7 +311,7 @@ The block strip rule means:
311
311
  - A block in a stage description does not appear in the operator log line
312
312
  - A block anywhere in the plan does not appear in a commit subject or commit body
313
313
 
314
- The strip happens where the loop reads the next task, `findNextTask` in `src/utils/tracker.ts`, and it follows fences the way a renderer shows them (`src/plan/blocks.ts`):
314
+ The strip happens where the loop reads the next task, `findNextTask` in `src/utils/tracker.ts`, and it follows fences the way a renderer shows them (`src/core/plan/blocks.ts`):
315
315
 
316
316
  - Only a closed, top-level `rafa:*` block hides its lines. Every other fence is transparent, so a `- [ ] ` line at column 0 inside a `markdown` or `text` illustration, or inside a `rafa:` fence nested in one, is dispatched as a task. A plan that illustrates the format indents its example lines.
317
317
  - A `rafa:` fence that is never closed hides nothing, because taking the rest of the document as its body would end the plan with its tasks unrun. `parsePlan` reports it as `unclosed-block`, and each open task line after it as `task-in-block`.
@@ -335,11 +335,12 @@ The strip happens where the loop reads the next task, `findNextTask` in `src/uti
335
335
  holding no nested braces and at least one recognised key, and it is
336
336
  never the whole task text. Two spaces separate it from the text.
337
337
  Anything failing one of those rules stays task text — a task ending on
338
- a code span carrying `{ "a": 1 }` is not a declaration. The one thing
339
- that may follow the block is the loop's own: on a blocked task's
340
- tracker line it writes `<!-- blocked: <text> -->` after the block, and
341
- takes that comment off before the block is read. The plan itself never
342
- holds one.
338
+ a code span carrying `{ "a": 1 }` is not a declaration. What may
339
+ follow the block is the loop's own: on a blocked task's tracker line
340
+ it writes `<!-- blocked: <text> -->` after the block, and on a repair
341
+ task's line `<!-- repairs: <text> -->` before that, naming the plan
342
+ task repaired. It takes both comments off before the block is read.
343
+ The plan itself never holds either.
343
344
  * Its tokens are space-separated `key=value` pairs, of the recognised keys
344
345
  in the table below; an unrecognised key is kept for telemetry and maps
345
346
  to no flag.
@@ -381,7 +382,7 @@ The recognised keys are the `DECLARATION_KEYS` of `src/utils/declaration.ts`, wh
381
382
 
382
383
  ### `skills=` declaration
383
384
 
384
- When a task needs help from a skill, name those skills with `skills=`. Skill names must come from the skill index provided in this prompt; naming a skill no tier holds is recorded as an issue. Names are comma-separated with no spaces.
385
+ When a task needs help from a skill, name those skills with `skills=`. Skill names must come from the skill index provided in this prompt. Naming a skill no tier holds is refused, not recorded: `rafa plan validate` exits 1 on the line that names it, and `rafa loop start`'s preflight refuses to start the plan, so nothing is dispatched. Names are comma-separated with no spaces.
385
386
 
386
387
  `skills` is a recognised key that maps to no flag: there is no CLI flag for a skill, so the names are parsed, kept on the dispatch record and stripped from the task text with the rest of the block. It stands on its own — `{skills=bun-testing}` is a declaration with no other key beside it — and a value that is not a comma-separated list of skill names is recorded as an issue rather than passed on.
387
388
 
@@ -411,6 +412,8 @@ The second example above has no `skills=` and is still a valid task declaration.
411
412
  - [ ] Move the test preload into `bunfig.toml` {tests=full}
412
413
  ```
413
414
 
415
+ A task's text never asks its session for a whole-suite run, or for any command that can outlast one Bash call, since the Bash tool stops a command at 10 minutes. The runner runs the suite through `tests=full` on the task. A task that needs a long run's output reads a file that a `[start]` prerequisite or the runner wrote, such as the `.output.txt` beside a suite run's JUnit file.
416
+
414
417
  ---
415
418
 
416
419
  ## Task sizing (session economics)
@@ -444,6 +447,11 @@ The second example above has no `skills=` and is still a valid task declaration.
444
447
  --write-tree origin/<base> HEAD`) and assemble the body material — the gate
445
448
  captures, the test plan, the recorded debt — into the plan's close-out
446
449
  notes for that wrap-up session to use.
450
+ * A task's text never asks its session for the whole suite, or for any
451
+ command that can outlast one Bash call. Declare `tests=full` on the task
452
+ and the runner runs the suite after the commit; a task that needs a long
453
+ run's output reads it from the file a `[start]` prerequisite or the
454
+ runner wrote.
447
455
 
448
456
  ---
449
457
 
@@ -472,6 +480,8 @@ The wrap-up session always receives `full` regardless of the configured mode.
472
480
  - [ ] {Tool} installed: `{tool} --version`
473
481
  - [ ] {Service name} answering on port {n}: `curl -sf http://localhost:{n}/health`
474
482
  - [ ] {VAR_NAME} set, obtained from {where}: `test -n "${VAR_NAME}"`
483
+ - [ ] [tasks] {Something only the tasks need}: `{command to verify}`
484
+ - [ ] [wrap-up] {Something only the wrap-up needs}: `{command to verify}`
475
485
 
476
486
  ## Credentials [human]
477
487
  - [ ] {Credential description}
@@ -488,6 +498,8 @@ How the file is read:
488
498
  - An item's tag is the `[auto]`, `[human]`, or `[start]` written right after its box. Without one it takes its section's tag: a heading carrying `[auto]` tags its section `auto`, one carrying `[human]` or naming `manual`, `human`, `sign-off` or `team` tags it `human`, and one carrying `[start]` tags it `start`. A heading's tag reaches the deeper headings under it and ends at the next heading of its own level or shallower. An item under no tagged heading is `human`.
489
499
  - An `auto` item's probe is the backticked span that ends it, after its final `: `. The item merges as a required prerequisite, the tier whose failure halts a run.
490
500
  - A `start` item's probe is read the same way. The item is probed on first dispatch only (skipped on resume), and failure halts a run on first dispatch.
501
+ - An item's scope is the `[tasks]` or `[wrap-up]` marker written at its opening, after its box and after its tag when it has one (`- [ ] [auto] [tasks] ...`). Without one it takes the marker of the nearest heading above it that carries one, which reaches the deeper headings under it and ends at the next heading of its own level or shallower, as a tag does; an item's own marker outranks its heading's. With no marker anywhere the scope is `both`, and the two markers written together read as `both` too. The marker is dropped from the item's text and is never read as its probe.
502
+ - The scope says which dispatches need an `auto` item: `tasks` the task sessions, `wrap-up` the wrap-up session, `both` every one. A marker on a `start` or `human` item is read and changes nothing: the `start` item is still probed on first dispatch only, and the `human` item is still a reminder.
491
503
  - A `human` item is a reminder: named to the operator, never probed, and never halting a run.
492
504
  - An `auto` or `start` item that does not end with `: ` and its command — the command first, text after it, or no span at all — is malformed: `rafa loop start` and `rafa doctor` refuse the plan, naming its line, and run nothing.
493
505
 
@@ -496,6 +508,7 @@ Rules:
496
508
  - An `[auto]` item holds exactly one backticked span, and that span is its command. The preflight runs it as written, so put no package name, path or other command in backticks anywhere in the item.
497
509
  - Tag an item `auto` only when a shell command proves it, and end the item with `: ` and that command. The command asks for no input and changes nothing.
498
510
  - Tag an item `start` only when a shell command proves it and it should only be checked on the first dispatch of a plan (not on resume). End it with `: ` and the command, one span, as for `auto`.
511
+ - Mark an `auto` item `[tasks]` when only the plan's tasks need it and `[wrap-up]` when only the wrap-up does (pushing, opening the pull request, releasing); leave it unmarked when both do or when unsure, since an unmarked item is always probed. Write the marker bare, at the item's opening or on its heading, never in backticks and never after the command: text after the span makes the item malformed.
499
512
  - Make the command complete: it exits 0 when the prerequisite holds. To prove a tool is installed, probe `<tool> --version`, `<tool> --help` or `which <tool>` — never a bare subcommand such as `uvx check-jsonschema`, which exits non-zero for want of arguments.
500
513
  - Tag every step for after the plan merges `human`, as the heading above does, so no run ever executes one as a probe.
501
514
  - Do not duplicate steps already documented in the repo's contributor docs (README, CONTRIBUTING, and the like).
@@ -506,10 +519,10 @@ Rules:
506
519
 
507
520
  ## Format validation
508
521
 
509
- The loop parses plan files through `src/plan/parse.ts`:
522
+ The loop parses plan files through `src/core/plan/parse.ts`:
510
523
 
511
- - **Block parsing** (`src/plan/blocks.ts`): Reads fenced `rafa:*` blocks. Tolerates documents with no blocks. Retains unknown kinds.
512
- - **Plan parsing** (`src/plan/parse.ts`): Builds the plan model over blocks and the checklist grammar. Each stage captures the tasks under it and the first `rafa:stage-context` block between its heading and the next `# Stage:` heading.
524
+ - **Block parsing** (`src/core/plan/blocks.ts`): Reads fenced `rafa:*` blocks. Tolerates documents with no blocks. Retains unknown kinds.
525
+ - **Plan parsing** (`src/core/plan/parse.ts`): Builds the plan model over blocks and the checklist grammar. Each stage captures the tasks under it and the first `rafa:stage-context` block between its heading and the next `# Stage:` heading.
513
526
  - **Declaration parsing** (`src/utils/declaration.ts`): Takes a trailing `{...}` block off a task line and reads its `key=value` entries. The block counts only when one of its keys is a recognized key (see Task declarations).
514
527
  - **Report parsing** (`src/report/parse.ts`): Reads the last `rafa:report` block from agent output and parses its YAML body. Answers an explicit absence record if no block is present.
515
528
 
@@ -537,7 +550,7 @@ When the spec adds or changes anything in `.rafa/effort/`:
537
550
  When planning work on rafa commands: every command that can start a Claude
538
551
  Code session must declare its `spends` field on its `RafaCommand` definition.
539
552
  The field tells the help system, `describe` output, and the spawn guard in
540
- `src/utils/claude.ts` what Claude usage the command declares. It is optional,
553
+ `src/core/loop/claude.ts` what Claude usage the command declares. It is optional,
541
554
  and takes one of four shapes:
542
555
 
543
556
  - `{ when: 'always'; what: string }` — the command always starts a session
@@ -626,4 +639,4 @@ Both follow the same structured format. The difference is:
626
639
  - **Hand-written plans** (by a planner agent): Prose in the description, stage contexts, and task granularity reflect careful thought about the work.
627
640
  - **Generated plans** (by `rafa plan`): Produced from a spec document; structure is the same.
628
641
 
629
- A hand-written plan read by `src/plan/parse.ts` produces the same data model as a generated one. This is the property the structured format enforces.
642
+ A hand-written plan read by `src/core/plan/parse.ts` produces the same data model as a generated one. This is the property the structured format enforces.
@@ -30,7 +30,7 @@ Two kinds of documentation are maintained:
30
30
  | **API (Swagger)** | `@asteasolutions/zod-to-openapi` + `swagger-ui-express` | `openapi.json` + served behind `ctx.requireAuth` at `GET /docs/` | `bun run docs:openapi` |
31
31
 
32
32
  > Both rows are INSTALLED in `@ar/service` — the OpenAPI half is no longer a
33
- > convention to adopt on some later day, and [`rules/openapi.md`](rules/openapi.md)
33
+ > convention to adopt on some later day, and this skill
34
34
  > records what is there rather than a setup to perform. The two scripts are
35
35
  > SIBLINGS sharing no output tree, which is worth stating because the pair of
36
36
  > names suggests they do: `docs:openapi` writes the gitignored `.docs/swagger/`,
@@ -46,16 +46,6 @@ Auto-generated outputs go in `.docs/` (dotfolder) and are always gitignored.
46
46
 
47
47
  ---
48
48
 
49
- ## Rules index
50
-
51
- | Rule file | When to use |
52
- | --- | --- |
53
- | [`rules/tsdoc.md`](rules/tsdoc.md) | Writing TSDoc comments on any TypeScript symbol |
54
- | [`rules/openapi.md`](rules/openapi.md) | Documenting Express routes with OpenAPI/Swagger |
55
- | [`rules/typedoc-setup.md`](rules/typedoc-setup.md) | Adding TypeDoc infra to the repo (or a project derived from it) |
56
-
57
- ---
58
-
59
49
  ## Workflow
60
50
 
61
51
  1. **Determine kind before touching**: identify whether documentation is manual or auto-generated before editing. Manual docs live in `docs/`; auto-generated outputs live in `.docs/`.
@@ -72,7 +62,7 @@ Before marking a documentation task done:
72
62
  - [ ] Every exported function, class, and interface has a TSDoc block with `@param` and `@returns`.
73
63
  - [ ] Every file has a `@packageDocumentation` comment (or is covered by a module-level JSDoc).
74
64
  - [ ] Every Express router factory is documented with `@remarks` listing its HTTP endpoints.
75
- - [ ] `typedoc.json`, `tsconfig.docs.json`, and a `docs:generate` script exist (see [`rules/typedoc-setup.md`](rules/typedoc-setup.md)).
65
+ - [ ] `typedoc.json`, `tsconfig.docs.json`, and a `docs:generate` script exist.
76
66
  - [ ] `openapi.ts` exists and every route is registered in it — `openapi-coverage.test.ts` is the gate that says so, and a route added without a binding-table entry reddens it.
77
67
  - [ ] `.docs/` is already gitignored twice over and needs no new entry: once at the repo root (`.gitignore`) and again at the package (`packages/service/.gitignore`), both files tracked. Running `git check-ignore -v` on the generated `openapi.json` names the PACKAGE rule, the nearer file winning — take the source off that output rather than predicting it.
78
68
  - [ ] `docs/` (manual ADRs) is **not** gitignored.