@anatomytool/validate 1.0.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.
Files changed (156) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +127 -0
  3. package/dist/canonical.d.ts +21 -0
  4. package/dist/canonical.d.ts.map +1 -0
  5. package/dist/canonical.js +76 -0
  6. package/dist/canonical.js.map +1 -0
  7. package/dist/checks/commands-no-test-warn.d.ts +6 -0
  8. package/dist/checks/commands-no-test-warn.d.ts.map +1 -0
  9. package/dist/checks/commands-no-test-warn.js +35 -0
  10. package/dist/checks/commands-no-test-warn.js.map +1 -0
  11. package/dist/checks/description-warn.d.ts +6 -0
  12. package/dist/checks/description-warn.d.ts.map +1 -0
  13. package/dist/checks/description-warn.js +23 -0
  14. package/dist/checks/description-warn.js.map +1 -0
  15. package/dist/checks/entry-point-alias-warn.d.ts +6 -0
  16. package/dist/checks/entry-point-alias-warn.d.ts.map +1 -0
  17. package/dist/checks/entry-point-alias-warn.js +25 -0
  18. package/dist/checks/entry-point-alias-warn.js.map +1 -0
  19. package/dist/checks/fingerprint-check.d.ts +6 -0
  20. package/dist/checks/fingerprint-check.d.ts.map +1 -0
  21. package/dist/checks/fingerprint-check.js +59 -0
  22. package/dist/checks/fingerprint-check.js.map +1 -0
  23. package/dist/checks/hash-check.d.ts +6 -0
  24. package/dist/checks/hash-check.d.ts.map +1 -0
  25. package/dist/checks/hash-check.js +36 -0
  26. package/dist/checks/hash-check.js.map +1 -0
  27. package/dist/checks/interface-form-check.d.ts +6 -0
  28. package/dist/checks/interface-form-check.d.ts.map +1 -0
  29. package/dist/checks/interface-form-check.js +66 -0
  30. package/dist/checks/interface-form-check.js.map +1 -0
  31. package/dist/checks/memory-dangling-ref-check.d.ts +6 -0
  32. package/dist/checks/memory-dangling-ref-check.d.ts.map +1 -0
  33. package/dist/checks/memory-dangling-ref-check.js +34 -0
  34. package/dist/checks/memory-dangling-ref-check.js.map +1 -0
  35. package/dist/checks/memory-fingerprint-check.d.ts +6 -0
  36. package/dist/checks/memory-fingerprint-check.d.ts.map +1 -0
  37. package/dist/checks/memory-fingerprint-check.js +20 -0
  38. package/dist/checks/memory-fingerprint-check.js.map +1 -0
  39. package/dist/checks/memory-supersession-check.d.ts +6 -0
  40. package/dist/checks/memory-supersession-check.d.ts.map +1 -0
  41. package/dist/checks/memory-supersession-check.js +61 -0
  42. package/dist/checks/memory-supersession-check.js.map +1 -0
  43. package/dist/checks/memory-verification-check.d.ts +6 -0
  44. package/dist/checks/memory-verification-check.d.ts.map +1 -0
  45. package/dist/checks/memory-verification-check.js +61 -0
  46. package/dist/checks/memory-verification-check.js.map +1 -0
  47. package/dist/checks/nested-path-escape.d.ts +6 -0
  48. package/dist/checks/nested-path-escape.d.ts.map +1 -0
  49. package/dist/checks/nested-path-escape.js +76 -0
  50. package/dist/checks/nested-path-escape.js.map +1 -0
  51. package/dist/checks/schema-check.d.ts +6 -0
  52. package/dist/checks/schema-check.d.ts.map +1 -0
  53. package/dist/checks/schema-check.js +32 -0
  54. package/dist/checks/schema-check.js.map +1 -0
  55. package/dist/checks/source-cross-check.d.ts +52 -0
  56. package/dist/checks/source-cross-check.d.ts.map +1 -0
  57. package/dist/checks/source-cross-check.js +473 -0
  58. package/dist/checks/source-cross-check.js.map +1 -0
  59. package/dist/checks/source-path-check.d.ts +6 -0
  60. package/dist/checks/source-path-check.d.ts.map +1 -0
  61. package/dist/checks/source-path-check.js +62 -0
  62. package/dist/checks/source-path-check.js.map +1 -0
  63. package/dist/checks/structure-path-check.d.ts +6 -0
  64. package/dist/checks/structure-path-check.d.ts.map +1 -0
  65. package/dist/checks/structure-path-check.js +31 -0
  66. package/dist/checks/structure-path-check.js.map +1 -0
  67. package/dist/checks/verify/ast-grep-verifier.d.ts +4 -0
  68. package/dist/checks/verify/ast-grep-verifier.d.ts.map +1 -0
  69. package/dist/checks/verify/ast-grep-verifier.js +153 -0
  70. package/dist/checks/verify/ast-grep-verifier.js.map +1 -0
  71. package/dist/checks/verify/detect-ast-grep.d.ts +9 -0
  72. package/dist/checks/verify/detect-ast-grep.d.ts.map +1 -0
  73. package/dist/checks/verify/detect-ast-grep.js +26 -0
  74. package/dist/checks/verify/detect-ast-grep.js.map +1 -0
  75. package/dist/checks/verify/detect-semgrep.d.ts +8 -0
  76. package/dist/checks/verify/detect-semgrep.d.ts.map +1 -0
  77. package/dist/checks/verify/detect-semgrep.js +36 -0
  78. package/dist/checks/verify/detect-semgrep.js.map +1 -0
  79. package/dist/checks/verify/glob-verifier.d.ts +5 -0
  80. package/dist/checks/verify/glob-verifier.d.ts.map +1 -0
  81. package/dist/checks/verify/glob-verifier.js +58 -0
  82. package/dist/checks/verify/glob-verifier.js.map +1 -0
  83. package/dist/checks/verify/semgrep-pattern-verifier.d.ts +4 -0
  84. package/dist/checks/verify/semgrep-pattern-verifier.d.ts.map +1 -0
  85. package/dist/checks/verify/semgrep-pattern-verifier.js +121 -0
  86. package/dist/checks/verify/semgrep-pattern-verifier.js.map +1 -0
  87. package/dist/checks/verify/semgrep-rule-file-verifier.d.ts +9 -0
  88. package/dist/checks/verify/semgrep-rule-file-verifier.d.ts.map +1 -0
  89. package/dist/checks/verify/semgrep-rule-file-verifier.js +151 -0
  90. package/dist/checks/verify/semgrep-rule-file-verifier.js.map +1 -0
  91. package/dist/checks/verify/types.d.ts +44 -0
  92. package/dist/checks/verify/types.d.ts.map +1 -0
  93. package/dist/checks/verify/types.js +6 -0
  94. package/dist/checks/verify/types.js.map +1 -0
  95. package/dist/checks/verify-check.d.ts +9 -0
  96. package/dist/checks/verify-check.d.ts.map +1 -0
  97. package/dist/checks/verify-check.js +67 -0
  98. package/dist/checks/verify-check.js.map +1 -0
  99. package/dist/discovery.d.ts +13 -0
  100. package/dist/discovery.d.ts.map +1 -0
  101. package/dist/discovery.js +82 -0
  102. package/dist/discovery.js.map +1 -0
  103. package/dist/errors.d.ts +38 -0
  104. package/dist/errors.d.ts.map +1 -0
  105. package/dist/errors.js +5 -0
  106. package/dist/errors.js.map +1 -0
  107. package/dist/index.d.ts +43 -0
  108. package/dist/index.d.ts.map +1 -0
  109. package/dist/index.js +81 -0
  110. package/dist/index.js.map +1 -0
  111. package/dist/memory.d.ts +19 -0
  112. package/dist/memory.d.ts.map +1 -0
  113. package/dist/memory.js +80 -0
  114. package/dist/memory.js.map +1 -0
  115. package/dist/parse.d.ts +17 -0
  116. package/dist/parse.d.ts.map +1 -0
  117. package/dist/parse.js +47 -0
  118. package/dist/parse.js.map +1 -0
  119. package/dist/schema-0.10.json +194 -0
  120. package/dist/schema-0.11.json +203 -0
  121. package/dist/schema-0.12.json +243 -0
  122. package/dist/schema-0.13.json +267 -0
  123. package/dist/schema-0.14.json +288 -0
  124. package/dist/schema-0.15.json +347 -0
  125. package/dist/schema-0.2.json +283 -0
  126. package/dist/schema-0.4.json +280 -0
  127. package/dist/schema-0.5.json +300 -0
  128. package/dist/schema-0.6.json +328 -0
  129. package/dist/schema-0.7.json +311 -0
  130. package/dist/schema-0.8.json +245 -0
  131. package/dist/schema-0.9.json +172 -0
  132. package/dist/schema-1.0.json +347 -0
  133. package/dist/schema-memory-0.1.json +43 -0
  134. package/dist/schema-memory-0.2.json +49 -0
  135. package/dist/schema-memory.d.ts +5 -0
  136. package/dist/schema-memory.d.ts.map +1 -0
  137. package/dist/schema-memory.js +16 -0
  138. package/dist/schema-memory.js.map +1 -0
  139. package/dist/schema.d.ts +6 -0
  140. package/dist/schema.d.ts.map +1 -0
  141. package/dist/schema.js +62 -0
  142. package/dist/schema.js.map +1 -0
  143. package/dist/schema.json +129 -0
  144. package/dist/types.d.ts +2 -0
  145. package/dist/types.d.ts.map +1 -0
  146. package/dist/types.generated.d.ts +1103 -0
  147. package/dist/types.generated.d.ts.map +1 -0
  148. package/dist/types.generated.js +7 -0
  149. package/dist/types.generated.js.map +1 -0
  150. package/dist/types.js +7 -0
  151. package/dist/types.js.map +1 -0
  152. package/dist/validate-tree.d.ts +20 -0
  153. package/dist/validate-tree.d.ts.map +1 -0
  154. package/dist/validate-tree.js +64 -0
  155. package/dist/validate-tree.js.map +1 -0
  156. package/package.json +48 -0
