trellis 1.0.8 → 2.0.6

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 (107) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +564 -83
  3. package/bin/trellis.mjs +2 -0
  4. package/dist/cli/index.js +4718 -0
  5. package/dist/core/index.js +12 -0
  6. package/dist/decisions/index.js +19 -0
  7. package/dist/embeddings/index.js +43 -0
  8. package/dist/index-1j1anhmr.js +4038 -0
  9. package/dist/index-3s0eak0p.js +1556 -0
  10. package/dist/index-8pce39mh.js +272 -0
  11. package/dist/index-a76rekgs.js +67 -0
  12. package/dist/index-cy9k1g6v.js +684 -0
  13. package/dist/index-fd4e26s4.js +69 -0
  14. package/dist/{store/eav-store.js → index-gkvhzm9f.js} +4 -6
  15. package/dist/index-gnw8d7d6.js +51 -0
  16. package/dist/index-vkpkfwhq.js +817 -0
  17. package/dist/index.js +118 -2876
  18. package/dist/links/index.js +55 -0
  19. package/dist/transformers-m9je15kg.js +32491 -0
  20. package/dist/vcs/index.js +110 -0
  21. package/logo.png +0 -0
  22. package/logo.svg +9 -0
  23. package/package.json +79 -76
  24. package/src/cli/index.ts +2340 -0
  25. package/src/core/index.ts +35 -0
  26. package/src/core/kernel/middleware.ts +44 -0
  27. package/src/core/persist/backend.ts +64 -0
  28. package/src/core/store/eav-store.ts +467 -0
  29. package/src/decisions/auto-capture.ts +136 -0
  30. package/src/decisions/hooks.ts +163 -0
  31. package/src/decisions/index.ts +261 -0
  32. package/src/decisions/types.ts +103 -0
  33. package/src/embeddings/chunker.ts +327 -0
  34. package/src/embeddings/index.ts +41 -0
  35. package/src/embeddings/model.ts +95 -0
  36. package/src/embeddings/search.ts +305 -0
  37. package/src/embeddings/store.ts +313 -0
  38. package/src/embeddings/types.ts +85 -0
  39. package/src/engine.ts +1083 -0
  40. package/src/garden/cluster.ts +330 -0
  41. package/src/garden/garden.ts +306 -0
  42. package/src/garden/index.ts +29 -0
  43. package/src/git/git-exporter.ts +286 -0
  44. package/src/git/git-importer.ts +329 -0
  45. package/src/git/git-reader.ts +189 -0
  46. package/src/git/index.ts +22 -0
  47. package/src/identity/governance.ts +211 -0
  48. package/src/identity/identity.ts +224 -0
  49. package/src/identity/index.ts +30 -0
  50. package/src/identity/signing-middleware.ts +97 -0
  51. package/src/index.ts +20 -0
  52. package/src/links/index.ts +49 -0
  53. package/src/links/lifecycle.ts +400 -0
  54. package/src/links/parser.ts +484 -0
  55. package/src/links/ref-index.ts +186 -0
  56. package/src/links/resolver.ts +314 -0
  57. package/src/links/types.ts +108 -0
  58. package/src/mcp/index.ts +22 -0
  59. package/src/mcp/server.ts +1278 -0
  60. package/src/semantic/csharp-parser.ts +493 -0
  61. package/src/semantic/go-parser.ts +585 -0
  62. package/src/semantic/index.ts +34 -0
  63. package/src/semantic/java-parser.ts +456 -0
  64. package/src/semantic/python-parser.ts +659 -0
  65. package/src/semantic/ruby-parser.ts +446 -0
  66. package/src/semantic/rust-parser.ts +784 -0
  67. package/src/semantic/semantic-merge.ts +210 -0
  68. package/src/semantic/ts-parser.ts +681 -0
  69. package/src/semantic/types.ts +175 -0
  70. package/src/sync/index.ts +32 -0
  71. package/src/sync/memory-transport.ts +66 -0
  72. package/src/sync/reconciler.ts +237 -0
  73. package/src/sync/sync-engine.ts +258 -0
  74. package/src/sync/types.ts +104 -0
  75. package/src/vcs/blob-store.ts +124 -0
  76. package/src/vcs/branch.ts +150 -0
  77. package/src/vcs/checkpoint.ts +64 -0
  78. package/src/vcs/decompose.ts +469 -0
  79. package/src/vcs/diff.ts +409 -0
  80. package/src/vcs/engine-context.ts +26 -0
  81. package/src/vcs/index.ts +23 -0
  82. package/src/vcs/issue.ts +800 -0
  83. package/src/vcs/merge.ts +425 -0
  84. package/src/vcs/milestone.ts +124 -0
  85. package/src/vcs/ops.ts +59 -0
  86. package/src/vcs/types.ts +213 -0
  87. package/src/vcs/vcs-middleware.ts +81 -0
  88. package/src/watcher/fs-watcher.ts +217 -0
  89. package/src/watcher/index.ts +9 -0
  90. package/src/watcher/ingestion.ts +116 -0
  91. package/dist/ai/index.js +0 -688
  92. package/dist/cli/server.js +0 -3321
  93. package/dist/cli/tql.js +0 -5282
  94. package/dist/client/tql-client.js +0 -108
  95. package/dist/graph/index.js +0 -2248
  96. package/dist/kernel/logic-middleware.js +0 -179
  97. package/dist/kernel/middleware.js +0 -0
  98. package/dist/kernel/operations.js +0 -32
  99. package/dist/kernel/schema-middleware.js +0 -34
  100. package/dist/kernel/security-middleware.js +0 -53
  101. package/dist/kernel/trellis-kernel.js +0 -2239
  102. package/dist/kernel/workspace.js +0 -91
  103. package/dist/persist/backend.js +0 -0
  104. package/dist/persist/sqlite-backend.js +0 -123
  105. package/dist/query/index.js +0 -1643
  106. package/dist/server/index.js +0 -3309
  107. package/dist/workflows/index.js +0 -3160
