@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 CHANGED
@@ -848,6 +848,38 @@ per repository, the files to commit there.
848
848
  Exit codes: 0 success, 1 failure, 2 usage — or a refusal without a TTY.
849
849
  `RNESS_DEBUG=1` adds stack traces; `RNESS_NO_DELEGATE=1` skips the delegation.
850
850
 
851
+ ## 0.22.2 - repository names in any case
852
+
853
+ - `rness add` takes a repository name in any case, as `create` does:
854
+ `rness add dApp` declares `dapp` in `rness.json` and clones into
855
+ `org/dapp`; the URL keeps the spelling typed. `create --repos` follows, and
856
+ `add --scopes apps/Web` declares scope `web`.
857
+ - A clone whose directory differs from its name only by case (`org/dApp` for
858
+ `dapp`) is renamed `org/dapp` by `rness add`, once its origin is checked:
859
+ the confirmation says so, and `--yes` consents to it. A path in another
860
+ case is the same on macOS and Windows but not on Linux, so a teammate's
861
+ clone would not match. Two such directories are refused, named.
862
+ - `rness add` adopts a clone whose origin differs from the URL only by case
863
+ or by transport (an HTTPS clone, an SSH URL in `rness.json`). Another
864
+ repository is still refused.
865
+ - `rness sync` names each directory under `org/` it does not read on a
866
+ `not read:` line, instead of skipping it silently; for `org/dApp` the line
867
+ points at `rness add dapp`, which renames it. A declared repository whose
868
+ directory differs only by case is not cloned a second time and gets no
869
+ block until renamed.
870
+ - `--scope` takes a scope name in any case: `rness context`, `rness sync`,
871
+ and `rness_context` over MCP.
872
+
873
+ ## 0.22.1 — what rness writes carries no em dash
874
+
875
+ - Nothing rness writes carries an em dash (U+2014) any more: the `AGENTS.md`
876
+ block, the title `rness doc new` opens (`# NNNN - Title`), the `rness:adr`,
877
+ `rness:spec` and `rness:plan` skills, the scaffold, the titles of a board's
878
+ issues (`NNNN - Title`, renamed once at the next `rness board push`), and
879
+ the messages of the CLI and of the mod: " - ", a comma or a colon take its
880
+ place. A title written with the old separator still reads. The
881
+ repository's lint refuses a new one in a string of the CLI or the mod.
882
+
851
883
  ## 0.22.0 — `board`, not `pulse`: `rness board push`, `rness note`, `boards` in rness.json
852
884
 
853
885
  - One word for the view, whatever the provider (spec 0033, see "Boards"):
package/dist/bin/rness.js CHANGED
@@ -4,11 +4,11 @@ import {
4
4
  catchUp,
5
5
  findDelegate,
6
6
  run
7
- } from "../chunk-S4NARIQP.js";
7
+ } from "../chunk-H5E6FMP6.js";
8
8
  import {
9
9
  VERSION,
10
10
  reportError
11
- } from "../chunk-XCO5ZT2H.js";
11
+ } from "../chunk-DFGZWBBW.js";
12
12
 
13
13
  // src/bin/rness.ts
14
14
  import { pathToFileURL } from "url";
@@ -15,7 +15,7 @@ import {
15
15
  recordNotice,
16
16
  resolveScope,
17
17
  statusTabs
18
- } from "./chunk-XCO5ZT2H.js";
18
+ } from "./chunk-DFGZWBBW.js";
19
19
 
20
20
  // src/commands/note.ts
21
21
  import { relative, resolve, sep } from "path";
@@ -173,7 +173,7 @@ async function postNote(input) {
173
173
  const row = (await statusTabs(c.rnessDir)).find((t) => t.name === "plans")?.rows.find((r) => r.path === plan);
174
174
  target = await fromGithub(
175
175
  c.provider.createJournalIssue(repo.owner, repo.name, plan, {
176
- title: `Implement ${row === void 0 ? plan : `${row.id} \u2014 ${row.title}`}`,
176
+ title: `Implement ${row === void 0 ? plan : `${row.id} - ${row.title}`}`,
177
177
  body: await implementationBody(c, plan, parent.number)
178
178
  })
179
179
  );
@@ -197,7 +197,7 @@ async function postNote(input) {
197
197
  }
198
198
  }
199
199
  if (why !== null)
200
- await recordNotice(`journal \u2014 ${why}, notes go to the plan's issue`);
200
+ await recordNotice(`journal: ${why}, notes go to the plan's issue`);
201
201
  const where = clone?.dir ?? input.cwd;
