@rness/cli 0.17.3 → 0.18.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 +108 -26
- package/dist/bin/rness.js +12 -7
- package/dist/bin/rness.js.map +1 -1
- package/dist/{chunk-MMPMXYZU.js → chunk-JHU2G7K7.js} +564 -264
- package/dist/chunk-JHU2G7K7.js.map +1 -0
- package/dist/index.js +1 -1
- package/package.json +2 -2
- package/scaffold/CONVENTIONS.md +5 -0
- package/scaffold/package.json +1 -1
- package/dist/chunk-MMPMXYZU.js.map +0 -1
package/README.md
CHANGED
|
@@ -102,28 +102,39 @@ the files a given agent needs, for the agents the team declares in
|
|
|
102
102
|
`.claude-plugin/plugin.json`, also carries the agent-plugins.org
|
|
103
103
|
`$schema`, the author, homepage, repository, licence and keywords, so a
|
|
104
104
|
scanner that looks for an Agent Plugins manifest finds one; Claude Code
|
|
105
|
-
reads the same file.
|
|
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
|
|
106
107
|
the version; the last line of the status skill names the workspace's
|
|
107
108
|
package manager, so changing `packageManager` in `.rness/package.json`
|
|
108
109
|
leaves it stale until the next `sync`. Claude Code loads the plugin once
|
|
109
110
|
the folder is trusted, in a session started there.
|
|
110
|
-
- **The lifecycle skills
|
|
111
|
-
|
|
112
|
-
`/rness:
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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, and a document named without one
|
|
137
|
+
(`NNNN-<slug>.md`, never a date). Each skill records its session: it adds
|
|
127
138
|
`{ id: <session id>, agent: <model> }` to `sessions:` in the front matter
|
|
128
139
|
of what it writes or closes. The agent is the model it runs as, as Claude
|
|
129
140
|
Code names it (`Claude Opus 5.5`): no variable gives it to a skill. An
|
|
@@ -385,11 +396,13 @@ it through one adapter; `git` still does what git does (clone, pull, push,
|
|
|
385
396
|
credentials), and the provider's API the rest (organizations, creating a
|
|
386
397
|
repository, the board).
|
|
387
398
|
|
|
388
|
-
- `rness create` asks `Where does your organization live
|
|
389
|
-
GitLab and Atlassian (Bitbucket + Jira) shown disabled, coming later
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
399
|
+
- `rness create` asks `Where does your organization live?` first: GitHub,
|
|
400
|
+
GitLab and Atlassian (Bitbucket + Jira) shown disabled, coming later, and
|
|
401
|
+
`No organization yet: a blank local workspace` (the `--blank` of
|
|
402
|
+
"Blank workspace"). `--provider github` answers it off a terminal;
|
|
403
|
+
`--org`, `--repos` and `--blank` settle it unasked. Joining an
|
|
404
|
+
organization asks first as well, then takes the provider its `rness.json`
|
|
405
|
+
names.
|
|
393
406
|
- A workspace without the key is read from its first repository URL: a
|
|
394
407
|
GitLab host reads as `gitlab`, any other host — or no repository — as
|
|
395
408
|
`github`. Nothing to change: `pulse create` writes it, and refuses a
|
|
@@ -461,8 +474,23 @@ anonymously.
|
|
|
461
474
|
GitHub, anonymous or with `--yes`, it prints the two manual steps instead
|
|
462
475
|
— create the empty repository on github.com, then `git remote add origin …
|
|
463
476
|
&& git push`. No other tool is ever needed.
|
|
464
|
-
-
|
|
465
|
-
|
|
477
|
+
- Logged in, the wizard lists the organizations you belong to that have
|
|
478
|
+
approved "Rness" — GitHub shows an OAuth app no other — your account
|
|
479
|
+
last, then `an organization not listed here…` for a typed name: one that
|
|
480
|
+
has not approved rness yet, an outside collaborator's, a public one.
|
|
481
|
+
Right after the
|
|
482
|
+
organization, before the SSH test, the probe of `<org>/.rness` and the
|
|
483
|
+
listing, `create` checks your access: an organization that restricts
|
|
484
|
+
OAuth apps and has not approved "Rness" hides its private repositories,
|
|
485
|
+
so the wizard asks `Open github.com to approve rness for <org> now?`,
|
|
486
|
+
opens the approval page in your browser (printed only over SSH) and waits
|
|
487
|
+
— polling every 5 seconds, for 10 minutes at most — until an owner's
|
|
488
|
+
click makes you a member in its eyes; then it goes on with the full
|
|
489
|
+
listing. Declined, or timed out, it goes on with what is visible and
|
|
490
|
+
names the page for later; with `--yes` or off a terminal it prints the
|
|
491
|
+
warning and the page, and asks nothing. The order matters: a private
|
|
492
|
+
`.rness` probed through a token the organization has not approved would
|
|
493
|
+
read as absent, and `create` would start a second one.
|
|
466
494
|
- Over HTTPS, rness's own clones and pulls carry the login — through the
|
|
467
495
|
environment of that one git command, never in a URL or `.git/config`. For
|
|
468
496
|
your own `git pull` and `git push`, `login` offers to make rness git's
|
|
@@ -576,6 +604,60 @@ per repository, the files to commit there.
|
|
|
576
604
|
Exit codes: 0 success, 1 failure, 2 usage — or a refusal without a TTY.
|
|
577
605
|
`RNESS_DEBUG=1` adds stack traces; `RNESS_NO_DELEGATE=1` skips the delegation.
|
|
578
606
|
|
|
607
|
+
## 0.18.1 — a document without a number is caught; small fixes
|
|
608
|
+
|
|
609
|
+
- `rness validate` and the edit hook name a document of `adr/`, `specs/` or
|
|
610
|
+
`plans/` whose file name has no number, with the next one:
|
|
611
|
+
`plans/2026-10-02-x.md: not numbered; name it 0002-<slug>.md, the next
|
|
612
|
+
number of plans`. A plan another agent's skill wrote with a dated name
|
|
613
|
+
is the usual case; rename it, or let the agent do it when the hook
|
|
614
|
+
tells it. A workspace with such a file fails `validate` (and its CI)
|
|
615
|
+
after the upgrade until it is renamed. The scaffold's `CONVENTIONS.md`
|
|
616
|
+
states the rule, and `upgrade` merges it in.
|
|
617
|
+
- A dated file name is no longer read as a number: `rness doc new` after
|
|
618
|
+
`2026-10-02-x.md` gave `2027`, and two dated plans of one year were
|
|
619
|
+
reported as one number twice.
|
|
620
|
+
- `rness doc new` racing another one at the same number says `<file>
|
|
621
|
+
exists; nothing written` (exit 1) instead of a raw `EEXIST`.
|
|
622
|
+
- `1 repository`, not `1 repositories`, in `create` and `sync`.
|
|
623
|
+
- When the SSH test passes only by asking for the key's passphrase,
|
|
624
|
+
`create`, `add` and `sync` say once how to load it into an agent
|
|
625
|
+
(`ssh-add`), since every clone would ask again.
|
|
626
|
+
- Ctrl+C while `create` waits for an organization's approval is a cancel
|
|
627
|
+
in the plain look too: `cancelled`, nothing written, exit 0 (it was 130).
|
|
628
|
+
|
|
629
|
+
## 0.18.0 — the wizard asks where first and waits for the approval; the skills on one grammar; Node 22.17
|
|
630
|
+
|
|
631
|
+
- The published CLI runs on **Node 22.17 or later** (ADR 0010); the guard
|
|
632
|
+
compares major and minor. A workspace pinned to 0.17.x keeps refusing
|
|
633
|
+
Node 22 until its pin moves: from inside it, `npx @rness/cli@latest
|
|
634
|
+
upgrade` works under Node 22, since `upgrade` is served by the copy
|
|
635
|
+
invoked, never the pinned one.
|
|
636
|
+
- `rness create` asks **where the organization lives first** — the blank
|
|
637
|
+
workspace is that question's last answer — then offers the login, which
|
|
638
|
+
now lists **the organizations you belong to that have approved rness**
|
|
639
|
+
(your account last, then `an organization not listed here…` for the
|
|
640
|
+
rest). Right after the organization and
|
|
641
|
+
before anything reads it, an organization that restricts OAuth apps and
|
|
642
|
+
has not approved "Rness" gets its **approval page opened in your
|
|
643
|
+
browser**; the wizard waits for the owner's click (10 minutes at most)
|
|
644
|
+
and then lists the private repositories too. See "GitHub login".
|
|
645
|
+
- `/rness:adr`, `/rness:spec` and `/rness:plan` read their first word as
|
|
646
|
+
the verb: `create`, `open` (a bare number), and for a plan `from <spec>`
|
|
647
|
+
— which **approves the specification** it plans — and `check NNNN`, the
|
|
648
|
+
proofs of a plan, in place of `/rness:done`. `/rness:done` is retired:
|
|
649
|
+
`rness sync` removes its `SKILL.md` where an earlier release wrote it
|
|
650
|
+
(`removed` in its output); commit the deletion in each repository, as
|
|
651
|
+
`upgrade`'s next steps list. Note: `/rness:plan 0028` now opens plan
|
|
652
|
+
0028; a plan is made with `from <spec>`. See "Agent targets".
|
|
653
|
+
- `rness doc new <collection> [--title <text>]` writes the next numbered
|
|
654
|
+
document of `adr`, `specs` or `plans` and prints its path: the skills
|
|
655
|
+
allocate with it instead of counting. `rness validate` and the edit hook
|
|
656
|
+
refuse two documents with one number in a collection.
|
|
657
|
+
- The day of a release, `pnpm create rness` runs the previous version:
|
|
658
|
+
pnpm ≥ 11 holds back a package younger than 24 hours
|
|
659
|
+
(`minimumReleaseAge`). `rness upgrade` installs the latest all the same.
|
|
660
|
+
|
|
579
661
|
## 0.17.3 — the packages name the product; the plugin manifest for scanners
|
|
580
662
|
|
|
581
663
|
- `homepage` of `@rness/cli`, `create-rness` and `@rness/create` is
|
|
@@ -1076,4 +1158,4 @@ workspace pins exactly that build and no cache serves an older one under its
|
|
|
1076
1158
|
number. To try it in a workspace that exists, run `rness upgrade <version>`
|
|
1077
1159
|
inside it; the deploy prints the line.
|
|
1078
1160
|
|
|
1079
|
-
Node ≥
|
|
1161
|
+
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-JHU2G7K7.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":[]}
|