@rness/cli 0.22.0 → 0.22.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -0
- package/dist/bin/rness.js +2 -2
- package/dist/{chunk-XCO5ZT2H.js → chunk-OUZQGG6V.js} +18 -16
- package/dist/chunk-OUZQGG6V.js.map +1 -0
- package/dist/{chunk-AEL2W76O.js → chunk-PW5RMU2G.js} +4 -4
- package/dist/chunk-PW5RMU2G.js.map +1 -0
- package/dist/{chunk-S4NARIQP.js → chunk-SX7D5W43.js} +48 -48
- package/dist/chunk-SX7D5W43.js.map +1 -0
- package/dist/index.js +2 -2
- package/dist/{note-XSJ7ASXM.js → note-MKUG7GOT.js} +3 -3
- package/dist/{summary-47SFWNSQ.js → summary-5DVUIOJM.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-MKUG7GOT.js.map} +0 -0
- /package/dist/{summary-47SFWNSQ.js.map → summary-5DVUIOJM.js.map} +0 -0
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
recordNotice,
|
|
16
16
|
resolveScope,
|
|
17
17
|
statusTabs
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-OUZQGG6V.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}
|
|
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
|
|
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-
|
|
263
|
+
//# sourceMappingURL=chunk-PW5RMU2G.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":[]}
|
|
@@ -102,7 +102,7 @@ import {
|
|
|
102
102
|
workspaceName,
|
|
103
103
|
writeFileAtomic,
|
|
104
104
|
writeManifest
|
|
105
|
-
} from "./chunk-
|
|
105
|
+
} from "./chunk-OUZQGG6V.js";
|
|
106
106
|
|
|
107
107
|
// src/core/transport.ts
|
|
108
108
|
import { spawn } from "child_process";
|
|
@@ -183,7 +183,7 @@ async function testGithubSsh(transport, interactive, announce) {
|
|
|
183
183
|
}
|
|
184
184
|
var loggedInAs = (login) => login === void 0 || login === null ? "" : `, logged in as ${login}`;
|
|
185
185
|
function usingSentence(access, login) {
|
|
186
|
-
return access.ok ? `SSH works for github.com (as ${access.login})
|
|
186
|
+
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
187
|
}
|
|
188
188
|
function isSshUrl(url, hosts) {
|
|
189
189
|
return url.startsWith(hosts.ssh);
|
|
@@ -192,7 +192,7 @@ var CHECKING_LINE = status("checking", "ssh access to github.com\u2026");
|
|
|
192
192
|
var CHECKING = [
|
|
193
193
|
"checking",
|
|
194
194
|
"ssh access to github.com\u2026",
|
|
195
|
-
"Checking SSH access to github.com
|
|
195
|
+
"Checking SSH access to github.com: ssh may ask for your passphrase"
|
|
196
196
|
];
|
|
197
197
|
function usingRest(access, login) {
|
|
198
198
|
return access.ok ? `ssh (github.com as ${access.login})` : `https (ssh to github.com unavailable: ${access.reason}${loggedInAs(login)})`;
|
|
@@ -288,7 +288,7 @@ function blockHash(body) {
|
|
|
288
288
|
function intro(scope, org, depth) {
|
|
289
289
|
if (scope === null) {
|
|
290
290
|
return [
|
|
291
|
-
`This is the root of rness workspace \`${org}\`. Full context lives in \`.rness
|
|
291
|
+
`This is the root of rness workspace \`${org}\`. Full context lives in \`.rness/\`:`,
|
|
292
292
|
"start at its `AGENTS.md`, then task-relevant `adr/`, `specs/`, `plans/`; live: `rness context`.",
|
|
293
293
|
"Every `org/<repo>/` carries its own block with the rules that apply there."
|
|
294
294
|
].join("\n");
|
|
@@ -296,7 +296,7 @@ function intro(scope, org, depth) {
|
|
|
296
296
|
const rel = `${"../".repeat(depth)}.rness/`;
|
|
297
297
|
return [
|
|
298
298
|
`This directory is scope \`${scope}\` of rness workspace \`${org}\`. Full context lives in`,
|
|
299
|
-
`\`${rel}
|
|
299
|
+
`\`${rel}\`: start at its \`AGENTS.md\`, then task-relevant \`adr/\`, \`specs/\`, \`plans/\`;`,
|
|
300
300
|
`live: \`rness context --scope ${scope}\`. If \`.rness/\` is not reachable, this is a`,
|
|
301
301
|
"standalone clone: the rules below are all you have."
|
|
302
302
|
].join("\n");
|
|
@@ -490,13 +490,13 @@ var allocateStep = (allocate, collection) => `Allocate the file: run \`${allocat
|
|
|
490
490
|
\`${collection}/NNNN-untitled.md\` with the next number, the front matter
|
|
491
491
|
and the opening sections, and prints the path. Rename it to
|
|
492
492
|
\`NNNN-<slug>.md\`, the slug a few lowercase words of the title joined by
|
|
493
|
-
hyphens, and write the title as \`# NNNN
|
|
493
|
+
hyphens, and write the title as \`# NNNN - <title>\`. Never choose the
|
|
494
494
|
number yourself.`;
|
|
495
495
|
var HOOK_LINE = (rness) => `The rness hook checks every edit under \`${rness}/\`: fix what it reports.`;
|
|
496
496
|
var LIFECYCLE = [
|
|
497
497
|
{
|
|
498
498
|
name: "adr",
|
|
499
|
-
description: "Record a decision of the rness workspace as an ADR in .rness/adr/
|
|
499
|
+
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
500
|
hint: "[create <subject> | open NNNN]",
|
|
501
501
|
tab: "adr",
|
|
502
502
|
body: (rness, allocate) => `You keep the decisions of this workspace: the ADRs in \`${rness}/adr/\`. The table
|
|
@@ -513,7 +513,7 @@ it; a bare reference is \`open\`; any other words are the subject of a
|
|
|
513
513
|
Creating:
|
|
514
514
|
|
|
515
515
|
1. If the developer did not ask for an ADR in so many words, propose one in
|
|
516
|
-
a single line
|
|
516
|
+
a single line - its title, and why the choice is hard to reverse - and
|
|
517
517
|
wait for a yes.
|
|
518
518
|
2. Read \`${rness}/CONVENTIONS.md\` and \`${rness}/adr/0000-template.md\`: they hold the
|
|
519
519
|
rules and the sections; this skill is only the procedure.
|
|
@@ -523,7 +523,7 @@ Creating:
|
|
|
523
523
|
4. ${allocateStep(allocate, "adr")}
|
|
524
524
|
5. Fill it: \`repo\` the repositories under \`org/\` it affects; the template's
|
|
525
525
|
sections, their guidance lines removed; an ADR it replaces named in
|
|
526
|
-
Context
|
|
526
|
+
Context - that one becomes \`Superseded\`, with \`superseded_by:\`, only once
|
|
527
527
|
the new ADR is \`Accepted\`. Add ${SESSION_LINE}.
|
|
528
528
|
6. ${HOOK_LINE(rness)}
|
|
529
529
|
|
|
@@ -541,7 +541,7 @@ ${COMMIT_RULE}
|
|
|
541
541
|
},
|
|
542
542
|
{
|
|
543
543
|
name: "spec",
|
|
544
|
-
description: "Write a specification of the rness workspace in .rness/specs/
|
|
544
|
+
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
545
|
hint: "[create <subject> | open NNNN]",
|
|
546
546
|
tab: "specs",
|
|
547
547
|
body: (rness, allocate) => `You keep the specifications of this workspace, in \`${rness}/specs/\`. The table
|
|
@@ -565,7 +565,7 @@ Creating:
|
|
|
565
565
|
what is in and out of scope, the ADRs it rests on: ask what the
|
|
566
566
|
conversation does not say, one question at a time.
|
|
567
567
|
4. ${allocateStep(allocate, "specs")}
|
|
568
|
-
5. Fill it: \`repo\`, and \`adr:\` linking the decisions it rests on
|
|
568
|
+
5. Fill it: \`repo\`, and \`adr:\` linking the decisions it rests on - or the
|
|
569
569
|
rationale in the body when none does; the sections it opened with
|
|
570
570
|
(Summary, Scope, Out of scope, Alternatives considered, To verify,
|
|
571
571
|
Tests), or the most recent specification's when the team's differ. What
|
|
@@ -574,8 +574,8 @@ Creating:
|
|
|
574
574
|
question. Add ${SESSION_LINE}.
|
|
575
575
|
6. ${HOOK_LINE(rness)}
|
|
576
576
|
|
|
577
|
-
Opening: read the specification and amend what the developer asks
|
|
578
|
-
section, a scope, an open question answered
|
|
577
|
+
Opening: read the specification and amend what the developer asks - a
|
|
578
|
+
section, a scope, an open question answered - \`updated\` today, the session
|
|
579
579
|
line added. A status moves only as the developer says, or by
|
|
580
580
|
\`/rness:plan from\`.
|
|
581
581
|
|
|
@@ -590,14 +590,14 @@ ${COMMIT_RULE}
|
|
|
590
590
|
},
|
|
591
591
|
{
|
|
592
592
|
name: "plan",
|
|
593
|
-
description: "The plans of the rness workspace in .rness/plans/
|
|
593
|
+
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
594
|
hint: "[create <subject> | from <spec> | open NNNN | check NNNN]",
|
|
595
595
|
tab: "plans",
|
|
596
596
|
body: (rness, allocate) => `You keep the plans of this workspace, in \`${rness}/plans/\`. The table above
|
|
597
597
|
lists the existing ones, newest first. Arguments: \`$ARGUMENTS\`.
|
|
598
598
|
|
|
599
599
|
The first word is the verb, when a reference (\`0037\`, or a path) follows
|
|
600
|
-
it
|
|
600
|
+
it - \`check\` alone means the plan \`In progress\`; a bare reference is
|
|
601
601
|
\`open\`; any other words are the subject of a \`create\`:
|
|
602
602
|
|
|
603
603
|
- \`from NNNN\`: a plan from specification NNNN, which this approves.
|
|
@@ -615,7 +615,7 @@ it \u2014 \`check\` alone means the plan \`In progress\`; a bare reference is
|
|
|
615
615
|
reopen it rather than write a second.
|
|
616
616
|
2. The developer typed this command: that is their approval, and the
|
|
617
617
|
specification moves from \`Draft\` or \`Proposed\` to \`Approved\`, \`updated\`
|
|
618
|
-
today, in the same commit as the plan
|
|
618
|
+
today, in the same commit as the plan - no confirmation question. If
|
|
619
619
|
you are proposing it yourself, propose it in a single line and wait for
|
|
620
620
|
a yes first: the approval is theirs, never yours.
|
|
621
621
|
3. Read the code and the repositories the specification touches: every
|
|
@@ -623,7 +623,7 @@ it \u2014 \`check\` alone means the plan \`In progress\`; a bare reference is
|
|
|
623
623
|
4. ${allocateStep(allocate, "plans")}
|
|
624
624
|
5. Fill it: \`spec:\` linking the specification; tasks in order, as
|
|
625
625
|
checkboxes, each with the files, what changes, and the command that
|
|
626
|
-
proves it (a test, a build, a run)
|
|
626
|
+
proves it (a test, a build, a run) - the last tasks the documentation
|
|
627
627
|
the work makes inaccurate, then the release when the repository has
|
|
628
628
|
one; where the plan decides something the specification leaves open, the
|
|
629
629
|
section it opened with says so. Add ${SESSION_LINE}.
|
|
@@ -634,7 +634,7 @@ for a plan in so many words, propose one in a single line and wait for a
|
|
|
634
634
|
yes. The body says what the work is and why it needs no specification.
|
|
635
635
|
|
|
636
636
|
\`open\`: read the plan and its specification; amend what the developer
|
|
637
|
-
asks
|
|
637
|
+
asks - a task added, split or reworded, a blocker recorded - \`updated\`
|
|
638
638
|
today, the session line added; move \`Draft\` to \`Ready\` or \`Blocked\` as they
|
|
639
639
|
say. A \`Completed\` or \`Abandoned\` plan is not reopened: offer a new plan of
|
|
640
640
|
the same specification.
|
|
@@ -652,7 +652,7 @@ the same specification.
|
|
|
652
652
|
check has no cache: run twice, it proves twice.
|
|
653
653
|
5. Every task proven:
|
|
654
654
|
- the plan: \`status: Completed\`, \`updated\` today, the checkboxes of the
|
|
655
|
-
proven tasks ticked, and a section \`Verification (YYYY-MM-DD)\`
|
|
655
|
+
proven tasks ticked, and a section \`Verification (YYYY-MM-DD)\` - what
|
|
656
656
|
ran, what it showed, what could not run and why;
|
|
657
657
|
- the specification: \`Implemented\` once every plan of it is
|
|
658
658
|
\`Completed\`; \`updated\` today;
|
|
@@ -1088,7 +1088,7 @@ async function driftWarning(cwd) {
|
|
|
1088
1088
|
if (drift === null) return null;
|
|
1089
1089
|
const pm = await workspacePackageManager(rnessDir);
|
|
1090
1090
|
return warn(
|
|
1091
|
-
`${basename(root)}/.rness pins @rness/cli ${drift.pin} but ${drift.installed ?? "nothing"} is installed
|
|
1091
|
+
`${basename(root)}/.rness pins @rness/cli ${drift.pin} but ${drift.installed ?? "nothing"} is installed: run ${pm} install in .rness`
|
|
1092
1092
|
);
|
|
1093
1093
|
}
|
|
1094
1094
|
var CHILD_DEADLINE_MS = 12e4;
|
|
@@ -1688,7 +1688,7 @@ async function syncCommand(opts, deps = {}) {
|
|
|
1688
1688
|
}
|
|
1689
1689
|
if (check && differences > 0)
|
|
1690
1690
|
problems.push(
|
|
1691
|
-
`${differences} block(s) out of date
|
|
1691
|
+
`${differences} block(s) out of date: run ${rnessCommand()} sync`
|
|
1692
1692
|
);
|
|
1693
1693
|
if (opts.scope === void 0) {
|
|
1694
1694
|
let stale = 0;
|
|
@@ -1704,7 +1704,7 @@ async function syncCommand(opts, deps = {}) {
|
|
|
1704
1704
|
}
|
|
1705
1705
|
if (stale > 0)
|
|
1706
1706
|
problems.push(
|
|
1707
|
-
`${stale} agent file(s) out of date
|
|
1707
|
+
`${stale} agent file(s) out of date: run ${rnessCommand()} sync`
|
|
1708
1708
|
);
|
|
1709
1709
|
if (!check)
|
|
1710
1710
|
for (const label of await leftoverTargets(ws.root, manifest))
|
|
@@ -1766,7 +1766,7 @@ async function addCommand(spec, opts, deps = {}) {
|
|
|
1766
1766
|
}
|
|
1767
1767
|
if (parsed.name === CONTEXT_REPO) {
|
|
1768
1768
|
process.stderr.write(
|
|
1769
|
-
`${CONTEXT_REPO} is the workspace context, not a member repository
|
|
1769
|
+
`${CONTEXT_REPO} is the workspace context, not a member repository: it is already cloned at ${basename2(ws.root)}/${CONTEXT_REPO}
|
|
1770
1770
|
`
|
|
1771
1771
|
);
|
|
1772
1772
|
return 2;
|
|
@@ -2413,7 +2413,7 @@ async function commitContext(input) {
|
|
|
2413
2413
|
ui.line("committed", `${shown}/.rness`);
|
|
2414
2414
|
} catch (e) {
|
|
2415
2415
|
ui.warn(
|
|
2416
|
-
`${e instanceof Error ? e.message : String(e)}
|
|
2416
|
+
`${e instanceof Error ? e.message : String(e)}: commit ${shown}/.rness yourself`
|
|
2417
2417
|
);
|
|
2418
2418
|
}
|
|
2419
2419
|
}
|
|
@@ -3024,14 +3024,14 @@ async function createCommand(opts, deps = {}) {
|
|
|
3024
3024
|
if (joining)
|
|
3025
3025
|
ui.line(
|
|
3026
3026
|
"found",
|
|
3027
|
-
`${org}/.rness
|
|
3028
|
-
`${org} has a workspace
|
|
3027
|
+
`${org}/.rness - joining`,
|
|
3028
|
+
`${org} has a workspace - joining it`
|
|
3029
3029
|
);
|
|
3030
3030
|
else
|
|
3031
3031
|
ui.line(
|
|
3032
3032
|
"not found",
|
|
3033
|
-
`${org}/.rness (or not visible to you)
|
|
3034
|
-
`${org} has no workspace yet (or none you can see)
|
|
3033
|
+
`${org}/.rness (or not visible to you) - starting a new workspace`,
|
|
3034
|
+
`${org} has no workspace yet (or none you can see) - starting one`
|
|
3035
3035
|
);
|
|
3036
3036
|
let catalogue = {
|
|
3037
3037
|
contract: 1,
|
|
@@ -3159,7 +3159,7 @@ async function createCommand(opts, deps = {}) {
|
|
|
3159
3159
|
else process.stdout.write(`
|
|
3160
3160
|
${next2.map((l) => ` ${l}`).join("\n")}
|
|
3161
3161
|
`);
|
|
3162
|
-
ui.outro(`You joined ${org}
|
|
3162
|
+
ui.outro(`You joined ${org}: your workspace is in ${shown}/`);
|
|
3163
3163
|
return failures2.length > 0 ? 1 : 0;
|
|
3164
3164
|
}
|
|
3165
3165
|
const built = await buildContext({
|
|
@@ -3461,7 +3461,7 @@ function finish(ui, cwd, rnessDir, label, target, ending) {
|
|
|
3461
3461
|
`git -C ${c.dir} add ${c.paths.join(" ")} && git -C ${c.dir} commit -m "${message3}"`
|
|
3462
3462
|
);
|
|
3463
3463
|
if (ending.commit !== "nothing")
|
|
3464
|
-
next.push("# teammates: git pull
|
|
3464
|
+
next.push("# teammates: git pull - the next rness command installs it");
|
|
3465
3465
|
if (ui.session) {
|
|
3466
3466
|
if (next.length > 0) ui.note("Next steps", next);
|
|
3467
3467
|
ui.outro(`${label} runs @rness/cli ${target}`);
|
|
@@ -3557,18 +3557,18 @@ async function upgradeCommand(version, opts, terminal = defaultTerminal, deps =
|
|
|
3557
3557
|
if (pin.spec === target && installed === target)
|
|
3558
3558
|
ui.line(
|
|
3559
3559
|
"scaffold",
|
|
3560
|
-
`@rness/cli ${target}
|
|
3560
|
+
`@rness/cli ${target}: merging it into ${label}`,
|
|
3561
3561
|
`Merging the @rness/cli ${target} scaffold into ${label}`
|
|
3562
3562
|
);
|
|
3563
3563
|
else if (pin.spec === target)
|
|
3564
3564
|
ui.line(
|
|
3565
3565
|
"install",
|
|
3566
|
-
`@rness/cli ${target} in ${label} (${pm})
|
|
3566
|
+
`@rness/cli ${target} in ${label} (${pm}): ${installed ?? "nothing"} is installed`
|
|
3567
3567
|
);
|
|
3568
3568
|
else {
|
|
3569
3569
|
ui.line(
|
|
3570
3570
|
"upgrade",
|
|
3571
|
-
`@rness/cli ${pin.spec} \u2192 ${target} in ${label} (${pm})${downgrading ? "
|
|
3571
|
+
`@rness/cli ${pin.spec} \u2192 ${target} in ${label} (${pm})${downgrading ? ", downgrading" : ""}`
|
|
3572
3572
|
);
|
|
3573
3573
|
ui.line("notes", NOTES, `Release notes: ${NOTES}`);
|
|
3574
3574
|
}
|
|
@@ -3597,7 +3597,7 @@ async function upgradeCommand(version, opts, terminal = defaultTerminal, deps =
|
|
|
3597
3597
|
ui.line(
|
|
3598
3598
|
"adopting",
|
|
3599
3599
|
`the @rness/cli ${target} scaffold (no scaffold commit in ${label} yet)`,
|
|
3600
|
-
`Adopting the @rness/cli ${target} scaffold
|
|
3600
|
+
`Adopting the @rness/cli ${target} scaffold: ${label} has no scaffold commit yet`
|
|
3601
3601
|
);
|
|
3602
3602
|
else
|
|
3603
3603
|
ui.line(
|
|
@@ -3685,12 +3685,12 @@ async function upgradeCommand(version, opts, terminal = defaultTerminal, deps =
|
|
|
3685
3685
|
if (committed.kind === "committed")
|
|
3686
3686
|
ui.line(
|
|
3687
3687
|
"committed",
|
|
3688
|
-
`${label}
|
|
3688
|
+
`${label}: ${message3}`,
|
|
3689
3689
|
`Committed ${label}: ${message3}`
|
|
3690
3690
|
);
|
|
3691
3691
|
if (committed.kind === "refused") {
|
|
3692
3692
|
ui.error(
|
|
3693
|
-
`the commit of ${label} was refused; everything is staged
|
|
3693
|
+
`the commit of ${label} was refused; everything is staged: deal with what git said, then commit`
|
|
3694
3694
|
);
|
|
3695
3695
|
for (const line3 of committed.output.split("\n"))
|
|
3696
3696
|
if (line3.trim() !== "") ui.hint(line3, "stderr");
|
|
@@ -3760,7 +3760,7 @@ async function checkBoards(rnessDir, manifest) {
|
|
|
3760
3760
|
await readmeDeclarations(rnessDir, collection).catch(() => ({}))
|
|
3761
3761
|
))
|
|
3762
3762
|
problems.push(
|
|
3763
|
-
`${collection}/README.md: "${k}" is declared in rness.json now
|
|
3763
|
+
`${collection}/README.md: "${k}" is declared in rness.json now: rness sync moves it`
|
|
3764
3764
|
);
|
|
3765
3765
|
}
|
|
3766
3766
|
for (const key of ["readme", "updates"]) {
|
|
@@ -3954,7 +3954,7 @@ async function docNewCommand(collection, opts) {
|
|
|
3954
3954
|
];
|
|
3955
3955
|
const sections = name === "adr" ? await adrSections(ws.rnessDir) : SECTIONS[name] ?? [];
|
|
3956
3956
|
const body = [
|
|
3957
|
-
`# ${number}
|
|
3957
|
+
`# ${number} - ${title}`,
|
|
3958
3958
|
// The rule under the title, as the ADR and specification templates draw it.
|
|
3959
3959
|
...name === "plans" ? [] : ["", "---"],
|
|
3960
3960
|
...sections.flatMap((s) => ["", `## ${s}`])
|
|
@@ -4037,7 +4037,7 @@ async function takeModNotice(env) {
|
|
|
4037
4037
|
);
|
|
4038
4038
|
} catch {
|
|
4039
4039
|
}
|
|
4040
|
-
return `rness: Claude Code ${version} shows no rness band, footer label or pane; ${MOD_FLOOR} or later does
|
|
4040
|
+
return `rness: Claude Code ${version} shows no rness band, footer label or pane; ${MOD_FLOOR} or later does: claude update`;
|
|
4041
4041
|
}
|
|
4042
4042
|
|
|
4043
4043
|
// src/core/edit-guard.ts
|
|
@@ -4145,13 +4145,13 @@ async function safetyNet(ws, manifest) {
|
|
|
4145
4145
|
const drift = await pinDrift(ws.rnessDir);
|
|
4146
4146
|
if (drift !== null)
|
|
4147
4147
|
notes.push(
|
|
4148
|
-
`.rness pins @rness/cli ${drift.pin} but ${drift.installed ?? "nothing"} is installed
|
|
4148
|
+
`.rness pins @rness/cli ${drift.pin} but ${drift.installed ?? "nothing"} is installed: run ${await workspacePackageManager(ws.rnessDir)} install in .rness`
|
|
4149
4149
|
);
|
|
4150
4150
|
try {
|
|
4151
4151
|
const { problems } = await checkWorkspace(ws, manifest);
|
|
4152
4152
|
if (problems.length > 0)
|
|
4153
4153
|
notes.push(
|
|
4154
|
-
`${count(problems.length, ["problem", "problems"])} in the workspace context
|
|
4154
|
+
`${count(problems.length, ["problem", "problems"])} in the workspace context: run rness validate`,
|
|
4155
4155
|
...problems.slice(0, SHOWN_PROBLEMS).map((p) => ` ${p}`)
|
|
4156
4156
|
);
|
|
4157
4157
|
} catch (e) {
|
|
@@ -4211,7 +4211,7 @@ async function documents(rnessDir, only) {
|
|
|
4211
4211
|
}
|
|
4212
4212
|
function line(d, withScope = false) {
|
|
4213
4213
|
const head = [d.id, d.status].filter((x) => x !== null).join(" ");
|
|
4214
|
-
return `- ${head === "" ? "" : `${head}
|
|
4214
|
+
return `- ${head === "" ? "" : `${head} - `}${d.title}${withScope ? ` \xB7 ${d.scope ?? "global"}` : ""} \xB7 ${d.path}`;
|
|
4215
4215
|
}
|
|
4216
4216
|
function isCollection(value) {
|
|
4217
4217
|
return COLLECTIONS.includes(value);
|
|
@@ -4353,7 +4353,7 @@ function mcpTools(cwd) {
|
|
|
4353
4353
|
{
|
|
4354
4354
|
name: "rness_context",
|
|
4355
4355
|
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
|
|
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: ids, statuses, titles and paths, no bodies. Start here, then read a document with rness_read.",
|
|
4357
4357
|
inputSchema: {
|
|
4358
4358
|
type: "object",
|
|
4359
4359
|
properties: {
|
|
@@ -4449,7 +4449,7 @@ function noteTool(cwd, githubApi) {
|
|
|
4449
4449
|
additionalProperties: false
|
|
4450
4450
|
},
|
|
4451
4451
|
call: (args) => guard(async () => {
|
|
4452
|
-
const { postNote } = await import("./note-
|
|
4452
|
+
const { postNote } = await import("./note-MKUG7GOT.js");
|
|
4453
4453
|
const given = (key) => {
|
|
4454
4454
|
const value = args[key];
|
|
4455
4455
|
return typeof value === "string" ? value : void 0;
|
|
@@ -4498,7 +4498,7 @@ async function scopeBanner(ws, manifest, scope) {
|
|
|
4498
4498
|
const n = summary.counts[c];
|
|
4499
4499
|
return n === void 0 ? [] : [count(n, NOUNS[c])];
|
|
4500
4500
|
});
|
|
4501
|
-
const banner2 = `rness ${VERSION} \xB7 ${workspaceName(manifest, ws.root)} \xB7 ${scope === null ? "global scope" : `scope ${scope}`} \
|
|
4501
|
+
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
4502
|
return { banner: banner2, lines: summary.lines };
|
|
4503
4503
|
}
|
|
4504
4504
|
var noteLines = (notes) => notes.map((n) => `rness: ${n}`);
|
|
@@ -4682,7 +4682,7 @@ async function sessionStart(input, io) {
|
|
|
4682
4682
|
notes = [message2(e)];
|
|
4683
4683
|
}
|
|
4684
4684
|
const failure = await takeFailure();
|
|
4685
|
-
if (failure !== null) notes.push(`board not updated
|
|
4685
|
+
if (failure !== null) notes.push(`board not updated: ${failure}`);
|
|
4686
4686
|
notes.push(...await takeNotices());
|
|
4687
4687
|
const warnings = noteLines(notes);
|
|
4688
4688
|
const compact = input["source"] === "compact";
|
|
@@ -5309,7 +5309,7 @@ function noteCommandOf(parent, state, former) {
|
|
|
5309
5309
|
).addOption(new Option("--github-api <base>").hideHelp()).addOption(new Option("--cwd <dir>").hideHelp()).action(
|
|
5310
5310
|
async (text, opts) => {
|
|
5311
5311
|
if (former !== void 0) formerly(former, "rness note");
|
|
5312
|
-
const { noteCommand } = await import("./note-
|
|
5312
|
+
const { noteCommand } = await import("./note-MKUG7GOT.js");
|
|
5313
5313
|
state.code = await noteCommand({
|
|
5314
5314
|
...opts,
|
|
5315
5315
|
...text === void 0 ? {} : { text }
|
|
@@ -5596,4 +5596,4 @@ export {
|
|
|
5596
5596
|
OWN_COMMANDS,
|
|
5597
5597
|
catchUp
|
|
5598
5598
|
};
|
|
5599
|
-
//# sourceMappingURL=chunk-
|
|
5599
|
+
//# sourceMappingURL=chunk-SX7D5W43.js.map
|