202
202
  const [branch, head] = await Promise.all([branchOf(where), headOf(where)]);
203
203
  const id = session.split(" \xB7 ").pop() ?? session;
@@ -260,4 +260,4 @@ export {
260
260
  postNote,
261
261
  noteCommand
262
262
  };
263
- //# sourceMappingURL=chunk-AEL2W76O.js.map
263
+ //# sourceMappingURL=chunk-A7NX55WK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/note.ts"],"sourcesContent":["import { relative, resolve, sep } from 'node:path'\n\nimport {\n notePosted,\n notesPosted,\n recordNotice,\n} from '../board/journal-state.ts'\nimport { blobUrl, issueUrl } from '../board/urls.ts'\nimport type { BoardAction } from '../core/board-declaration.ts'\nimport { parseFrontMatter } from '../core/frontmatter.ts'\nimport { branchOf, headOf } from '../core/git.ts'\nimport { JournalRefused } from '../core/github-journal.ts'\nimport type { JournalIssue } from '../core/github-journal.ts'\nimport { cloneHolding } from '../core/repos.ts'\nimport { resolveScope } from '../core/scope.ts'\nimport { plansInProgress, statusTabs } from '../core/status.ts'\nimport {\n type Context,\n type Declared,\n context,\n declaredBoards,\n fromGithub,\n} from './board.ts'\n\n/**\n * `rness note` and `rness_note` (spec 0030 §4, §5): a short note of\n * the agent's on the plan it implements — on the plan's issue in `.rness`,\n * or on an implementation issue in the repository the session works in, a\n * sub-issue of the plan's (§3). Loaded through `import()` only.\n */\n\nexport const KINDS = ['approach', 'deviation', 'blocker', 'done'] as const\nexport type Kind = (typeof KINDS)[number]\nconst TITLE: Readonly<Record<Kind, string>> = {\n approach: 'Approach',\n deviation: 'Deviation',\n blocker: 'Blocker',\n done: 'Done',\n}\nconst MAX = 4000\n/** What a credential looks like; a note that matches is refused, never redacted. */\nconst SECRETS = [\n /ghp_/,\n /gho_/,\n /github_pat_/,\n /AKIA[0-9A-Z]{16}/,\n /-----BEGIN [A-Z ]*PRIVATE KEY/,\n /xox[abpr]-/,\n /sk-[A-Za-z0-9]{20,}/,\n]\n\n/** A refusal said to the agent in one line: the note is not posted. */\nexport class NoteRefused extends Error {}\n\nexport interface NoteInput {\n /** The session's directory. */\n cwd: string\n text: string\n kind?: string\n /** `.rness/`-relative: `plans/0021-x.md`; absent, the one plan in progress. */\n plan?: string\n /** `claude · 1a2b3c4d`, or a session id; absent, `CLAUDE_CODE_SESSION_ID`. */\n session?: string\n env?: NodeJS.ProcessEnv\n /** Internal (tests): GitHub API base. */\n githubApi?: string\n}\n\n/** Where a note went: `acme/api#87`, the reference a pull request uses. */\nexport interface Posted {\n reference: string\n to: 'plan' | 'repo'\n}\n\n/** The session as the hooks name it: `claude · 1a2b3c4d`; null without one. */\nexport function sessionFrom(\n given: string | undefined,\n env: NodeJS.ProcessEnv\n): string | null {\n const raw = given ?? env['CLAUDE_CODE_SESSION_ID'] ?? ''\n if (raw.trim() === '') return null\n // Claude Code's Bash tool carries `CLAUDE_CODE_SESSION_ID` (read\n // 2026-10-06, 2.1.291); a session already named is kept as named.\n return raw.includes(' · ') ? raw : `claude · ${raw.slice(0, 8)}`\n}\n\n/** The text, its kind and the session, checked before anything is read. */\nfunction checked(input: NoteInput): { kind: Kind; session: string } {\n const length = input.text.trim().length\n if (length < 1 || length > MAX)\n throw new NoteRefused(\n `a note holds 1 to ${MAX.toLocaleString('en')} characters (this one ${length})`\n )\n if (SECRETS.some((s) => s.test(input.text)))\n throw new NoteRefused('the note looks like it holds a credential')\n const kind = KINDS.find((k) => k === (input.kind ?? 'approach'))\n if (kind === undefined)\n throw new NoteRefused(\n `--kind is one of ${KINDS.slice(0, -1).join(', ')} or ${KINDS.at(-1)}`\n )\n const session = sessionFrom(input.session, input.env ?? process.env)\n if (session === null)\n throw new NoteRefused(\n 'no session: write it from a Claude Code session, or pass --session'\n )\n return { kind, session }\n}\n\nexport type Journal = Extract<BoardAction, { action: 'journal' }>\n\n/** The board that keeps the journal: the first whose session start declares `journal`. */\nexport function journalOf(\n declared: readonly Declared[]\n): { board: Declared; journal: Journal } | null {\n for (const d of declared)\n for (const a of d.declaration.hooks['session-start'] ?? [])\n if (a.action === 'journal') return { board: d, journal: a }\n return null\n}\n\n/** `git@github.com:acme/api.git` or `https://github.com/acme/api` → `acme`, `api`; null on another host. */\nexport function githubRepo(\n url: string\n): { owner: string; name: string } | null {\n const m =\n /^(?:git@github\\.com:|ssh:\\/\\/git@github\\.com\\/|https:\\/\\/github\\.com\\/)([^/]+)\\/(.+?)(?:\\.git)?\\/?$/.exec(\n url.trim()\n )\n return m === null || m[1] === undefined || m[2] === undefined\n ? null\n : { owner: m[1], name: m[2] }\n}\n\n/** The plan the note is on (spec 0030 §2). */\nasync function planOf(\n c: Context,\n cwd: string,\n given?: string\n): Promise<string> {\n const tabs = await statusTabs(c.rnessDir)\n const plans = tabs.find((t) => t.name === 'plans')?.rows ?? []\n if (given !== undefined) {\n const path = given.replace(/^\\.rness\\//, '')\n if (!plans.some((r) => r.path === path))\n throw new NoteRefused(`${given} is no plan of .rness`)\n return path\n }\n const scope = resolveScope(\n c.manifest,\n relative(c.root, resolve(cwd)).split(sep).join('/')\n )\n const candidates = await plansInProgress(\n { root: c.root, rnessDir: c.rnessDir },\n c.manifest,\n scope\n )\n if (candidates.length === 0)\n throw new NoteRefused(\n `no plan in progress in scope ${scope ?? 'global'}: set one In progress first`\n )\n if (candidates.length > 1)\n throw new NoteRefused(\n `several plans in progress: pass --plan, one of ${candidates.join(', ')}`\n )\n return candidates[0] ?? ''\n}\n\n/** A plan's issue in `.rness`, found by its card's `Path` on the journal's board. */\nexport async function planIssue(\n c: Context,\n board: Declared,\n plan: string\n): Promise<JournalIssue> {\n const items = await fromGithub(\n c.provider.items(board.board, { bodies: false })\n )\n const number = items.find((i) => i.path === plan)?.issue?.number\n const found =\n number === undefined\n ? null\n : await fromGithub(c.provider.issueOf(c.org, '.rness', number))\n if (found === null)\n throw new NoteRefused(`${plan} has no issue yet: rness board push`)\n return {\n id: found.id,\n number: found.number,\n repository: `${c.org}/.rness`,\n }\n}\n\n/** A GitHub refusal to write (a token or organization policy, spec 0028). */\nconst refusedWrite = (e: unknown): boolean =>\n e instanceof Error &&\n /not accessible|forbidden|permission|must have push access/i.test(e.message)\n\n/** The implementation issue's body (spec 0030 §3.2): the plan, its issue, its specification. */\nasync function implementationBody(\n c: Context,\n plan: string,\n planNumber: number\n): Promise<string> {\n const lines = [\n `Plan [\\`${plan}\\`](${blobUrl(c.org, plan)}) · [plan issue](${issueUrl(c.org, planNumber)})`,\n ]\n try {\n const { readFile } = await import('node:fs/promises')\n const front =\n parseFrontMatter(\n await readFile(resolve(c.rnessDir, ...plan.split('/')), 'utf8')\n ) ?? {}\n const spec = /\\(\\.\\.\\/(specs\\/[^)\\s]+\\.md)\\)/.exec(\n String(front['spec'] ?? '')\n )\n if (spec?.[1] !== undefined)\n lines.push(`Specification [\\`${spec[1]}\\`](${blobUrl(c.org, spec[1])})`)\n } catch {\n // No specification named: the plan alone.\n }\n return `${lines.join('\\n')}\\n\\nThe agent's notes on this implementation follow as comments. The pull request that completes it carries \\`Closes\\` with this issue's reference.`\n}\n\n/** Posts a note; throws {@link NoteRefused} or GitHub's error, in one line. */\nexport async function postNote(input: NoteInput): Promise<Posted> {\n const { kind, session } = checked(input)\n const c = await context({\n cwd: input.cwd,\n ...(input.githubApi === undefined ? {} : { githubApi: input.githubApi }),\n })\n const declared = await declaredBoards(c)\n const kept = journalOf(declared)\n if (kept === null)\n throw new NoteRefused(\n 'no board keeps a journal: add { \"action\": \"journal\", \"to\": \"plan\" } to its session-start hooks'\n )\n const plan = await planOf(c, input.cwd, input.plan)\n if ((await notesPosted(c.rnessDir, session, plan)) >= kept.journal.limit)\n throw new NoteRefused(\n 'journal full for this session: put the rest in the pull request'\n )\n const parent = await planIssue(c, kept.board, plan)\n const clone = cloneHolding(c.root, c.manifest.repos, input.cwd)\n\n let target: JournalIssue = parent\n let why: string | null = null\n if (kept.journal.to === 'repo' && clone !== null) {\n const repo = githubRepo(clone.url)\n if (repo === null || repo.owner.toLowerCase() !== c.org.toLowerCase())\n why = `${clone.name} is not on the workspace's provider`\n else\n try {\n const there = await fromGithub(\n c.provider.journalIssue(repo.owner, repo.name, plan)\n )\n if (there !== null) target = there\n else {\n const row = (await statusTabs(c.rnessDir))\n .find((t) => t.name === 'plans')\n ?.rows.find((r) => r.path === plan)\n target = await fromGithub(\n c.provider.createJournalIssue(repo.owner, repo.name, plan, {\n title: `Implement ${row === undefined ? plan : `${row.id} - ${row.title}`}`,\n body: await implementationBody(c, plan, parent.number),\n })\n )\n try {\n await fromGithub(c.provider.addSubIssue(parent.id, target.id))\n } catch {\n // A link GitHub refuses: the issue named on the plan's instead (§3.3).\n await fromGithub(\n c.provider.comment(\n parent.id,\n `Implementation: ${target.repository}#${target.number}`\n )\n )\n }\n }\n } catch (e) {\n if (e instanceof JournalRefused)\n why =\n e.why === 'issues'\n ? `${repo.owner}/${repo.name} takes no issues`\n : `${repo.owner}/${repo.name} is not on GitHub, or this login cannot see it`\n else if (refusedWrite(e))\n why = `${repo.owner}/${repo.name} refuses this login's write`\n else throw e\n }\n }\n if (why !== null)\n await recordNotice(`journal: ${why}, notes go to the plan's issue`)\n\n const where = clone?.dir ?? input.cwd\n const [branch, head] = await Promise.all([branchOf(where), headOf(where)])\n const id = session.split(' · ').pop() ?? session\n const header = [\n `**${TITLE[kind]}**`,\n session,\n ...(branch === null || head === null\n ? []\n : [`\\`${branch}\\` @ \\`${head.slice(0, 7)}\\``]),\n ].join(' · ')\n const body = [\n ...(why === null\n ? []\n : [`_${why}: this note goes to the plan's issue._`, '']),\n header,\n '',\n input.text.trim(),\n '',\n `<!-- rness note ${id} -->`,\n ].join('\\n')\n await fromGithub(c.provider.comment(target.id, body))\n const reference = `${target.repository}#${target.number}`\n await notePosted(c.rnessDir, session, plan, { id: target.id, reference })\n return {\n reference,\n to: target === parent ? 'plan' : 'repo',\n }\n}\n\n/** `rness note`: the text from the argument, or stdin when it is absent or `-`. */\nexport async function noteCommand(opts: {\n text?: string\n kind?: string\n plan?: string\n session?: string\n cwd?: string\n githubApi?: string\n /** Internal (tests): what stdin holds. */\n stdin?: () => Promise<string>\n}): Promise<number> {\n try {\n const text =\n opts.text === undefined || opts.text === '-'\n ? await (opts.stdin ?? readStdin)()\n : opts.text\n const posted = await postNote({\n cwd: opts.cwd ?? process.cwd(),\n text,\n ...(opts.kind === undefined ? {} : { kind: opts.kind }),\n ...(opts.plan === undefined ? {} : { plan: opts.plan }),\n ...(opts.session === undefined ? {} : { session: opts.session }),\n ...(opts.githubApi === undefined ? {} : { githubApi: opts.githubApi }),\n })\n process.stdout.write(`${posted.reference}\\n`)\n return 0\n } catch (e) {\n process.stderr.write(\n `rness: ${e instanceof Error ? e.message : String(e)}\\n`\n )\n return 1\n }\n}\n\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = []\n for await (const chunk of process.stdin) chunks.push(Buffer.from(chunk))\n return Buffer.concat(chunks).toString('utf8')\n}\n"],"mappings":"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","names":[]}