docsgov 0.1.0 → 0.1.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.
Files changed (41) hide show
  1. package/README.md +46 -24
  2. package/dist/apispec/apispec.js +1 -1
  3. package/dist/apispec/apispec.test.js +2 -2
  4. package/dist/check/run.js +1 -1
  5. package/dist/check/run.test.js +6 -6
  6. package/dist/check/suggest.js +1 -1
  7. package/dist/check/tokens.js +1 -1
  8. package/dist/cmd/main.js +17 -17
  9. package/dist/cmd/main.test.js +13 -13
  10. package/dist/codeq/errors.js +2 -2
  11. package/dist/codeq/index.js +1 -1
  12. package/dist/codeq/resolver.test.js +1 -1
  13. package/dist/config/config.js +2 -2
  14. package/dist/config/config.test.js +5 -5
  15. package/dist/config/fs.js +1 -1
  16. package/dist/config/glob.js +1 -1
  17. package/dist/config/glob.test.js +1 -1
  18. package/dist/dedup/configload.js +3 -3
  19. package/dist/dedup/configload.test.js +5 -5
  20. package/dist/dedup/dedup.index.test.js +9 -9
  21. package/dist/dedup/dedup.js +5 -5
  22. package/dist/dedup/dedup.test.js +4 -4
  23. package/dist/dedup/dedupcfg/config.js +2 -2
  24. package/dist/dedup/embedder/cache.js +4 -4
  25. package/dist/dedup/embedder/cache.test.js +13 -13
  26. package/dist/dedup/embedder/embedder.js +2 -2
  27. package/dist/dedup/embedder/embedder.mock.test.js +1 -1
  28. package/dist/dedup/embedder/embedder.test.js +4 -4
  29. package/dist/dedup/embedder/session.test.js +1 -1
  30. package/dist/dedup/gitignore.js +5 -5
  31. package/dist/dedup/gitignore.test.js +2 -2
  32. package/dist/dedup/indexdb/indexdb.js +2 -2
  33. package/dist/repo/exists.test.js +7 -7
  34. package/dist/repo/index.js +1 -1
  35. package/dist/repo/overlay.test.js +6 -6
  36. package/dist/repo/repo.js +10 -10
  37. package/dist/repo/repo.test.js +35 -35
  38. package/dist/repo/testutil.js +1 -1
  39. package/dist/repo/write.test.js +12 -12
  40. package/dist/violation/types.js +1 -1
  41. package/package.json +2 -2
@@ -5,27 +5,27 @@ import { find } from "./repo.js";
5
5
  import { makeDir } from "./testutil.js";
6
6
  const dec = new TextDecoder();
