@rness/cli 0.5.0 → 0.5.2

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
@@ -103,9 +103,20 @@ dependency does this: `util.styleText`, and a banner kept as a constant.
103
103
  The version is written in one place, `.rness/package.json`. `upgrade` pins it
104
104
  there (exact, the rest of the file untouched), installs with the workspace's
105
105
  package manager, then syncs through the new copy; a failed install restores
106
- the file. Commit `.rness`; teammates pull and install in `.rness`. Until they
107
- do, every command warns that the workspace pins one version and holds
108
- another. It is never delegated to the pinned copy, which is what it replaces
106
+ the file. Commit `.rness`. Teammates pull, and the next `rness` command in that
107
+ workspace installs the new pin itself — frozen, so the working tree stays
108
+ clean — and carries on: nothing to remember, nothing to run.
109
+ `RNESS_NO_INSTALL=1` turns that off and restores the warning, for CI, a
110
+ container image, or a machine that cannot install. A workspace still on 0.5.0
111
+ has no such catch-up: moving it to 0.5.1 is the last manual install.
112
+
113
+ Usually nobody runs `upgrade` at all. A workspace ships
114
+ `.github/dependabot.yml`, so each release opens a pull request on the
115
+ organization's `.rness`: the pin and the lockfile in the diff, `validate`
116
+ running on the new version, review, merge. `upgrade` writes that file into
117
+ workspaces created before 0.5.1.
118
+
119
+ `upgrade` is never delegated to the pinned copy, which is what it replaces
109
120
  — so a workspace pinned below 0.5.0, whose copy has no such command, starts
110
121
  with the `npx` form.
111
122
 
@@ -116,6 +127,34 @@ its content does.
116
127
  Exit codes: 0 success, 1 failure, 2 usage — or a refusal without a TTY.
117
128
  `RNESS_DEBUG=1` adds stack traces; `RNESS_NO_DELEGATE=1` skips the delegation.
118
129
 
130
+ ## 0.5.2 — the block points at a file that exists
131
+
132
+ - The generated block told agents to read `.rness/STATUS.md`, a file neither
133
+ the scaffold nor any command writes. It now sends them to
134
+ `.rness/AGENTS.md`, which every workspace has and which sets the reading
135
+ order.
136
+ - The intro is part of the hashed body: every block written by 0.5.1 or
137
+ earlier is out of date under 0.5.2. Run `rness sync` once after upgrading,
138
+ then commit the refreshed `AGENTS.md` in each repository; until then
139
+ `rness sync --check` exits 1.
140
+
141
+ ## 0.5.1 — the version of a workspace moves by pull request
142
+
143
+ - Joining an organization pinned to an older `@rness/cli` no longer mentions
144
+ versions, and no longer invites a newcomer to move the whole team: the
145
+ workspace is served by the version the organization agreed on.
146
+ - A workspace whose pin moved is reinstalled on the next command, with the
147
+ package manager's frozen install so the working tree stays clean. Set
148
+ `RNESS_NO_INSTALL=1` to keep the old warning instead — for CI, a container
149
+ image, or a machine that cannot install.
150
+ - New workspaces ship `.github/dependabot.yml`, and `rness upgrade` writes it
151
+ into workspaces created earlier: a pull request per release, reviewed, with
152
+ `validate` running on the new version before the merge.
153
+ - A delegated child can no longer wait on an invisible SSH passphrase prompt:
154
+ it fails with a readable line instead of hanging.
155
+ - A join that wrote its blocks succeeds even when a repository nobody picked
156
+ failed to clone; those failures are hints.
157
+
119
158
  ## 0.5.0 — the organization is the workspace; rness.json is its catalogue
120
159
 
