@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.
@@ -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-XCO5ZT2H.js";
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}) \u2014 repositories are cloned over SSH` : `No SSH access to github.com (${access.reason}) \u2014 repositories are cloned over HTTPS${loggedInAs(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 \u2014 ssh may ask for your passphrase"
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/\` \u2014`,
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}\` \u2014 start at its \`AGENTS.md\`, then task-relevant \`adr/\`, \`specs/\`, \`plans/\`;`,
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 \u2014 <title>\`. Never choose the
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/ \u2014 a choice expensive to reverse or that creates a lasting constraint \u2014 or reopen one. Use when the developer asks for an ADR, or when the conversation reaches such a decision.",
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 \u2014 its title, and why the choice is hard to reverse \u2014 and
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 \u2014 that one becomes \`Superseded\`, with \`superseded_by:\`, only once
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/ \u2014 the outcome wanted and its scope, before any plan \u2014 or reopen one. Use when the developer asks for a spec, or when agreed work is too large to start without one.",
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 \u2014 or the
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 \u2014 a
578
- section, a scope, an open question answered \u2014 \`updated\` today, the session
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/ \u2014 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.",
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 \u2014 \`check\` alone means the plan \`In progress\`; a bare reference is
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 \u2014 no confirmation question. If
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) \u2014 the last tasks the documentation
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 \u2014 a task added, split or reworded, a blocker recorded \u2014 \`updated\`
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)\` \u2014 what
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 \u2014 run ${pm} install in .rness`
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
- async function syncCommand(opts, deps = {}) {
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 clonesIn(ws.root);
1534
- const missing = Object.keys(manifest.repos).filter((n) => !clones.has(n));
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 \u2014 run ${rnessCommand()} sync`
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 \u2014 run ${rnessCommand()} sync`
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 \u2014 it is already cloned at ${basename2(ws.root)}/${CONTEXT_REPO}
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 present = await exists(dir);
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 = present ? `adopt org/${parsed.name}` : `clone ${parsed.url} into org/${parsed.name}`;
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) => [r.action, `org/${r.name}`]
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
- if (!Object.hasOwn(manifest.scopes, opts.scope)) {
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 = opts.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)} \u2014 commit ${shown}/.rness yourself`
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 \u2014 joining`,
3028
- `${org} has a workspace \u2014 joining it`
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) \u2014 starting a new workspace`,
3034
- `${org} has no workspace yet (or none you can see) \u2014 starting one`
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} \u2014 your workspace is in ${shown}/`);
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 \u2014 the next rness command installs it");
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} \u2014 merging it into ${label}`,
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}) \u2014 ${installed ?? "nothing"} is installed`
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 ? " \u2014 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 \u2014 ${label} has no scaffold commit yet`
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} \u2014 ${message3}`,
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 \u2014 deal with what git said, then commit`
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 \u2014 rness sync moves it`
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} \u2014 ${title}`,
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 \u2014 claude update`;
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 \u2014 run ${await workspacePackageManager(ws.rnessDir)} install in .rness`
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 \u2014 run rness validate`,
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} \u2014 `}${d.title}${withScope ? ` \u2014 ${d.scope ?? "global"}` : ""} \u2014 ${d.path}`;
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
- if (typeof args["scope"] !== "string" || !Object.hasOwn(manifest.scopes, args["scope"]))
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 = args["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 \u2014 ids, statuses, titles and paths, no bodies. Start here, then read a document with rness_read.",
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-XSJ7ASXM.js");
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}`} \u2014 ${counts.length === 0 ? "nothing applies yet" : counts.join(", ")}`;
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 \u2014 ${failure}`);
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-XSJ7ASXM.js");
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-S4NARIQP.js.map
5629
+ //# sourceMappingURL=chunk-H5E6FMP6.js.map