7
7
  describe("find: repo-root discovery", () => {
8
- // WHY: when a .docgov/ exists in the ancestor chain, that ancestor is the
8
+ // WHY: when a .docsgov/ exists in the ancestor chain, that ancestor is the
9
9
  // repo root — governance config lives relative to it.
10
- test("returns the ancestor that owns .docgov/ when CWD is the root", async () => {
11
- const root = await makeDir(".docgov");
10
+ test("returns the ancestor that owns .docsgov/ when CWD is the root", async () => {
11
+ const root = await makeDir(".docsgov");
12
12
  const r = await find(root);
13
13
  expect(r.root()).toBe(root);
14
14
  // The FS must be usable — list the sentinel dir through it.
15
15
  const entries = await r.fs().readDir(".");
16
- expect(entries.map((e) => e.name())).toContain(".docgov");
16
+ expect(entries.map((e) => e.name())).toContain(".docsgov");
17
17
  });
18
- // WHY: gen/add must be able to bootstrap a repo that has no .docgov/ yet;
18
+ // WHY: gen/add must be able to bootstrap a repo that has no .docsgov/ yet;
19
19
  // falling back to the supplied dir is what makes that possible.
20
- test("falls back to the supplied dir when no .docgov/ exists (bootstrapping)", async () => {
21
- const root = await makeDir(); // no .docgov
20
+ test("falls back to the supplied dir when no .docsgov/ exists (bootstrapping)", async () => {
21
+ const root = await makeDir(); // no .docsgov
22
22
  const r = await find(root);
23
23
  expect(r.root()).toBe(root);
24
24
  });
25
25
  // WHY: a check run from a nested working directory must resolve the same repo
26
26
  // root as a run from the top — the walk-up is what guarantees that.
27
- test("walks up from a nested directory to the .docgov/ owner", async () => {
28
- const root = await makeDir(".docgov", "a/b/c");
27
+ test("walks up from a nested directory to the .docsgov/ owner", async () => {
28
+ const root = await makeDir(".docsgov", "a/b/c");
29
29
  const nested = path.join(root, "a", "b", "c");
30
30
  const r = await find(nested);
31
31
  expect(r.root()).toBe(root);
@@ -35,7 +35,7 @@ describe("find: repo-root discovery", () => {
35
35
  // boundary keeps every downstream parser CRLF-agnostic and reports
36
36
  // byte-identical across platforms.
37
37
  test("readFile normalises CRLF to LF so callers never see CR", async () => {
38
- const root = await makeDir(".docgov");
38
+ const root = await makeDir(".docsgov");
39
39
  await nodefs.writeFile(path.join(root, "test.txt"), "line one\r\nline two\r\n");
40
40
  const r = await find(root);
41
41
  const got = dec.decode(await r.readFile("test.txt"));
@@ -47,7 +47,7 @@ describe("exists: exact-case file presence for the docs guard", () => {
47
47
  // WHY: the docs guard validates file references; a real regular file at the
48
48
  // exact path must report present so a valid reference is not flagged broken.
49
49
  test("returns true for an existing regular file (exact case)", async () => {
50
- const root = await makeDir(".docgov", "docs/adr");
50
+ const root = await makeDir(".docsgov", "docs/adr");
51
51
  const r = await find(root);
52
52
  await r.writeFile("docs/adr/0001.md", enc.encode("x\n"));
53
53
  expect(await r.exists("docs/adr/0001.md")).toBe(true);
@@ -55,7 +55,7 @@ describe("exists: exact-case file presence for the docs guard", () => {
55
55
  // WHY: host filesystems case-fold on macOS/Windows; exists() must NOT, or a
56
56
  // wrong-case reference ("Docs/...") would be wrongly accepted and ship broken.
57
57
  test("returns false when a path segment differs only in case", async () => {
58
- const root = await makeDir(".docgov", "docs/adr");
58
+ const root = await makeDir(".docsgov", "docs/adr");
59
59
  const r = await find(root);
60
60
  await r.writeFile("docs/adr/0001.md", enc.encode("x\n"));
61
61
  expect(await r.exists("Docs/adr/0001.md")).toBe(false);
@@ -64,14 +64,14 @@ describe("exists: exact-case file presence for the docs guard", () => {
64
64
  // WHY: the guard checks file references, not directory references; a reference
65
65
  // that resolves to a directory must be rejected as not-a-file.
66
66
  test("returns false when the final segment is a directory", async () => {
67
- const root = await makeDir(".docgov", "docs/adr");
67
+ const root = await makeDir(".docsgov", "docs/adr");
68
68
  const r = await find(root);
69
69
  expect(await r.exists("docs/adr")).toBe(false);
70
70
  });
71
71
  // WHY: a reference whose interior segment is a file (not a dir) cannot be
72
72
  // descended into; treating it as present would mask a malformed reference.
73
73
  test("returns false when an interior segment is a file, not a directory", async () => {
74
- const root = await makeDir(".docgov", "docs");
74
+ const root = await makeDir(".docsgov", "docs");
75
75
  const r = await find(root);
76
76
  await r.writeFile("docs/a.md", enc.encode("x\n"));
77
77
  // a.md is a file, so "a.md/inner.md" cannot descend.
@@ -80,14 +80,14 @@ describe("exists: exact-case file presence for the docs guard", () => {
80
80
  // WHY: a missing leaf in an existing directory is the common "broken
81
81
  // reference" case the guard must catch — it must report absent, not error.
82
82
  test("returns false for a missing final segment", async () => {
83
- const root = await makeDir(".docgov", "docs");
83
+ const root = await makeDir(".docsgov", "docs");
84
84
  const r = await find(root);
85
85
  expect(await r.exists("docs/missing.md")).toBe(false);
86
86
  });
87
87
  // WHY: an empty or root-only path is never a file reference; returning false
88
88
  // keeps the guard from treating "." as a present file.
89
89
  test("returns false for the root / empty path", async () => {
90
- const root = await makeDir(".docgov");
90
+ const root = await makeDir(".docsgov");
91
91
  const r = await find(root);
92
92
  expect(await r.exists("/")).toBe(false);
93
93
  expect(await r.exists("")).toBe(false);
@@ -95,7 +95,7 @@ describe("exists: exact-case file presence for the docs guard", () => {
95
95
  // WHY: a leading slash is a slash-relative reference, not an absolute OS path;
96
96
  // it must be stripped so the lookup still resolves under the repo root.
97
97
  test("strips a leading slash before resolving", async () => {
98
- const root = await makeDir(".docgov", "docs");
98
+ const root = await makeDir(".docsgov", "docs");
99
99
  const r = await find(root);
100
100
  await r.writeFile("docs/a.md", enc.encode("x\n"));
101
101
  expect(await r.exists("/docs/a.md")).toBe(true);
@@ -105,7 +105,7 @@ describe("fileExists / dirExists: write-with-backup precondition checks", () =>
105
105
  // WHY: the write-with-backup layer asks "is there already a file here?"; a
106
106
  // genuine file must report true so it backs up instead of clobbering.
107
107
  test("fileExists is true for a file and false for a directory or missing path", async () => {
108
- const root = await makeDir(".docgov", "docs");
108
+ const root = await makeDir(".docsgov", "docs");
109
109
  const r = await find(root);
110
110
  await r.writeFile("docs/a.md", enc.encode("x\n"));
111
111
  expect(await r.fileExists("docs/a.md")).toBe(true);
@@ -116,14 +116,14 @@ describe("fileExists / dirExists: write-with-backup precondition checks", () =>
116
116
  // so the caller falls through to the write that surfaces a richer error; an
117
117
  // escaping path must therefore be reported absent, not throw here.
118
118
  test("fileExists returns false for a path that escapes the repo root", async () => {
119
- const root = await makeDir(".docgov");
119
+ const root = await makeDir(".docsgov");
120
120
  const r = await find(root);
121
121
  expect(await r.fileExists("../outside.md")).toBe(false);
122
122
  });
123
123
  // WHY: dirExists gates directory operations (rename targets, group dirs); a
124
124
  // real directory must report true and a file or missing path false.
125
125
  test("dirExists is true for a directory and false for a file or missing path", async () => {
126
- const root = await makeDir(".docgov", "docs");
126
+ const root = await makeDir(".docsgov", "docs");
127
127
  const r = await find(root);
128
128
  await r.writeFile("docs/a.md", enc.encode("x\n"));
129
129
  expect(await r.dirExists("docs")).toBe(true);
@@ -133,16 +133,16 @@ describe("fileExists / dirExists: write-with-backup precondition checks", () =>
133
133
  // WHY: same swallow-faults contract — an escaping directory path must be
134
134
  // reported absent rather than throwing, so callers branch on a boolean.
135
135
  test("dirExists returns false for a path that escapes the repo root", async () => {
136
- const root = await makeDir(".docgov");
136
+ const root = await makeDir(".docsgov");
137
137
  const r = await find(root);
138
138
  expect(await r.dirExists("../outside")).toBe(false);
139
139
  });
140
140
  });
141
141
  describe("writeFile: the sole owner of OS writes", () => {
142
- // WHY: docgov generates files into nested doc dirs that may not exist yet;
142
+ // WHY: docsgov generates files into nested doc dirs that may not exist yet;
143
143
  // writeFile must create parents so generation does not fail on a fresh repo.
144
144
  test("creates missing parent directories", async () => {
145
- const root = await makeDir(".docgov");
145
+ const root = await makeDir(".docsgov");
146
146
  const r = await find(root);
147
147
  await r.writeFile("docs/deep/nested/a.md", enc.encode("hello\n"));
148
148
  expect(dec.decode(await r.readFile("docs/deep/nested/a.md"))).toBe("hello\n");
@@ -151,7 +151,7 @@ describe("writeFile: the sole owner of OS writes", () => {
151
151
  // root must be refused (via toAbs) so generation can never scribble outside
152
152
  // the repo. The error names the offending path for diagnosis.
153
153
  test("refuses a path that escapes the repo root", async () => {
154
- const root = await makeDir(".docgov");
154
+ const root = await makeDir(".docsgov");
155
155
  const r = await find(root);
156
156
  await expect(r.writeFile("../escape.md", enc.encode("x"))).rejects.toThrow(/escapes repository root/);
157
157
  });
@@ -160,7 +160,7 @@ describe("renameDir / removeAll: directory lifecycle", () => {
160
160
  // WHY: rename is used to move a generated group dir into place; it must move
161
161
  // the tree atomically so a half-renamed dir never appears.
162
162
  test("renameDir moves a directory tree to a new name", async () => {
163
- const root = await makeDir(".docgov", "old");
163
+ const root = await makeDir(".docsgov", "old");
164
164
  const r = await find(root);
165
165
  await r.writeFile("old/a.md", enc.encode("x\n"));
166
166
  await r.renameDir("old", "new");
@@ -170,14 +170,14 @@ describe("renameDir / removeAll: directory lifecycle", () => {
170
170
  // WHY: a failed rename (e.g. missing source) must throw with context naming
171
171
  // both paths so the operator can see which move broke — Rule 12 fail loud.
172
172
  test("renameDir throws with both paths when the source is missing", async () => {
173
- const root = await makeDir(".docgov");
173
+ const root = await makeDir(".docsgov");
174
174
  const r = await find(root);
175
175
  await expect(r.renameDir("missing", "dest")).rejects.toThrow(/repo\.renameDir/);
176
176
  });
177
177
  // WHY: removeAll backs the stale-.bak cleanup; it must delete an existing tree
178
178
  // so a leftover backup dir does not block the next write.
179
179
  test("removeAll deletes an existing directory tree", async () => {
180
- const root = await makeDir(".docgov", "junk");
180
+ const root = await makeDir(".docsgov", "junk");
181
181
  const r = await find(root);
182
182
  await r.writeFile("junk/a.md", enc.encode("x\n"));
183
183
  await r.removeAll("junk");
@@ -186,7 +186,7 @@ describe("renameDir / removeAll: directory lifecycle", () => {
186
186
  // WHY: the cleanup use-case calls removeAll even when nothing is there; it
187
187
  // must be a no-op (force:true), never throw, so cleanup is idempotent.
188
188
  test("removeAll is a no-op for a missing path", async () => {
189
- const root = await makeDir(".docgov");
189
+ const root = await makeDir(".docsgov");
190
190
  const r = await find(root);
191
191
  await expect(r.removeAll("nope")).resolves.toBeUndefined();
192
192
  });
@@ -196,11 +196,11 @@ describe("atomicWriteFile + PendingWrite: crash-safe flips", () => {
196
196
  // and is atomic; if the temp landed in the OS temp dir the rename could cross
197
197
  // devices and silently degrade to a non-atomic copy.
198
198
  test("writes a sibling temp file, not one in the OS temp dir", async () => {
199
- const root = await makeDir(".docgov", "docs");
199
+ const root = await makeDir(".docsgov", "docs");
200
200
  const r = await find(root);
201
201
  const pending = await r.atomicWriteFile("docs/a.md", enc.encode("new\n"));
202
202
  const tmp = pending.tmpAbsForTest();
203
- expect(tmp).toBe(path.join(root, "docs", "a.md.docgov-flip.tmp"));
203
+ expect(tmp).toBe(path.join(root, "docs", "a.md.docsgov-flip.tmp"));
204
204
  // The target itself is not yet written before commit.
205
205
  expect(await r.fileExists("docs/a.md")).toBe(false);
206
206
  await pending.commit(true);
@@ -208,7 +208,7 @@ describe("atomicWriteFile + PendingWrite: crash-safe flips", () => {
208
208
  // WHY: commit(true) is what makes the new content visible; after it the target
209
209
  // holds the new bytes and the temp is gone (renamed into place).
210
210
  test("commit(true) renames the temp into place", async () => {
211
- const root = await makeDir(".docgov", "docs");
211
+ const root = await makeDir(".docsgov", "docs");
212
212
  const r = await find(root);
213
213
  const pending = await r.atomicWriteFile("docs/a.md", enc.encode("committed\n"));
214
214
  await pending.commit(true);
@@ -218,7 +218,7 @@ describe("atomicWriteFile + PendingWrite: crash-safe flips", () => {
218
218
  // WHY: commit(false) is the rollback path; it must remove the temp and leave
219
219
  // any original untouched, so an aborted flip changes nothing on disk.
220
220
  test("commit(false) removes the temp and leaves the original untouched", async () => {
221
- const root = await makeDir(".docgov", "docs");
221
+ const root = await makeDir(".docsgov", "docs");
222
222
  const r = await find(root);
223
223
  await r.writeFile("docs/a.md", enc.encode("original\n"));
224
224
  const pending = await r.atomicWriteFile("docs/a.md", enc.encode("new\n"));
@@ -230,7 +230,7 @@ describe("atomicWriteFile + PendingWrite: crash-safe flips", () => {
230
230
  // must swallow the ENOENT (not re-throw), so a double-rollback never crashes
231
231
  // the cleanup path.
232
232
  test("commit(false) is a no-op when the temp is already removed", async () => {
233
- const root = await makeDir(".docgov", "docs");
233
+ const root = await makeDir(".docsgov", "docs");
234
234
  const r = await find(root);
235
235
  const pending = await r.atomicWriteFile("docs/a.md", enc.encode("x\n"));
236
236
  await nodefs.rm(pending.tmpAbsForTest()); // remove it out from under commit
@@ -239,7 +239,7 @@ describe("atomicWriteFile + PendingWrite: crash-safe flips", () => {
239
239
  // WHY: atomicWriteFile must create the target's parent dirs, mirroring
240
240
  // writeFile, so a flip into a not-yet-existing doc dir succeeds.
241
241
  test("creates missing parent directories for the temp", async () => {
242
- const root = await makeDir(".docgov");
242
+ const root = await makeDir(".docsgov");
243
243
  const r = await find(root);
244
244
  const pending = await r.atomicWriteFile("docs/new/a.md", enc.encode("y\n"));
245
245
  await pending.commit(true);
@@ -248,7 +248,7 @@ describe("atomicWriteFile + PendingWrite: crash-safe flips", () => {
248
248
  // WHY: atomicWriteFile is also a guarded write; an escaping path must be
249
249
  // refused before any temp is created.
250
250
  test("refuses a path that escapes the repo root", async () => {
251
- const root = await makeDir(".docgov");
251
+ const root = await makeDir(".docsgov");
252
252
  const r = await find(root);
253
253
  await expect(r.atomicWriteFile("../escape.md", enc.encode("x"))).rejects.toThrow(/escapes repository root/);
254
254
  });
@@ -13,7 +13,7 @@ afterEach(async () => {
13
13
  }
14
14
  });
15
15
  export async function makeDir(...dirs) {
16
- const root = await nodefs.mkdtemp(path.join(os.tmpdir(), "docgov-repo-"));
16
+ const root = await nodefs.mkdtemp(path.join(os.tmpdir(), "docsgov-repo-"));
17
17
  // Resolve symlinks (macOS /var -> /private/var) so toAbs prefix checks and
18
18
  // root equality assertions compare canonical paths.
19
19
  const realRoot = await nodefs.realpath(root);
@@ -22,7 +22,7 @@ describe("write capability", () => {
22
22
  // WHY: gen writes to nested paths; without parent creation every subdirectory
23
23
  // write fails and gen can never produce a multi-file tree.
24
24
  test("writeFile creates all missing parent directories", async () => {
25
- const root = await makeDir(".docgov");
25
+ const root = await makeDir(".docsgov");
26
26
  const r = await find(root);
27
27
  const content = enc.encode("hello\n");
28
28
  await r.writeFile(".claude/skills/write-docs/adr/adr.md", content);
@@ -32,7 +32,7 @@ describe("write capability", () => {
32
32
  // WHY: a slash path must map onto the OS separator so files land at the right
33
33
  // location on every platform.
34
34
  test("writeFile maps a slash path to the nested OS path", async () => {
35
- const root = await makeDir(".docgov");
35
+ const root = await makeDir(".docsgov");
36
36
  const r = await find(root);
37
37
  await r.writeFile("subdir/file.txt", enc.encode("data\n"));
38
38
  const got = await nodefs.readFile(path.join(root, "subdir", "file.txt"));
@@ -41,14 +41,14 @@ describe("write capability", () => {
41
41
  // WHY: allowing ".." traversal would let gen overwrite arbitrary files on the
42
42
  // user's system — a security and correctness boundary.
43
43
  test("writeFile refuses a path that escapes the repo root", async () => {
44
- const root = await makeDir(".docgov");
44
+ const root = await makeDir(".docsgov");
45
45
  const r = await find(root);
46
46
  await expect(r.writeFile("../escape.txt", enc.encode("should not be written"))).rejects.toThrow();
47
47
  });
48
48
  // WHY: write-with-backup renames the existing skill dir to <skill>.bak; if
49
49
  // renameDir is broken the backup protocol can't protect the user's tree.
50
50
  test("renameDir moves a directory and its contents", async () => {
51
- const root = await makeDir(".docgov", ".claude/skills/write-docs");
51
+ const root = await makeDir(".docsgov", ".claude/skills/write-docs");
52
52
  await nodefs.writeFile(path.join(root, ".claude", "skills", "write-docs", "sentinel.txt"), "x");
53
53
  const r = await find(root);
54
54
  await r.renameDir(".claude/skills/write-docs", ".claude/skills/write-docs.bak");
@@ -58,7 +58,7 @@ describe("write capability", () => {
58
58
  // WHY: rollback deletes the partial skill dir before restoring the backup; an
59
59
  // incomplete removeAll leaves partial state in the user's repository.
60
60
  test("removeAll removes a directory tree", async () => {
61
- const root = await makeDir(".docgov", ".claude/skills/partial/nested");
61
+ const root = await makeDir(".docsgov", ".claude/skills/partial/nested");
62
62
  await nodefs.writeFile(path.join(root, ".claude", "skills", "partial", "nested", "f.txt"), "y");
63
63
  const r = await find(root);
64
64
  await r.removeAll(".claude/skills/partial");
@@ -67,7 +67,7 @@ describe("write capability", () => {
67
67
  // WHY: stale-bak cleanup calls removeAll unconditionally on first run when no
68
68
  // .bak exists — it must silently succeed.
69
69
  test("removeAll on a nonexistent path is a no-op", async () => {
70
- const root = await makeDir(".docgov");
70
+ const root = await makeDir(".docsgov");
71
71
  const r = await find(root);
72
72
  await expect(r.removeAll(".claude/skills/does-not-exist.bak")).resolves.toBeUndefined();
73
73
  });
@@ -75,7 +75,7 @@ describe("write capability", () => {
75
75
  // deciding to back up; a wrong answer skips a needed backup or crashes a
76
76
  // rename of a nonexistent dir.
77
77
  test("dirExists reports true for an existing dir and false otherwise", async () => {
78
- const root = await makeDir(".docgov", ".claude/skills/write-docs");
78
+ const root = await makeDir(".docsgov", ".claude/skills/write-docs");
79
79
  const r = await find(root);
80
80
  expect(await r.dirExists(".claude/skills/write-docs")).toBe(true);
81
81
  expect(await r.dirExists(".claude/skills/no-such-dir")).toBe(false);
@@ -86,17 +86,17 @@ describe("write capability", () => {
86
86
  // mutates the original or leaves a stray temp file breaks that invariant.
87
87
  describe("atomicWriteFile two-phase commit", () => {
88
88
  test("commit(false) rolls back leaving the original untouched and no temp", async () => {
89
- const root = await makeDir(".docgov", "docs");
89
+ const root = await makeDir(".docsgov", "docs");
90
90
  const r = await find(root);
91
91
  const target = "docs/a.md";
92
92
  await r.writeFile(target, enc.encode("ORIGINAL\n"));
93
93
  const pw = await r.atomicWriteFile(target, enc.encode("NEW\n"));
94
94
  await pw.commit(false);
95
95
  expect(dec.decode(await r.readFile(target))).toBe("ORIGINAL\n");
96
- expect(await statSafe(path.join(root, "docs", "a.md.docgov-flip.tmp"))).toBe(false);
96
+ expect(await statSafe(path.join(root, "docs", "a.md.docsgov-flip.tmp"))).toBe(false);
97
97
  });
98
98
  test("commit(true) atomically renames the temp into place", async () => {
99
- const root = await makeDir(".docgov", "docs");
99
+ const root = await makeDir(".docsgov", "docs");
100
100
  const r = await find(root);
101
101
  const target = "docs/a.md";
102
102
  await r.writeFile(target, enc.encode("ORIGINAL\n"));
@@ -110,7 +110,7 @@ describe("atomicWriteFile two-phase commit", () => {
110
110
  // mid-flight. The real temp path comes from PendingWrite, so this genuinely
111
111
  // fails if the impl changes to use the OS temp dir.
112
112
  test("the temp file is a sibling of the target, not in the OS temp dir", async () => {
113
- const root = await makeDir(".docgov", "docs");
113
+ const root = await makeDir(".docsgov", "docs");
114
114
  const r = await find(root);
115
115
  const target = "docs/a.md";
116
116
  await r.writeFile(target, enc.encode("ORIGINAL\n"));
@@ -119,7 +119,7 @@ describe("atomicWriteFile two-phase commit", () => {
119
119
  const targetDir = path.join(root, "docs");
120
120
  expect(path.dirname(actualTmpPath)).toBe(targetDir);
121
121
  // The temp file must exist on disk before commit is called.
122
- expect(await statSafe(path.join(targetDir, "a.md.docgov-flip.tmp"))).toBe(true);
122
+ expect(await statSafe(path.join(targetDir, "a.md.docsgov-flip.tmp"))).toBe(true);
123
123
  await pw.commit(false); // rollback
124
124
  });
125
125
  });
@@ -1,5 +1,5 @@
1
1
  // Package violation defines the Violation Record and the closed Rule enum for
2
- // the docgov check surface. It is a leaf package: it imports nothing internal.
2
+ // the docsgov check surface. It is a leaf package: it imports nothing internal.
3
3
  // Every rule the check surface can emit is listed in the Rule set; the set is
4
4
  // closed and must exactly match the rule registry in docs/flows/check.md §5.
5
5
  // Rules is the closed set of all rule identifiers the check surface can emit.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docsgov",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Config-driven documentation governance: checks that {{code:…}} and {{api:…}} references in your Markdown docs still resolve, that doc links exist, and (via dedup) flags near-duplicate concepts.",
5
5
  "license": "GPL-3.0",
6
6
  "type": "module",
@@ -8,7 +8,7 @@
8
8
  "node": ">=22"
9
9
  },
10
10
  "bin": {
11
- "docgov": "dist/cmd/main.js"
11
+ "docsgov": "dist/cmd/main.js"
12
12
  },
13
13
  "files": [
14
14
  "dist"