rulebookguard 0.9.0 → 0.10.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.
package/README.md CHANGED
@@ -239,6 +239,7 @@ func validateDocument(country, number string) error {
239
239
  | [`show <id>`](#show-id-l2) | the full rule (L2) |
240
240
  | [`search <text>`](#search-text---context-c---json) | rules holding every word of a text |
241
241
  | [`for <path>`](#for-path) | the active rules anchored to a file |
242
+ | [`for --changed <ref>`](#for---changed-ref) | the active rules anchored to the files changed since a ref |
242
243
  | [`impact <id>`](#impact-id) | the files and tests a rule touches |
243
244
  | [`new <context>`](#new-context---prefix-p) | scaffolds the next rule of a context |
244
245
  | [`lint`](#lint---base-ref---json) | checks the whole catalog, and optionally changes since a ref |
@@ -326,6 +327,23 @@ R-CLI-001 (clients): A client document number is unique per country. (lines 12-3
326
327
 
327
328
  When the file holds `@implements` regions of a rule, its line ends with their line ranges; `--json` rows carry them as `regions: [{ line, endLine }]` (or `[]`). Exits 1 when the path is outside the rulebook root.
328
329
 
330
+ ### `for --changed <ref>`
331
+
332
+ Active rules anchored to the files changed since a git ref, each with those files. This is what a reviewer needs to know about a pull request: which rules it touches, even when no rule file changed.
333
+
334
+ ```sh
335
+ $ rulebookguard for --changed origin/main
336
+ R-BIL-001 (billing): Every new client gets a zero-balance account.
337
+ src/clients/create.ts
338
+ R-CLI-001 (clients): A client document number is unique per country.
339
+ src/clients/create.ts
340
+ src/clients/update.ts
341
+ ```
342
+
343
+ It looks at the difference between the ref and the working tree, including deleted files and untracked ones that are not ignored, as `lint --base` does. A renamed file counts under both paths, so a file moved away from its anchors still reports their rules. On a branch that is behind the ref, the files changed on the ref since the branch point count too, so in CI compare against the base of the pull request on the merge commit, which is what a pull request checkout gives you.
344
+
345
+ `--json` prints `{ base, files, rules }`, where `files` lists every changed file and each rule carries its own `files`. Prints `No active rules anchored to the files changed since <ref>.` when there are none. Exits 1 for an unknown ref or outside a git work tree, and 2 when given both a path and `--changed`.
346
+
329
347
  ### `impact <id>`
330
348
 
331
349
  Files matched by a rule's anchors and the tests tagging it.
@@ -464,7 +482,7 @@ Run it again after changing rules, for example in CI or before committing: it ov
464
482
 
465
483
  ### `export agents-md [--out <dir>]`
466
484
 
467
- Keeps an index of the active rules in `AGENTS.md`, at the rulebook root or in `--out`. `AGENTS.md` has no path scoping and is always read, so it holds each rule's id, anchors (or `no anchors`), summary and rule file, not the full text. The index lives between `<!-- rulebookguard:start -->` and `<!-- rulebookguard:end -->`: the rest of the file is kept, the block is appended the first time and replaced after that, and it is removed when no rule is active. Anything other than one start marker followed by one end marker, or neither, fails with exit code 1 and leaves the file untouched.
485
+ Keeps an index of the active rules in `AGENTS.md`, at the rulebook root or in `--out`. `AGENTS.md` has no path scoping and is always read, so it holds each rule's id, anchors (or `no anchors`), summary and rule file, not the full text. The index lives between `<!-- rulebookguard:start -->` and `<!-- rulebookguard:end -->`: the rest of the file is kept, the block is appended the first time and replaced after that, and it is removed when no rule is active, along with the file if nothing else is left (printing `removed AGENTS.md`). Anything other than one start marker followed by one end marker, or neither, fails with exit code 1 and leaves the file untouched.
468
486
 
469
487
  ### `hook`
470
488
 
@@ -559,7 +577,7 @@ jobs:
559
577
  - uses: actions/setup-node@v6
560
578
  with:
561
579
  node-version: 22
562
- - run: npx --yes rulebookguard@0.9.0 lint --base origin/${{ github.base_ref }}
580
+ - run: npx --yes rulebookguard@0.10.0 lint --base origin/${{ github.base_ref }}
563
581
  ```
564
582
 
565
583
  > [!TIP]
@@ -1,4 +1,4 @@
1
- import { v as createGlobMatcher, x as toRepoPath } from "./lint-CaJnNLmU.mjs";
1
+ import { S as toRepoPath, y as createGlobMatcher } from "./lint-BPdk6XxH.mjs";
2
2
  // src/catalog/anchors.ts
3
3
  function rulesForPath(rules, path) {
4
4
  const target = toRepoPath(path);
package/dist/cli.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { B as formatIssue, F as CONFIG_FILE_NAME, O as isRuleId, R as messages, a as CliError, c as openCatalog, d as writeLines, f as scanImplementations, g as loadCatalog, h as findRulebookRoot, j as CONTEXT_FILE_NAME, l as shownPath, m as scanTestTags, o as findRule, r as lintCommand, s as gitFallbackWarning, u as writeJson, x as toRepoPath, y as expandGlobs, z as FormatError } from "./lint-CaJnNLmU.mjs";
3
- import { t as rulesForPath } from "./anchors-DQwbqb7w.mjs";
2
+ import { B as FormatError, I as CONFIG_FILE_NAME, M as CONTEXT_FILE_NAME, S as toRepoPath, V as formatIssue, _ as loadCatalog, b as expandGlobs, c as gitFallbackWarning, d as writeJson, f as writeLines, g as findRulebookRoot, h as scanTestTags, i as lintCommand, k as isRuleId, l as openCatalog, o as CliError, p as scanImplementations, s as findRule, t as changedFiles, u as shownPath, z as messages } from "./lint-BPdk6XxH.mjs";
3
+ import { t as rulesForPath } from "./anchors-jf2bKfyg.mjs";
4
4
  import { access, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
5
5
  import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
6
6
  import { parseArgs } from "node:util";
@@ -115,9 +115,18 @@ async function writeAgentsMd(catalog, io, rules, dir) {
115
115
  if (rules.length === 0 && !hasBlock) return [text.noActiveRules];
116
116
  const before = hasBlock ? existing.slice(0, start) : existing;
117
117
  const after = hasBlock ? existing.slice(end + 26) : "";
118
+ if (rules.length === 0) {
119
+ const rest = withoutBlock(before, after);
120
+ if (rest === "") {
121
+ await rm(file);
122
+ return [text.noActiveRules, text.removedExport(shown)];
123
+ }
124
+ await writeFile(file, rest);
125
+ return [text.noActiveRules, shown];
126
+ }
118
127
  await mkdir(dir, { recursive: true });
119
- await writeFile(file, rules.length === 0 ? withoutBlock(before, after) : withBlock(before, after, agentsBlock(rules, text), hasBlock));
120
- return rules.length === 0 ? [text.noActiveRules, shown] : [shown];
128
+ await writeFile(file, withBlock(before, after, agentsBlock(rules, text), hasBlock));
129
+ return [shown];
121
130
  }
122
131
  function withBlock(before, after, block, hasBlock) {
123
132
  if (hasBlock) return `${before}${block}${after}`;
@@ -325,6 +334,33 @@ async function forCommand(catalog, io, input, json) {
325
334
  }
326
335
  writeLines(io, rules.map((rule) => `${rule.id} (${rule.context}): ${rule.summary}${rule.regions.length === 0 ? "" : ` (${text.lines(formatSpans(rule.regions))})`}`));
327
336
  }
337
+ async function forChangedCommand(catalog, io, base, json) {
338
+ const text = messages(catalog.config.language);
339
+ const { files } = await changedFiles(catalog.root, base, text, "for --changed", { bothRenamePaths: true });
340
+ const touched = /* @__PURE__ */ new Map();
341
+ for (const file of files) for (const rule of rulesForPath(catalog.rules, file)) touched.set(rule.id, [...touched.get(rule.id) ?? [], file]);
342
+ const rules = sortById(catalog.rules.filter((rule) => rule.status === "active")).flatMap((rule) => {
343
+ const ruleFiles = touched.get(rule.id);
344
+ return ruleFiles === void 0 ? [] : [{
345
+ ...toSummary(rule),
346
+ file: rule.file,
347
+ files: ruleFiles
348
+ }];
349
+ });
350
+ if (json) {
351
+ writeJson(io, {
352
+ base,
353
+ files,
354
+ rules
355
+ });
356
+ return;
357
+ }
358
+ if (rules.length === 0) {
359
+ writeLines(io, [text.noActiveRulesForChanged(base)]);
360
+ return;
361
+ }
362
+ writeLines(io, rules.flatMap((rule) => [`${rule.id} (${rule.context}): ${rule.summary}`, ...indent(rule.files, text.none)]));
363
+ }
328
364
  async function regionsIn(root, path) {
329
365
  const found = (await scanImplementations(root, [path])).regions;
330
366
  return (id) => (found.get(id) ?? []).map(({ line, endLine }) => ({
@@ -459,7 +495,7 @@ function render(path, rules, regions, text) {
459
495
  return parts.join("\n\n");
460
496
  }
461
497
  // package.json
462
- var version = "0.9.0";
498
+ var version = "0.10.0";
463
499
  // src/commands/new.ts
464
500
  const MAX_NUMBER = 999;
465
501
  const CONTEXT_NAME = /^[a-z0-9][a-z0-9_-]*$/;
@@ -738,6 +774,8 @@ Commands:
738
774
  search <text> [--context <c>] [--json] rules whose id, summary, entities or text hold every
739
775
  word of <text>, ignoring case
740
776
  for <path> [--json] active rules anchored to a path
777
+ for --changed <ref> [--json] active rules anchored to the files changed since <ref>,
778
+ each with those files
741
779
  impact <id> [--json] files matched by a rule's anchors and tests tagging it
742
780
  new <context> [--prefix <P>] scaffold the next free rule id as a proposed rule;
743
781
  creates the context first when it does not exist,
@@ -809,9 +847,13 @@ const COMMANDS = {
809
847
  }
810
848
  },
811
849
  for: {
812
- usage: "rulebookguard for <path> [--json]",
850
+ usage: "rulebookguard for <path>|--changed <ref> [--json]",
813
851
  argument: "path",
814
- options: JSON_OPTION
852
+ argumentUnless: "changed",
853
+ options: {
854
+ ...JSON_OPTION,
855
+ changed: { type: "string" }
856
+ }
815
857
  },
816
858
  impact: {
817
859
  usage: "rulebookguard impact <id> [--json]",
@@ -893,7 +935,7 @@ async function dispatch(argv, io) {
893
935
  return 0;
894
936
  }
895
937
  if (name === "site" || name === "site:generate" || name === "site:run") {
896
- const { siteCommand } = await import("./site-BTCwdt_H.mjs");
938
+ const { siteCommand } = await import("./site-B7g8lbjx.mjs");
897
939
  await siteCommand(io, {
898
940
  out: values.out,
899
941
  base: values.base,
@@ -937,7 +979,8 @@ async function dispatch(argv, io) {
937
979
  });
938
980
  break;
939
981
  case "for":
940
- await forCommand(catalog, io, argument, json);
982
+ if (values.changed === void 0) await forCommand(catalog, io, argument, json);
983
+ else await forChangedCommand(catalog, io, values.changed, json);
941
984
  break;
942
985
  case "impact":
943
986
  await impactCommand(catalog, io, argument, json);
@@ -971,7 +1014,8 @@ function parse(spec, args) {
971
1014
  } catch (error) {
972
1015
  throw new CliError(`${error.message}\nUsage: ${spec.usage}`, 2);
973
1016
  }
974
- const expected = spec.argument === void 0 ? 0 : 1;
1017
+ const replaced = spec.argumentUnless !== void 0 && parsed.values[spec.argumentUnless] !== void 0;
1018
+ const expected = spec.argument === void 0 || replaced ? 0 : 1;
975
1019
  if (parsed.positionals.length < expected) throw new CliError(`Missing argument <${spec.argument}>. Usage: ${spec.usage}`, 2);
976
1020
  if (parsed.positionals.length > expected) throw new CliError(`Unexpected argument "${parsed.positionals[expected]}". Usage: ${spec.usage}`, 2);
977
1021
  return {
package/dist/index.d.mts CHANGED
@@ -179,6 +179,14 @@ interface ForJson {
179
179
  regions: LineSpanJson[];
180
180
  })[];
181
181
  }
182
+ interface ForChangedJson {
183
+ base: string;
184
+ files: string[];
185
+ rules: (RuleSummaryJson & {
186
+ file: string;
187
+ files: string[];
188
+ })[];
189
+ }
182
190
  interface LineSpanJson {
183
191
  line: number;
184
192
  endLine: number;
@@ -212,4 +220,4 @@ interface LintOptions {
212
220
  export declare function lintCatalog(catalog: Catalog, scan?: TagScan, onGitFallback?: GitFallbackListener): Promise<LintFinding[]>;
213
221
  export declare function pendingImplementation(catalog: Catalog, scan: TagScan, base: string, changed: string[], lines: Map<string, LineSpan[]>): LintFinding[];
214
222
  export declare function formatFinding(finding: LintFinding): string;
215
- export type { Catalog, CatalogIssue, CatalogIssueCode, ContextDoc, ContextFrontmatter, ContextsJson, ForJson, FormatIssue, Frontmatter, GitFallbackListener, ImpactJson, ImplementationScan, ImplementsTagProblemCode, LintFinding, LintJson, LintOptions, LintSeverity, ListJson, ParseOptions, RegionIndex, RegionKind, RuleDoc, RuleFrontmatter, RuleLanguage, RuleRegion, RuleRegions, RuleStatus, RuleSummaryJson, RuleTag, RuleTagProblem, RuleTagProblemCode, RulebookConfig, ShowJson, TagIndex, TagLocation, TagProblem, TagRegion, TagScan };
223
+ export type { Catalog, CatalogIssue, CatalogIssueCode, ContextDoc, ContextFrontmatter, ContextsJson, ForChangedJson, ForJson, FormatIssue, Frontmatter, GitFallbackListener, ImpactJson, ImplementationScan, ImplementsTagProblemCode, LintFinding, LintJson, LintOptions, LintSeverity, ListJson, ParseOptions, RegionIndex, RegionKind, RuleDoc, RuleFrontmatter, RuleLanguage, RuleRegion, RuleRegions, RuleStatus, RuleSummaryJson, RuleTag, RuleTagProblem, RuleTagProblemCode, RulebookConfig, ShowJson, TagIndex, TagLocation, TagProblem, TagRegion, TagScan };
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { A as parseRule, B as formatIssue, C as IMPLEMENTS_MARKER_PATTERN, D as findRuleTags, E as findRuleRegions, F as CONFIG_FILE_NAME, I as loadConfig, L as parseConfig, M as loadContext, N as parseContext, O as isRuleId, P as splitFrontmatter, T as RULE_TAG_PATTERN, _ as relativeToRoot, b as listRepoFiles, f as scanImplementations, g as loadCatalog, h as findRulebookRoot, i as pendingImplementation, j as CONTEXT_FILE_NAME, k as loadRule, m as scanTestTags, n as lintCatalog, p as scanTestRegions, t as formatFinding, v as createGlobMatcher, w as RULE_MARKER_PATTERN, x as toRepoPath, y as expandGlobs, z as FormatError } from "./lint-CaJnNLmU.mjs";
2
- import { t as rulesForPath } from "./anchors-DQwbqb7w.mjs";
1
+ import { A as loadRule, B as FormatError, D as findRuleRegions, E as RULE_TAG_PATTERN, F as splitFrontmatter, I as CONFIG_FILE_NAME, L as loadConfig, M as CONTEXT_FILE_NAME, N as loadContext, O as findRuleTags, P as parseContext, R as parseConfig, S as toRepoPath, T as RULE_MARKER_PATTERN, V as formatIssue, _ as loadCatalog, a as pendingImplementation, b as expandGlobs, g as findRulebookRoot, h as scanTestTags, j as parseRule, k as isRuleId, m as scanTestRegions, n as formatFinding, p as scanImplementations, r as lintCatalog, v as relativeToRoot, w as IMPLEMENTS_MARKER_PATTERN, x as listRepoFiles, y as createGlobMatcher } from "./lint-BPdk6XxH.mjs";
2
+ import { t as rulesForPath } from "./anchors-jf2bKfyg.mjs";
3
3
  export { CONFIG_FILE_NAME, CONTEXT_FILE_NAME, FormatError, IMPLEMENTS_MARKER_PATTERN, RULE_MARKER_PATTERN, RULE_TAG_PATTERN, createGlobMatcher, expandGlobs, findRuleRegions, findRuleTags, findRulebookRoot, formatFinding, formatIssue, isRuleId, lintCatalog, listRepoFiles, loadCatalog, loadConfig, loadContext, loadRule, parseConfig, parseContext, parseRule, pendingImplementation, relativeToRoot, rulesForPath, scanImplementations, scanTestRegions, scanTestTags, splitFrontmatter, toRepoPath };
@@ -187,6 +187,7 @@ const MESSAGES = {
187
187
  noContexts: "No contexts found. Create one with \"rulebookguard new <context>\".",
188
188
  noRules: "No rules found.",
189
189
  noActiveRulesFor: (path) => `No active rules anchored to ${path}.`,
190
+ noActiveRulesForChanged: (ref) => `No active rules anchored to the files changed since ${ref}.`,
190
191
  lines: (spans) => `lines ${spans}`,
191
192
  filesMatched: (count) => `Files matched by anchors (${count}):`,
192
193
  testsTagging: (id, count) => `Tests tagging ${id} (${count}):`,
@@ -259,7 +260,7 @@ const MESSAGES = {
259
260
  contextOverBudgetHint: "split the context into smaller ones, or raise contextBudget in rulebookguard.config.yaml",
260
261
  pendingImplementationHint: (id) => `update or add a test inside an "@rule ${id}" … "@endrule ${id}" region that covers the changed rule`,
261
262
  lintSummary: (errors, warnings) => `${errors} ${errors === 1 ? "error" : "errors"}, ${warnings} ${warnings === 1 ? "warning" : "warnings"}`,
262
- needsWorkTree: (root) => `lint --base needs a git work tree, but ${root} is not inside one.`,
263
+ needsWorkTree: (command, root) => `${command} needs a git work tree, but ${root} is not inside one.`,
263
264
  unknownRef: (ref) => `Unknown git ref "${ref}".`,
264
265
  cannotListChanged: (ref, reason) => `Cannot list the files changed since "${ref}": ${reason}`
265
266
  },
@@ -294,6 +295,7 @@ const MESSAGES = {
294
295
  noContexts: "No se encontraron contextos. Crea uno con \"rulebookguard new <contexto>\".",
295
296
  noRules: "No se encontraron reglas.",
296
297
  noActiveRulesFor: (path) => `No hay reglas activas ancladas a ${path}.`,
298
+ noActiveRulesForChanged: (ref) => `No hay reglas activas ancladas a los archivos cambiados desde ${ref}.`,
297
299
  lines: (spans) => `líneas ${spans}`,
298
300
  filesMatched: (count) => `Archivos que cubren los anchors (${count}):`,
299
301
  testsTagging: (id, count) => `Tests que etiquetan ${id} (${count}):`,
@@ -366,7 +368,7 @@ const MESSAGES = {
366
368
  contextOverBudgetHint: "divide el contexto en otros más chicos o sube contextBudget en rulebookguard.config.yaml",
367
369
  pendingImplementationHint: (id) => `actualiza o agrega un test dentro de una región "@rule ${id}" … "@endrule ${id}" que cubra el cambio de la regla`,
368
370
  lintSummary: (errors, warnings) => `${errors} ${errors === 1 ? "error" : "errores"}, ${warnings} ${warnings === 1 ? "aviso" : "avisos"}`,
369
- needsWorkTree: (root) => `lint --base necesita un work tree de git, pero ${root} no está en uno.`,
371
+ needsWorkTree: (command, root) => `${command} necesita un work tree de git, pero ${root} no está en uno.`,
370
372
  unknownRef: (ref) => `La referencia de git "${ref}" no existe.`,
371
373
  cannotListChanged: (ref, reason) => `No se pudieron listar los archivos cambiados desde "${ref}": ${reason}`
372
374
  }
@@ -613,10 +615,11 @@ async function isCommitRef(cwd, ref) {
613
615
  return false;
614
616
  }
615
617
  }
616
- async function changedSince(cwd, ref) {
618
+ async function changedSince(cwd, ref, { bothRenamePaths = false } = {}) {
617
619
  const changed = await gitPaths(cwd, "diff", [
618
620
  "--name-only",
619
621
  "--relative",
622
+ ...bothRenamePaths ? ["--no-renames"] : [],
620
623
  ref,
621
624
  "--"
622
625
  ]);
@@ -1001,7 +1004,7 @@ function writeLines(io, lines) {
1001
1004
  }
1002
1005
  function shownPath(cwd, file) {
1003
1006
  const fromCwd = relative(cwd, file);
1004
- return fromCwd.startsWith("..") || isAbsolute(fromCwd) ? file : fromCwd;
1007
+ return fromCwd.startsWith("..") || isAbsolute(fromCwd) ? file : toRepoPath(fromCwd);
1005
1008
  }
1006
1009
  function gitFallbackWarning(io, language) {
1007
1010
  const text = messages(language);
@@ -1035,7 +1038,7 @@ async function lintCommand(io, options) {
1035
1038
  }, messages("en"))), options.json, messages("en"));
1036
1039
  }
1037
1040
  const text = messages(catalog.config.language);
1038
- const changed = options.base === void 0 ? void 0 : await changedFiles(catalog.root, options.base, text);
1041
+ const changed = options.base === void 0 ? void 0 : await changedFiles(catalog.root, options.base, text, "lint --base");
1039
1042
  const warn = gitFallbackWarning(io, catalog.config.language);
1040
1043
  const scan = await scanTestRegions(catalog.root, catalog.config.testGlobs, warn);
1041
1044
  const findings = await lintCatalog(catalog, scan, warn);
@@ -1201,11 +1204,11 @@ async function testLineChanges(catalog, scan, base, changed, text) {
1201
1204
  }
1202
1205
  return lines;
1203
1206
  }
1204
- async function changedFiles(root, base, text) {
1205
- if (!await isInsideWorkTree(root)) throw new CliError(text.needsWorkTree(root));
1207
+ async function changedFiles(root, base, text, command, options) {
1208
+ if (!await isInsideWorkTree(root)) throw new CliError(text.needsWorkTree(command, root));
1206
1209
  if (!await isCommitRef(root, base)) throw new CliError(text.unknownRef(base));
1207
1210
  try {
1208
- return await changedSince(root, base);
1211
+ return await changedSince(root, base, options);
1209
1212
  } catch (error) {
1210
1213
  throw new CliError(text.cannotListChanged(base, gitFailureReason(error)));
1211
1214
  }
@@ -1229,4 +1232,4 @@ function sortFindings(findings) {
1229
1232
  function compare(a, b) {
1230
1233
  return a < b ? -1 : a > b ? 1 : 0;
1231
1234
  }
1232
- export { parseRule as A, formatIssue as B, IMPLEMENTS_MARKER_PATTERN as C, findRuleTags as D, findRuleRegions as E, CONFIG_FILE_NAME as F, loadConfig as I, parseConfig as L, loadContext as M, parseContext as N, isRuleId as O, splitFrontmatter as P, messages as R, runGit as S, RULE_TAG_PATTERN as T, relativeToRoot as _, CliError as a, listRepoFiles as b, openCatalog as c, writeLines as d, scanImplementations as f, loadCatalog as g, findRulebookRoot as h, pendingImplementation as i, CONTEXT_FILE_NAME as j, loadRule as k, shownPath as l, scanTestTags as m, lintCatalog as n, findRule as o, scanTestRegions as p, lintCommand as r, gitFallbackWarning as s, formatFinding as t, writeJson as u, createGlobMatcher as v, RULE_MARKER_PATTERN as w, toRepoPath as x, expandGlobs as y, FormatError as z };
1235
+ export { loadRule as A, FormatError as B, runGit as C, findRuleRegions as D, RULE_TAG_PATTERN as E, splitFrontmatter as F, CONFIG_FILE_NAME as I, loadConfig as L, CONTEXT_FILE_NAME as M, loadContext as N, findRuleTags as O, parseContext as P, parseConfig as R, toRepoPath as S, RULE_MARKER_PATTERN as T, formatIssue as V, loadCatalog as _, pendingImplementation as a, expandGlobs as b, gitFallbackWarning as c, writeJson as d, writeLines as f, findRulebookRoot as g, scanTestTags as h, lintCommand as i, parseRule as j, isRuleId as k, openCatalog as l, scanTestRegions as m, formatFinding as n, CliError as o, scanImplementations as p, lintCatalog as r, findRule as s, changedFiles as t, shownPath as u, relativeToRoot as v, IMPLEMENTS_MARKER_PATTERN as w, listRepoFiles as x, createGlobMatcher as y, messages as z };
@@ -1,4 +1,4 @@
1
- import { S as runGit, a as CliError, c as openCatalog, d as writeLines, n as lintCatalog, p as scanTestRegions, s as gitFallbackWarning, y as expandGlobs } from "./lint-CaJnNLmU.mjs";
1
+ import { C as runGit, S as toRepoPath, b as expandGlobs, c as gitFallbackWarning, f as writeLines, l as openCatalog, m as scanTestRegions, o as CliError, r as lintCatalog } from "./lint-BPdk6XxH.mjs";
2
2
  import { createRequire } from "node:module";
3
3
  import { readFile, readdir, stat, writeFile } from "node:fs/promises";
4
4
  import { dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
@@ -417,7 +417,7 @@ async function siteCommand(io, options, until = untilInterrupted()) {
417
417
  const catalog = await openCatalog(io);
418
418
  const out = resolve(io.cwd, options.out ?? "site");
419
419
  const fromCwd = relative(io.cwd, out);
420
- const shown = fromCwd === "" ? "." : fromCwd.startsWith("..") || isAbsolute(fromCwd) ? out : fromCwd;
420
+ const shown = fromCwd === "" ? "." : fromCwd.startsWith("..") || isAbsolute(fromCwd) ? out : toRepoPath(fromCwd);
421
421
  await assertReplaceable(out, shown);
422
422
  const site = await importSitePackage([catalog.root, dirname(fileURLToPath(import.meta.url))]);
423
423
  const language = catalog.config.language ?? "en";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rulebookguard",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "Keep business rules as the single source of truth, bound to code and tests.",
5
5
  "homepage": "https://github.com/JuanCJR/rulebookguard#readme",
6
6
  "bugs": {
@@ -36,14 +36,14 @@
36
36
  },
37
37
  "devDependencies": {
38
38
  "@modelcontextprotocol/client": "2.3.1",
39
- "@rulebookguard/site": "0.9.0",
39
+ "@rulebookguard/site": "0.10.0",
40
40
  "@types/node": "^20.19.43",
41
41
  "@types/picomatch": "^4.0.3",
42
42
  "typescript": "^7.0.2",
43
43
  "vite-plus": "^1.4.0"
44
44
  },
45
45
  "peerDependencies": {
46
- "@rulebookguard/site": "^0.9.0"
46
+ "@rulebookguard/site": "^0.10.0"
47
47
  },
48
48
  "peerDependenciesMeta": {
49
49
  "@rulebookguard/site": {