@rness/cli 0.22.0 → 0.22.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 +32 -0
- package/dist/bin/rness.js +2 -2
- package/dist/{chunk-AEL2W76O.js → chunk-A7NX55WK.js} +4 -4
- package/dist/chunk-A7NX55WK.js.map +1 -0
- package/dist/{chunk-XCO5ZT2H.js → chunk-DFGZWBBW.js} +202 -140
- package/dist/chunk-DFGZWBBW.js.map +1 -0
- package/dist/{chunk-S4NARIQP.js → chunk-H5E6FMP6.js} +89 -59
- package/dist/chunk-H5E6FMP6.js.map +1 -0
- package/dist/index.js +2 -2
- package/dist/{note-XSJ7ASXM.js → note-PANYS7DK.js} +3 -3
- package/dist/{summary-47SFWNSQ.js → summary-K5ETHXOX.js} +3 -3
- package/package.json +1 -1
- package/scaffold/README.md +3 -3
- package/scaffold/WORKSPACE.md +2 -2
- package/scaffold/adr/0000-template.md +5 -5
- package/dist/chunk-AEL2W76O.js.map +0 -1
- package/dist/chunk-S4NARIQP.js.map +0 -1
- package/dist/chunk-XCO5ZT2H.js.map +0 -1
- /package/dist/{note-XSJ7ASXM.js.map → note-PANYS7DK.js.map} +0 -0
- /package/dist/{summary-47SFWNSQ.js.map → summary-K5ETHXOX.js.map} +0 -0
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
DEFAULT_HOST,
|
|
5
5
|
MAX_PAGES,
|
|
6
6
|
NAME,
|
|
7
|
+
NAME_RULE,
|
|
7
8
|
ORG_NAME,
|
|
8
9
|
PACKAGE_MANAGERS,
|
|
9
10
|
PER_PAGE,
|
|
@@ -42,6 +43,7 @@ import {
|
|
|
42
43
|
documentNumber,
|
|
43
44
|
documentTitle,
|
|
44
45
|
documentsIn,
|
|
46
|
+
entryFor,
|
|
45
47
|
exists,
|
|
46
48
|
findTab,
|
|
47
49
|
findWorkspace,
|
|
@@ -65,6 +67,7 @@ import {
|
|
|
65
67
|
openInBrowser,
|
|
66
68
|
openProvider,
|
|
67
69
|
optionColor,
|
|
70
|
+
orgDirs,
|
|
68
71
|
ownerScope,
|
|
69
72
|
packageManagerVersion,
|
|
70
73
|
paint,
|
|
@@ -102,7 +105,7 @@ import {
|
|
|
102
105
|
workspaceName,
|
|
103
106
|
writeFileAtomic,
|
|
104
107
|
writeManifest
|
|
105
|
-
} from "./chunk-
|
|
108
|
+
} from "./chunk-DFGZWBBW.js";
|
|
106
109
|
|
|
107
110
|
// src/core/transport.ts
|
|
108
111
|
import { spawn } from "child_process";
|
|
@@ -183,7 +186,7 @@ async function testGithubSsh(transport, interactive, announce) {
|
|
|
183
186
|
}
|
|
184
187
|
var loggedInAs = (login) => login === void 0 || login === null ? "" : `, logged in as ${login}`;
|
|
185
188
|
function usingSentence(access, login) {
|
|
186
|
-
return access.ok ? `SSH works for github.com (as ${access.login})
|
|
189
|
+
return access.ok ? `SSH works for github.com (as ${access.login}): repositories are cloned over SSH` : `No SSH access to github.com (${access.reason}): repositories are cloned over HTTPS${loggedInAs(login)}`;
|
|
187
190
|
}
|
|
188
191
|
function isSshUrl(url, hosts) {
|
|
189
192
|
return url.startsWith(hosts.ssh);
|
|
@@ -192,7 +195,7 @@ var CHECKING_LINE = status("checking", "ssh access to github.com\u2026");
|
|
|
192
195
|
var CHECKING = [
|
|
193
196
|
"checking",
|
|
194
197
|
"ssh access to github.com\u2026",
|
|
195
|
-
"Checking SSH access to github.com
|
|
198
|
+
"Checking SSH access to github.com: ssh may ask for your passphrase"
|
|
196
199
|
];
|
|
197
200
|
function usingRest(access, login) {
|
|
198
201
|
return access.ok ? `ssh (github.com as ${access.login})` : `https (ssh to github.com unavailable: ${access.reason}${loggedInAs(login)})`;
|
|
@@ -288,7 +291,7 @@ function blockHash(body) {
|
|
|
288
291
|
function intro(scope, org, depth) {
|
|
289
292
|
if (scope === null) {
|
|
290
293
|
return [
|
|
291
|
-
`This is the root of rness workspace \`${org}\`. Full context lives in \`.rness
|
|
294
|
+
`This is the root of rness workspace \`${org}\`. Full context lives in \`.rness/\`:`,
|
|
292
295
|
"start at its `AGENTS.md`, then task-relevant `adr/`, `specs/`, `plans/`; live: `rness context`.",
|
|
293
296
|
"Every `org/<repo>/` carries its own block with the rules that apply there."
|
|
294
297
|
].join("\n");
|
|
@@ -296,7 +299,7 @@ function intro(scope, org, depth) {
|
|
|
296
299
|
const rel = `${"../".repeat(depth)}.rness/`;
|
|
297
300
|
return [
|
|
298
301
|
`This directory is scope \`${scope}\` of rness workspace \`${org}\`. Full context lives in`,
|
|
299
|
-
`\`${rel}
|
|
302
|
+
`\`${rel}\`: start at its \`AGENTS.md\`, then task-relevant \`adr/\`, \`specs/\`, \`plans/\`;`,
|
|
300
303
|
`live: \`rness context --scope ${scope}\`. If \`.rness/\` is not reachable, this is a`,
|
|
301
304
|
"standalone clone: the rules below are all you have."
|
|
302
305
|
].join("\n");
|
|
@@ -490,13 +493,13 @@ var allocateStep = (allocate, collection) => `Allocate the file: run \`${allocat
|
|
|
490
493
|
\`${collection}/NNNN-untitled.md\` with the next number, the front matter
|
|
491
494
|
and the opening sections, and prints the path. Rename it to
|
|
492
495
|
\`NNNN-<slug>.md\`, the slug a few lowercase words of the title joined by
|
|
493
|
-
hyphens, and write the title as \`# NNNN
|
|
496
|
+
hyphens, and write the title as \`# NNNN - <title>\`. Never choose the
|
|
494
497
|
number yourself.`;
|
|
495
498
|
var HOOK_LINE = (rness) => `The rness hook checks every edit under \`${rness}/\`: fix what it reports.`;
|
|
496
499
|
var LIFECYCLE = [
|
|
497
500
|
{
|
|
498
501
|
name: "adr",
|
|
499
|
-
description: "Record a decision of the rness workspace as an ADR in .rness/adr/
|
|
502
|
+
description: "Record a decision of the rness workspace as an ADR in .rness/adr/ - a choice expensive to reverse or that creates a lasting constraint - or reopen one. Use when the developer asks for an ADR, or when the conversation reaches such a decision.",
|
|
500
503
|
hint: "[create <subject> | open NNNN]",
|
|
501
504
|
tab: "adr",
|
|
502
505
|
body: (rness, allocate) => `You keep the decisions of this workspace: the ADRs in \`${rness}/adr/\`. The table
|
|
@@ -513,7 +516,7 @@ it; a bare reference is \`open\`; any other words are the subject of a
|
|
|
513
516
|
Creating:
|
|
514
517
|
|
|
515
518
|
1. If the developer did not ask for an ADR in so many words, propose one in
|
|
516
|
-
a single line
|
|
519
|
+
a single line - its title, and why the choice is hard to reverse - and
|
|
517
520
|
wait for a yes.
|
|
518
521
|
2. Read \`${rness}/CONVENTIONS.md\` and \`${rness}/adr/0000-template.md\`: they hold the
|
|
519
522
|
rules and the sections; this skill is only the procedure.
|
|
@@ -523,7 +526,7 @@ Creating:
|
|
|
523
526
|
4. ${allocateStep(allocate, "adr")}
|
|
524
527
|
5. Fill it: \`repo\` the repositories under \`org/\` it affects; the template's
|
|
525
528
|
sections, their guidance lines removed; an ADR it replaces named in
|
|
526
|
-
Context
|
|
529
|
+
Context - that one becomes \`Superseded\`, with \`superseded_by:\`, only once
|
|
527
530
|
the new ADR is \`Accepted\`. Add ${SESSION_LINE}.
|
|
528
531
|
6. ${HOOK_LINE(rness)}
|
|
529
532
|
|
|
@@ -541,7 +544,7 @@ ${COMMIT_RULE}
|
|
|
541
544
|
},
|
|
542
545
|
{
|
|
543
546
|
name: "spec",
|
|
544
|
-
description: "Write a specification of the rness workspace in .rness/specs/
|
|
547
|
+
description: "Write a specification of the rness workspace in .rness/specs/ - the outcome wanted and its scope, before any plan - or reopen one. Use when the developer asks for a spec, or when agreed work is too large to start without one.",
|
|
545
548
|
hint: "[create <subject> | open NNNN]",
|
|
546
549
|
tab: "specs",
|
|
547
550
|
body: (rness, allocate) => `You keep the specifications of this workspace, in \`${rness}/specs/\`. The table
|
|
@@ -565,7 +568,7 @@ Creating:
|
|
|
565
568
|
what is in and out of scope, the ADRs it rests on: ask what the
|
|
566
569
|
conversation does not say, one question at a time.
|
|
567
570
|
4. ${allocateStep(allocate, "specs")}
|
|
568
|
-
5. Fill it: \`repo\`, and \`adr:\` linking the decisions it rests on
|
|
571
|
+
5. Fill it: \`repo\`, and \`adr:\` linking the decisions it rests on - or the
|
|
569
572
|
rationale in the body when none does; the sections it opened with
|
|
570
573
|
(Summary, Scope, Out of scope, Alternatives considered, To verify,
|
|
571
574
|
Tests), or the most recent specification's when the team's differ. What
|
|
@@ -574,8 +577,8 @@ Creating:
|
|
|
574
577
|
question. Add ${SESSION_LINE}.
|
|
575
578
|
6. ${HOOK_LINE(rness)}
|
|
576
579
|
|
|
577
|
-
Opening: read the specification and amend what the developer asks
|
|
578
|
-
section, a scope, an open question answered
|
|
580
|
+
Opening: read the specification and amend what the developer asks - a
|
|
581
|
+
section, a scope, an open question answered - \`updated\` today, the session
|
|
579
582
|
line added. A status moves only as the developer says, or by
|
|
580
583
|
\`/rness:plan from\`.
|
|
581
584
|
|
|
@@ -590,14 +593,14 @@ ${COMMIT_RULE}
|
|
|
590
593
|
},
|
|
591
594
|
{
|
|
592
595
|
name: "plan",
|
|
593
|
-
description: "The plans of the rness workspace in .rness/plans/
|
|
596
|
+
description: "The plans of the rness workspace in .rness/plans/ - a plan from a specification (from, which approves it), from the conversation (create), reopened (open), or closed on evidence (check). Use when the developer asks for a plan, to approve a specification, or to check the work of a plan.",
|
|
594
597
|
hint: "[create <subject> | from <spec> | open NNNN | check NNNN]",
|
|
595
598
|
tab: "plans",
|
|
596
599
|
body: (rness, allocate) => `You keep the plans of this workspace, in \`${rness}/plans/\`. The table above
|
|
597
600
|
lists the existing ones, newest first. Arguments: \`$ARGUMENTS\`.
|
|
598
601
|
|
|
599
602
|
The first word is the verb, when a reference (\`0037\`, or a path) follows
|
|
600
|
-
it
|
|
603
|
+
it - \`check\` alone means the plan \`In progress\`; a bare reference is
|
|
601
604
|
\`open\`; any other words are the subject of a \`create\`:
|
|
602
605
|
|
|
603
606
|
- \`from NNNN\`: a plan from specification NNNN, which this approves.
|
|
@@ -615,7 +618,7 @@ it \u2014 \`check\` alone means the plan \`In progress\`; a bare reference is
|
|
|
615
618
|
reopen it rather than write a second.
|
|
616
619
|
2. The developer typed this command: that is their approval, and the
|
|
617
620
|
specification moves from \`Draft\` or \`Proposed\` to \`Approved\`, \`updated\`
|
|
618
|
-
today, in the same commit as the plan
|
|
621
|
+
today, in the same commit as the plan - no confirmation question. If
|
|
619
622
|
you are proposing it yourself, propose it in a single line and wait for
|
|
620
623
|
a yes first: the approval is theirs, never yours.
|
|
621
624
|
3. Read the code and the repositories the specification touches: every
|
|
@@ -623,7 +626,7 @@ it \u2014 \`check\` alone means the plan \`In progress\`; a bare reference is
|
|
|
623
626
|
4. ${allocateStep(allocate, "plans")}
|
|
624
627
|
5. Fill it: \`spec:\` linking the specification; tasks in order, as
|
|
625
628
|
checkboxes, each with the files, what changes, and the command that
|
|
626
|
-
proves it (a test, a build, a run)
|
|
629
|
+
proves it (a test, a build, a run) - the last tasks the documentation
|
|
627
630
|
the work makes inaccurate, then the release when the repository has
|
|
628
631
|
one; where the plan decides something the specification leaves open, the
|
|
629
632
|
section it opened with says so. Add ${SESSION_LINE}.
|
|
@@ -634,7 +637,7 @@ for a plan in so many words, propose one in a single line and wait for a
|
|
|
634
637
|
yes. The body says what the work is and why it needs no specification.
|
|
635
638
|
|
|
636
639
|
\`open\`: read the plan and its specification; amend what the developer
|
|
637
|
-
asks
|
|
640
|
+
asks - a task added, split or reworded, a blocker recorded - \`updated\`
|
|
638
641
|
today, the session line added; move \`Draft\` to \`Ready\` or \`Blocked\` as they
|
|
639
642
|
say. A \`Completed\` or \`Abandoned\` plan is not reopened: offer a new plan of
|
|
640
643
|
the same specification.
|
|
@@ -652,7 +655,7 @@ the same specification.
|
|
|
652
655
|
check has no cache: run twice, it proves twice.
|
|
653
656
|
5. Every task proven:
|
|
654
657
|
- the plan: \`status: Completed\`, \`updated\` today, the checkboxes of the
|
|
655
|
-
proven tasks ticked, and a section \`Verification (YYYY-MM-DD)\`
|
|
658
|
+
proven tasks ticked, and a section \`Verification (YYYY-MM-DD)\` - what
|
|
656
659
|
ran, what it showed, what could not run and why;
|
|
657
660
|
- the specification: \`Implemented\` once every plan of it is
|
|
658
661
|
\`Completed\`; \`updated\` today;
|
|
@@ -1088,7 +1091,7 @@ async function driftWarning(cwd) {
|
|
|
1088
1091
|
if (drift === null) return null;
|
|
1089
1092
|
const pm = await workspacePackageManager(rnessDir);
|
|
1090
1093
|
return warn(
|
|
1091
|
-
`${basename(root)}/.rness pins @rness/cli ${drift.pin} but ${drift.installed ?? "nothing"} is installed
|
|
1094
|
+
`${basename(root)}/.rness pins @rness/cli ${drift.pin} but ${drift.installed ?? "nothing"} is installed: run ${pm} install in .rness`
|
|
1092
1095
|
);
|
|
1093
1096
|
}
|
|
1094
1097
|
var CHILD_DEADLINE_MS = 12e4;
|
|
@@ -1455,7 +1458,18 @@ async function askWhatToSync(input) {
|
|
|
1455
1458
|
if (p.isCancel(ok) || ok !== true) return cancelled2();
|
|
1456
1459
|
return [];
|
|
1457
1460
|
}
|
|
1458
|
-
|
|
1461
|
+
function unreadWhy(dir, clones) {
|
|
1462
|
+
const lower = dir.toLowerCase();
|
|
1463
|
+
const step = /^(.+)\.rness-rename$/.exec(dir);
|
|
1464
|
+
if (step !== null)
|
|
1465
|
+
return `left by an interrupted rename: move it back to org/${step[1]}`;
|
|
1466
|
+
if (!NAME.test(lower)) return `not a repository name: ${NAME_RULE}`;
|
|
1467
|
+
if (clones.has(lower))
|
|
1468
|
+
return `names are lowercase, and org/${lower} is another directory`;
|
|
1469
|
+
return `names are lowercase: ${rnessCommand()} add ${lower} renames it org/${lower}`;
|
|
1470
|
+
}
|
|
1471
|
+
async function syncCommand(given, deps = {}) {
|
|
1472
|
+
const opts = given.scope === void 0 ? given : { ...given, scope: given.scope.toLowerCase() };
|
|
1459
1473
|
const terminal = deps.terminal ?? defaultTerminal;
|
|
1460
1474
|
const transport = deps.transport ?? defaultTransport;
|
|
1461
1475
|
let provider = deps.provider;
|
|
@@ -1530,8 +1544,13 @@ async function syncCommand(opts, deps = {}) {
|
|
|
1530
1544
|
if (boards.changed)
|
|
1531
1545
|
ui.hint("rness.json changed: commit it in .rness, for the whole team");
|
|
1532
1546
|
}
|
|
1533
|
-
const clones = await
|
|
1534
|
-
const
|
|
1547
|
+
const { clones, unread } = await orgDirs(ws.root);
|
|
1548
|
+
const misnamed = new Set(
|
|
1549
|
+
unread.map((d) => d.toLowerCase()).filter((n) => Object.hasOwn(manifest.repos, n) && !clones.has(n))
|
|
1550
|
+
);
|
|
1551
|
+
const missing = Object.keys(manifest.repos).filter(
|
|
1552
|
+
(n) => !clones.has(n) && !misnamed.has(n)
|
|
1553
|
+
);
|
|
1535
1554
|
let toClone = new Set(opts.all === true && !check ? missing : []);
|
|
1536
1555
|
if (!check && opts.yes !== true) {
|
|
1537
1556
|
const answer = await askWhatToSync({
|
|
@@ -1572,6 +1591,7 @@ async function syncCommand(opts, deps = {}) {
|
|
|
1572
1591
|
try {
|
|
1573
1592
|
const notCloned = /* @__PURE__ */ new Set();
|
|
1574
1593
|
for (const [name, repo] of Object.entries(manifest.repos)) {
|
|
1594
|
+
if (misnamed.has(name)) continue;
|
|
1575
1595
|
const dir = join6(ws.root, "org", name);
|
|
1576
1596
|
const label = `org/${name}`;
|
|
1577
1597
|
if (!await exists(dir)) {
|
|
@@ -1624,11 +1644,15 @@ async function syncCommand(opts, deps = {}) {
|
|
|
1624
1644
|
lines.push(
|
|
1625
1645
|
`not in rness.json: ${undeclared.join(", ")} (${rnessCommand()} add <name> declares it)`
|
|
1626
1646
|
);
|
|
1647
|
+
for (const d of unread)
|
|
1648
|
+
lines.push(`not read: org/${d} (${unreadWhy(d, clones)})`);
|
|
1627
1649
|
if (!await exists(join6(ws.root, "org"))) {
|
|
1628
1650
|
lines.push(["skipped", "blocks (no org/ directory here)"]);
|
|
1629
1651
|
} else {
|
|
1630
1652
|
let differences = 0;
|
|
1631
1653
|
for (const t of targetsOf(manifest, ws.root, opts.scope)) {
|
|
1654
|
+
const owner = t.label.startsWith("org/") ? t.label.split("/")[1] : void 0;
|
|
1655
|
+
if (owner !== void 0 && misnamed.has(owner)) continue;
|
|
1632
1656
|
if (!await exists(t.dir)) {
|
|
1633
1657
|
const repo = t.label.split("/")[1];
|
|
1634
1658
|
if (!t.label.startsWith("org/") || repo === void 0 || !notCloned.has(repo))
|
|
@@ -1688,7 +1712,7 @@ async function syncCommand(opts, deps = {}) {
|
|
|
1688
1712
|
}
|
|
1689
1713
|
if (check && differences > 0)
|
|
1690
1714
|
problems.push(
|
|
1691
|
-
`${differences} block(s) out of date
|
|
1715
|
+
`${differences} block(s) out of date: run ${rnessCommand()} sync`
|
|
1692
1716
|
);
|
|
1693
1717
|
if (opts.scope === void 0) {
|
|
1694
1718
|
let stale = 0;
|
|
@@ -1704,7 +1728,7 @@ async function syncCommand(opts, deps = {}) {
|
|
|
1704
1728
|
}
|
|
1705
1729
|
if (stale > 0)
|
|
1706
1730
|
problems.push(
|
|
1707
|
-
`${stale} agent file(s) out of date
|
|
1731
|
+
`${stale} agent file(s) out of date: run ${rnessCommand()} sync`
|
|
1708
1732
|
);
|
|
1709
1733
|
if (!check)
|
|
1710
1734
|
for (const label of await leftoverTargets(ws.root, manifest))
|
|
@@ -1766,7 +1790,7 @@ async function addCommand(spec, opts, deps = {}) {
|
|
|
1766
1790
|
}
|
|
1767
1791
|
if (parsed.name === CONTEXT_REPO) {
|
|
1768
1792
|
process.stderr.write(
|
|
1769
|
-
`${CONTEXT_REPO} is the workspace context, not a member repository
|
|
1793
|
+
`${CONTEXT_REPO} is the workspace context, not a member repository: it is already cloned at ${basename2(ws.root)}/${CONTEXT_REPO}
|
|
1770
1794
|
`
|
|
1771
1795
|
);
|
|
1772
1796
|
return 2;
|
|
@@ -1826,10 +1850,11 @@ async function addCommand(spec, opts, deps = {}) {
|
|
|
1826
1850
|
parsed = parseRepoSpec(spec, org, host);
|
|
1827
1851
|
const scopes = (opts.scopes ?? "").split(",").map((s) => s.trim()).filter((s) => s !== "");
|
|
1828
1852
|
const dir = join7(ws.root, "org", parsed.name);
|
|
1829
|
-
const
|
|
1853
|
+
const entry = await entryFor(ws.root, parsed.name);
|
|
1854
|
+
const present = entry !== null;
|
|
1830
1855
|
if (interactive) {
|
|
1831
1856
|
const { confirm, isCancel } = await terminal.prompts();
|
|
1832
|
-
const plan =
|
|
1857
|
+
const plan = entry === null ? `clone ${parsed.url} into org/${parsed.name}` : entry === parsed.name ? `adopt org/${parsed.name}` : `adopt org/${entry}, rename it org/${parsed.name}`;
|
|
1833
1858
|
const ok = await confirm({
|
|
1834
1859
|
message: `${plan}, declare scope "${parsed.name}" in rness.json, then sync?`
|
|
1835
1860
|
});
|
|
@@ -1842,7 +1867,7 @@ async function addCommand(spec, opts, deps = {}) {
|
|
|
1842
1867
|
const chosenHost = host;
|
|
1843
1868
|
let result = await ui.step(
|
|
1844
1869
|
{
|
|
1845
|
-
doing: `${present ? "adopting" : "cloning "} org/${parsed.name}`,
|
|
1870
|
+
doing: `${present ? "adopting" : "cloning "} org/${entry ?? parsed.name}`,
|
|
1846
1871
|
git: true
|
|
1847
1872
|
},
|
|
1848
1873
|
() => addRepository({
|
|
@@ -1855,7 +1880,10 @@ async function addCommand(spec, opts, deps = {}) {
|
|
|
1855
1880
|
scopes,
|
|
1856
1881
|
credentialsFor: () => credentials
|
|
1857
1882
|
}),
|
|
1858
|
-
(r) => [
|
|
1883
|
+
(r) => [
|
|
1884
|
+
r.action,
|
|
1885
|
+
r.renamed === null ? `org/${r.name}` : `org/${r.renamed} as org/${r.name}`
|
|
1886
|
+
]
|
|
1859
1887
|
);
|
|
1860
1888
|
const announced = /* @__PURE__ */ new Set();
|
|
1861
1889
|
printDeclared(ui, result, announced);
|
|
@@ -1926,12 +1954,13 @@ async function contextCommand(opts) {
|
|
|
1926
1954
|
const manifest = await loadManifest(ws.rnessDir);
|
|
1927
1955
|
let scope;
|
|
1928
1956
|
if (opts.scope !== void 0) {
|
|
1929
|
-
|
|
1957
|
+
const wanted = opts.scope.toLowerCase();
|
|
1958
|
+
if (!Object.hasOwn(manifest.scopes, wanted)) {
|
|
1930
1959
|
process.stderr.write(`unknown scope: ${opts.scope}
|
|
1931
1960
|
`);
|
|
1932
1961
|
return 1;
|
|
1933
1962
|
}
|
|
1934
|
-
scope =
|
|
1963
|
+
scope = wanted;
|
|
1935
1964
|
} else {
|
|
1936
1965
|
const rel = relative(ws.root, cwd).split(sep).join(posix.sep);
|
|
1937
1966
|
scope = resolveScope(manifest, rel);
|
|
@@ -2413,7 +2442,7 @@ async function commitContext(input) {
|
|
|
2413
2442
|
ui.line("committed", `${shown}/.rness`);
|
|
2414
2443
|
} catch (e) {
|
|
2415
2444
|
ui.warn(
|
|
2416
|
-
`${e instanceof Error ? e.message : String(e)}
|
|
2445
|
+
`${e instanceof Error ? e.message : String(e)}: commit ${shown}/.rness yourself`
|
|
2417
2446
|
);
|
|
2418
2447
|
}
|
|
2419
2448
|
}
|
|
@@ -3024,14 +3053,14 @@ async function createCommand(opts, deps = {}) {
|
|
|
3024
3053
|
if (joining)
|
|
3025
3054
|
ui.line(
|
|
3026
3055
|
"found",
|
|
3027
|
-
`${org}/.rness
|
|
3028
|
-
`${org} has a workspace
|
|
3056
|
+
`${org}/.rness - joining`,
|
|
3057
|
+
`${org} has a workspace - joining it`
|
|
3029
3058
|
);
|
|
3030
3059
|
else
|
|
3031
3060
|
ui.line(
|
|
3032
3061
|
"not found",
|
|
3033
|
-
`${org}/.rness (or not visible to you)
|
|
3034
|
-
`${org} has no workspace yet (or none you can see)
|
|
3062
|
+
`${org}/.rness (or not visible to you) - starting a new workspace`,
|
|
3063
|
+
`${org} has no workspace yet (or none you can see) - starting one`
|
|
3035
3064
|
);
|
|
3036
3065
|
let catalogue = {
|
|
3037
3066
|
contract: 1,
|
|
@@ -3159,7 +3188,7 @@ async function createCommand(opts, deps = {}) {
|
|
|
3159
3188
|
else process.stdout.write(`
|
|
3160
3189
|
${next2.map((l) => ` ${l}`).join("\n")}
|
|
3161
3190
|
`);
|
|
3162
|
-
ui.outro(`You joined ${org}
|
|
3191
|
+
ui.outro(`You joined ${org}: your workspace is in ${shown}/`);
|
|
3163
3192
|
return failures2.length > 0 ? 1 : 0;
|
|
3164
3193
|
}
|
|
3165
3194
|
const built = await buildContext({
|
|
@@ -3461,7 +3490,7 @@ function finish(ui, cwd, rnessDir, label, target, ending) {
|
|
|
3461
3490
|
`git -C ${c.dir} add ${c.paths.join(" ")} && git -C ${c.dir} commit -m "${message3}"`
|
|
3462
3491
|
);
|
|
3463
3492
|
if (ending.commit !== "nothing")
|
|
3464
|
-
next.push("# teammates: git pull
|
|
3493
|
+
next.push("# teammates: git pull - the next rness command installs it");
|
|
3465
3494
|
if (ui.session) {
|
|
3466
3495
|
if (next.length > 0) ui.note("Next steps", next);
|
|
3467
3496
|
ui.outro(`${label} runs @rness/cli ${target}`);
|
|
@@ -3557,18 +3586,18 @@ async function upgradeCommand(version, opts, terminal = defaultTerminal, deps =
|
|
|
3557
3586
|
if (pin.spec === target && installed === target)
|
|
3558
3587
|
ui.line(
|
|
3559
3588
|
"scaffold",
|
|
3560
|
-
`@rness/cli ${target}
|
|
3589
|
+
`@rness/cli ${target}: merging it into ${label}`,
|
|
3561
3590
|
`Merging the @rness/cli ${target} scaffold into ${label}`
|
|
3562
3591
|
);
|
|
3563
3592
|
else if (pin.spec === target)
|
|
3564
3593
|
ui.line(
|
|
3565
3594
|
"install",
|
|
3566
|
-
`@rness/cli ${target} in ${label} (${pm})
|
|
3595
|
+
`@rness/cli ${target} in ${label} (${pm}): ${installed ?? "nothing"} is installed`
|
|
3567
3596
|
);
|
|
3568
3597
|
else {
|
|
3569
3598
|
ui.line(
|
|
3570
3599
|
"upgrade",
|
|
3571
|
-
`@rness/cli ${pin.spec} \u2192 ${target} in ${label} (${pm})${downgrading ? "
|
|
3600
|
+
`@rness/cli ${pin.spec} \u2192 ${target} in ${label} (${pm})${downgrading ? ", downgrading" : ""}`
|
|
3572
3601
|
);
|
|
3573
3602
|
ui.line("notes", NOTES, `Release notes: ${NOTES}`);
|
|
3574
3603
|
}
|
|
@@ -3597,7 +3626,7 @@ async function upgradeCommand(version, opts, terminal = defaultTerminal, deps =
|
|
|
3597
3626
|
ui.line(
|
|
3598
3627
|
"adopting",
|
|
3599
3628
|
`the @rness/cli ${target} scaffold (no scaffold commit in ${label} yet)`,
|
|
3600
|
-
`Adopting the @rness/cli ${target} scaffold
|
|
3629
|
+
`Adopting the @rness/cli ${target} scaffold: ${label} has no scaffold commit yet`
|
|
3601
3630
|
);
|
|
3602
3631
|
else
|
|
3603
3632
|
ui.line(
|
|
@@ -3685,12 +3714,12 @@ async function upgradeCommand(version, opts, terminal = defaultTerminal, deps =
|
|
|
3685
3714
|
if (committed.kind === "committed")
|
|
3686
3715
|
ui.line(
|
|
3687
3716
|
"committed",
|
|
3688
|
-
`${label}
|
|
3717
|
+
`${label}: ${message3}`,
|
|
3689
3718
|
`Committed ${label}: ${message3}`
|
|
3690
3719
|
);
|
|
3691
3720
|
if (committed.kind === "refused") {
|
|
3692
3721
|
ui.error(
|
|
3693
|
-
`the commit of ${label} was refused; everything is staged
|
|
3722
|
+
`the commit of ${label} was refused; everything is staged: deal with what git said, then commit`
|
|
3694
3723
|
);
|
|
3695
3724
|
for (const line3 of committed.output.split("\n"))
|
|
3696
3725
|
if (line3.trim() !== "") ui.hint(line3, "stderr");
|
|
@@ -3760,7 +3789,7 @@ async function checkBoards(rnessDir, manifest) {
|
|
|
3760
3789
|
await readmeDeclarations(rnessDir, collection).catch(() => ({}))
|
|
3761
3790
|
))
|
|
3762
3791
|
problems.push(
|
|
3763
|
-
`${collection}/README.md: "${k}" is declared in rness.json now
|
|
3792
|
+
`${collection}/README.md: "${k}" is declared in rness.json now: rness sync moves it`
|
|
3764
3793
|
);
|
|
3765
3794
|
}
|
|
3766
3795
|
for (const key of ["readme", "updates"]) {
|
|
@@ -3954,7 +3983,7 @@ async function docNewCommand(collection, opts) {
|
|
|
3954
3983
|
];
|
|
3955
3984
|
const sections = name === "adr" ? await adrSections(ws.rnessDir) : SECTIONS[name] ?? [];
|
|
3956
3985
|
const body = [
|
|
3957
|
-
`# ${number}
|
|
3986
|
+
`# ${number} - ${title}`,
|
|
3958
3987
|
// The rule under the title, as the ADR and specification templates draw it.
|
|
3959
3988
|
...name === "plans" ? [] : ["", "---"],
|
|
3960
3989
|
...sections.flatMap((s) => ["", `## ${s}`])
|
|
@@ -4037,7 +4066,7 @@ async function takeModNotice(env) {
|
|
|
4037
4066
|
);
|
|
4038
4067
|
} catch {
|
|
4039
4068
|
}
|
|
4040
|
-
return `rness: Claude Code ${version} shows no rness band, footer label or pane; ${MOD_FLOOR} or later does
|
|
4069
|
+
return `rness: Claude Code ${version} shows no rness band, footer label or pane; ${MOD_FLOOR} or later does: claude update`;
|
|
4041
4070
|
}
|
|
4042
4071
|
|
|
4043
4072
|
// src/core/edit-guard.ts
|
|
@@ -4145,13 +4174,13 @@ async function safetyNet(ws, manifest) {
|
|
|
4145
4174
|
const drift = await pinDrift(ws.rnessDir);
|
|
4146
4175
|
if (drift !== null)
|
|
4147
4176
|
notes.push(
|
|
4148
|
-
`.rness pins @rness/cli ${drift.pin} but ${drift.installed ?? "nothing"} is installed
|
|
4177
|
+
`.rness pins @rness/cli ${drift.pin} but ${drift.installed ?? "nothing"} is installed: run ${await workspacePackageManager(ws.rnessDir)} install in .rness`
|
|
4149
4178
|
);
|
|
4150
4179
|
try {
|
|
4151
4180
|
const { problems } = await checkWorkspace(ws, manifest);
|
|
4152
4181
|
if (problems.length > 0)
|
|
4153
4182
|
notes.push(
|
|
4154
|
-
`${count(problems.length, ["problem", "problems"])} in the workspace context
|
|
4183
|
+
`${count(problems.length, ["problem", "problems"])} in the workspace context: run rness validate`,
|
|
4155
4184
|
...problems.slice(0, SHOWN_PROBLEMS).map((p) => ` ${p}`)
|
|
4156
4185
|
);
|
|
4157
4186
|
} catch (e) {
|
|
@@ -4211,7 +4240,7 @@ async function documents(rnessDir, only) {
|
|
|
4211
4240
|
}
|
|
4212
4241
|
function line(d, withScope = false) {
|
|
4213
4242
|
const head = [d.id, d.status].filter((x) => x !== null).join(" ");
|
|
4214
|
-
return `- ${head === "" ? "" : `${head}
|
|
4243
|
+
return `- ${head === "" ? "" : `${head} - `}${d.title}${withScope ? ` \xB7 ${d.scope ?? "global"}` : ""} \xB7 ${d.path}`;
|
|
4215
4244
|
}
|
|
4216
4245
|
function isCollection(value) {
|
|
4217
4246
|
return COLLECTIONS.includes(value);
|
|
@@ -4224,11 +4253,12 @@ async function context(cwd, args) {
|
|
|
4224
4253
|
let scope;
|
|
4225
4254
|
if (args["scope"] !== void 0) {
|
|
4226
4255
|
const known = Object.keys(manifest.scopes).sort();
|
|
4227
|
-
|
|
4256
|
+
const wanted = typeof args["scope"] === "string" ? args["scope"].toLowerCase() : null;
|
|
4257
|
+
if (wanted === null || !Object.hasOwn(manifest.scopes, wanted))
|
|
4228
4258
|
return refuse(
|
|
4229
4259
|
`unknown scope ${JSON.stringify(args["scope"])}; known: ${known.length === 0 ? "none" : known.join(", ")}`
|
|
4230
4260
|
);
|
|
4231
|
-
scope =
|
|
4261
|
+
scope = wanted;
|
|
4232
4262
|
} else
|
|
4233
4263
|
scope = resolveScope(
|
|
4234
4264
|
manifest,
|
|
@@ -4353,7 +4383,7 @@ function mcpTools(cwd) {
|
|
|
4353
4383
|
{
|
|
4354
4384
|
name: "rness_context",
|
|
4355
4385
|
title: "rness: what applies here",
|
|
4356
|
-
description: "The rness scope of the current repository (or the one named) and what applies to it: the standards, decisions (ADRs), specifications and plans of that scope and of the scopes it extends
|
|
4386
|
+
description: "The rness scope of the current repository (or the one named) and what applies to it: the standards, decisions (ADRs), specifications and plans of that scope and of the scopes it extends: ids, statuses, titles and paths, no bodies. Start here, then read a document with rness_read.",
|
|
4357
4387
|
inputSchema: {
|
|
4358
4388
|
type: "object",
|
|
4359
4389
|
properties: {
|
|
@@ -4449,7 +4479,7 @@ function noteTool(cwd, githubApi) {
|
|
|
4449
4479
|
additionalProperties: false
|
|
4450
4480
|
},
|
|
4451
4481
|
call: (args) => guard(async () => {
|
|
4452
|
-
const { postNote } = await import("./note-
|
|
4482
|
+
const { postNote } = await import("./note-PANYS7DK.js");
|
|
4453
4483
|
const given = (key) => {
|
|
4454
4484
|
const value = args[key];
|
|
4455
4485
|
return typeof value === "string" ? value : void 0;
|
|
@@ -4498,7 +4528,7 @@ async function scopeBanner(ws, manifest, scope) {
|
|
|
4498
4528
|
const n = summary.counts[c];
|
|
4499
4529
|
return n === void 0 ? [] : [count(n, NOUNS[c])];
|
|
4500
4530
|
});
|
|
4501
|
-
const banner2 = `rness ${VERSION} \xB7 ${workspaceName(manifest, ws.root)} \xB7 ${scope === null ? "global scope" : `scope ${scope}`} \
|
|
4531
|
+
const banner2 = `rness ${VERSION} \xB7 ${workspaceName(manifest, ws.root)} \xB7 ${scope === null ? "global scope" : `scope ${scope}`} \xB7 ${counts.length === 0 ? "nothing applies yet" : counts.join(", ")}`;
|
|
4502
4532
|
return { banner: banner2, lines: summary.lines };
|
|
4503
4533
|
}
|
|
4504
4534
|
var noteLines = (notes) => notes.map((n) => `rness: ${n}`);
|
|
@@ -4682,7 +4712,7 @@ async function sessionStart(input, io) {
|
|
|
4682
4712
|
notes = [message2(e)];
|
|
4683
4713
|
}
|
|
4684
4714
|
const failure = await takeFailure();
|
|
4685
|
-
if (failure !== null) notes.push(`board not updated
|
|
4715
|
+
if (failure !== null) notes.push(`board not updated: ${failure}`);
|
|
4686
4716
|
notes.push(...await takeNotices());
|
|
4687
4717
|
const warnings = noteLines(notes);
|
|
4688
4718
|
const compact = input["source"] === "compact";
|
|
@@ -5309,7 +5339,7 @@ function noteCommandOf(parent, state, former) {
|
|
|
5309
5339
|
).addOption(new Option("--github-api <base>").hideHelp()).addOption(new Option("--cwd <dir>").hideHelp()).action(
|
|
5310
5340
|
async (text, opts) => {
|
|
5311
5341
|
if (former !== void 0) formerly(former, "rness note");
|
|
5312
|
-
const { noteCommand } = await import("./note-
|
|
5342
|
+
const { noteCommand } = await import("./note-PANYS7DK.js");
|
|
5313
5343
|
state.code = await noteCommand({
|
|
5314
5344
|
...opts,
|
|
5315
5345
|
...text === void 0 ? {} : { text }
|
|
@@ -5596,4 +5626,4 @@ export {
|
|
|
5596
5626
|
OWN_COMMANDS,
|
|
5597
5627
|
catchUp
|
|
5598
5628
|
};
|
|
5599
|
-
//# sourceMappingURL=chunk-
|
|
5629
|
+
//# sourceMappingURL=chunk-H5E6FMP6.js.map
|