@rness/cli 0.2.0 → 0.4.0

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.
@@ -1,402 +0,0 @@
1
- // src/version.ts
2
- var VERSION = "0.2.0";
3
-
4
- // src/core/workspace.ts
5
- import { access } from "fs/promises";
6
- import { dirname, join, parse, resolve } from "path";
7
- async function exists(p) {
8
- try {
9
- await access(p);
10
- return true;
11
- } catch {
12
- return false;
13
- }
14
- }
15
- async function findWorkspace(startDir) {
16
- let dir = resolve(startDir);
17
- const { root: fsRoot } = parse(dir);
18
- while (true) {
19
- if (await exists(join(dir, ".rness", "rness.json"))) {
20
- return { root: dir, rnessDir: join(dir, ".rness") };
21
- }
22
- if (dir === fsRoot) break;
23
- dir = dirname(dir);
24
- }
25
- throw new Error(`no rness workspace found above ${startDir}`);
26
- }
27
-
28
- // src/core/manifest.ts
29
- import { readFile } from "fs/promises";
30
- import { join as join2 } from "path";
31
- var NAME = /^[a-z0-9][a-z0-9-]*$/;
32
- function fail(message) {
33
- throw new Error(`rness.json: ${message}`);
34
- }
35
- function isRecord(value) {
36
- return value !== null && typeof value === "object" && !Array.isArray(value);
37
- }
38
- function checkPath(scope, path) {
39
- if (typeof path !== "string" || path === "") fail(`scope "${scope}" needs a string "path"`);
40
- if (path.startsWith("/")) fail(`scope "${scope}" path must be relative`);
41
- if (path.split("/").includes("..")) fail(`scope "${scope}" path must not contain ".."`);
42
- return path;
43
- }
44
- function readRepos(value) {
45
- const raw = value ?? {};
46
- if (!isRecord(raw)) fail('"repos" must be an object');
47
- const repos = {};
48
- for (const [name, entry] of Object.entries(raw)) {
49
- if (!NAME.test(name)) fail(`repo name "${name}" is not [a-z0-9-]`);
50
- if (!isRecord(entry) || typeof entry.url !== "string") fail(`repo "${name}" needs a string "url"`);
51
- repos[name] = { url: entry.url };
52
- }
53
- return repos;
54
- }
55
- function readScopes(value) {
56
- const raw = value ?? {};
57
- if (!isRecord(raw)) fail('"scopes" must be an object');
58
- const scopes = {};
59
- for (const [name, entry] of Object.entries(raw)) {
60
- if (!NAME.test(name)) fail(`scope name "${name}" is not [a-z0-9-]`);
61
- if (!isRecord(entry)) fail(`scope "${name}" must be an object`);
62
- const path = checkPath(name, entry.path);
63
- const ext = entry.extends ?? [];
64
- if (!Array.isArray(ext) || !ext.every((t) => typeof t === "string")) {
65
- fail(`scope "${name}" extends must be an array of scope names`);
66
- }
67
- scopes[name] = { path, extends: ext };
68
- }
69
- for (const [name, entry] of Object.entries(scopes)) {
70
- for (const target of entry.extends) {
71
- if (!Object.hasOwn(scopes, target)) fail(`scope "${name}" extends unknown scope "${target}"`);
72
- }
73
- }
74
- return scopes;
75
- }
76
- async function loadManifest(rnessDir) {
77
- let raw;
78
- try {
79
- raw = await readFile(join2(rnessDir, "rness.json"), "utf8");
80
- } catch {
81
- fail("not found");
82
- }
83
- let data;
84
- try {
85
- data = JSON.parse(raw);
86
- } catch (e) {
87
- fail(`invalid JSON (${e instanceof Error ? e.message : String(e)})`);
88
- }
89
- if (!isRecord(data)) fail("must be a JSON object");
90
- if (data.contract !== 1) fail(`unsupported contract: ${JSON.stringify(data.contract)} (expected 1)`);
91
- return { contract: 1, repos: readRepos(data.repos), scopes: readScopes(data.scopes) };
92
- }
93
-
94
- // src/core/scope.ts
95
- function isPrefix(prefix, target) {
96
- return prefix === target || target.startsWith(`${prefix}/`);
97
- }
98
- function resolveScope(manifest, relDir) {
99
- let best = null;
100
- let bestLen = -1;
101
- for (const [name, entry] of Object.entries(manifest.scopes)) {
102
- if (isPrefix(entry.path, relDir) && entry.path.length > bestLen) {
103
- best = name;
104
- bestLen = entry.path.length;
105
- }
106
- }
107
- return best;
108
- }
109
- function scopeChain(manifest, scope) {
110
- if (scope === null) return [];
111
- const chain = [];
112
- const seen = /* @__PURE__ */ new Set();
113
- const visit = (name, stack) => {
114
- if (stack.has(name)) throw new Error(`extends cycle at scope "${name}"`);
115
- if (seen.has(name)) return;
116
- seen.add(name);
117
- chain.push(name);
118
- stack.add(name);
119
- const entry = Object.hasOwn(manifest.scopes, name) ? manifest.scopes[name] : void 0;
120
- for (const target of entry?.extends ?? []) visit(target, stack);
121
- stack.delete(name);
122
- };
123
- visit(scope, /* @__PURE__ */ new Set());
124
- return chain;
125
- }
126
-
127
- // src/core/frontmatter.ts
128
- import { parse as parse2 } from "yaml";
129
- var FRONT_MATTER = /^---\r?\n(?:([\s\S]*?)\r?\n)?---(?:\r?\n|$)/;
130
- function fail2(message) {
131
- throw new Error(`front matter: ${message}`);
132
- }
133
- function stripBom(source) {
134
- return source.startsWith("\uFEFF") ? source.slice(1) : source;
135
- }
136
- function parseFrontMatter(source) {
137
- const match = stripBom(source).match(FRONT_MATTER);
138
- if (match === null) return null;
139
- const block = match[1] ?? "";
140
- if (block.trim() === "") return {};
141
- let doc;
142
- try {
143
- doc = parse2(block, { logLevel: "error" });
144
- } catch (e) {
145
- fail2(e instanceof Error ? (e.message.split("\n")[0] ?? "invalid YAML").replace(/:$/, "") : "invalid YAML");
146
- }
147
- if (doc === null || doc === void 0) return {};
148
- if (typeof doc !== "object" || Array.isArray(doc)) fail2("block must be a mapping of keys to values");
149
- return doc;
150
- }
151
- function extractTitle(source) {
152
- return stripBom(source).match(/^# (.+)$/m)?.[1]?.trim() ?? null;
153
- }
154
-
155
- // src/core/collect.ts
156
- import { glob, readFile as readFile2 } from "fs/promises";
157
- import { join as join3, posix, sep } from "path";
158
- function toPosix(rel) {
159
- return rel.split(sep).join(posix.sep);
160
- }
161
- async function collectMarkdown(dir) {
162
- const rels = [];
163
- for await (const rel of glob("**/*.md", { cwd: dir })) rels.push(toPosix(rel));
164
- const items = await Promise.all(
165
- rels.map(async (rel) => {
166
- const path = join3(dir, ...rel.split(posix.sep));
167
- const body = await readFile2(path, "utf8");
168
- let fields = null;
169
- let fieldsError = null;
170
- try {
171
- fields = parseFrontMatter(body);
172
- } catch (e) {
173
- fieldsError = e instanceof Error ? e.message : String(e);
174
- }
175
- return { path, rel, fields, fieldsError, title: extractTitle(body), body };
176
- })
177
- );
178
- return items.sort((a, b) => a.rel < b.rel ? -1 : a.rel > b.rel ? 1 : 0);
179
- }
180
-
181
- // src/core/context.ts
182
- import { join as join4 } from "path";
183
- var COLLECTIONS = ["standards", "adr", "specs", "plans", "skills"];
184
- function frontMatterScopes(fields) {
185
- const value = fields?.scopes;
186
- if (typeof value === "string") return value.split(/[,\s]+/).filter(Boolean);
187
- if (Array.isArray(value)) return value.filter((s) => typeof s === "string");
188
- return [];
189
- }
190
- function ownerScope(rel) {
191
- const slash = rel.indexOf("/");
192
- return slash === -1 ? null : rel.slice(0, slash);
193
- }
194
- async function assembleCollection(dir, name, chain) {
195
- const items = await collectMarkdown(dir);
196
- const chainSet = new Set(chain);
197
- const groups = new Map(chain.map((s) => [s, []]));
198
- const rootFiles = [];
199
- for (const item of items) {
200
- const owner = ownerScope(item.rel);
201
- if (owner === null) {
202
- rootFiles.push({ ...item, scope: null });
203
- continue;
204
- }
205
- if (item.fields?.scope === "global") continue;
206
- if (chainSet.has(owner)) {
207
- groups.get(owner)?.push({ ...item, scope: owner });
208
- continue;
209
- }
210
- const via = frontMatterScopes(item.fields).find((s) => chainSet.has(s));
211
- if (via !== void 0) groups.get(via)?.push({ ...item, scope: via });
212
- }
213
- const files = [];
214
- const seen = /* @__PURE__ */ new Set();
215
- const push = (f) => {
216
- if (seen.has(f.path)) return;
217
- seen.add(f.path);
218
- files.push({ rel: f.rel, scope: f.scope, title: f.title, body: f.body });
219
- };
220
- for (const s of chain) for (const f of groups.get(s) ?? []) push(f);
221
- for (const f of rootFiles) push(f);
222
- return { name, files };
223
- }
224
- async function assembleContext({ rnessDir, manifest, scope }) {
225
- const chain = scopeChain(manifest, scope);
226
- const collections = await Promise.all(
227
- COLLECTIONS.map((name) => assembleCollection(join4(rnessDir, name), name, chain))
228
- );
229
- return { scope, collections };
230
- }
231
-
232
- // src/report.ts
233
- function reportError(e) {
234
- const debug = process.env["RNESS_DEBUG"] === "1";
235
- if (debug && e instanceof Error && e.stack) {
236
- process.stderr.write(`${e.stack}
237
- `);
238
- } else {
239
- const message = e instanceof Error ? e.message : String(e);
240
- process.stderr.write(`${message}
241
- `);
242
- }
243
- return 1;
244
- }
245
-
246
- // src/commands/context.ts
247
- import { posix as posix2, relative, sep as sep2 } from "path";
248
- function renderMarkdown(ctx) {
249
- const parts = [];
250
- for (const collection of ctx.collections) {
251
- if (collection.files.length === 0) continue;
252
- parts.push(`## ${collection.name}
253
- `);
254
- for (const file of collection.files) {
255
- parts.push(`<!-- rness: ${collection.name}/${file.rel} -->
256
- ${file.body.trim()}
257
- `);
258
- }
259
- }
260
- return `${parts.join("\n")}
261
- `;
262
- }
263
- async function contextCommand(opts) {
264
- const cwd = opts.cwd ?? process.cwd();
265
- try {
266
- const ws = await findWorkspace(cwd);
267
- const manifest = await loadManifest(ws.rnessDir);
268
- let scope;
269
- if (opts.scope !== void 0) {
270
- if (!Object.hasOwn(manifest.scopes, opts.scope)) {
271
- process.stderr.write(`unknown scope: ${opts.scope}
272
- `);
273
- return 1;
274
- }
275
- scope = opts.scope;
276
- } else {
277
- const rel = relative(ws.root, cwd).split(sep2).join(posix2.sep);
278
- scope = resolveScope(manifest, rel);
279
- }
280
- const ctx = await assembleContext({ rnessDir: ws.rnessDir, manifest, scope });
281
- process.stdout.write(opts.json ? `${JSON.stringify(ctx, null, 2)}
282
- ` : renderMarkdown(ctx));
283
- return 0;
284
- } catch (e) {
285
- return reportError(e);
286
- }
287
- }
288
-
289
- // src/core/contract.ts
290
- import { join as join5 } from "path";
291
- var STATUSES = {
292
- adr: ["Proposed", "Accepted", "Rejected", "Superseded"],
293
- specs: ["Draft", "Proposed", "Approved", "Implemented", "Superseded", "Rejected"],
294
- plans: ["Draft", "Ready", "In progress", "Blocked", "Completed", "Abandoned"]
295
- };
296
- var SKIP = /* @__PURE__ */ new Set(["0000-template.md"]);
297
- async function checkContract(rnessDir) {
298
- const problems = [];
299
- for (const [name, allowed] of Object.entries(STATUSES)) {
300
- const items = await collectMarkdown(join5(rnessDir, name));
301
- for (const item of items) {
302
- if (SKIP.has(item.rel)) continue;
303
- const where = `${name}/${item.rel}`;
304
- if (item.fieldsError !== null) {
305
- problems.push(`${where}: invalid front matter (${item.fieldsError})`);
306
- continue;
307
- }
308
- if (item.fields === null) {
309
- problems.push(`${where}: missing a front-matter block`);
310
- continue;
311
- }
312
- if (item.title === null) problems.push(`${where}: missing a "# " title`);
313
- const status = item.fields.status;
314
- if (status === void 0 || status === null || status === "") {
315
- problems.push(`${where}: missing "status"`);
316
- } else if (typeof status !== "string" || !allowed.includes(status)) {
317
- problems.push(`${where}: unknown status ${JSON.stringify(status)} (expected ${allowed.join(", ")})`);
318
- }
319
- }
320
- }
321
- return problems;
322
- }
323
-
324
- // src/commands/validate.ts
325
- async function validateCommand(opts) {
326
- const cwd = opts.cwd ?? process.cwd();
327
- try {
328
- const ws = await findWorkspace(cwd);
329
- const rnessDir = ws.rnessDir;
330
- const manifest = await loadManifest(rnessDir);
331
- for (const s of Object.keys(manifest.scopes)) scopeChain(manifest, s);
332
- const problems = await checkContract(rnessDir);
333
- if (problems.length > 0) {
334
- for (const p of problems) process.stderr.write(`${p}
335
- `);
336
- return 1;
337
- }
338
- process.stdout.write("context ok\n");
339
- return 0;
340
- } catch (e) {
341
- return reportError(e);
342
- }
343
- }
344
-
345
- // src/cli.ts
346
- import { Command, CommanderError, Option } from "commander";
347
- function buildProgram(state) {
348
- const program = new Command().name("rness").description("Configuration-plane CLI for rness workspaces").version(VERSION, "-v, --version", "print the version").exitOverride().showHelpAfterError().configureOutput({
349
- writeOut: (s) => {
350
- process.stdout.write(s);
351
- },
352
- writeErr: (s) => {
353
- process.stderr.write(s);
354
- }
355
- });
356
- program.command("context").description("Resolve and print the context for a scope").option("--scope <name>", "scope to resolve (default: the scope owning the current directory)").option("--json", "print JSON instead of Markdown").addOption(new Option("--cwd <dir>").hideHelp()).action(async (opts) => {
357
- state.code = await contextCommand(opts);
358
- });
359
- program.command("validate").description("Check the .rness/ tree against the contract").addOption(new Option("--cwd <dir>").hideHelp()).action(async (opts) => {
360
- state.code = await validateCommand(opts);
361
- });
362
- return program;
363
- }
364
- async function run(argv) {
365
- const state = { code: 0 };
366
- const program = buildProgram(state);
367
- if (argv.length === 0) {
368
- process.stdout.write(program.helpInformation());
369
- return 0;
370
- }
371
- try {
372
- await program.parseAsync(argv, { from: "user" });
373
- } catch (e) {
374
- if (e instanceof CommanderError) {
375
- return e.exitCode === 0 ? 0 : 2;
376
- }
377
- throw e;
378
- }
379
- return state.code;
380
- }
381
-
382
- export {
383
- VERSION,
384
- findWorkspace,
385
- NAME,
386
- loadManifest,
387
- resolveScope,
388
- scopeChain,
389
- parseFrontMatter,
390
- extractTitle,
391
- collectMarkdown,
392
- COLLECTIONS,
393
- assembleContext,
394
- reportError,
395
- renderMarkdown,
396
- contextCommand,
397
- STATUSES,
398
- checkContract,
399
- validateCommand,
400
- run
401
- };
402
- //# sourceMappingURL=chunk-6ASX7VBO.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/version.ts","../src/core/workspace.ts","../src/core/manifest.ts","../src/core/scope.ts","../src/core/frontmatter.ts","../src/core/collect.ts","../src/core/context.ts","../src/report.ts","../src/commands/context.ts","../src/core/contract.ts","../src/commands/validate.ts","../src/cli.ts"],"sourcesContent":["// Single source of the package version. test/version.test.ts keeps it equal\n// to package.json; bump both together.\nexport const VERSION = '0.2.0'\n","import { access } from 'node:fs/promises'\nimport { dirname, join, parse, resolve } from 'node:path'\nimport type { Workspace } from './types.ts'\n\nasync function exists(p: string): Promise<boolean> {\n try {\n await access(p)\n return true\n } catch {\n return false\n }\n}\n\n/** Walk up from `startDir`; the first directory holding `.rness/rness.json` is the root. */\nexport async function findWorkspace(startDir: string): Promise<Workspace> {\n let dir = resolve(startDir)\n const { root: fsRoot } = parse(dir)\n while (true) {\n if (await exists(join(dir, '.rness', 'rness.json'))) {\n return { root: dir, rnessDir: join(dir, '.rness') }\n }\n if (dir === fsRoot) break\n dir = dirname(dir)\n }\n throw new Error(`no rness workspace found above ${startDir}`)\n}\n","import { readFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type { Manifest, RepoEntry, ScopeEntry } from './types.ts'\n\nexport const NAME = /^[a-z0-9][a-z0-9-]*$/\n\nfunction fail(message: string): never {\n throw new Error(`rness.json: ${message}`)\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction checkPath(scope: string, path: unknown): string {\n if (typeof path !== 'string' || path === '') fail(`scope \"${scope}\" needs a string \"path\"`)\n if (path.startsWith('/')) fail(`scope \"${scope}\" path must be relative`)\n if (path.split('/').includes('..')) fail(`scope \"${scope}\" path must not contain \"..\"`)\n return path\n}\n\nfunction readRepos(value: unknown): Record<string, RepoEntry> {\n const raw = value ?? {}\n if (!isRecord(raw)) fail('\"repos\" must be an object')\n const repos: Record<string, RepoEntry> = {}\n for (const [name, entry] of Object.entries(raw)) {\n if (!NAME.test(name)) fail(`repo name \"${name}\" is not [a-z0-9-]`)\n if (!isRecord(entry) || typeof entry.url !== 'string') fail(`repo \"${name}\" needs a string \"url\"`)\n repos[name] = { url: entry.url }\n }\n return repos\n}\n\nfunction readScopes(value: unknown): Record<string, ScopeEntry> {\n const raw = value ?? {}\n if (!isRecord(raw)) fail('\"scopes\" must be an object')\n const scopes: Record<string, ScopeEntry> = {}\n for (const [name, entry] of Object.entries(raw)) {\n if (!NAME.test(name)) fail(`scope name \"${name}\" is not [a-z0-9-]`)\n if (!isRecord(entry)) fail(`scope \"${name}\" must be an object`)\n const path = checkPath(name, entry.path)\n const ext = entry.extends ?? []\n if (!Array.isArray(ext) || !ext.every((t) => typeof t === 'string')) {\n fail(`scope \"${name}\" extends must be an array of scope names`)\n }\n scopes[name] = { path, extends: ext as string[] }\n }\n for (const [name, entry] of Object.entries(scopes)) {\n for (const target of entry.extends) {\n if (!Object.hasOwn(scopes, target)) fail(`scope \"${name}\" extends unknown scope \"${target}\"`)\n }\n }\n return scopes\n}\n\n/** Read and validate `<rnessDir>/rness.json`. Every error starts with `rness.json:`. */\nexport async function loadManifest(rnessDir: string): Promise<Manifest> {\n let raw: string\n try {\n raw = await readFile(join(rnessDir, 'rness.json'), 'utf8')\n } catch {\n fail('not found')\n }\n let data: unknown\n try {\n data = JSON.parse(raw)\n } catch (e) {\n fail(`invalid JSON (${e instanceof Error ? e.message : String(e)})`)\n }\n if (!isRecord(data)) fail('must be a JSON object')\n if (data.contract !== 1) fail(`unsupported contract: ${JSON.stringify(data.contract)} (expected 1)`)\n return { contract: 1, repos: readRepos(data.repos), scopes: readScopes(data.scopes) }\n}\n","import type { Manifest } from './types.ts'\n\nfunction isPrefix(prefix: string, target: string): boolean {\n return prefix === target || target.startsWith(`${prefix}/`)\n}\n\n/** The scope whose `path` is the longest path-segment prefix of `relDir`; null = global. */\nexport function resolveScope(manifest: Manifest, relDir: string): string | null {\n let best: string | null = null\n let bestLen = -1\n for (const [name, entry] of Object.entries(manifest.scopes)) {\n if (isPrefix(entry.path, relDir) && entry.path.length > bestLen) {\n best = name\n bestLen = entry.path.length\n }\n }\n return best\n}\n\n/** `scope` then its transitive `extends`, nearest first, de-duplicated. Throws on a cycle. */\nexport function scopeChain(manifest: Manifest, scope: string | null): string[] {\n if (scope === null) return []\n const chain: string[] = []\n const seen = new Set<string>()\n const visit = (name: string, stack: Set<string>): void => {\n if (stack.has(name)) throw new Error(`extends cycle at scope \"${name}\"`)\n if (seen.has(name)) return\n seen.add(name)\n chain.push(name)\n stack.add(name)\n const entry = Object.hasOwn(manifest.scopes, name) ? manifest.scopes[name] : undefined\n for (const target of entry?.extends ?? []) visit(target, stack)\n stack.delete(name)\n }\n visit(scope, new Set())\n return chain\n}\n","import { parse } from 'yaml'\nimport type { Fields } from './types.ts'\n\n// The inner group is optional so that `---\\n---\\n` (an empty block with no line\n// between the fences) is still recognised as front matter.\nconst FRONT_MATTER = /^---\\r?\\n(?:([\\s\\S]*?)\\r?\\n)?---(?:\\r?\\n|$)/\n\nfunction fail(message: string): never {\n throw new Error(`front matter: ${message}`)\n}\n\n/** Strip a leading UTF-8 BOM so `---` is still recognised as the first thing in the file. */\nfunction stripBom(source: string): string {\n return source.startsWith('') ? source.slice(1) : source\n}\n\n/**\n * Parse the leading `---` block as YAML (1.2 core schema: `2026-09-07` stays a\n * string, `1` becomes a number). Returns null when there is no block, `{}`\n * for an empty block, and throws a `front matter:`-prefixed error when the\n * YAML is invalid or is not a mapping.\n */\nexport function parseFrontMatter(source: string): Fields | null {\n const match = stripBom(source).match(FRONT_MATTER)\n if (match === null) return null\n const block = match[1] ?? ''\n if (block.trim() === '') return {}\n let doc: unknown\n try {\n // 'error': suppress the printed YAMLWarning (e.g. an unresolved `!!tag`)\n // without silencing real parse errors — `logLevel: 'silent'` would do that too.\n doc = parse(block, { logLevel: 'error' })\n } catch (e) {\n fail(e instanceof Error ? (e.message.split('\\n')[0] ?? 'invalid YAML').replace(/:$/, '') : 'invalid YAML')\n }\n if (doc === null || doc === undefined) return {}\n if (typeof doc !== 'object' || Array.isArray(doc)) fail('block must be a mapping of keys to values')\n return doc as Fields\n}\n\nexport function extractTitle(source: string): string | null {\n return stripBom(source).match(/^# (.+)$/m)?.[1]?.trim() ?? null\n}\n","import { glob, readFile } from 'node:fs/promises'\nimport { join, posix, sep } from 'node:path'\nimport { parseFrontMatter, extractTitle } from './frontmatter.ts'\nimport type { MarkdownItem } from './types.ts'\n\nfunction toPosix(rel: string): string {\n return rel.split(sep).join(posix.sep)\n}\n\n/**\n * Every `*.md` under `dir`, recursively, sorted by `rel`. A missing directory\n * yields []. A file whose front matter fails to parse is kept with\n * `fields: null` and the error in `fieldsError`, so one broken file cannot\n * hide a whole collection.\n */\nexport async function collectMarkdown(dir: string): Promise<MarkdownItem[]> {\n const rels: string[] = []\n for await (const rel of glob('**/*.md', { cwd: dir })) rels.push(toPosix(rel))\n const items = await Promise.all(\n rels.map(async (rel): Promise<MarkdownItem> => {\n const path = join(dir, ...rel.split(posix.sep))\n const body = await readFile(path, 'utf8')\n let fields: MarkdownItem['fields'] = null\n let fieldsError: string | null = null\n try {\n fields = parseFrontMatter(body)\n } catch (e) {\n fieldsError = e instanceof Error ? e.message : String(e)\n }\n return { path, rel, fields, fieldsError, title: extractTitle(body), body }\n }),\n )\n return items.sort((a, b) => (a.rel < b.rel ? -1 : a.rel > b.rel ? 1 : 0))\n}\n","import { join } from 'node:path'\nimport { collectMarkdown } from './collect.ts'\nimport { scopeChain } from './scope.ts'\nimport type { CollectionName, Context, ContextCollection, ContextFile, Fields, Manifest, MarkdownItem } from './types.ts'\n\nexport const COLLECTIONS: readonly CollectionName[] = ['standards', 'adr', 'specs', 'plans', 'skills']\n\n/** Front-matter `scopes`: a comma/space separated string or a YAML list. */\nfunction frontMatterScopes(fields: Fields | null): string[] {\n const value = fields?.scopes\n if (typeof value === 'string') return value.split(/[,\\s]+/).filter(Boolean)\n if (Array.isArray(value)) return value.filter((s): s is string => typeof s === 'string')\n return []\n}\n\nfunction ownerScope(rel: string): string | null {\n const slash = rel.indexOf('/')\n return slash === -1 ? null : rel.slice(0, slash)\n}\n\ntype Owned = MarkdownItem & { scope: string | null }\n\nasync function assembleCollection(dir: string, name: CollectionName, chain: string[]): Promise<ContextCollection> {\n const items = await collectMarkdown(dir)\n const chainSet = new Set(chain)\n const groups = new Map<string, Owned[]>(chain.map((s) => [s, []]))\n const rootFiles: Owned[] = []\n\n for (const item of items) {\n const owner = ownerScope(item.rel)\n if (owner === null) {\n rootFiles.push({ ...item, scope: null })\n continue\n }\n if (item.fields?.scope === 'global') continue\n if (chainSet.has(owner)) {\n groups.get(owner)?.push({ ...item, scope: owner })\n continue\n }\n const via = frontMatterScopes(item.fields).find((s) => chainSet.has(s))\n if (via !== undefined) groups.get(via)?.push({ ...item, scope: via })\n }\n\n const files: ContextFile[] = []\n const seen = new Set<string>()\n const push = (f: Owned): void => {\n if (seen.has(f.path)) return\n seen.add(f.path)\n files.push({ rel: f.rel, scope: f.scope, title: f.title, body: f.body })\n }\n for (const s of chain) for (const f of groups.get(s) ?? []) push(f)\n for (const f of rootFiles) push(f)\n return { name, files }\n}\n\nexport interface AssembleInput {\n rnessDir: string\n manifest: Manifest\n scope: string | null\n}\n\n/** Resolve every scoped collection for `scope` (null = global only). */\nexport async function assembleContext({ rnessDir, manifest, scope }: AssembleInput): Promise<Context> {\n const chain = scopeChain(manifest, scope)\n const collections = await Promise.all(\n COLLECTIONS.map((name) => assembleCollection(join(rnessDir, name), name, chain)),\n )\n return { scope, collections }\n}\n","/**\n * Shared CLI error contract: one line on stderr, and — only under\n * `RNESS_DEBUG=1` — the stack trace instead of the plain message (the stack\n * already starts with `Error: <message>`, so printing both would repeat it).\n */\nexport function reportError(e: unknown): number {\n const debug = process.env['RNESS_DEBUG'] === '1'\n if (debug && e instanceof Error && e.stack) {\n process.stderr.write(`${e.stack}\\n`)\n } else {\n const message = e instanceof Error ? e.message : String(e)\n process.stderr.write(`${message}\\n`)\n }\n return 1\n}\n","import { posix, relative, sep } from 'node:path'\nimport { findWorkspace } from '../core/workspace.ts'\nimport { loadManifest } from '../core/manifest.ts'\nimport { resolveScope } from '../core/scope.ts'\nimport { assembleContext } from '../core/context.ts'\nimport type { Context } from '../core/types.ts'\nimport { reportError } from '../report.ts'\n\nexport interface ContextOptions {\n /** Scope to resolve; default: the scope owning `cwd`. */\n scope?: string\n /** Print the resolved context as JSON instead of Markdown. */\n json?: boolean\n /** Internal (tests): directory to resolve from; default `process.cwd()`. */\n cwd?: string\n}\n\nexport function renderMarkdown(ctx: Context): string {\n const parts: string[] = []\n for (const collection of ctx.collections) {\n if (collection.files.length === 0) continue\n parts.push(`## ${collection.name}\\n`)\n for (const file of collection.files) {\n parts.push(`<!-- rness: ${collection.name}/${file.rel} -->\\n${file.body.trim()}\\n`)\n }\n }\n return `${parts.join('\\n')}\\n`\n}\n\n/** `rness context`: resolve and print the context for a scope. Returns the exit code. */\nexport async function contextCommand(opts: ContextOptions): Promise<number> {\n const cwd = opts.cwd ?? process.cwd()\n try {\n const ws = await findWorkspace(cwd)\n const manifest = await loadManifest(ws.rnessDir)\n\n let scope: string | null\n if (opts.scope !== undefined) {\n if (!Object.hasOwn(manifest.scopes, opts.scope)) {\n process.stderr.write(`unknown scope: ${opts.scope}\\n`)\n return 1\n }\n scope = opts.scope\n } else {\n const rel = relative(ws.root, cwd).split(sep).join(posix.sep)\n scope = resolveScope(manifest, rel)\n }\n\n const ctx = await assembleContext({ rnessDir: ws.rnessDir, manifest, scope })\n process.stdout.write(opts.json ? `${JSON.stringify(ctx, null, 2)}\\n` : renderMarkdown(ctx))\n return 0\n } catch (e) {\n return reportError(e)\n }\n}\n","import { join } from 'node:path'\nimport { collectMarkdown } from './collect.ts'\n\nexport const STATUSES: Record<'adr' | 'specs' | 'plans', readonly string[]> = {\n adr: ['Proposed', 'Accepted', 'Rejected', 'Superseded'],\n specs: ['Draft', 'Proposed', 'Approved', 'Implemented', 'Superseded', 'Rejected'],\n plans: ['Draft', 'Ready', 'In progress', 'Blocked', 'Completed', 'Abandoned'],\n}\nconst SKIP = new Set(['0000-template.md'])\n\n/** Human-readable problems in `adr/`, `specs/`, `plans/`; empty when the tree is valid. */\nexport async function checkContract(rnessDir: string): Promise<string[]> {\n const problems: string[] = []\n for (const [name, allowed] of Object.entries(STATUSES)) {\n const items = await collectMarkdown(join(rnessDir, name))\n for (const item of items) {\n if (SKIP.has(item.rel)) continue\n const where = `${name}/${item.rel}`\n if (item.fieldsError !== null) {\n problems.push(`${where}: invalid front matter (${item.fieldsError})`)\n continue\n }\n if (item.fields === null) {\n problems.push(`${where}: missing a front-matter block`)\n continue\n }\n if (item.title === null) problems.push(`${where}: missing a \"# \" title`)\n const status = item.fields.status\n if (status === undefined || status === null || status === '') {\n problems.push(`${where}: missing \"status\"`)\n } else if (typeof status !== 'string' || !allowed.includes(status)) {\n problems.push(`${where}: unknown status ${JSON.stringify(status)} (expected ${allowed.join(', ')})`)\n }\n }\n }\n return problems\n}\n","import { findWorkspace } from '../core/workspace.ts'\nimport { loadManifest } from '../core/manifest.ts'\nimport { scopeChain } from '../core/scope.ts'\nimport { checkContract } from '../core/contract.ts'\nimport { reportError } from '../report.ts'\n\nexport interface ValidateOptions {\n /** Internal (tests): directory to resolve from; default `process.cwd()`. */\n cwd?: string\n}\n\n/** `rness validate`: manifest, extends cycles, and the front-matter contract. Returns the exit code. */\nexport async function validateCommand(opts: ValidateOptions): Promise<number> {\n const cwd = opts.cwd ?? process.cwd()\n try {\n const ws = await findWorkspace(cwd)\n const rnessDir = ws.rnessDir\n const manifest = await loadManifest(rnessDir)\n // loadManifest only checks that extends targets exist; walk every scope so\n // an extends cycle is reported here rather than breaking `context` later.\n for (const s of Object.keys(manifest.scopes)) scopeChain(manifest, s)\n\n const problems = await checkContract(rnessDir)\n if (problems.length > 0) {\n for (const p of problems) process.stderr.write(`${p}\\n`)\n return 1\n }\n process.stdout.write('context ok\\n')\n return 0\n } catch (e) {\n return reportError(e)\n }\n}\n","import { Command, CommanderError, Option } from 'commander'\nimport { VERSION } from './version.ts'\nimport { contextCommand, type ContextOptions } from './commands/context.ts'\nimport { validateCommand, type ValidateOptions } from './commands/validate.ts'\n\ninterface RunState {\n code: number\n}\n\nfunction buildProgram(state: RunState): Command {\n const program = new Command()\n .name('rness')\n .description('Configuration-plane CLI for rness workspaces')\n .version(VERSION, '-v, --version', 'print the version')\n .exitOverride()\n .showHelpAfterError()\n .configureOutput({\n writeOut: (s) => {\n process.stdout.write(s)\n },\n writeErr: (s) => {\n process.stderr.write(s)\n },\n })\n\n program\n .command('context')\n .description('Resolve and print the context for a scope')\n .option('--scope <name>', 'scope to resolve (default: the scope owning the current directory)')\n .option('--json', 'print JSON instead of Markdown')\n .addOption(new Option('--cwd <dir>').hideHelp())\n .action(async (opts: ContextOptions) => {\n state.code = await contextCommand(opts)\n })\n\n program\n .command('validate')\n .description('Check the .rness/ tree against the contract')\n .addOption(new Option('--cwd <dir>').hideHelp())\n .action(async (opts: ValidateOptions) => {\n state.code = await validateCommand(opts)\n })\n\n return program\n}\n\n/**\n * Parse user arguments and run the matching command. Returns the exit code\n * and never calls process.exit: 0 success, 1 handled error, 2 bad usage.\n */\nexport async function run(argv: string[]): Promise<number> {\n const state: RunState = { code: 0 }\n const program = buildProgram(state)\n if (argv.length === 0) {\n process.stdout.write(program.helpInformation())\n return 0\n }\n try {\n await program.parseAsync(argv, { from: 'user' })\n } catch (e) {\n if (e instanceof CommanderError) {\n // Commander 15 reuses `commander.help`'s code for both the successful\n // `--help` path and error paths (e.g. `help wat`, a lone `--`), so the\n // exit code it already computed is the only reliable signal here.\n return e.exitCode === 0 ? 0 : 2\n }\n throw e\n }\n return state.code\n}\n"],"mappings":"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","names":["join","parse","fail","readFile","join","join","readFile","join","join","posix","sep","sep","posix","join","join"]}