llmnav 0.5.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 (68) hide show
  1. package/CHANGELOG.md +113 -0
  2. package/LICENSE +21 -0
  3. package/README.md +294 -0
  4. package/ROADMAP.md +71 -0
  5. package/bin/llmnav.js +16 -0
  6. package/docs/agent-integration.md +114 -0
  7. package/docs/api.md +290 -0
  8. package/docs/architecture.md +286 -0
  9. package/docs/benchmarking.md +164 -0
  10. package/docs/ci.md +196 -0
  11. package/docs/cli.md +233 -0
  12. package/docs/configuration.md +117 -0
  13. package/docs/editor-integration.md +29 -0
  14. package/docs/faq.md +59 -0
  15. package/docs/graph.md +92 -0
  16. package/docs/language-examples.md +130 -0
  17. package/docs/migration.md +130 -0
  18. package/docs/performance-v0.2.md +42 -0
  19. package/docs/provider-neutral-integration.md +66 -0
  20. package/docs/publishing.md +86 -0
  21. package/docs/quickstart.md +139 -0
  22. package/docs/research.md +31 -0
  23. package/docs/spec.md +424 -0
  24. package/examples/provider-neutral-host.d.mts +17 -0
  25. package/examples/provider-neutral-host.mjs +40 -0
  26. package/package.json +79 -0
  27. package/schema/config.schema.json +296 -0
  28. package/src/agent-protocol.js +117 -0
  29. package/src/agent-tools.js +61 -0
  30. package/src/agents.js +127 -0
  31. package/src/boundaries.js +50 -0
  32. package/src/changes.js +168 -0
  33. package/src/cli.js +459 -0
  34. package/src/config.js +305 -0
  35. package/src/contracts.js +70 -0
  36. package/src/declaration.js +334 -0
  37. package/src/doctor.js +124 -0
  38. package/src/editor.js +107 -0
  39. package/src/evaluation.js +67 -0
  40. package/src/files.js +81 -0
  41. package/src/formatter.js +23 -0
  42. package/src/generator.js +528 -0
  43. package/src/graph-input.js +157 -0
  44. package/src/graph.js +403 -0
  45. package/src/incremental.js +262 -0
  46. package/src/index.d.ts +673 -0
  47. package/src/index.js +115 -0
  48. package/src/initializer.js +137 -0
  49. package/src/inverted-index.js +350 -0
  50. package/src/parser.js +449 -0
  51. package/src/project.js +65 -0
  52. package/src/prompt-bundle.js +108 -0
  53. package/src/registry.js +107 -0
  54. package/src/sarif.js +70 -0
  55. package/src/search-shards.js +75 -0
  56. package/src/search.js +636 -0
  57. package/src/spec.d.ts +27 -0
  58. package/src/spec.js +237 -0
  59. package/src/tokenizer.js +37 -0
  60. package/src/transaction.js +557 -0
  61. package/src/util.js +256 -0
  62. package/src/validator.js +635 -0
  63. package/templates/file-card.txt +8 -0
  64. package/templates/lexicon.json +7 -0
  65. package/templates/line-card.txt +9 -0
  66. package/templates/module-card.txt +9 -0
  67. package/templates/queries.jsonl +1 -0
  68. package/templates/symbol-card.txt +10 -0