@@ -0,0 +1,456 @@
1
+ /**
2
+ * Java Parser Adapter
3
+ *
4
+ * Tier 1 regex-based parser for Java source files.
5
+ * Extracts classes, interfaces, enums, methods, fields,
6
+ * annotations, imports, and package declarations.
7
+ *
8
+ * @see TRL-9
9
+ */
10
+
11
+ import type {
12
+ ParserAdapter,
13
+ ParseResult,
14
+ ASTEntity,
15
+ ASTEntityKind,
16
+ ImportRelation,
17
+ ExportRelation,
18
+ SemanticPatch,
19
+ } from './types.js';
20
+
21
+ // ---------------------------------------------------------------------------
22
+ // Parser Adapter
23
+ // ---------------------------------------------------------------------------
24
+
25
+ export const javaParser: ParserAdapter = {
26
+ languages: ['java'],
27
+
28
+ parse(content: string, filePath: string): ParseResult {
29
+ const fileEntityId = `file:${filePath}`;
30
+
31
+ return {
32
+ fileEntityId,
33
+ filePath,
34
+ language: 'java',
35
+ declarations: extractDeclarations(content, filePath),
36
+ imports: extractImports(content),
37
+ exports: extractExports(content, filePath),
38
+ };
39
+ },
40
+
41
+ diff(oldResult: ParseResult, newResult: ParseResult): SemanticPatch[] {
42
+ return computeSemanticDiff(oldResult, newResult);
43
+ },
44
+ };
45
+
46
+ // ---------------------------------------------------------------------------
47
+ // Declaration extraction
48
+ // ---------------------------------------------------------------------------
49
+
50
+ const MODIFIERS = /(?:(?:public|private|protected|static|final|abstract|synchronized|native|transient|volatile|strictfp|sealed|non-sealed|default)\s+)*/;
51
+ const CLASS_RE = new RegExp(`^${MODIFIERS.source}(class|interface|enum|record|@interface)\\s+(\\w+)`);
52
+ const METHOD_RE = new RegExp(`^${MODIFIERS.source}(?:<[^>]+>\\s+)?(?:\\w[\\w<>\\[\\],\\s?]*?)\\s+(\\w+)\\s*\\(`);
53
+ const FIELD_RE = new RegExp(`^${MODIFIERS.source}(?:\\w[\\w<>\\[\\],\\s?]*?)\\s+(\\w+)\\s*[;=]`);
54
+
55
+ function extractDeclarations(content: string, filePath: string): ASTEntity[] {
56
+ const declarations: ASTEntity[] = [];
57
+ const lines = content.split('\n');
58
+
59
+ let i = 0;
60
+ while (i < lines.length) {
61
+ const trimmed = lines[i].trim();
62
+
63
+ // Skip empty lines, comments, package, import
64
+ if (
65
+ !trimmed ||
66
+ trimmed.startsWith('//') ||
67
+ trimmed.startsWith('/*') ||
68
+ trimmed.startsWith('*') ||
69
+ trimmed.startsWith('package ') ||
70
+ trimmed.startsWith('import ')
71
+ ) {
72
+ i++;
73
+ continue;
74
+ }
75
+
76
+ // Collect annotations
77
+ const annotations: string[] = [];
78
+ const annoStart = i;
79
+ while (i < lines.length && lines[i].trim().startsWith('@')) {
80
+ annotations.push(lines[i].trim());
81
+ i++;
82
+ }
83
+ if (i >= lines.length) break;
84
+
85
+ const declLine = lines[i].trim();
86
+
87
+ // Strip annotations from matching
88
+ const stripped = declLine;
89
+
90
+ // Class/Interface/Enum/Record
91
+ const classMatch = stripped.match(CLASS_RE);
92
+ if (classMatch) {
93
+ const typeKind = classMatch[1];
94
+ const name = classMatch[2];
95
+ const kind: ASTEntityKind = typeKind === 'interface' || typeKind === '@interface'
96
+ ? 'InterfaceDef'
97
+ : typeKind === 'enum'
98
+ ? 'EnumDef'
99
+ : 'ClassDef';
100
+ const result = extractBraceBlock(name, kind, lines, annotations.length > 0 ? annoStart : i, i, filePath);
101
+ result.entity.children = extractClassMembers(lines, i, result.endLine, name, filePath);
102
+ declarations.push(result.entity);
103
+ i = result.endLine + 1;
104
+ continue;
105
+ }
106
+
107
+ // Top-level method (in case of no class wrapper, or inner classes parsed separately)
108
+ const methodMatch = stripped.match(METHOD_RE);
109
+ if (methodMatch && !stripped.includes(' class ') && !stripped.includes(' interface ') && !stripped.includes(' new ')) {
110
+ const name = methodMatch[1];
111
+ if (name !== 'if' && name !== 'for' && name !== 'while' && name !== 'switch' && name !== 'catch') {
112
+ if (stripped.includes('{') || (i + 1 < lines.length && lines[i + 1].trim() === '{')) {
113
+ const result = extractBraceBlock(name, 'FunctionDef', lines, annotations.length > 0 ? annoStart : i, i, filePath);
114
+ declarations.push(result.entity);
115
+ i = result.endLine + 1;
116
+ continue;
117
+ }
118
+ }
119
+ }
120
+
121
+ // If annotations were collected but no match, skip
122
+ if (annotations.length > 0) {
123
+ i++;
124
+ continue;
125
+ }
126
+
127
+ i++;
128
+ }
129
+
130
+ return declarations;
131
+ }
132
+
133
+ // ---------------------------------------------------------------------------
134
+ // Block extraction
135
+ // ---------------------------------------------------------------------------
136
+
137
+ interface ExtractionResult {
138
+ entity: ASTEntity;
139
+ endLine: number;
140
+ }
141
+
142
+ function extractBraceBlock(
143
+ name: string,
144
+ kind: ASTEntityKind,
145
+ lines: string[],
146
+ startLine: number,
147
+ defLine: number,
148
+ filePath: string,
149
+ ): ExtractionResult {
150
+ let depth = 0;
151
+ let foundOpen = false;
152
+ let endLine = defLine;
153
+
154
+ for (let i = defLine; i < lines.length; i++) {
155
+ for (const ch of lines[i]) {
156
+ if (ch === '{') { depth++; foundOpen = true; }
157
+ else if (ch === '}') { depth--; }
158
+ }
159
+ if (foundOpen && depth <= 0) { endLine = i; break; }
160
+ if (i > defLine + 500) { endLine = i; break; }
161
+ endLine = i;
162
+ }
163
+
164
+ const rawText = lines.slice(startLine, endLine + 1).join('\n');
165
+ const startOffset = lines.slice(0, startLine).join('\n').length + (startLine > 0 ? 1 : 0);
166
+
167
+ return {
168
+ entity: {
169
+ id: makeEntityId(filePath, kind, name),
170
+ kind,
171
+ name,
172
+ scopePath: name,
173
+ span: [startOffset, startOffset + rawText.length],
174
+ rawText,
175
+ signature: normalizeSignature(rawText),
176
+ children: [],
177
+ },
178
+ endLine,
179
+ };
180
+ }
181
+
182
+ // ---------------------------------------------------------------------------
183
+ // Class member extraction
184
+ // ---------------------------------------------------------------------------
185
+
186
+ function extractClassMembers(
187
+ lines: string[],
188
+ startLine: number,
189
+ endLine: number,
190
+ parentName: string,
191
+ filePath: string,
192
+ ): ASTEntity[] {
193
+ const children: ASTEntity[] = [];
194
+ let depth = 0;
195
+
196
+ for (let i = startLine; i <= endLine; i++) {
197
+ const line = lines[i];
198
+ const depthBefore = depth;
199
+
200
+ for (const ch of line) {
201
+ if (ch === '{') depth++;
202
+ else if (ch === '}') depth--;
203
+ }
204
+
205
+ // Only look at depth 1 (direct children)
206
+ if (depthBefore !== 1) continue;
207
+
208
+ const trimmed = line.trim();
209
+
210
+ // Skip annotations, comments, empty
211
+ if (!trimmed || trimmed.startsWith('@') || trimmed.startsWith('//') || trimmed.startsWith('/*') || trimmed.startsWith('*')) continue;
212
+
213
+ // Nested class/interface/enum
214
+ const classMatch = trimmed.match(CLASS_RE);
215
+ if (classMatch) {
216
+ const typeKind = classMatch[1];
217
+ const name = classMatch[2];
218
+ const kind: ASTEntityKind = typeKind === 'interface' ? 'InterfaceDef' : typeKind === 'enum' ? 'EnumDef' : 'ClassDef';
219
+ children.push({
220
+ id: makeEntityId(filePath, kind, `${parentName}.${name}`),
221
+ kind,
222
+ name,
223
+ scopePath: `${parentName}.${name}`,
224
+ span: [0, 0],
225
+ rawText: trimmed,
226
+ signature: normalizeSignature(trimmed),
227
+ children: [],
228
+ });
229
+ continue;
230
+ }
231
+
232
+ // Constructor: ClassName(
233
+ const ctorMatch = trimmed.match(new RegExp(`^${MODIFIERS.source}${parentName}\\s*\\(`));
234
+ if (ctorMatch) {
235
+ children.push({
236
+ id: makeEntityId(filePath, 'Constructor', `${parentName}.${parentName}`),
237
+ kind: 'Constructor',
238
+ name: parentName,
239
+ scopePath: `${parentName}.${parentName}`,
240
+ span: [0, 0],
241
+ rawText: trimmed,
242
+ signature: normalizeSignature(trimmed),
243
+ children: [],
244
+ });
245
+ continue;
246
+ }
247
+
248
+ // Method: returnType name(
249
+ const methodMatch = trimmed.match(METHOD_RE);
250
+ if (methodMatch) {
251
+ const name = methodMatch[1];
252
+ if (name !== 'if' && name !== 'for' && name !== 'while' && name !== 'switch' && name !== 'catch' && name !== 'return') {
253
+ children.push({
254
+ id: makeEntityId(filePath, 'MethodDef', `${parentName}.${name}`),
255
+ kind: 'MethodDef',
256
+ name,
257
+ scopePath: `${parentName}.${name}`,
258
+ span: [0, 0],
259
+ rawText: trimmed,
260
+ signature: normalizeSignature(trimmed),
261
+ children: [],
262
+ });
263
+ continue;
264
+ }
265
+ }
266
+
267
+ // Field: type name ; or type name =
268
+ const fieldMatch = trimmed.match(FIELD_RE);
269
+ if (fieldMatch) {
270
+ const name = fieldMatch[1];
271
+ if (name !== 'return' && name !== 'throw' && name !== 'new') {
272
+ children.push({
273
+ id: makeEntityId(filePath, 'PropertyDef', `${parentName}.${name}`),
274
+ kind: 'PropertyDef',
275
+ name,
276
+ scopePath: `${parentName}.${name}`,
277
+ span: [0, 0],
278
+ rawText: trimmed,
279
+ signature: normalizeSignature(trimmed),
280
+ children: [],
281
+ });
282
+ }
283
+ }
284
+ }
285
+ return children;
286
+ }
287
+
288
+ // ---------------------------------------------------------------------------
289
+ // Import extraction
290
+ // ---------------------------------------------------------------------------
291
+
292
+ function extractImports(content: string): ImportRelation[] {
293
+ const imports: ImportRelation[] = [];
294
+ const lines = content.split('\n');
295
+
296
+ for (const line of lines) {
297
+ const trimmed = line.trim();
298
+
299
+ // import [static] package.Class;
300
+ const match = trimmed.match(/^import\s+(static\s+)?([^;]+);/);
301
+ if (match) {
302
+ const isStatic = !!match[1];
303
+ const path = match[2].trim();
304
+ const isWildcard = path.endsWith('.*');
305
+ const source = isWildcard ? path.slice(0, -2) : path;
306
+ const lastPart = path.split('.').pop()!;
307
+
308
+ imports.push({
309
+ source,
310
+ specifiers: isWildcard ? ['*'] : [lastPart],
311
+ isDefault: !isWildcard && !isStatic,
312
+ isNamespace: isWildcard,
313
+ rawText: trimmed,
314
+ span: [0, trimmed.length],
315
+ });
316
+ }
317
+ }
318
+
319
+ return imports;
320
+ }
321
+
322
+ // ---------------------------------------------------------------------------
323
+ // Export extraction
324
+ // ---------------------------------------------------------------------------
325
+
326
+ function extractExports(content: string, filePath: string): ExportRelation[] {
327
+ const exports: ExportRelation[] = [];
328
+ const lines = content.split('\n');
329
+
330
+ for (const line of lines) {
331
+ const trimmed = line.trim();
332
+
333
+ // Public class/interface/enum at top level
334
+ const match = trimmed.match(/^public\s+(?:(?:abstract|final|sealed|static)\s+)*(class|interface|enum|record)\s+(\w+)/);
335
+ if (match) {
336
+ exports.push({
337
+ name: match[2],
338
+ isDefault: false,
339
+ rawText: trimmed.split('{')[0].trim(),
340
+ span: [0, 0],
341
+ });
342
+ }
343
+ }
344
+
345
+ return exports;
346
+ }
347
+
348
+ // ---------------------------------------------------------------------------
349
+ // Semantic diff
350
+ // ---------------------------------------------------------------------------
351
+
352
+ function computeSemanticDiff(
353
+ oldResult: ParseResult,
354
+ newResult: ParseResult,
355
+ ): SemanticPatch[] {
356
+ const patches: SemanticPatch[] = [];
357
+ const fileId = newResult.fileEntityId;
358
+
359
+ const oldDecls = new Map(oldResult.declarations.map(d => [d.id, d]));
360
+ const newDecls = new Map(newResult.declarations.map(d => [d.id, d]));
361
+
362
+ for (const [id, entity] of newDecls) {
363
+ if (!oldDecls.has(id)) {
364
+ const oldEntity = findRenamedEntity(entity, oldResult.declarations, newDecls);
365
+ if (oldEntity) {
366
+ patches.push({ kind: 'symbolRename', entityId: oldEntity.id, oldName: oldEntity.name, newName: entity.name });
367
+ } else {
368
+ patches.push({ kind: 'symbolAdd', entity });
369
+ }
370
+ }
371
+ }
372
+
373
+ for (const [id, entity] of oldDecls) {
374
+ if (!newDecls.has(id)) {
375
+ const wasRenamed = findRenamedEntity(entity, newResult.declarations, oldDecls);
376
+ if (!wasRenamed) {
377
+ patches.push({ kind: 'symbolRemove', entityId: id, entityName: entity.name });
378
+ }
379
+ }
380
+ }
381
+
382
+ for (const [id, newEntity] of newDecls) {
383
+ const oldEntity = oldDecls.get(id);
384
+ if (oldEntity && oldEntity.signature !== newEntity.signature) {
385
+ patches.push({
386
+ kind: 'symbolModify', entityId: id, entityName: newEntity.name,
387
+ oldSignature: oldEntity.signature, newSignature: newEntity.signature,
388
+ oldRawText: oldEntity.rawText, newRawText: newEntity.rawText,
389
+ });
390
+ }
391
+ }
392
+
393
+ const oldImports = new Map(oldResult.imports.map(imp => [imp.source, imp]));
394
+ const newImports = new Map(newResult.imports.map(imp => [imp.source, imp]));
395
+
396
+ for (const [source, imp] of newImports) {
397
+ const oldImp = oldImports.get(source);
398
+ if (!oldImp) {
399
+ patches.push({ kind: 'importAdd', fileId, source, specifiers: imp.specifiers, rawText: imp.rawText });
400
+ } else if (JSON.stringify(oldImp.specifiers.sort()) !== JSON.stringify(imp.specifiers.sort())) {
401
+ patches.push({ kind: 'importModify', fileId, source, oldSpecifiers: oldImp.specifiers, newSpecifiers: imp.specifiers });
402
+ }
403
+ }
404
+ for (const [source] of oldImports) {
405
+ if (!newImports.has(source)) {
406
+ patches.push({ kind: 'importRemove', fileId, source });
407
+ }
408
+ }
409
+
410
+ const oldExports = new Map(oldResult.exports.map(exp => [exp.name, exp]));
411
+ const newExports = new Map(newResult.exports.map(exp => [exp.name, exp]));
412
+ for (const [name, exp] of newExports) {
413
+ if (!oldExports.has(name)) {
414
+ patches.push({ kind: 'exportAdd', fileId, name, rawText: exp.rawText });
415
+ }
416
+ }
417
+ for (const [name] of oldExports) {
418
+ if (!newExports.has(name)) {
419
+ patches.push({ kind: 'exportRemove', fileId, name });
420
+ }
421
+ }
422
+
423
+ return patches;
424
+ }
425
+
426
+ // ---------------------------------------------------------------------------
427
+ // Helpers
428
+ // ---------------------------------------------------------------------------
429
+
430
+ function findRenamedEntity(
431
+ entity: ASTEntity,
432
+ candidates: ASTEntity[],
433
+ existingIds: Map<string, ASTEntity>,
434
+ ): ASTEntity | null {
435
+ for (const candidate of candidates) {
436
+ if (candidate.kind !== entity.kind) continue;
437
+ if (candidate.name === entity.name) continue;
438
+ if (existingIds.has(candidate.id)) continue;
439
+ const normalizedOld = candidate.signature.replace(new RegExp(candidate.name, 'g'), '___');
440
+ const normalizedNew = entity.signature.replace(new RegExp(entity.name, 'g'), '___');
441
+ if (normalizedOld === normalizedNew) return candidate;
442
+ }
443
+ return null;
444
+ }
445
+
446
+ function makeEntityId(filePath: string, kind: string, name: string): string {
447
+ return `${kind}:${filePath}:${name}`;
448
+ }
449
+
450
+ function normalizeSignature(text: string): string {
451
+ return text
452
+ .replace(/\/\/[^\n]*/g, '')
453
+ .replace(/\/\*[\s\S]*?\*\//g, '')
454
+ .replace(/\s+/g, ' ')
455
+ .trim();
456
+ }