@rness/cli 0.17.2 → 0.18.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 +103 -26
- package/dist/bin/rness.js +12 -7
- package/dist/bin/rness.js.map +1 -1
- package/dist/{chunk-REDELHNC.js → chunk-VGBS7HDY.js} +551 -280
- package/dist/chunk-VGBS7HDY.js.map +1 -0
- package/dist/index.js +1 -1
- package/package.json +3 -3
- package/scaffold/package.json +1 -1
- package/dist/chunk-REDELHNC.js.map +0 -1
package/README.md
CHANGED
|
@@ -98,28 +98,42 @@ the files a given agent needs, for the agents the team declares in
|
|
|
98
98
|
get a Claude Code plugin, `.claude/skills/rness/`, with five commands:
|
|
99
99
|
`/rness:status [tab]`, the tables of `rness status`, and the lifecycle
|
|
100
100
|
skills below. rness owns those files whole — an edit by hand is reported
|
|
101
|
-
by `sync --check` and written back by `sync`.
|
|
101
|
+
by `sync --check` and written back by `sync`. The plugin's manifest,
|
|
102
|
+
`.claude-plugin/plugin.json`, also carries the agent-plugins.org
|
|
103
|
+
`$schema`, the author, homepage, repository, licence and keywords, so a
|
|
104
|
+
scanner that looks for an Agent Plugins manifest finds one; Claude Code
|
|
105
|
+
reads the same file. The repository root also carries a `plugin.json` in
|
|
106
|
+
that form, describing the repository, where a scanner looks first. Nothing in them depends on
|
|
102
107
|
the version; the last line of the status skill names the workspace's
|
|
103
108
|
package manager, so changing `packageManager` in `.rness/package.json`
|
|
104
109
|
leaves it stale until the next `sync`. Claude Code loads the plugin once
|
|
105
110
|
the folder is trusted, in a session started there.
|
|
106
|
-
- **The lifecycle skills
|
|
107
|
-
|
|
108
|
-
`/rness:
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
111
|
+
- **The lifecycle skills**, one per collection, on one grammar: the first
|
|
112
|
+
word is the verb, a bare number reopens, anything else is the subject of
|
|
113
|
+
a `create`. `/rness:adr [create <subject> | open NNNN]` records a decision
|
|
114
|
+
as an ADR or reopens one; `/rness:spec [create <subject> | open NNNN]`
|
|
115
|
+
writes a specification or reopens one; `/rness:plan` takes four verbs:
|
|
116
|
+
`from <spec NNNN>` writes a plan from a specification and approves it
|
|
117
|
+
(typing the command is the approval), `create [subject]` writes a plan
|
|
118
|
+
from the conversation for work too small for a specification, `open NNNN`
|
|
119
|
+
reopens a plan, and `check NNNN` runs the proofs of a plan — each task's
|
|
120
|
+
command, run now — and closes it when they all pass: the plan `Completed`,
|
|
121
|
+
its specification `Implemented`, the documents the work made inaccurate
|
|
122
|
+
corrected; one task without evidence and nothing moves. Each is a
|
|
123
|
+
procedure loaded into the conversation, not a file generator: after a
|
|
124
|
+
decision has been discussed, `/rness:adr` writes it from the
|
|
125
|
+
conversation; otherwise it asks, one question at a time. The skill stays
|
|
126
|
+
in the conversation for the next turns, and the file carries the work to
|
|
127
|
+
the next session (`/rness:adr 0010` reopens it). The agent may start one
|
|
128
|
+
itself — an ADR when a choice is expensive to reverse — but writes nothing
|
|
129
|
+
without a yes, except `/rness:plan check` on a plan whose last task has
|
|
130
|
+
just passed. The rules stay in `.rness/CONVENTIONS.md`; the skills only
|
|
131
|
+
add the steps. A new document takes the collection's first status
|
|
132
|
+
(`Proposed` for an ADR, `Draft` otherwise) and the next number, allocated
|
|
133
|
+
by `rness doc new <collection>` — the second pre-approved line of each
|
|
134
|
+
skill, so that every runtime and a bare terminal get the same number;
|
|
135
|
+
`rness validate` refuses two documents with one number, the case a merge
|
|
136
|
+
of two branches can still produce. Each skill records its session: it adds
|
|
123
137
|
`{ id: <session id>, agent: <model> }` to `sessions:` in the front matter
|
|
124
138
|
of what it writes or closes. The agent is the model it runs as, as Claude
|
|
125
139
|
Code names it (`Claude Opus 5.5`): no variable gives it to a skill. An
|
|
@@ -381,11 +395,13 @@ it through one adapter; `git` still does what git does (clone, pull, push,
|
|
|
381
395
|
credentials), and the provider's API the rest (organizations, creating a
|
|
382
396
|
repository, the board).
|
|
383
397
|
|
|
384
|
-
- `rness create` asks `Where does your organization live
|
|
385
|
-
GitLab and Atlassian (Bitbucket + Jira) shown disabled, coming later
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
398
|
+
- `rness create` asks `Where does your organization live?` first: GitHub,
|
|
399
|
+
GitLab and Atlassian (Bitbucket + Jira) shown disabled, coming later, and
|
|
400
|
+
`No organization yet: a blank local workspace` (the `--blank` of
|
|
401
|
+
"Blank workspace"). `--provider github` answers it off a terminal;
|
|
402
|
+
`--org`, `--repos` and `--blank` settle it unasked. Joining an
|
|
403
|
+
organization asks first as well, then takes the provider its `rness.json`
|
|
404
|
+
names.
|
|
389
405
|
- A workspace without the key is read from its first repository URL: a
|
|
390
406
|
GitLab host reads as `gitlab`, any other host — or no repository — as
|
|
391
407
|
`github`. Nothing to change: `pulse create` writes it, and refuses a
|
|
@@ -457,8 +473,23 @@ anonymously.
|
|
|
457
473
|
GitHub, anonymous or with `--yes`, it prints the two manual steps instead
|
|
458
474
|
— create the empty repository on github.com, then `git remote add origin …
|
|
459
475
|
&& git push`. No other tool is ever needed.
|
|
460
|
-
-
|
|
461
|
-
|
|
476
|
+
- Logged in, the wizard lists the organizations you belong to that have
|
|
477
|
+
approved "Rness" — GitHub shows an OAuth app no other — your account
|
|
478
|
+
last, then `an organization not listed here…` for a typed name: one that
|
|
479
|
+
has not approved rness yet, an outside collaborator's, a public one.
|
|
480
|
+
Right after the
|
|
481
|
+
organization, before the SSH test, the probe of `<org>/.rness` and the
|
|
482
|
+
listing, `create` checks your access: an organization that restricts
|
|
483
|
+
OAuth apps and has not approved "Rness" hides its private repositories,
|
|
484
|
+
so the wizard asks `Open github.com to approve rness for <org> now?`,
|
|
485
|
+
opens the approval page in your browser (printed only over SSH) and waits
|
|
486
|
+
— polling every 5 seconds, for 10 minutes at most — until an owner's
|
|
487
|
+
click makes you a member in its eyes; then it goes on with the full
|
|
488
|
+
listing. Declined, or timed out, it goes on with what is visible and
|
|
489
|
+
names the page for later; with `--yes` or off a terminal it prints the
|
|
490
|
+
warning and the page, and asks nothing. The order matters: a private
|
|
491
|
+
`.rness` probed through a token the organization has not approved would
|
|
492
|
+
read as absent, and `create` would start a second one.
|
|
462
493
|
- Over HTTPS, rness's own clones and pulls carry the login — through the
|
|
463
494
|
environment of that one git command, never in a URL or `.git/config`. For
|
|
464
495
|
your own `git pull` and `git push`, `login` offers to make rness git's
|
|
@@ -572,6 +603,52 @@ per repository, the files to commit there.
|
|
|
572
603
|
Exit codes: 0 success, 1 failure, 2 usage — or a refusal without a TTY.
|
|
573
604
|
`RNESS_DEBUG=1` adds stack traces; `RNESS_NO_DELEGATE=1` skips the delegation.
|
|
574
605
|
|
|
606
|
+
## 0.18.0 — the wizard asks where first and waits for the approval; the skills on one grammar; Node 22.17
|
|
607
|
+
|
|
608
|
+
- The published CLI runs on **Node 22.17 or later** (ADR 0010); the guard
|
|
609
|
+
compares major and minor. A workspace pinned to 0.17.x keeps refusing
|
|
610
|
+
Node 22 until its pin moves: from inside it, `npx @rness/cli@latest
|
|
611
|
+
upgrade` works under Node 22, since `upgrade` is served by the copy
|
|
612
|
+
invoked, never the pinned one.
|
|
613
|
+
- `rness create` asks **where the organization lives first** — the blank
|
|
614
|
+
workspace is that question's last answer — then offers the login, which
|
|
615
|
+
now lists **the organizations you belong to that have approved rness**
|
|
616
|
+
(your account last, then `an organization not listed here…` for the
|
|
617
|
+
rest). Right after the organization and
|
|
618
|
+
before anything reads it, an organization that restricts OAuth apps and
|
|
619
|
+
has not approved "Rness" gets its **approval page opened in your
|
|
620
|
+
browser**; the wizard waits for the owner's click (10 minutes at most)
|
|
621
|
+
and then lists the private repositories too. See "GitHub login".
|
|
622
|
+
- `/rness:adr`, `/rness:spec` and `/rness:plan` read their first word as
|
|
623
|
+
the verb: `create`, `open` (a bare number), and for a plan `from <spec>`
|
|
624
|
+
— which **approves the specification** it plans — and `check NNNN`, the
|
|
625
|
+
proofs of a plan, in place of `/rness:done`. `/rness:done` is retired:
|
|
626
|
+
`rness sync` removes its `SKILL.md` where an earlier release wrote it
|
|
627
|
+
(`removed` in its output); commit the deletion in each repository, as
|
|
628
|
+
`upgrade`'s next steps list. Note: `/rness:plan 0028` now opens plan
|
|
629
|
+
0028; a plan is made with `from <spec>`. See "Agent targets".
|
|
630
|
+
- `rness doc new <collection> [--title <text>]` writes the next numbered
|
|
631
|
+
document of `adr`, `specs` or `plans` and prints its path: the skills
|
|
632
|
+
allocate with it instead of counting. `rness validate` and the edit hook
|
|
633
|
+
refuse two documents with one number in a collection.
|
|
634
|
+
- The day of a release, `pnpm create rness` runs the previous version:
|
|
635
|
+
pnpm ≥ 11 holds back a package younger than 24 hours
|
|
636
|
+
(`minimumReleaseAge`). `rness upgrade` installs the latest all the same.
|
|
637
|
+
|
|
638
|
+
## 0.17.3 — the packages name the product; the plugin manifest for scanners
|
|
639
|
+
|
|
640
|
+
- `homepage` of `@rness/cli`, `create-rness` and `@rness/create` is
|
|
641
|
+
`https://rness.dev`; `repository` and `bugs` stay on GitHub. That is
|
|
642
|
+
how a scanner tells an official package from a fork;
|
|
643
|
+
`pnpm check:versions` checks it with the versions.
|
|
644
|
+
- `.claude/skills/rness/.claude-plugin/plugin.json`, written by the Claude
|
|
645
|
+
target, carries the agent-plugins.org `$schema`, the author, homepage,
|
|
646
|
+
repository, licence and keywords. `rness sync` rewrites it once in each
|
|
647
|
+
repository; commit it there.
|
|
648
|
+
- `skills/rness/SKILL.md` at the root of the repository: when to use Rness
|
|
649
|
+
and how to install and run it, for `npx skills add rness-dev/rness`
|
|
650
|
+
and skills.sh.
|
|
651
|
+
|
|
575
652
|
## 0.17.2 — the lifecycle skills move statuses and commit their files
|
|
576
653
|
|
|
577
654
|
- `/rness:adr`, `/rness:spec`, `/rness:plan` and `/rness:done` let the
|
|
@@ -1058,4 +1135,4 @@ workspace pins exactly that build and no cache serves an older one under its
|
|
|
1058
1135
|
number. To try it in a workspace that exists, run `rness upgrade <version>`
|
|
1059
1136
|
inside it; the deploy prints the line.
|
|
1060
1137
|
|
|
1061
|
-
Node ≥
|
|
1138
|
+
Node ≥ 22.17. MIT.
|
package/dist/bin/rness.js
CHANGED
|
@@ -6,19 +6,24 @@ import {
|
|
|
6
6
|
findDelegate,
|
|
7
7
|
reportError,
|
|
8
8
|
run
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-VGBS7HDY.js";
|
|
10
10
|
|
|
11
11
|
// src/bin/rness.ts
|
|
12
12
|
import { pathToFileURL } from "url";
|
|
13
13
|
|
|
14
14
|
// src/core/node-version.ts
|
|
15
|
-
var
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
var MIN_NODE = { major: 22, minor: 17 };
|
|
16
|
+
var MIN_NODE_LABEL = `${MIN_NODE.major}.${MIN_NODE.minor}`;
|
|
17
|
+
function component(version, index) {
|
|
18
|
+
const n = Number.parseInt(version.split(".")[index] ?? "", 10);
|
|
19
|
+
return Number.isNaN(n) ? -1 : n;
|
|
19
20
|
}
|
|
20
21
|
function isSupportedNode(version) {
|
|
21
|
-
|
|
22
|
+
const major = component(version, 0);
|
|
23
|
+
const minor = component(version, 1);
|
|
24
|
+
if (major < 0 || minor < 0) return false;
|
|
25
|
+
if (major !== MIN_NODE.major) return major > MIN_NODE.major;
|
|
26
|
+
return minor >= MIN_NODE.minor;
|
|
22
27
|
}
|
|
23
28
|
|
|
24
29
|
// src/bin/rness.ts
|
|
@@ -29,7 +34,7 @@ process.stdout.on("error", (e) => {
|
|
|
29
34
|
async function main() {
|
|
30
35
|
if (!isSupportedNode(process.versions.node)) {
|
|
31
36
|
process.stderr.write(
|
|
32
|
-
`rness needs Node ${
|
|
37
|
+
`rness needs Node ${MIN_NODE_LABEL} or newer (running ${process.version})
|
|
33
38
|
`
|
|
34
39
|
);
|
|
35
40
|
return 1;
|
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 {
|
|
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":[]}
|