package/src/spec.js ADDED
@@ -0,0 +1,237 @@
1
+ export const PACKAGE_VERSION = "0.5.1";
2
+ export const SPEC_VERSION = "1";
3
+
4
+ export const SCOPES = Object.freeze(["file", "module", "symbol"]);
5
+ export const STABILITIES = Object.freeze(["architecture", "contract", "implementation"]);
6
+
7
+ export const KEY_ORDER = Object.freeze([
8
+ "id",
9
+ "role",
10
+ "owns",
11
+ "excludes",
12
+ "search",
13
+ "invariant",
14
+ "effect",
15
+ "risk",
16
+ "rel",
17
+ "stability",
18
+ ]);
19
+
20
+ export const REQUIRED_KEYS = Object.freeze(["id", "role", "stability"]);
21
+ export const REPEATABLE_KEYS = Object.freeze(["invariant", "rel"]);
22
+ export const LIST_KEYS = Object.freeze(["owns", "excludes", "search", "effect", "risk"]);
23
+ export const SCALAR_KEYS = Object.freeze(["id", "role", "stability"]);
24
+ export const ALLOWED_KEYS = Object.freeze([...KEY_ORDER]);
25
+
26
+ export const EFFECT_KINDS_WITH_ARGUMENT = Object.freeze([
27
+ "db.read",
28
+ "db.write",
29
+ "cache.read",
30
+ "cache.write",
31
+ "event.emit",
32
+ "event.consume",
33
+ "net.call",
34
+ "lock.acquire",
35
+ "cookie.write",
36
+ "auth.check",
37
+ ]);
38
+
39
+ export const EFFECT_KINDS_WITHOUT_ARGUMENT = Object.freeze([
40
+ "fs.read",
41
+ "fs.write",
42
+ "process.spawn",
43
+ "clock.read",
44
+ "random.read",
45
+ ]);
46
+
47
+ export const EFFECT_KINDS = Object.freeze([
48
+ ...EFFECT_KINDS_WITH_ARGUMENT,
49
+ ...EFFECT_KINDS_WITHOUT_ARGUMENT,
50
+ ]);
51
+
52
+ export const RISK_KINDS = Object.freeze([
53
+ "auth",
54
+ "money",
55
+ "privacy",
56
+ "concurrency",
57
+ "migration",
58
+ "availability",
59
+ "performance",
60
+ ]);
61
+
62
+ export const STRICT_RISKS = Object.freeze(["auth", "money", "privacy"]);
63
+
64
+ export const RELATION_KINDS = Object.freeze([
65
+ "policy",
66
+ "workflow",
67
+ "fallback",
68
+ "mirror",
69
+ "migration",
70
+ "test",
71
+ "replaces",
72
+ "deprecated-by",
73
+ "cross-repo",
74
+ ]);
75
+
76
+ export const FORBIDDEN_STRUCTURE_RELATIONS = Object.freeze([
77
+ "calls",
78
+ "imports",
79
+ "references",
80
+ "implements",
81
+ "exports",
82
+ "overrides",
83
+ ]);
84
+
85
+ export const FORBIDDEN_VOLATILE_KEYS = Object.freeze([
86
+ "path",
87
+ "line",
88
+ "span",
89
+ "commit",
90
+ "updated_at",
91
+ "updated-at",
92
+ "owner",
93
+ "callers",
94
+ "callees",
95
+ "imports",
96
+ "references",
97
+ "implementation_count",
98
+ "implementation-count",
99
+ "test_status",
100
+ "test-status",
101
+ "current_signature",
102
+ "current-signature",
103
+ ]);
104
+
105
+ export const DEFAULT_INCLUDE_EXTENSIONS = Object.freeze([
106
+ ".ts",
107
+ ".tsx",
108
+ ".js",
109
+ ".jsx",
110
+ ".mjs",
111
+ ".cjs",
112
+ ".go",
113
+ ".rs",
114
+ ".py",
115
+ ".java",
116
+ ".kt",
117
+ ".kts",
118
+ ".c",
119
+ ".cc",
120
+ ".cpp",
121
+ ".h",
122
+ ".hpp",
123
+ ".cs",
124
+ ".swift",
125
+ ".dart",
126
+ ".php",
127
+ ".rb",
128
+ ".sh",
129
+ ".bash",
130
+ ".zsh",
131
+ ".sql",
132
+ ".svelte",
133
+ ".astro",
134
+ ".vue",
135
+ ]);
136
+
137
+ export const DEFAULT_EXCLUDED_DIRECTORIES = Object.freeze([
138
+ ".git",
139
+ ".hg",
140
+ ".svn",
141
+ ".idea",
142
+ ".vscode",
143
+ "node_modules",
144
+ "vendor",
145
+ "dist",
146
+ "build",
147
+ "coverage",
148
+ ".next",
149
+ ".nuxt",
150
+ ".svelte-kit",
151
+ ".astro",
152
+ ".turbo",
153
+ ".cache",
154
+ "target",
155
+ "bin",
156
+ "obj",
157
+ ]);
158
+
159
+ export const DEFAULT_GENERIC_SEARCH_TERMS = Object.freeze([
160
+ "service",
161
+ "manager",
162
+ "handler",
163
+ "helper",
164
+ "utility",
165
+ "util",
166
+ "data",
167
+ "process",
168
+ "logic",
169
+ "common",
170
+ "shared",
171
+ ]);
172
+
173
+ export const DEFAULT_VAGUE_ROLE_WORDS = Object.freeze([
174
+ "handle",
175
+ "handles",
176
+ "manage",
177
+ "manages",
178
+ "process",
179
+ "processes",
180
+ "utility",
181
+ "helper",
182
+ "service",
183
+ ]);
184
+
185
+ export const ID_PATTERN = /^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9-]*){1,5}$/u;
186
+ export const CROSS_REPO_ID_PATTERN = /^[a-z][a-z0-9-]*\/[a-z][a-z0-9]*(?:\.[a-z][a-z0-9-]*){1,5}$/u;
187
+
188
+ export const DEFAULT_CONFIG = Object.freeze({
189
+ $schema: "./schema/config.schema.json",
190
+ version: 1,
191
+ repositoryId: "change-me",
192
+ sourceRoots: ["."],
193
+ includeExtensions: [...DEFAULT_INCLUDE_EXTENSIONS],
194
+ excludeDirectories: [...DEFAULT_EXCLUDED_DIRECTORIES],
195
+ excludeFiles: ["*.min.js", "*.bundle.js", "*.generated.*", "*.gen.*"],
196
+ coverageRules: [],
197
+ graph: {
198
+ indexFiles: [],
199
+ },
200
+ lint: {
201
+ maxRoleLength: 180,
202
+ maxSearchTerms: 6,
203
+ minSearchTerms: 2,
204
+ maxInvariants: 4,
205
+ maxEffects: 6,
206
+ maxRelations: 6,
207
+ maxBlockBytes: {
208
+ file: 400,
209
+ module: 1200,
210
+ symbol: 900,
211
+ },
212
+ maxSemanticRatio: 0.015,
213
+ minimumSourceBytesForRatio: 50000,
214
+ searchTermSaturation: 0.05,
215
+ minimumCardsForSaturation: 20,
216
+ genericSearchTerms: [...DEFAULT_GENERIC_SEARCH_TERMS],
217
+ vagueRoleWords: [...DEFAULT_VAGUE_ROLE_WORDS],
218
+ strictRisks: [...STRICT_RISKS],
219
+ additionalEffects: [],
220
+ additionalRisks: [],
221
+ additionalRelations: [],
222
+ requireCanonicalOrder: true,
223
+ requireCanonicalFormatting: true,
224
+ },
225
+ generation: {
226
+ cacheDirectory: ".llmnav/cache",
227
+ moduleDepth: 2,
228
+ searchShardSize: 0,
229
+ repositoryCatalogStabilities: ["architecture"],
230
+ moduleCatalogStabilities: ["architecture", "contract"],
231
+ },
232
+ evaluation: {
233
+ queryFile: ".llmnav/eval/queries.jsonl",
234
+ minimumRecallAt1: 0.75,
235
+ minimumRecallAt5: 0.9,
236
+ },
237
+ });
@@ -0,0 +1,37 @@
1
+ /* llmnav/1 module
2
+ id=llmnav.search.tokenize
3
+ role=Normalize task text and emit deterministic word and CJK n-gram tokens for semantic retrieval.
4
+ owns=query normalization|CJK n-grams|tokenizer version
5
+ excludes=card ranking|inverted-index persistence
6
+ search=search tokenizer|CJK ngram|query normalization
7
+ rel=workflow>llmnav.search.query
8
+ stability=architecture
9
+ */
10
+
11
+ export const TOKENIZER_VERSION = 1;
12
+
13
+ export function normalizeSearchText(value) {
14
+ return String(value ?? "").normalize("NFKC").toLocaleLowerCase("en-US").trim();
15
+ }
16
+
17
+ export function tokenize(value) {
18
+ const normalized = normalizeSearchText(value);
19
+ const base = normalized.match(/[\p{L}\p{N}]+/gu) ?? [];
20
+ const tokens = [...base];
21
+ for (const token of base) {
22
+ if (containsCjk(token) && [...token].length >= 3) {
23
+ const characters = [...token];
24
+ for (let index = 0; index <= characters.length - 2; index += 1) {
25
+ tokens.push(characters.slice(index, index + 2).join(""));
26
+ }
27
+ for (let index = 0; index <= characters.length - 3; index += 1) {
28
+ tokens.push(characters.slice(index, index + 3).join(""));
29
+ }
30
+ }
31
+ }
32
+ return tokens;
33
+ }
34
+
35
+ function containsCjk(value) {
36
+ return /[\p{Script=Han}\p{Script=Hangul}\p{Script=Hiragana}\p{Script=Katakana}]/u.test(value);
37
+ }