@@ -0,0 +1,473 @@
1
+ // src/checks/source-cross-check.ts
2
+ // Post-Pass-2 drift check. Flags two classes of authoring drift:
3
+ // 1. [[substance.key_dependencies]].name with no quoted reference in
4
+ // scanned source ("unused-dependency-claim").
5
+ // 2. Stale host-port / scoped-package / source-path literals embedded in
6
+ // [[rules]].rule|why, [[flows]].summary, [[decisions]].topic|reason
7
+ // ("literal-not-in-source").
8
+ // Skipped when repoRoot is undefined (matches structure-path-check pattern).
9
+ // See docs/superpowers/specs/2026-05-09-pass2-source-cross-check-design.md.
10
+ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
11
+ import { resolve, join } from "node:path";
12
+ const HOST_PORT_RE = /\b(?:localhost|127\.0\.0\.1|0\.0\.0\.0):\d{2,5}\b/g;
13
+ const SCOPED_PACKAGE_RE = /(?<![\w/])@[a-z0-9][\w-]*\/[a-z0-9][\w.-]*(?![\w/])/g;
14
+ const SOURCE_PATH_RE = /(?<![\w/])(?:src|lib|app|bin|cmd|pkg|internal|test|tests|spec|specs|docs)\/[\w/.-]+\.(?:ts|tsx|js|jsx|mjs|cjs|py|go|rs|java|kt|swift|c|cpp|h|hpp|rb|php|md|json|toml|yaml|yml|sql|sh|bash)\b/g;
15
+ export function extractLiterals(text) {
16
+ if (typeof text !== "string" || text.length === 0)
17
+ return [];
18
+ const seen = new Set();
19
+ const out = [];
20
+ const push = (literal, kind) => {
21
+ const key = `${kind}\x00${literal}`;
22
+ if (seen.has(key))
23
+ return;
24
+ seen.add(key);
25
+ out.push({ literal, kind });
26
+ };
27
+ for (const m of text.matchAll(HOST_PORT_RE))
28
+ push(m[0], "host-port");
29
+ for (const m of text.matchAll(SCOPED_PACKAGE_RE)) {
30
+ if (m[0].startsWith("@types/"))
31
+ continue;
32
+ push(m[0], "scoped-package");
33
+ }
34
+ for (const m of text.matchAll(SOURCE_PATH_RE))
35
+ push(m[0], "source-path");
36
+ return out;
37
+ }
38
+ /** Returns true if `name` appears in `haystack` inside a quoted string,
39
+ * bounded on the right by either a closing quote or `/` (subpath imports
40
+ * like `'@fontsource/inter/400.css'` or `'react-dom/client'`). The right-
41
+ * side `/` is the only addition over a strict closing-quote match — `-` and
42
+ * `.` are still rejected so `react` does not match `react-dom`/`react.foo`. */
43
+ export function findQuotedReference(name, haystack) {
44
+ if (!name || !haystack)
45
+ return false;
46
+ return (haystack.includes(`'${name}'`) || haystack.includes(`"${name}"`) ||
47
+ haystack.includes(`'${name}/`) || haystack.includes(`"${name}/`));
48
+ }
49
+ const EXCLUDE_DIRS = new Set([
50
+ "node_modules", ".git", "dist", "build", "target", "out",
51
+ ".next", ".turbo", "__pycache__", ".pytest_cache",
52
+ ".venv", "venv", "coverage", ".cache",
53
+ // Documentation build outputs — generated HTML / static site artifacts that
54
+ // bloat the byte budget but never carry a meaningful dep / rule literal.
55
+ // Names match site generators' default output dirs (mkdocs `site/`, jekyll
56
+ // `_site/`, sphinx `_build/`). The 50-repo stress test hit budget exhaustion
57
+ // on fastapi/docs/pt translations and Alamofire/docs jazzy output via paths
58
+ // not in the original exclude list.
59
+ "site", "_site", "_build",
60
+ ]);
61
+ // Files that almost never carry a primary source reference but eat the byte
62
+ // budget on large repos. Cheap extension test before stat() avoids reading
63
+ // pre-rendered HTML, minified bundles, lockfiles, jupyter notebooks, and
64
+ // translation/data files from the haystack. If a project genuinely needs
65
+ // these scanned (rare), they can raise ANATOMY_SOURCE_SCAN_BYTES — but then
66
+ // they should also know that adding `.html` to a real source-of-truth list
67
+ // is unusual.
68
+ const SKIP_EXT_RE = /\.(?:html|htm|svg|min\.js|min\.css|map|lock|sum|snap|ipynb|csv|tsv|po|pot|jsonl|ndjson)$/i;
69
+ const TOP_LEVEL_CONFIG_RE = /^\.?(vite|webpack|esbuild|rollup|jest|vitest|eslint|prettier|tsconfig|babel|tailwind|postcss|biome|swc|turbo|nx|lerna|pnpm-workspace)[\w.-]*\.(?:js|ts|cjs|mjs|json|yaml|yml)?$/;
70
+ const TOP_LEVEL_CONFIG_LITERALS = new Set([
71
+ "Makefile", "Dockerfile", "docker-compose.yml", "docker-compose.yaml",
72
+ ]);
73
+ // 32 MB default — the prior 8 MB cap was tight enough that 7 of 50 mainstream
74
+ // repos in the v0.12 stress test (curl, fastapi, prettier, pandoc, Alamofire,
75
+ // Kong, plus one) hit `source-cross-check-truncated` despite mostly being
76
+ // bloated by docs/translations rather than source. With the doc-output
77
+ // EXCLUDE_DIRS additions and SKIP_EXT_RE blocklist below, 32 MB clears nearly
78
+ // all of them while still bounding pathological repos. Reading 32 MB of text
79
+ // into a haystack takes well under a second on any modern machine.
80
+ const DEFAULT_MAX_TOTAL_BYTES = 32 * 1024 * 1024;
81
+ const MAX_FILE_BYTES = 256 * 1024; // 256 KB
82
+ const MAX_DEPTH = 10;
83
+ const NUL_SCAN_BYTES = 4096;
84
+ /** Reads ANATOMY_SOURCE_SCAN_BYTES (e.g. "16M", "32768K", "16777216").
85
+ * Defaults to DEFAULT_MAX_TOTAL_BYTES (8 MB) when unset/malformed.
86
+ * Surfaced via the source-cross-check-truncated warning when the budget
87
+ * is exhausted, so monorepo users with >8MB of source can raise the cap
88
+ * without splitting into cascading sub-.anatomy files (per the
89
+ * 2026-05-09 stress test on openclaw-fresh). */
90
+ export function getMaxTotalBytes() {
91
+ const raw = process.env.ANATOMY_SOURCE_SCAN_BYTES;
92
+ if (!raw)
93
+ return DEFAULT_MAX_TOTAL_BYTES;
94
+ const m = /^(\d+)([KkMmGg]?)$/.exec(raw.trim());
95
+ if (!m)
96
+ return DEFAULT_MAX_TOTAL_BYTES;
97
+ const n = Number(m[1]);
98
+ if (!isFinite(n) || n <= 0)
99
+ return DEFAULT_MAX_TOTAL_BYTES;
100
+ const suffix = m[2].toLowerCase();
101
+ const mul = suffix === "k" ? 1024 : suffix === "m" ? 1024 * 1024 : suffix === "g" ? 1024 * 1024 * 1024 : 1;
102
+ return n * mul;
103
+ }
104
+ const TYPES_DEP_PREFIX = "@types/";
105
+ const TOOLING_DEP_ALLOWLIST = new Set(["husky", "lint-staged"]);
106
+ /** Sections of package.json that are *declarations* of deps, not uses. They
107
+ * must be excluded from the haystack — otherwise every declared dep would
108
+ * match as a quoted reference and Class 1 could never fire. */
109
+ const PACKAGE_JSON_DECLARATION_SECTIONS = [
110
+ "dependencies", "devDependencies", "peerDependencies",
111
+ "optionalDependencies", "bundleDependencies", "bundledDependencies",
112
+ ];
113
+ /** Tokens that delimit commands within a package.json script string. */
114
+ const SCRIPT_TOKEN_DELIMITERS = /[\s&|;><]+/;
115
+ /** Returns true if `name` appears as a whitespace/operator-bounded token in
116
+ * any value of the parsed package.json scripts. Handles bare invocation
117
+ * (`"prettier --write ."`), `npx <name>`, and chained commands
118
+ * (`"npm run lint && vitest run"`). For `@scope/name` deps, also matches
119
+ * the conventional bin form `<scope>-<name>` (e.g. `@electron/rebuild`
120
+ * publishes a bin called `electron-rebuild`). */
121
+ export function isUsedInScripts(name, scripts) {
122
+ if (!name || !scripts)
123
+ return false;
124
+ const candidates = [name];
125
+ const scopedMatch = /^@([a-z0-9][\w-]*)\/([a-z0-9][\w.-]*)$/.exec(name);
126
+ if (scopedMatch)
127
+ candidates.push(`${scopedMatch[1]}-${scopedMatch[2]}`);
128
+ for (const value of Object.values(scripts)) {
129
+ if (typeof value !== "string")
130
+ continue;
131
+ const tokens = value.split(SCRIPT_TOKEN_DELIMITERS).filter(Boolean);
132
+ for (const c of candidates)
133
+ if (tokens.includes(c))
134
+ return true;
135
+ }
136
+ return false;
137
+ }
138
+ /** Source-file extensions for the top-level source-file scan (matches the
139
+ * source-path regex's extension list). Repos that put code at the root
140
+ * rather than under src/ rely on this so dep imports there land in the
141
+ * haystack. */
142
+ const TOP_LEVEL_SOURCE_EXT_RE = /\.(?:ts|tsx|js|jsx|mjs|cjs|py|go|rs|java|kt|swift|c|cpp|h|hpp|rb|php)$/;
143
+ function isProbablyBinary(buf) {
144
+ const limit = Math.min(buf.length, NUL_SCAN_BYTES);
145
+ for (let i = 0; i < limit; i++) {
146
+ if (buf[i] === 0)
147
+ return true;
148
+ }
149
+ return false;
150
+ }
151
+ function recordSkip(builder, scanRoot, absPath) {
152
+ builder.truncated = true;
153
+ if (builder.firstSkippedRel === null) {
154
+ let rel = absPath.slice(scanRoot.length);
155
+ if (rel.startsWith("/") || rel.startsWith("\\"))
156
+ rel = rel.slice(1);
157
+ builder.firstSkippedRel = rel || absPath;
158
+ }
159
+ }
160
+ /** Loads package.json into the haystack but strips dep-declaration sections
161
+ * (`dependencies`, `devDependencies`, etc.). Without this, every quoted dep
162
+ * name in the manifest matches as a "use" and Class 1 cannot fire on any
163
+ * declared dep — which is the very case it exists to catch. Also captures
164
+ * the parsed scripts so checkDependencyUsage can detect bare-command usage.
165
+ * Falls back to plain text load if the file is not parseable JSON. */
166
+ function loadPackageJson(builder, scanRoot) {
167
+ const absPath = join(scanRoot, "package.json");
168
+ if (!existsSync(absPath))
169
+ return undefined;
170
+ if (builder.seenAbs.has(absPath))
171
+ return undefined;
172
+ let raw;
173
+ try {
174
+ raw = readFileSync(absPath, "utf8");
175
+ }
176
+ catch {
177
+ return undefined;
178
+ }
179
+ let parsed;
180
+ try {
181
+ parsed = JSON.parse(raw);
182
+ }
183
+ catch {
184
+ tryLoadFile(builder, scanRoot, absPath);
185
+ return undefined;
186
+ }
187
+ const filtered = { ...parsed };
188
+ for (const k of PACKAGE_JSON_DECLARATION_SECTIONS)
189
+ delete filtered[k];
190
+ const filteredText = JSON.stringify(filtered, null, 2);
191
+ const size = Buffer.byteLength(filteredText, "utf8");
192
+ if (builder.totalBytes + size > builder.maxTotalBytes) {
193
+ recordSkip(builder, scanRoot, absPath);
194
+ return undefined;
195
+ }
196
+ builder.files.push({ relPath: "package.json", content: filteredText });
197
+ builder.totalBytes += size;
198
+ builder.seenAbs.add(absPath);
199
+ const scripts = {};
200
+ const rawScripts = parsed.scripts;
201
+ if (rawScripts && typeof rawScripts === "object") {
202
+ for (const [k, v] of Object.entries(rawScripts)) {
203
+ if (typeof v === "string")
204
+ scripts[k] = v;
205
+ }
206
+ }
207
+ return scripts;
208
+ }
209
+ function tryLoadFile(builder, scanRoot, absPath) {
210
+ if (builder.truncated)
211
+ return;
212
+ if (builder.seenAbs.has(absPath))
213
+ return;
214
+ // Cheap extension test before stat() — skip rendered HTML, minified bundles,
215
+ // lockfiles, jupyter notebooks, translation/data files. None of these
216
+ // typically carry the dep / rule literals the cross-check is looking for,
217
+ // and on large repos they collectively dominate the byte budget.
218
+ if (SKIP_EXT_RE.test(absPath))
219
+ return;
220
+ let st;
221
+ try {
222
+ st = statSync(absPath);
223
+ }
224
+ catch {
225
+ return;
226
+ }
227
+ if (!st.isFile())
228
+ return;
229
+ if (st.size > MAX_FILE_BYTES)
230
+ return;
231
+ if (builder.totalBytes + st.size > builder.maxTotalBytes) {
232
+ recordSkip(builder, scanRoot, absPath);
233
+ return;
234
+ }
235
+ let buf;
236
+ try {
237
+ buf = readFileSync(absPath);
238
+ }
239
+ catch {
240
+ return;
241
+ }
242
+ if (isProbablyBinary(buf))
243
+ return;
244
+ let relPath = absPath.slice(scanRoot.length);
245
+ if (relPath.startsWith("/") || relPath.startsWith("\\"))
246
+ relPath = relPath.slice(1);
247
+ builder.files.push({ relPath, content: buf.toString("utf8") });
248
+ builder.totalBytes += st.size;
249
+ builder.seenAbs.add(absPath);
250
+ }
251
+ function walkDir(builder, scanRoot, dirAbs, depth) {
252
+ if (builder.truncated)
253
+ return;
254
+ if (depth > MAX_DEPTH)
255
+ return;
256
+ let entries;
257
+ try {
258
+ entries = readdirSync(dirAbs, { withFileTypes: true });
259
+ }
260
+ catch {
261
+ return;
262
+ }
263
+ for (const e of entries) {
264
+ if (builder.truncated)
265
+ return;
266
+ if (e.isDirectory()) {
267
+ if (EXCLUDE_DIRS.has(e.name))
268
+ continue;
269
+ walkDir(builder, scanRoot, join(dirAbs, e.name), depth + 1);
270
+ }
271
+ else if (e.isFile()) {
272
+ tryLoadFile(builder, scanRoot, join(dirAbs, e.name));
273
+ }
274
+ }
275
+ }
276
+ export function buildSourceIndex(scanRoot, structureEntries) {
277
+ const maxTotalBytes = getMaxTotalBytes();
278
+ const builder = {
279
+ files: [],
280
+ totalBytes: 0,
281
+ truncated: false,
282
+ firstSkippedRel: null,
283
+ maxTotalBytes,
284
+ seenAbs: new Set(),
285
+ };
286
+ if (!existsSync(scanRoot)) {
287
+ return { files: [], combinedHaystack: "", truncated: false, maxTotalBytes };
288
+ }
289
+ // 1. package.json — load FIRST so the filtered version (dep-declaration
290
+ // sections stripped) is what lands in the haystack. The structure walker
291
+ // below skips already-seen absolute paths, so a structure entry like
292
+ // path = "." won't re-load the unfiltered file.
293
+ const packageJsonScripts = loadPackageJson(builder, scanRoot);
294
+ // 2. Structure dirs (every entry, regardless of kind).
295
+ for (const entry of structureEntries) {
296
+ if (typeof entry?.path !== "string")
297
+ continue;
298
+ const dirAbs = resolve(scanRoot, entry.path);
299
+ if (!existsSync(dirAbs))
300
+ continue;
301
+ let st;
302
+ try {
303
+ st = statSync(dirAbs);
304
+ }
305
+ catch {
306
+ continue;
307
+ }
308
+ if (st.isFile()) {
309
+ tryLoadFile(builder, scanRoot, dirAbs);
310
+ }
311
+ else if (st.isDirectory()) {
312
+ walkDir(builder, scanRoot, dirAbs, 0);
313
+ }
314
+ }
315
+ // 3. Top-level config files + top-level source files. Source-file inclusion
316
+ // handles small repos that put server.js / database.js / main.py at the
317
+ // root rather than under src/ — without this, deps imported there look
318
+ // "unused" because the structure entries don't cover them.
319
+ let topEntries;
320
+ try {
321
+ topEntries = readdirSync(scanRoot, { withFileTypes: true });
322
+ }
323
+ catch {
324
+ topEntries = [];
325
+ }
326
+ for (const e of topEntries) {
327
+ if (!e.isFile())
328
+ continue;
329
+ if (TOP_LEVEL_CONFIG_LITERALS.has(e.name) ||
330
+ TOP_LEVEL_CONFIG_RE.test(e.name) ||
331
+ TOP_LEVEL_SOURCE_EXT_RE.test(e.name)) {
332
+ tryLoadFile(builder, scanRoot, join(scanRoot, e.name));
333
+ }
334
+ }
335
+ // 4. .github/workflows/*.{yml,yaml}.
336
+ const workflowsDir = join(scanRoot, ".github", "workflows");
337
+ if (existsSync(workflowsDir)) {
338
+ let wfEntries;
339
+ try {
340
+ wfEntries = readdirSync(workflowsDir, { withFileTypes: true });
341
+ }
342
+ catch {
343
+ wfEntries = [];
344
+ }
345
+ for (const e of wfEntries) {
346
+ if (!e.isFile())
347
+ continue;
348
+ if (e.name.endsWith(".yml") || e.name.endsWith(".yaml")) {
349
+ tryLoadFile(builder, scanRoot, join(workflowsDir, e.name));
350
+ }
351
+ }
352
+ }
353
+ const combinedHaystack = builder.files.map(f => f.content).join("\n\x00\n");
354
+ return {
355
+ files: builder.files,
356
+ combinedHaystack,
357
+ truncated: builder.truncated,
358
+ maxTotalBytes,
359
+ firstSkippedRel: builder.firstSkippedRel ?? undefined,
360
+ packageJsonScripts,
361
+ };
362
+ }
363
+ function checkDependencyUsage(keyDependencies, index) {
364
+ const warnings = [];
365
+ for (let i = 0; i < keyDependencies.length; i++) {
366
+ const name = keyDependencies[i]?.name;
367
+ if (typeof name !== "string" || name.length === 0)
368
+ continue;
369
+ if (name.startsWith(TYPES_DEP_PREFIX))
370
+ continue;
371
+ if (TOOLING_DEP_ALLOWLIST.has(name))
372
+ continue;
373
+ if (findQuotedReference(name, index.combinedHaystack))
374
+ continue;
375
+ if (isUsedInScripts(name, index.packageJsonScripts))
376
+ continue;
377
+ warnings.push({
378
+ code: "unused-dependency-claim",
379
+ message: `key_dependencies[${i}].name "${name}" not found as a quoted reference in scanned source. Either it's unused (consider removing) or it's referenced in a location the cross-check doesn't scan.`,
380
+ pointer: `/substance/key_dependencies/${i}`,
381
+ actual: name,
382
+ });
383
+ }
384
+ return warnings;
385
+ }
386
+ function collectClaimFields(doc) {
387
+ const out = [];
388
+ const d = doc;
389
+ if (Array.isArray(d.rules)) {
390
+ for (let i = 0; i < d.rules.length; i++) {
391
+ const r = d.rules[i];
392
+ if (typeof r?.rule === "string")
393
+ out.push({ arrayName: "rules", index: i, field: "rule", text: r.rule });
394
+ if (typeof r?.why === "string")
395
+ out.push({ arrayName: "rules", index: i, field: "why", text: r.why });
396
+ }
397
+ }
398
+ if (Array.isArray(d.flows)) {
399
+ for (let i = 0; i < d.flows.length; i++) {
400
+ const f = d.flows[i];
401
+ if (typeof f?.summary === "string")
402
+ out.push({ arrayName: "flows", index: i, field: "summary", text: f.summary });
403
+ }
404
+ }
405
+ if (Array.isArray(d.decisions)) {
406
+ for (let i = 0; i < d.decisions.length; i++) {
407
+ const dec = d.decisions[i];
408
+ if (typeof dec?.topic === "string")
409
+ out.push({ arrayName: "decisions", index: i, field: "topic", text: dec.topic });
410
+ if (typeof dec?.reason === "string")
411
+ out.push({ arrayName: "decisions", index: i, field: "reason", text: dec.reason });
412
+ }
413
+ }
414
+ return out;
415
+ }
416
+ function checkLiteralCrossReferences(fields, scanRoot, index) {
417
+ const warnings = [];
418
+ for (const f of fields) {
419
+ const literals = extractLiterals(f.text);
420
+ for (const { literal, kind } of literals) {
421
+ let found = false;
422
+ if (kind === "source-path") {
423
+ if (existsSync(resolve(scanRoot, literal))) {
424
+ found = true;
425
+ }
426
+ else if (index.combinedHaystack.includes(literal)) {
427
+ found = true;
428
+ }
429
+ }
430
+ else {
431
+ if (index.combinedHaystack.includes(literal))
432
+ found = true;
433
+ }
434
+ if (found)
435
+ continue;
436
+ warnings.push({
437
+ code: "literal-not-in-source",
438
+ message: `${kind} literal "${literal}" referenced in ${f.arrayName}[${f.index}].${f.field} not found in scanned source. Either the claim is stale or the literal is in an unscanned location.`,
439
+ pointer: `/${f.arrayName}/${f.index}/${f.field}`,
440
+ actual: literal,
441
+ literalKind: kind,
442
+ });
443
+ }
444
+ }
445
+ return warnings;
446
+ }
447
+ export function sourceCrossCheck(doc, repoRoot, anatomyDir) {
448
+ if (!repoRoot)
449
+ return { errors: [], warnings: [] };
450
+ const scanRoot = anatomyDir ? resolve(repoRoot, anatomyDir) : repoRoot;
451
+ const structureEntries = doc?.structure?.entries ?? [];
452
+ const keyDependencies = doc?.substance?.key_dependencies ?? [];
453
+ const claimFields = collectClaimFields(doc);
454
+ if (keyDependencies.length === 0 && claimFields.length === 0) {
455
+ return { errors: [], warnings: [] };
456
+ }
457
+ const index = buildSourceIndex(scanRoot, structureEntries);
458
+ const warnings = [];
459
+ if (index.truncated) {
460
+ const skippedNote = index.firstSkippedRel
461
+ ? ` First file skipped: ${JSON.stringify(index.firstSkippedRel)}.`
462
+ : "";
463
+ warnings.push({
464
+ code: "source-cross-check-truncated",
465
+ message: `source-cross-check stopped indexing at ${index.maxTotalBytes} bytes; some files were not scanned.${skippedNote} Set ANATOMY_SOURCE_SCAN_BYTES (e.g. 16M, 64M) to raise the budget, or split via cascading sub-.anatomy files for monorepos. Drift in unscanned files cannot be detected.`,
466
+ pointer: "",
467
+ });
468
+ }
469
+ warnings.push(...checkDependencyUsage(keyDependencies, index));
470
+ warnings.push(...checkLiteralCrossReferences(claimFields, scanRoot, index));
471
+ return { errors: [], warnings };
472
+ }
473
+ //# sourceMappingURL=source-cross-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-cross-check.js","sourceRoot":"","sources":["../../src/checks/source-cross-check.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { ValidationError, Warning } from "../errors.js";
2
+ export declare function sourcePathCheck(doc: unknown, repoRoot?: string, anatomyDir?: string): {
3
+ errors: ValidationError[];
4
+ warnings: Warning[];
5
+ };
6
+ //# sourceMappingURL=source-path-check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-path-check.d.ts","sourceRoot":"","sources":["../../src/checks/source-path-check.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE7D,wBAAgB,eAAe,CAC7B,GAAG,EAAE,OAAO,EACZ,QAAQ,CAAC,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,GAClB;IACD,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB,CAkDA"}
@@ -0,0 +1,62 @@
1
+ // src/checks/source-path-check.ts
2
+ // For [[substance.capabilities|limitations]].source:
3
+ // - Structured form ({ path, symbol }): hard error if path doesn't exist
4
+ // under repoRoot.
5
+ // - String form ("path#fragment"): soft warning if the leading path doesn't
6
+ // exist (the v0.1 string format was deliberately permissive).
7
+ // When repoRoot is undefined: skipped entirely.
8
+ import { existsSync } from "node:fs";
9
+ import { resolve } from "node:path";
10
+ export function sourcePathCheck(doc, repoRoot, anatomyDir) {
11
+ if (!repoRoot)
12
+ return { errors: [], warnings: [] };
13
+ const base = anatomyDir ? resolve(repoRoot, anatomyDir) : repoRoot;
14
+ const errors = [];
15
+ const warnings = [];
16
+ const subst = doc?.substance;
17
+ if (!subst)
18
+ return { errors, warnings };
19
+ for (const arrName of ["capabilities", "limitations"]) {
20
+ const arr = subst[arrName];
21
+ if (!Array.isArray(arr))
22
+ continue;
23
+ for (let i = 0; i < arr.length; i++) {
24
+ const src = arr[i]?.source;
25
+ if (src === undefined)
26
+ continue;
27
+ let path;
28
+ let isStructured = false;
29
+ if (typeof src === "string") {
30
+ const hashIdx = src.indexOf("#");
31
+ path = hashIdx === -1 ? src : src.slice(0, hashIdx);
32
+ if (path === "")
33
+ continue;
34
+ }
35
+ else if (src && typeof src === "object" && typeof src.path === "string") {
36
+ path = src.path;
37
+ isStructured = true;
38
+ }
39
+ if (path === undefined)
40
+ continue;
41
+ if (existsSync(resolve(base, path)))
42
+ continue;
43
+ if (isStructured) {
44
+ errors.push({
45
+ code: "source-path-not-found",
46
+ message: `substance.${arrName}[${i}].source.path not found: ${path}`,
47
+ pointer: `/substance/${arrName}/${i}/source/path`,
48
+ actual: path,
49
+ });
50
+ }
51
+ else {
52
+ warnings.push({
53
+ code: "source-path-soft-not-found",
54
+ message: `substance.${arrName}[${i}].source path not found: ${path} (string form is best-effort)`,
55
+ pointer: `/substance/${arrName}/${i}/source`,
56
+ });
57
+ }
58
+ }
59
+ }
60
+ return { errors, warnings };
61
+ }
62
+ //# sourceMappingURL=source-path-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-path-check.js","sourceRoot":"","sources":["../../src/checks/source-path-check.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAClC,qDAAqD;AACrD,2EAA2E;AAC3E,sBAAsB;AACtB,8EAA8E;AAC9E,kEAAkE;AAClE,gDAAgD;AAEhD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,MAAM,UAAU,eAAe,CAC7B,GAAY,EACZ,QAAiB,EACjB,UAAmB;IAKnB,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAEnD,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IACnE,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAI,GAA+E,EAAE,SAAS,CAAC;IAC1G,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IAExC,KAAK,MAAM,OAAO,IAAI,CAAC,cAAc,EAAE,aAAa,CAAU,EAAE,CAAC;QAC/D,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;YAAE,SAAS;QAElC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACpC,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC;YAC3B,IAAI,GAAG,KAAK,SAAS;gBAAE,SAAS;YAEhC,IAAI,IAAwB,CAAC;YAC7B,IAAI,YAAY,GAAG,KAAK,CAAC;YAEzB,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;gBAC5B,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBACjC,IAAI,GAAG,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;gBACpD,IAAI,IAAI,KAAK,EAAE;oBAAE,SAAS;YAC5B,CAAC;iBAAM,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,OAAQ,GAA0B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAClG,IAAI,GAAI,GAAwB,CAAC,IAAI,CAAC;gBACtC,YAAY,GAAG,IAAI,CAAC;YACtB,CAAC;YAED,IAAI,IAAI,KAAK,SAAS;gBAAE,SAAS;YACjC,IAAI,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBAAE,SAAS;YAE9C,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,uBAAuB;oBAC7B,OAAO,EAAE,aAAa,OAAO,IAAI,CAAC,4BAA4B,IAAI,EAAE;oBACpE,OAAO,EAAE,cAAc,OAAO,IAAI,CAAC,cAAc;oBACjD,MAAM,EAAE,IAAI;iBACb,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,4BAA4B;oBAClC,OAAO,EAAE,aAAa,OAAO,IAAI,CAAC,4BAA4B,IAAI,+BAA+B;oBACjG,OAAO,EAAE,cAAc,OAAO,IAAI,CAAC,SAAS;iBAC7C,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { ValidationError, Warning } from "../errors.js";
2
+ export declare function structurePathCheck(doc: unknown, repoRoot?: string, anatomyDir?: string): {
3
+ errors: ValidationError[];
4
+ warnings: Warning[];
5
+ };
6
+ //# sourceMappingURL=structure-path-check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structure-path-check.d.ts","sourceRoot":"","sources":["../../src/checks/structure-path-check.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE7D,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,OAAO,EACZ,QAAQ,CAAC,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,GAClB;IACD,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB,CAsBA"}
@@ -0,0 +1,31 @@
1
+ // src/checks/structure-path-check.ts
2
+ // Verifies every [[structure.entries]].path exists on disk relative to the
3
+ // caller-supplied repoRoot. When repoRoot is undefined (library callers,
4
+ // conformance fixtures), the check is a no-op — paths are not checked.
5
+ import { existsSync } from "node:fs";
6
+ import { resolve } from "node:path";
7
+ export function structurePathCheck(doc, repoRoot, anatomyDir) {
8
+ if (!repoRoot)
9
+ return { errors: [], warnings: [] };
10
+ const entries = doc?.structure?.entries;
11
+ if (!Array.isArray(entries))
12
+ return { errors: [], warnings: [] };
13
+ const base = anatomyDir ? resolve(repoRoot, anatomyDir) : repoRoot;
14
+ const errors = [];
15
+ for (let i = 0; i < entries.length; i++) {
16
+ const p = entries[i]?.path;
17
+ if (typeof p !== "string")
18
+ continue; // schema-check catches malformed
19
+ const abs = resolve(base, p);
20
+ if (!existsSync(abs)) {
21
+ errors.push({
22
+ code: "structure-path-not-found",
23
+ message: `structure entry path not found: ${p}`,
24
+ pointer: `/structure/entries/${i}/path`,
25
+ actual: p,
26
+ });
27
+ }
28
+ }
29
+ return { errors, warnings: [] };
30
+ }
31
+ //# sourceMappingURL=structure-path-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structure-path-check.js","sourceRoot":"","sources":["../../src/checks/structure-path-check.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,2EAA2E;AAC3E,yEAAyE;AACzE,uEAAuE;AAEvE,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,MAAM,UAAU,kBAAkB,CAChC,GAAY,EACZ,QAAiB,EACjB,UAAmB;IAKnB,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAEnD,MAAM,OAAO,GAAI,GAA8D,EAAE,SAAS,EAAE,OAAO,CAAC;IACpG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAEjE,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IACnE,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;QAC3B,IAAI,OAAO,CAAC,KAAK,QAAQ;YAAE,SAAS,CAAC,iCAAiC;QACtE,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAC7B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,0BAA0B;gBAChC,OAAO,EAAE,mCAAmC,CAAC,EAAE;gBAC/C,OAAO,EAAE,sBAAsB,CAAC,OAAO;gBACvC,MAAM,EAAE,CAAC;aACV,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AAClC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { Warning } from "../../errors.js";
2
+ import type { AstPatternConfig } from "./types.js";
3
+ export declare function verifyAstPattern(repoRoot: string, cfg: AstPatternConfig, pointer: string): Promise<Warning[]>;
4
+ //# sourceMappingURL=ast-grep-verifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast-grep-verifier.d.ts","sourceRoot":"","sources":["../../../src/checks/verify/ast-grep-verifier.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAoDnD,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,gBAAgB,EACrB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,OAAO,EAAE,CAAC,CA0GpB"}