121
160
  - `create <org>` names the organization, not a directory any more (`--org
@@ -209,9 +248,26 @@ Exit codes: 0 success, 1 failure, 2 usage — or a refusal without a TTY.
209
248
  pnpm --filter @rness/cli test # node:test on the TypeScript sources
210
249
  pnpm --filter @rness/cli typecheck
211
250
  pnpm --filter @rness/cli build # tsup → dist/
212
- RNESS_NO_DELEGATE=1 node packages/cli/src/bin/rness.ts --help
251
+ pnpm dev --help # the CLI, straight from these sources
252
+
253
+ `pnpm dev` runs `packages/cli/src/bin/rness.ts`: Node ≥ 24 strips the types,
254
+ so nothing is built between an edit and the next run. It turns delegation off,
255
+ because inside a workspace the launcher would otherwise hand the command to the
256
+ published `@rness/cli` pinned in `.rness/` rather than to the sources under
257
+ test; `RNESS_NO_DELEGATE=0 pnpm dev …` puts it back, to exercise delegation
258
+ itself.
259
+
260
+ To reach it from a workspace elsewhere on the machine, link it once:
261
+
262
+ ln -s "$PWD/scripts/dev.mjs" ~/.local/bin/rness-dev # from the repository root
263
+ cd ~/somewhere/acme && rness-dev validate
264
+
265
+ `create` is never delegated, so it always runs these sources — and it refuses
266
+ to run inside a workspace, so call it from an empty directory.
213
267
 
214
- Inside a workspace whose `.rness/` pins a published `@rness/cli`, set
215
- `RNESS_NO_DELEGATE=1` to run this source tree instead of delegating.
268
+ `pnpm verdaccio` is the other loop: a local registry that serves this build as
269
+ a real package, for what only shows up through an install (`npm create rness`,
270
+ the pinned copy, a version bump). It is slower, and its caches have to be
271
+ forgotten on every redeploy, which `deploy` now does.
216
272
 
217
273
  Node ≥ 24. MIT.
package/dist/bin/rness.js CHANGED
@@ -2,12 +2,17 @@
2
2
  import {
3
3
  VERSION,
4
4
  driftWarning,
5
+ ensureInstalled,
5
6
  findDelegate,
7
+ findWorkspace,
8
+ pinDrift,
9
+ pinnedBinPath,
6
10
  reportError,
7
11
  run
8
- } from "../chunk-WSGPDTPQ.js";
12
+ } from "../chunk-P4YG6P7I.js";
9
13
 
10
14
  // src/bin/rness.ts
15
+ import { spawnSync } from "child_process";
11
16
  import { pathToFileURL } from "url";
12
17
 
13
18
  // src/core/node-version.ts
@@ -45,10 +50,27 @@ async function main() {
45
50
  const noDelegate = process.env["RNESS_NO_DELEGATE"] === "1";
46
51
  const skipDelegation = own || noDelegate;
47
52
  const command = argv[0];
48
- if (command !== void 0 && !command.startsWith("-") && !own && !noDelegate) {
49
- const warning = await driftWarning(process.cwd());
50
- if (warning !== null) process.stderr.write(`${warning}
53
+ if (command !== void 0 && !command.startsWith("-") && !skipDelegation) {
54
+ const ws = await findWorkspace(process.cwd()).catch(() => null);
55
+ const outcome = ws === null ? null : await ensureInstalled(ws.rnessDir, {
56
+ announce: (pin) => process.stderr.write(`installing @rness/cli ${pin} in .rness\u2026
57
+ `)
58
+ });
59
+ if (outcome !== null && !outcome.installed) {
60
+ const warning = await driftWarning(process.cwd());
61
+ if (warning !== null) process.stderr.write(`${warning}
51
62
  `);
63
+ }
64
+ if (ws !== null && outcome?.installed === true && await pinDrift(ws.rnessDir) === null) {
65
+ const pinnedBin = await pinnedBinPath(ws.rnessDir);
66
+ if (pinnedBin !== null) {
67
+ const { status } = spawnSync(process.execPath, [pinnedBin, ...argv], {
68
+ cwd: process.cwd(),
69
+ stdio: "inherit"
70
+ });
71
+ return status ?? 1;
72
+ }
73
+ }
52
74
  }
53
75
  const delegate = skipDelegation ? null : await findDelegate(process.cwd(), VERSION);
54
76
  if (delegate !== null) {
@@ -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 { findDelegate } from '../core/delegate.ts'\nimport { MIN_NODE_MAJOR, isSupportedNode } from '../core/node-version.ts'\nimport { driftWarning } from '../core/pinned.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_MAJOR} or newer (running ${process.version})\\n`\n )\n return 1\n }\n const argv = process.argv.slice(2)\n // `create` makes a workspace and `upgrade` replaces the pinned copy: both\n // are served by the copy the user invoked (spec 0006 §3). The login concerns\n // the machine, not a workspace — and git runs `git-credential` from inside\n // a clone, on every fetch: no delegation, and no warning there either.\n const own = [\n 'create',\n 'upgrade',\n 'update',\n 'login',\n 'logout',\n 'git-credential',\n ].includes(argv[0] ?? '')\n const noDelegate = process.env['RNESS_NO_DELEGATE'] === '1'\n const skipDelegation = own || noDelegate\n const command = argv[0]\n if (\n command !== undefined &&\n !command.startsWith('-') &&\n !own &&\n !noDelegate\n ) {\n const warning = await driftWarning(process.cwd())\n if (warning !== null) process.stderr.write(`${warning}\\n`)\n }\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","export const MIN_NODE_MAJOR = 24\n\nexport function nodeMajor(version: string): number {\n const major = Number.parseInt(version.split('.')[0] ?? '', 10)\n return Number.isNaN(major) ? 0 : major\n}\n\nexport function isSupportedNode(version: string): boolean {\n return nodeMajor(version) >= MIN_NODE_MAJOR\n}\n"],"mappings":";;;;;;;;;;AACA,SAAS,qBAAqB;;;ACDvB,IAAM,iBAAiB;AAEvB,SAAS,UAAU,SAAyB;AACjD,QAAM,QAAQ,OAAO,SAAS,QAAQ,MAAM,GAAG,EAAE,CAAC,KAAK,IAAI,EAAE;AAC7D,SAAO,OAAO,MAAM,KAAK,IAAI,IAAI;AACnC;AAEO,SAAS,gBAAgB,SAA0B;AACxD,SAAO,UAAU,OAAO,KAAK;AAC/B;;;ADKA,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;AAKjC,QAAM,MAAM;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,SAAS,KAAK,CAAC,KAAK,EAAE;AACxB,QAAM,aAAa,QAAQ,IAAI,mBAAmB,MAAM;AACxD,QAAM,iBAAiB,OAAO;AAC9B,QAAM,UAAU,KAAK,CAAC;AACtB,MACE,YAAY,UACZ,CAAC,QAAQ,WAAW,GAAG,KACvB,CAAC,OACD,CAAC,YACD;AACA,UAAM,UAAU,MAAM,aAAa,QAAQ,IAAI,CAAC;AAChD,QAAI,YAAY,KAAM,SAAQ,OAAO,MAAM,GAAG,OAAO;AAAA,CAAI;AAAA,EAC3D;AACA,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":[]}
1
+ {"version":3,"sources":["../../src/bin/rness.ts","../../src/core/node-version.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { spawnSync } from 'node:child_process'\nimport { pathToFileURL } from 'node:url'\n\nimport { run } from '../cli.ts'\nimport { findDelegate, pinnedBinPath } from '../core/delegate.ts'\nimport { MIN_NODE_MAJOR, isSupportedNode } from '../core/node-version.ts'\nimport { driftWarning, ensureInstalled, pinDrift } from '../core/pinned.ts'\nimport { findWorkspace } from '../core/workspace.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_MAJOR} or newer (running ${process.version})\\n`\n )\n return 1\n }\n const argv = process.argv.slice(2)\n // `create` makes a workspace and `upgrade` replaces the pinned copy: both\n // are served by the copy the user invoked (spec 0006 §3). The login concerns\n // the machine, not a workspace — and git runs `git-credential` from inside\n // a clone, on every fetch: no delegation, and no warning there either.\n const own = [\n 'create',\n 'upgrade',\n 'update',\n 'login',\n 'logout',\n 'git-credential',\n ].includes(argv[0] ?? '')\n const noDelegate = process.env['RNESS_NO_DELEGATE'] === '1'\n const skipDelegation = own || noDelegate\n const command = argv[0]\n if (command !== undefined && !command.startsWith('-') && !skipDelegation) {\n const ws = await findWorkspace(process.cwd()).catch(() => null)\n // The version was decided by the pull request that moved the pin, so\n // catching up asks nothing (spec 0008 §4).\n const outcome =\n ws === null\n ? null\n : await ensureInstalled(ws.rnessDir, {\n announce: (pin) =>\n process.stderr.write(`installing @rness/cli ${pin} in .rness…\\n`),\n })\n if (outcome !== null && !outcome.installed) {\n const warning = await driftWarning(process.cwd())\n if (warning !== null) process.stderr.write(`${warning}\\n`)\n }\n // The pinned tree was just rebuilt: importing out of it in this process is\n // fragile, so the freshly installed copy runs as its own process.\n // Only hand off when the install actually closed the drift: a child that\n // would install again on every run must never be spawned.\n if (\n ws !== null &&\n outcome?.installed === true &&\n (await pinDrift(ws.rnessDir)) === null\n ) {\n const pinnedBin = await pinnedBinPath(ws.rnessDir)\n if (pinnedBin !== null) {\n const { status } = spawnSync(process.execPath, [pinnedBin, ...argv], {\n cwd: process.cwd(),\n stdio: 'inherit',\n })\n return status ?? 1\n }\n }\n }\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","export const MIN_NODE_MAJOR = 24\n\nexport function nodeMajor(version: string): number {\n const major = Number.parseInt(version.split('.')[0] ?? '', 10)\n return Number.isNaN(major) ? 0 : major\n}\n\nexport function isSupportedNode(version: string): boolean {\n return nodeMajor(version) >= MIN_NODE_MAJOR\n}\n"],"mappings":"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","names":[]}