@rness/cli 0.20.0 → 0.21.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 +221 -35
- package/dist/bin/rness.js +5 -3
- package/dist/bin/rness.js.map +1 -1
- package/dist/chunk-4BM4FUWO.js +263 -0
- package/dist/chunk-4BM4FUWO.js.map +1 -0
- package/dist/chunk-D3D2WCGW.js +6897 -0
- package/dist/chunk-D3D2WCGW.js.map +1 -0
- package/dist/chunk-T5PINUCP.js +5582 -0
- package/dist/chunk-T5PINUCP.js.map +1 -0
- package/dist/index.js +32 -26
- package/dist/index.js.map +1 -1
- package/dist/note-RBG7OXVI.js +22 -0
- package/dist/note-RBG7OXVI.js.map +1 -0
- package/dist/summary-UCMFESSA.js +91 -0
- package/dist/summary-UCMFESSA.js.map +1 -0
- package/mod/hooks/register.tsx +20 -3
- package/package.json +1 -1
- package/dist/chunk-WIZHU4WT.js +0 -10305
- package/dist/chunk-WIZHU4WT.js.map +0 -1
package/README.md
CHANGED
|
@@ -31,6 +31,7 @@ Inside a workspace, every `rness` delegates to the copy pinned in
|
|
|
31
31
|
rness status [<tab>] [--json]
|
|
32
32
|
rness pulse create [<collection>] [-y]
|
|
33
33
|
rness pulse sync
|
|
34
|
+
rness pulse note [--plan <path>] [--kind approach|deviation|blocker|done] [<text>]
|
|
34
35
|
rness validate
|
|
35
36
|
rness mcp
|
|
36
37
|
|
|
@@ -65,7 +66,7 @@ when dropped, red `?` when missing.
|
|
|
65
66
|
`yellow` for `In progress`; `red` without a status) and its item there
|
|
66
67
|
(`link`, the board filtered on its path; null without a pulse) — the
|
|
67
68
|
board (`pulse`), and what a Claude Code session shows of the workspace,
|
|
68
|
-
worded by the CLI — the session-start banner, the
|
|
69
|
+
worded by the CLI — the session-start banner, the footer's label, the
|
|
69
70
|
scope's plans `In progress` and the notes of the safety net (see
|
|
70
71
|
"Hooks"). The plugin's mod reads it (see
|
|
71
72
|
"The mod").
|
|
@@ -176,9 +177,11 @@ the pinned copy, and computes nothing itself:
|
|
|
176
177
|
installed copy does not match, problems `validate` would report): those
|
|
177
178
|
notes. The banner is not repeated there; the session-start line says it
|
|
178
179
|
once, in the transcript.
|
|
179
|
-
- **
|
|
180
|
-
|
|
181
|
-
|
|
180
|
+
- **A label in the prompt footer**, among the session modes (`focus`,
|
|
181
|
+
`memory paused`), dim: `rness · <scope> · <n> in progress`, with `⚠ <n>`
|
|
182
|
+
when there are notes. Not the pinned status line a plugin can set:
|
|
183
|
+
Claude Code draws every pinned line after a `⚠` in its warning colour
|
|
184
|
+
(2.1.291), the wrong sign for a line that informs.
|
|
182
185
|
- **`/rness:status [tab]` as a pane** beside the conversation, a tab per
|
|
183
186
|
collection, a row per document, its status in the colour Agent Pulse
|
|
184
187
|
gives it (yellow in progress, green done, red blocked, gray draft or
|
|
@@ -205,13 +208,15 @@ It reads the snapshot again at session start, after an `Edit` or `Write`
|
|
|
205
208
|
of a file under `.rness/`, and at the end of each turn, off the turn's
|
|
206
209
|
path. The module runs the pinned copy at the one path `sync` writes into it
|
|
207
210
|
for its place (`.rness` at the root, `../../.rness` in a clone), as the
|
|
208
|
-
settings hooks do: never a copy a clone's own tree could hold.
|
|
211
|
+
settings hooks do: never a copy a clone's own tree could hold. Like them,
|
|
212
|
+
it never installs: a pin that drifts from the installed copy is a note in
|
|
213
|
+
the band, and `npm install` in `.rness` is the developer's. It loads
|
|
209
214
|
where the plugin loads — a trusted folder, `claude -p` included — on a
|
|
210
215
|
Claude Code that has mods: run by 2.1.280 and later, ignored without an
|
|
211
216
|
error by 2.1.240 and 2.1.199, where the skills work as before (verified on
|
|
212
217
|
2026-10-04). An older Claude Code is told so once per version and machine,
|
|
213
218
|
in the session-start line: `rness: Claude Code 2.1.240 shows no rness band,
|
|
214
|
-
|
|
219
|
+
footer label or pane; 2.1.280 or later does — claude update`. The version
|
|
215
220
|
comes from `AI_AGENT`, which Claude Code sets (2.1.240 does); one that does
|
|
216
221
|
not set it, or not in that form, is told nothing. The versions told are kept
|
|
217
222
|
in `claude-code.json` beside the login (`~/.config/rness/` by default). Not in
|
|
@@ -240,7 +245,9 @@ workspace root's carry four Claude Code hooks, all run by the pinned copy:
|
|
|
240
245
|
repository or nothing installed there, a `rness.json` rness refuses, a pin
|
|
241
246
|
the installed copy does not match, the problems `rness validate` reports.
|
|
242
247
|
A Claude Code too old for the plugin's mod gets one more line, once (see
|
|
243
|
-
"The mod").
|
|
248
|
+
"The mod"). When a board keeps a journal and the scope has a plan in
|
|
249
|
+
progress, the model gets one more line: how and when to post a note (see
|
|
250
|
+
"Pulse"). After a compaction, the context only.
|
|
244
251
|
- **Before an edit** (`PreToolUse` on `Edit|Write`): refused, with the
|
|
245
252
|
reason for the model, when it would change what `sync` generates — a
|
|
246
253
|
line of the block of an `AGENTS.md` or `CLAUDE.md` (the reason names the
|
|
@@ -254,10 +261,13 @@ workspace root's carry four Claude Code hooks, all run by the pinned copy:
|
|
|
254
261
|
- **After an edit** (`PostToolUse` on `Edit|Write`): when the file is under
|
|
255
262
|
`.rness/`, its front-matter problems — or those of `rness.json` — go back
|
|
256
263
|
to the model, which fixes them in the same turn. Any other edit costs one
|
|
257
|
-
path check. Stale blocks are left to `sync`.
|
|
258
|
-
edit is then marked on
|
|
259
|
-
|
|
260
|
-
|
|
264
|
+
path check. Stale blocks are left to `sync`. When a board declares
|
|
265
|
+
`mark` and holds the document, the edit is then marked on it, broken or
|
|
266
|
+
not; see "Pulse".
|
|
267
|
+
- **At session end** (`SessionEnd`): when a board declares `clear-marks`,
|
|
268
|
+
clears the marks this session set and syncs; when one declares
|
|
269
|
+
`journal-summary`, posts the session's summary; see "Pulse". Without
|
|
270
|
+
either, nothing.
|
|
261
271
|
|
|
262
272
|
Each hook is one fixed `sh` line: it runs
|
|
263
273
|
`<.rness>/node_modules/@rness/cli/dist/bin/rness.js hook <event>` when that
|
|
@@ -269,7 +279,8 @@ own hooks stay where they are.
|
|
|
269
279
|
|
|
270
280
|
Claude Code runs hooks from a committed settings file without asking each
|
|
271
281
|
developer, including in `claude -p`. These four read `.rness/`, write
|
|
272
|
-
|
|
282
|
+
no file of the workspace and run no install; with a journal, the session
|
|
283
|
+
start records the clone's `HEAD` in its git directory. Only with a pulse declared do
|
|
273
284
|
they reach the network, through a detached `rness` process that uses your
|
|
274
285
|
login; when that process fails, it writes why to `pulse.json` in rness's
|
|
275
286
|
configuration directory (`~/.config/rness/` by default), which the next
|
|
@@ -284,10 +295,70 @@ status, it received the problem. The `sh` line is not verified on Windows.
|
|
|
284
295
|
rness pulse create marketing # a collection's own project (0.17.0)
|
|
285
296
|
rness pulse sync # every declared project, as often as wanted
|
|
286
297
|
|
|
287
|
-
A projection of rness's state on the organization's GitHub Projects
|
|
288
|
-
|
|
289
|
-
document of `.rness/`, and sees when an agent is at work
|
|
290
|
-
writes the
|
|
298
|
+
A projection of rness's state on the organization's GitHub Projects,
|
|
299
|
+
each declared in `rness.json`: first **Agent Pulse**, where the team sees —
|
|
300
|
+
and reads — every document of `.rness/`, and sees when an agent is at work
|
|
301
|
+
on one. rness writes the boards; if it is not in rness, it does not belong
|
|
302
|
+
there.
|
|
303
|
+
|
|
304
|
+
- **Boards declared in `rness.json`** (0.21.0): `projects` maps a name to
|
|
305
|
+
a board, written whole — its `number`, `collections`, `colors`,
|
|
306
|
+
`fields`, `labels`, `views`, and optionally `title`, `description`,
|
|
307
|
+
`readme` and `updates` (files of `.rness/`). What `rness.json` says is
|
|
308
|
+
the board; what it does not declare, the board does not have, but the
|
|
309
|
+
engine's own: one issue of `.rness` per document, found by its `Path`,
|
|
310
|
+
its `Status`, the label `rness`. Nothing knows Agent Pulse by name: it
|
|
311
|
+
is a board like any other, made from the preset `agent-pulse`, and the
|
|
312
|
+
example a team copies for another.
|
|
313
|
+
- `collections`: `"all"` (ADR, specs and plans with the contract's
|
|
314
|
+
statuses, then every other directory `rness status` finds, but those
|
|
315
|
+
another board holds), or directories, each with `statuses` —
|
|
316
|
+
`"contract"`, `"found"` or a list in order — a `label` and an optional
|
|
317
|
+
`field`, a select of its statuses alone.
|
|
318
|
+
- `fields`: each a `type` (`text`, `date`, `select`, `number`) and a
|
|
319
|
+
`from`: a front-matter key, or what rness knows — `$collection`,
|
|
320
|
+
`$status`, `$agent` (`working` while a session marks the card),
|
|
321
|
+
`$session`, `$sessions`, `$id` — or a list, the first present winning.
|
|
322
|
+
`Path`, `Status` and GitHub's own fields cannot be declared.
|
|
323
|
+
- `views`: each a `name` and a `layout` (`board`, `table`, `roadmap`),
|
|
324
|
+
optionally `collection` and `filter`; a board's `columns`, a table's
|
|
325
|
+
`fields`, a roadmap's `date`.
|
|
326
|
+
- `colors`: option → `gray`, `blue`, `green`, `yellow`, `orange`, `red`,
|
|
327
|
+
`pink` or `purple`; an option not named takes its kind's colour (a
|
|
328
|
+
status its tone, a collection pink). A colour changed is set at the
|
|
329
|
+
next sync, every card keeping its value.
|
|
330
|
+
- A board that `rness.json` declares wrongly is refused alone, by its
|
|
331
|
+
full key (`"projects.marketing.views[2].date" must name a date
|
|
332
|
+
field`); the others sync. `validate` reports it, and also a collection
|
|
333
|
+
that is no directory of `.rness/`, one on two boards, a `readme` or
|
|
334
|
+
`updates` not there, a README that still declares (below). `readme`
|
|
335
|
+
and `updates` are paths within `.rness/`: a path out of it, or a file
|
|
336
|
+
that is a link leading out, is refused before anything is read.
|
|
337
|
+
- A view declared and missing is made; one whose filter or fields differ
|
|
338
|
+
is updated in place, keeping its id, sort and widths (GitHub returns a
|
|
339
|
+
filter as given and the fields in the project's order, read on
|
|
340
|
+
2026-10-06); one whose layout or columns differ is made again. A view
|
|
341
|
+
rness made and no longer declared is deleted; one the team made is
|
|
342
|
+
left, and said once per clone (`note view Roadmap is not declared:
|
|
343
|
+
delete it on GitHub if unwanted`), as is a field no longer declared and
|
|
344
|
+
views out of the declared order (GitHub reorders none). A roadmap's
|
|
345
|
+
date is chosen in its settings: GitHub's API does not set it.
|
|
346
|
+
- **Presets and their revisions.** `pulse create` writes a board from a
|
|
347
|
+
preset, `agent-pulse` or `collection`, recording it (`"preset":
|
|
348
|
+
"agent-pulse/1"`). When a later rness ships a newer revision, `rness
|
|
349
|
+
sync` merges it into the board value by value: a value the team never
|
|
350
|
+
changed takes the new one, one it changed is kept, and said when the
|
|
351
|
+
revision changed it too (`kept projects.pulse.colors.Draft: kept orange,
|
|
352
|
+
agent-pulse/2 gives blue`). Removing `preset` takes a board off the
|
|
353
|
+
merge. An upgrade commits the result, for the team to read before
|
|
354
|
+
pushing.
|
|
355
|
+
- **From 0.20 and before.** A board declared by its number
|
|
356
|
+
(`"pulse": 4`) is read as its preset, and `rness sync` — which `rness
|
|
357
|
+
upgrade` runs — writes it whole; nothing changes on GitHub. A
|
|
358
|
+
collection's `README.md` that declared `description`, `statuses`,
|
|
359
|
+
`fields` or `labels` has them moved into its board and out of its front
|
|
360
|
+
matter (a value declared otherwise in both is refused, naming both).
|
|
361
|
+
Until then, `pulse sync` skips a board whose README still declares.
|
|
291
362
|
|
|
292
363
|
- **Items**: one per document of `rness status`, an issue of
|
|
293
364
|
`<org>/.rness` added to the project. GitHub shows it only to people who
|
|
@@ -377,8 +448,9 @@ Session → Working session`). A board per directory, named as
|
|
|
377
448
|
that restricts OAuth apps must approve "Rness", as for its private
|
|
378
449
|
repositories.
|
|
379
450
|
- **`pulse create`** needs an `org` in `rness.json` (a blank workspace is
|
|
380
|
-
refused) and no pulse yet. It creates the project and at once writes
|
|
381
|
-
|
|
451
|
+
refused) and no pulse yet. It creates the project and at once writes the
|
|
452
|
+
board whole, from the preset `agent-pulse`, into `projects.pulse` (and
|
|
453
|
+
the `provider`) in `rness.json`,
|
|
382
454
|
then adds the fields, options and views, and runs a first sync; its
|
|
383
455
|
`created` lines say what it added. If a step after the project fails, it
|
|
384
456
|
exits 1 with the pulse declared, and `rness pulse sync` completes the
|
|
@@ -409,13 +481,17 @@ added to project`) may change a field of rness's items; the next sync
|
|
|
409
481
|
writes it back.
|
|
410
482
|
- **A collection's own project** (0.17.0): `rness pulse create <collection>`
|
|
411
483
|
gives a directory of `.rness/` whose documents carry a status — a tab of
|
|
412
|
-
`rness status` — a project of its own, named after it,
|
|
413
|
-
|
|
484
|
+
`rness status` — a project of its own, named after it, written whole
|
|
485
|
+
from the preset `collection` into `projects.<collection>` (0.21.0;
|
|
486
|
+
before, `"projects": { "pulse": 4, "marketing": 5 }`). Agent Pulse keeps every
|
|
414
487
|
other collection and the `Working` table; the collection's items leave
|
|
415
488
|
it (`deleteProjectV2Item`, their issues untouched) once its project
|
|
416
489
|
holds them. `pulse sync` syncs the collections' projects, then Agent
|
|
417
490
|
Pulse. The project is written from the collection's files, one way:
|
|
418
|
-
- `<collection>/README.md` is its README
|
|
491
|
+
- `<collection>/README.md` is its README (`readme` in its board since
|
|
492
|
+
0.21.0, where `description`, `statuses`, `fields` and `labels` are
|
|
493
|
+
declared too: what follows is how a README declared them before,
|
|
494
|
+
which `rness sync` moves); its front matter may give
|
|
419
495
|
`description:` (the short description), `statuses:` (the columns, in
|
|
420
496
|
order, each there even when empty), `fields:` (each a name, a `type` —
|
|
421
497
|
`text`, `date`, `select`, `number` — and `from`, the front-matter key
|
|
@@ -434,9 +510,25 @@ added to project`) may change a field of rness's items; the next sync
|
|
|
434
510
|
none of this reaches Agent Pulse: a workspace that declares no collection
|
|
435
511
|
keeps its board as 0.16 made it.
|
|
436
512
|
|
|
437
|
-
- **Hooks**, with `claude` in `agents
|
|
438
|
-
|
|
439
|
-
|
|
513
|
+
- **Hooks**, with `claude` in `agents`: what a session does to a board is
|
|
514
|
+
declared in its `hooks` (spec 0032, 0.21.0), each event — `session-start`,
|
|
515
|
+
`edit`, `session-end` — listing actions from a fixed catalogue:
|
|
516
|
+
`mark-in-progress` (the documents of the session's scope in the given
|
|
517
|
+
`collections` and `statuses`, `plans` and `In progress` by default),
|
|
518
|
+
`mark` (the document edited, on a board that holds it) and `clear-marks`
|
|
519
|
+
(the session's marks, then a sync). Marks are written through the
|
|
520
|
+
board's select from `$agent` and its text from `$session`, whatever their
|
|
521
|
+
names. A hook never runs a command `rness.json` names: the file is the
|
|
522
|
+
organization's and the hooks run on every developer's machine. The
|
|
523
|
+
preset `agent-pulse` declares all three, which is 0.20's behaviour;
|
|
524
|
+
removing `hooks` from a board turns its marking off, and a board without
|
|
525
|
+
them is only what `pulse sync` makes of the documents. For each event,
|
|
526
|
+
one detached `rness pulse run <event>` does every board's actions, in
|
|
527
|
+
the order of `projects`; a failure is recorded naming the board and the
|
|
528
|
+
action (`mark on Marketing failed: …`). `rness pulse mark`, which 0.20's
|
|
529
|
+
hooks started, stays, hidden, through 0.21.x. With Agent Pulse's preset:
|
|
530
|
+
session start marks the `In progress` plans of the session's scope
|
|
531
|
+
`Agent: working`, with the session; an edit of a document of `.rness/` marks it — one the agent has just written, with no item yet, gets its issue first
|
|
440
532
|
through a sync, and so does one whose status the edit changed, so its
|
|
441
533
|
card moves within seconds rather than at the session's end; an edit that
|
|
442
534
|
leaves the status alone, or of any other file of `.rness/`, costs no sync;
|
|
@@ -453,6 +545,40 @@ added to project`) may change a field of rness's items; the next sync
|
|
|
453
545
|
`the pulse needs the project scope: run rness login` or
|
|
454
546
|
`cannot reach GitHub: …`. Two sessions marking one plan both write; the
|
|
455
547
|
last wins.
|
|
548
|
+
- **Agent journal** (spec 0030, 0.21.0): how a plan was implemented, in
|
|
549
|
+
the agent's words. A board that holds `plans` declares
|
|
550
|
+
`{ "action": "journal", "to": "plan" | "repo", "limit": 5 }` at
|
|
551
|
+
`session-start`, and `journal-summary` at `session-end`. With a plan
|
|
552
|
+
`In progress` in the session's scope, the session start tells the model
|
|
553
|
+
to post a note — `rness pulse note`, or `rness_note` — when it chooses an
|
|
554
|
+
approach, deviates from the plan, is blocked, and when done: decisions
|
|
555
|
+
and their reasons, not steps. A note is a comment headed
|
|
556
|
+
`**Approach** · claude · 1a2b3c4d · \`feat/limits\` @ \`9f8e7d6\``
|
|
557
|
+
(`--kind`titles it; the branch and commit are those of the session's
|
|
558
|
+
repository), then the text, from the argument or stdin. With`"plan"`it goes to the plan's issue in`.rness`. With `"repo"`, to the plan's
|
|
559
|
+
implementation issue in the repository the session works in: labelled
|
|
560
|
+
`rness:plan`, found again by the last line of its body, made by the
|
|
561
|
+
first note and made a sub-issue of the plan's. The note prints where it
|
|
562
|
+
went (`acme/api#87`), for the pull request that completes the plan there
|
|
563
|
+
to carry `Closes acme/api#87`and an earlier one`Refs acme/api#87`.
|
|
564
|
+
GitHub closes the issue when a person merges that pull request into the
|
|
565
|
+
default branch; rness closes nothing. A repository with its issues off,
|
|
566
|
+
that refuses this login's write, or not under the organization on GitHub
|
|
567
|
+
sends the note to the plan's issue, its first line saying why, and the
|
|
568
|
+
next session start says so once. A session in `.rness/`or at the root
|
|
569
|
+
writes on the plan's issue. With several plans in progress,`--plan`names one. Each note holds 1 to 4,000 characters; a session posts at most`limit` per plan (`journal full for this session: put the rest in the
|
|
570
|
+
pull request`); a note that looks like it holds a credential (`ghp_`,
|
|
571
|
+
`gho_`, `github_pat_`, `AKIA…`, a private key, `xox…-`, `sk-…`) is
|
|
572
|
+
refused, never redacted. The counts stay in the `.rness` clone's git
|
|
573
|
+
directory (`rness/journal`), never pushed. At the session's end,
|
|
574
|
+
`journal-summary`posts`**Session summary** · claude · 1a2b3c4d ·
|
|
575
|
+
47 min`, the branch and its commits since the session started (its
|
|
576
|
+
`HEAD`, recorded in the clone's git directory, `rness/sessions/<id>`)
|
|
577
|
+
and the branch's pull request: to each issue the notes went to, else to
|
|
578
|
+
the one plan in progress when there is a commit; with neither, nothing.
|
|
579
|
+
It counts toward no limit. Not verified against GitHub yet (2026-10-06):
|
|
580
|
+
a sub-issue across repositories, and `Closes` on a pull request merged
|
|
581
|
+
into the default branch.
|
|
456
582
|
- **One issue per document**: before making an issue, `pulse sync` reads
|
|
457
583
|
the open issues of `.rness` labelled `rness` (one request per 100, and
|
|
458
584
|
only when it has one to make). One whose body starts with the document's
|
|
@@ -496,7 +622,9 @@ repository, the board).
|
|
|
496
622
|
detected provider this version cannot talk to. The order of keys is
|
|
497
623
|
`contract`, `provider`, `org`, `agents`, `projects`, `repos`, `scopes`.
|
|
498
624
|
The former `"pulse": { "project": <number> }` still reads, as
|
|
499
|
-
`"projects": { "pulse": <number> }`; both at once are refused.
|
|
625
|
+
`"projects": { "pulse": <number> }`; both at once are refused. Since
|
|
626
|
+
0.21.0 a board in `projects` is written whole, on several lines; a
|
|
627
|
+
number still reads, as its preset, until `rness sync` writes it whole.
|
|
500
628
|
- A provider _written_ in `rness.json` that this version cannot talk to
|
|
501
629
|
(`gitlab`) is refused by `validate`, `create`, `login` and `pulse`:
|
|
502
630
|
`provider "gitlab" is not supported by @rness/cli 0.17.1 (supported:
|
|
@@ -507,22 +635,26 @@ github)`. `add`, `sync` and the local commands never refuse. `null` is not a
|
|
|
507
635
|
|
|
508
636
|
rness mcp # started by the agent over stdio, not by hand
|
|
509
637
|
|
|
510
|
-
A local
|
|
511
|
-
|
|
512
|
-
|
|
638
|
+
A local MCP server over the workspace's `.rness/`, for an agent to find what
|
|
639
|
+
applies to the repository it works in and where a subject was decided. It
|
|
640
|
+
is read-only but for `rness_note`, listed only when a board keeps a journal
|
|
641
|
+
as the server starts (Claude Code starts it with the session):
|
|
513
642
|
|
|
514
|
-
| Tool
|
|
515
|
-
|
|
|
516
|
-
| `rness_context({ scope? })`
|
|
517
|
-
| `rness_list({ collection, status? })`
|
|
518
|
-
| `rness_read({ path })`
|
|
519
|
-
| `rness_search({ query, collection? })`
|
|
643
|
+
| Tool | Returns |
|
|
644
|
+
| --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
645
|
+
| `rness_context({ scope? })` | the scope of the working directory (or the one named) and what applies to it: standards, decisions, specifications, plans — id, status, title, path |
|
|
646
|
+
| `rness_list({ collection, status? })` | every document of a collection, across scopes, optionally of one status |
|
|
647
|
+
| `rness_read({ path })` | one file of `.rness/`, 256 KiB at most; nothing outside it |
|
|
648
|
+
| `rness_search({ query, collection? })` | the documents that match, most matching first, with the matching lines |
|
|
649
|
+
| `rness_note({ text, session, kind?, plan? })` | a note of the agent's journal posted to GitHub, as `rness pulse note` posts it; the issue it went to (see "Pulse") |
|
|
520
650
|
|
|
521
651
|
- MCP over stdio, one message per line: the `2026-07-28` revision and the
|
|
522
652
|
earlier ones that open with `initialize` (`2025-11-25` back to
|
|
523
653
|
`2024-11-05`). No MCP SDK, no added dependency.
|
|
524
654
|
- `.rness/` is read again on each call, so an edit shows at once. Nothing is
|
|
525
|
-
written.
|
|
655
|
+
written, but by `rness_note`, which posts with your login. It takes the
|
|
656
|
+
session as an argument (`claude · 1a2b3c4d`, as the session start spells
|
|
657
|
+
it): the server's environment names none.
|
|
526
658
|
- With `claude` in `agents`, `sync` registers it in each clone:
|
|
527
659
|
`.mcp.json` gets `mcpServers.rness`, which runs the pinned copy
|
|
528
660
|
(`node ../../.rness/node_modules/@rness/cli/dist/bin/rness.js mcp`). A
|
|
@@ -691,6 +823,60 @@ per repository, the files to commit there.
|
|
|
691
823
|
Exit codes: 0 success, 1 failure, 2 usage — or a refusal without a TTY.
|
|
692
824
|
`RNESS_DEBUG=1` adds stack traces; `RNESS_NO_DELEGATE=1` skips the delegation.
|
|
693
825
|
|
|
826
|
+
## 0.21.0 — boards declared in rness.json; what a session does to a board, declared; the agent's journal
|
|
827
|
+
|
|
828
|
+
- The agent journal (spec 0030, see "Pulse"): a board declares `journal`
|
|
829
|
+
at `session-start` and `journal-summary` at `session-end`. The agent
|
|
830
|
+
posts notes on the plan it implements — `rness pulse note`, or
|
|
831
|
+
`rness_note` of `rness mcp` — to the plan's issue in `.rness`, or to an
|
|
832
|
+
implementation issue in the repository it works in, a sub-issue of the
|
|
833
|
+
plan's, which the pull request closes. The session's end posts a summary:
|
|
834
|
+
its commits, its pull request, its duration. The preset `agent-pulse`
|
|
835
|
+
declares neither: nothing changes until a board does.
|
|
836
|
+
- Boards are declared in `rness.json` (spec 0031, see "Pulse"): each one's
|
|
837
|
+
collections, statuses, colours, fields, labels and views, written whole.
|
|
838
|
+
Agent Pulse is the preset `agent-pulse`, no longer a special case of the
|
|
839
|
+
code. `pulse create` writes the board it makes; `rness sync` (which
|
|
840
|
+
`rness upgrade` runs) writes a board declared by its number whole, moves
|
|
841
|
+
a collection's README declarations into its board, and merges a newer
|
|
842
|
+
revision of a preset value by value. Views are updated in place where
|
|
843
|
+
GitHub allows; a view rness made and no longer declared is deleted, the
|
|
844
|
+
team's are said once. Nothing changes on GitHub for a board 0.20 made.
|
|
845
|
+
For the package's API: `Projects` is `Record<string, number |
|
|
846
|
+
BoardDeclaration>`; `BoardDeclaration` and `parseBoard` are exported.
|
|
847
|
+
- A board's `readme` and `updates` stay within `.rness/`: a path out of
|
|
848
|
+
it, or a link leading out, is refused before anything is read.
|
|
849
|
+
- What a session does to a board is declared in its `hooks` (spec 0032):
|
|
850
|
+
`mark-in-progress`, `mark` and `clear-marks`, from a fixed catalogue; a
|
|
851
|
+
hook never runs a command `rness.json` names. The preset `agent-pulse`
|
|
852
|
+
declares today's three, so nothing changes on GitHub. The hooks start
|
|
853
|
+
`rness pulse run <event>`; `rness pulse mark` stays, hidden, through
|
|
854
|
+
0.21.x, for sessions started before an upgrade.
|
|
855
|
+
- `upgrade` run by a workspace's pinned copy installed with pnpm no longer
|
|
856
|
+
ends on `mod directory not found next to the @rness/cli package`. After
|
|
857
|
+
its commit it lists the files to commit in the clones, and that list read
|
|
858
|
+
the plugin's mod from the folder of the copy running it, which the install
|
|
859
|
+
had just removed. The list now takes the paths alone. The upgrade itself
|
|
860
|
+
was complete: 0.20.0 to 0.20.1 printed the error after its commit. An
|
|
861
|
+
upgrade from 0.20.1 still prints it, since the copy that runs it is the
|
|
862
|
+
old one; `pnpm dlx @rness/cli upgrade` runs the new one.
|
|
863
|
+
|
|
864
|
+
## 0.20.1 — the workspace's line in the prompt footer, without a warning sign; the mod never installs the pin
|
|
865
|
+
|
|
866
|
+
- The workspace's line in Claude Code moves from the pinned status line to
|
|
867
|
+
the prompt footer, among the session modes, dim and without a sign:
|
|
868
|
+
`rness · web · 1 in progress`, `⚠ <n>` at its end when notes need action.
|
|
869
|
+
Claude Code draws every pinned line a plugin sets after a `⚠` in its
|
|
870
|
+
warning colour, the wrong sign for a line that informs. `rness status
|
|
871
|
+
--json`'s `statusLine` carries the leading `rness` again. VS Code and
|
|
872
|
+
mobile surfaces, which draw no session modes, show no line; the
|
|
873
|
+
`/rness:status` pane stays.
|
|
874
|
+
- The mod no longer installs the pin from inside Claude Code. It ran
|
|
875
|
+
`status --json` with catch-up on, so in a workspace whose pin drifts each
|
|
876
|
+
refresh ran `npm install` in `.rness`, without asking, and replaced a
|
|
877
|
+
local copy. It now runs with `RNESS_NO_DELEGATE=1`: the drift is a note
|
|
878
|
+
in the band, as the settings hooks report it.
|
|
879
|
+
|
|
694
880
|
## 0.20.0 — the status pane opens a document; ↑/↓ select, Tab changes the tab; Agent Pulse's colours and links
|
|
695
881
|
|
|
696
882
|
- `/rness:status` in Claude Code: each row's status in Agent Pulse's colour;
|
package/dist/bin/rness.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
OWN_COMMANDS,
|
|
4
|
-
VERSION,
|
|
5
4
|
catchUp,
|
|
6
5
|
findDelegate,
|
|
7
|
-
reportError,
|
|
8
6
|
run
|
|
9
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-T5PINUCP.js";
|
|
8
|
+
import {
|
|
9
|
+
VERSION,
|
|
10
|
+
reportError
|
|
11
|
+
} from "../chunk-D3D2WCGW.js";
|
|
10
12
|
|
|
11
13
|
// src/bin/rness.ts
|
|
12
14
|
import { pathToFileURL } from "url";
|
package/dist/bin/rness.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/bin/rness.ts","../../src/core/node-version.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { pathToFileURL } from 'node:url'\n\nimport { run } from '../cli.ts'\nimport { OWN_COMMANDS, catchUp } from '../core/catch-up.ts'\nimport { findDelegate } from '../core/delegate.ts'\nimport { MIN_NODE_LABEL, isSupportedNode } from '../core/node-version.ts'\nimport { reportError } from '../report.ts'\nimport { VERSION } from '../version.ts'\n\n// `rness context | head`: once the reader has its lines it closes the pipe and\n// every further write emits EPIPE on stdout. Nothing is left to deliver, so end\n// quietly with success. This is the one process.exit() in the code base — it\n// runs only when there is no output left to drain (see main() below).\nprocess.stdout.on('error', (e: NodeJS.ErrnoException) => {\n if (e.code === 'EPIPE') process.exit(0)\n throw e\n})\n\n// Set process.exitCode rather than calling process.exit(): process.exit()\n// terminates before Node drains an async stdout pipe, truncating piped output\n// at the ~64 KiB pipe buffer (breaks `rness context --json | jq`, `$(...)`).\nasync function main(): Promise<number> {\n if (!isSupportedNode(process.versions.node)) {\n process.stderr.write(\n `rness needs Node ${MIN_NODE_LABEL} or newer (running ${process.version})\\n`\n )\n return 1\n }\n const argv = process.argv.slice(2)\n const skipDelegation =\n OWN_COMMANDS.includes(argv[0] ?? '') ||\n process.env['RNESS_NO_DELEGATE'] === '1'\n // A pin that moved is installed first, and the fresh copy runs the command\n // as its own process (spec 0008 §4).\n const handedOff = await catchUp(argv)\n if (handedOff !== null) return handedOff\n const delegate = skipDelegation\n ? null\n : await findDelegate(process.cwd(), VERSION)\n if (delegate !== null) {\n const broken = (reason: string): Error =>\n new Error(\n `@rness/cli ${delegate.version} pinned in ${delegate.root}/.rness is not installed correctly (${reason}); reinstall in .rness/`\n )\n if (process.env['RNESS_DEBUG'] === '1') {\n process.stderr.write(\n `rness: delegating to @rness/cli ${delegate.version} (${delegate.entry})\\n`\n )\n }\n let mod: Record<string, unknown>\n try {\n mod = (await import(pathToFileURL(delegate.entry).href)) as Record<\n string,\n unknown\n >\n } catch (e) {\n throw broken(e instanceof Error ? e.message : String(e))\n }\n if (typeof mod['run'] !== 'function')\n throw broken('dist/index.js does not export run')\n const delegateRun = mod['run'] as (argv: string[]) => Promise<unknown>\n const code = await delegateRun(argv)\n return typeof code === 'number' ? code : 1\n }\n return run(argv)\n}\n\nmain()\n .then((code) => {\n process.exitCode = code\n })\n .catch((e: unknown) => {\n process.exitCode = reportError(e)\n })\n","/** The runtime floor of the published CLI (ADR 0010): Node 22.17, the line where `fs.glob` is stable. */\nexport const MIN_NODE = { major: 22, minor: 17 } as const\nexport const MIN_NODE_LABEL = `${MIN_NODE.major}.${MIN_NODE.minor}`\n\nfunction component(version: string, index: number): number {\n const n = Number.parseInt(version.split('.')[index] ?? '', 10)\n return Number.isNaN(n) ? -1 : n\n}\n\nexport function nodeMajor(version: string): number {\n return Math.max(component(version, 0), 0)\n}\n\n/** True from `MIN_NODE` on: a newer major, or the same major from its minor. */\nexport function isSupportedNode(version: string): boolean {\n const major = component(version, 0)\n const minor = component(version, 1)\n if (major < 0 || minor < 0) return false\n if (major !== MIN_NODE.major) return major > MIN_NODE.major\n return minor >= MIN_NODE.minor\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../src/bin/rness.ts","../../src/core/node-version.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { pathToFileURL } from 'node:url'\n\nimport { run } from '../cli.ts'\nimport { OWN_COMMANDS, catchUp } from '../core/catch-up.ts'\nimport { findDelegate } from '../core/delegate.ts'\nimport { MIN_NODE_LABEL, isSupportedNode } from '../core/node-version.ts'\nimport { reportError } from '../report.ts'\nimport { VERSION } from '../version.ts'\n\n// `rness context | head`: once the reader has its lines it closes the pipe and\n// every further write emits EPIPE on stdout. Nothing is left to deliver, so end\n// quietly with success. This is the one process.exit() in the code base — it\n// runs only when there is no output left to drain (see main() below).\nprocess.stdout.on('error', (e: NodeJS.ErrnoException) => {\n if (e.code === 'EPIPE') process.exit(0)\n throw e\n})\n\n// Set process.exitCode rather than calling process.exit(): process.exit()\n// terminates before Node drains an async stdout pipe, truncating piped output\n// at the ~64 KiB pipe buffer (breaks `rness context --json | jq`, `$(...)`).\nasync function main(): Promise<number> {\n if (!isSupportedNode(process.versions.node)) {\n process.stderr.write(\n `rness needs Node ${MIN_NODE_LABEL} or newer (running ${process.version})\\n`\n )\n return 1\n }\n const argv = process.argv.slice(2)\n const skipDelegation =\n OWN_COMMANDS.includes(argv[0] ?? '') ||\n process.env['RNESS_NO_DELEGATE'] === '1'\n // A pin that moved is installed first, and the fresh copy runs the command\n // as its own process (spec 0008 §4).\n const handedOff = await catchUp(argv)\n if (handedOff !== null) return handedOff\n const delegate = skipDelegation\n ? null\n : await findDelegate(process.cwd(), VERSION)\n if (delegate !== null) {\n const broken = (reason: string): Error =>\n new Error(\n `@rness/cli ${delegate.version} pinned in ${delegate.root}/.rness is not installed correctly (${reason}); reinstall in .rness/`\n )\n if (process.env['RNESS_DEBUG'] === '1') {\n process.stderr.write(\n `rness: delegating to @rness/cli ${delegate.version} (${delegate.entry})\\n`\n )\n }\n let mod: Record<string, unknown>\n try {\n mod = (await import(pathToFileURL(delegate.entry).href)) as Record<\n string,\n unknown\n >\n } catch (e) {\n throw broken(e instanceof Error ? e.message : String(e))\n }\n if (typeof mod['run'] !== 'function')\n throw broken('dist/index.js does not export run')\n const delegateRun = mod['run'] as (argv: string[]) => Promise<unknown>\n const code = await delegateRun(argv)\n return typeof code === 'number' ? code : 1\n }\n return run(argv)\n}\n\nmain()\n .then((code) => {\n process.exitCode = code\n })\n .catch((e: unknown) => {\n process.exitCode = reportError(e)\n })\n","/** The runtime floor of the published CLI (ADR 0010): Node 22.17, the line where `fs.glob` is stable. */\nexport const MIN_NODE = { major: 22, minor: 17 } as const\nexport const MIN_NODE_LABEL = `${MIN_NODE.major}.${MIN_NODE.minor}`\n\nfunction component(version: string, index: number): number {\n const n = Number.parseInt(version.split('.')[index] ?? '', 10)\n return Number.isNaN(n) ? -1 : n\n}\n\nexport function nodeMajor(version: string): number {\n return Math.max(component(version, 0), 0)\n}\n\n/** True from `MIN_NODE` on: a newer major, or the same major from its minor. */\nexport function isSupportedNode(version: string): boolean {\n const major = component(version, 0)\n const minor = component(version, 1)\n if (major < 0 || minor < 0) return false\n if (major !== MIN_NODE.major) return major > MIN_NODE.major\n return minor >= MIN_NODE.minor\n}\n"],"mappings":";;;;;;;;;;;;;AACA,SAAS,qBAAqB;;;ACAvB,IAAM,WAAW,EAAE,OAAO,IAAI,OAAO,GAAG;AACxC,IAAM,iBAAiB,GAAG,SAAS,KAAK,IAAI,SAAS,KAAK;AAEjE,SAAS,UAAU,SAAiB,OAAuB;AACzD,QAAM,IAAI,OAAO,SAAS,QAAQ,MAAM,GAAG,EAAE,KAAK,KAAK,IAAI,EAAE;AAC7D,SAAO,OAAO,MAAM,CAAC,IAAI,KAAK;AAChC;AAOO,SAAS,gBAAgB,SAA0B;AACxD,QAAM,QAAQ,UAAU,SAAS,CAAC;AAClC,QAAM,QAAQ,UAAU,SAAS,CAAC;AAClC,MAAI,QAAQ,KAAK,QAAQ,EAAG,QAAO;AACnC,MAAI,UAAU,SAAS,MAAO,QAAO,QAAQ,SAAS;AACtD,SAAO,SAAS,SAAS;AAC3B;;;ADNA,QAAQ,OAAO,GAAG,SAAS,CAAC,MAA6B;AACvD,MAAI,EAAE,SAAS,QAAS,SAAQ,KAAK,CAAC;AACtC,QAAM;AACR,CAAC;AAKD,eAAe,OAAwB;AACrC,MAAI,CAAC,gBAAgB,QAAQ,SAAS,IAAI,GAAG;AAC3C,YAAQ,OAAO;AAAA,MACb,oBAAoB,cAAc,sBAAsB,QAAQ,OAAO;AAAA;AAAA,IACzE;AACA,WAAO;AAAA,EACT;AACA,QAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AACjC,QAAM,iBACJ,aAAa,SAAS,KAAK,CAAC,KAAK,EAAE,KACnC,QAAQ,IAAI,mBAAmB,MAAM;AAGvC,QAAM,YAAY,MAAM,QAAQ,IAAI;AACpC,MAAI,cAAc,KAAM,QAAO;AAC/B,QAAM,WAAW,iBACb,OACA,MAAM,aAAa,QAAQ,IAAI,GAAG,OAAO;AAC7C,MAAI,aAAa,MAAM;AACrB,UAAM,SAAS,CAAC,WACd,IAAI;AAAA,MACF,cAAc,SAAS,OAAO,cAAc,SAAS,IAAI,uCAAuC,MAAM;AAAA,IACxG;AACF,QAAI,QAAQ,IAAI,aAAa,MAAM,KAAK;AACtC,cAAQ,OAAO;AAAA,QACb,mCAAmC,SAAS,OAAO,KAAK,SAAS,KAAK;AAAA;AAAA,MACxE;AAAA,IACF;AACA,QAAI;AACJ,QAAI;AACF,YAAO,MAAM,OAAO,cAAc,SAAS,KAAK,EAAE;AAAA,IAIpD,SAAS,GAAG;AACV,YAAM,OAAO,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AAAA,IACzD;AACA,QAAI,OAAO,IAAI,KAAK,MAAM;AACxB,YAAM,OAAO,mCAAmC;AAClD,UAAM,cAAc,IAAI,KAAK;AAC7B,UAAM,OAAO,MAAM,YAAY,IAAI;AACnC,WAAO,OAAO,SAAS,WAAW,OAAO;AAAA,EAC3C;AACA,SAAO,IAAI,IAAI;AACjB;AAEA,KAAK,EACF,KAAK,CAAC,SAAS;AACd,UAAQ,WAAW;AACrB,CAAC,EACA,MAAM,CAAC,MAAe;AACrB,UAAQ,WAAW,YAAY,CAAC;AAClC,CAAC;","names":[]}
|