@specverse/engines 6.0.7 → 6.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analyse-prepass/adapters/index.d.ts +9 -0
- package/dist/analyse-prepass/adapters/index.d.ts.map +1 -0
- package/dist/analyse-prepass/adapters/index.js +9 -0
- package/dist/analyse-prepass/adapters/index.js.map +1 -0
- package/dist/analyse-prepass/adapters/typescript-prisma.d.ts +67 -0
- package/dist/analyse-prepass/adapters/typescript-prisma.d.ts.map +1 -0
- package/dist/analyse-prepass/adapters/typescript-prisma.js +167 -0
- package/dist/analyse-prepass/adapters/typescript-prisma.js.map +1 -0
- package/dist/analyse-prepass/backends/codegraph.d.ts +56 -0
- package/dist/analyse-prepass/backends/codegraph.d.ts.map +1 -0
- package/dist/analyse-prepass/backends/codegraph.js +303 -0
- package/dist/analyse-prepass/backends/codegraph.js.map +1 -0
- package/dist/analyse-prepass/backends/gitnexus.d.ts +71 -0
- package/dist/analyse-prepass/backends/gitnexus.d.ts.map +1 -0
- package/dist/analyse-prepass/backends/gitnexus.js +367 -0
- package/dist/analyse-prepass/backends/gitnexus.js.map +1 -0
- package/dist/analyse-prepass/backends/grep-only.d.ts +33 -0
- package/dist/analyse-prepass/backends/grep-only.d.ts.map +1 -0
- package/dist/analyse-prepass/backends/grep-only.js +377 -0
- package/dist/analyse-prepass/backends/grep-only.js.map +1 -0
- package/dist/analyse-prepass/backends/index.d.ts +28 -0
- package/dist/analyse-prepass/backends/index.d.ts.map +1 -0
- package/dist/analyse-prepass/backends/index.js +36 -0
- package/dist/analyse-prepass/backends/index.js.map +1 -0
- package/dist/analyse-prepass/backends/method-patterns.d.ts +27 -0
- package/dist/analyse-prepass/backends/method-patterns.d.ts.map +1 -0
- package/dist/analyse-prepass/backends/method-patterns.js +177 -0
- package/dist/analyse-prepass/backends/method-patterns.js.map +1 -0
- package/dist/analyse-prepass/backends/walk.d.ts +7 -0
- package/dist/analyse-prepass/backends/walk.d.ts.map +1 -0
- package/dist/analyse-prepass/backends/walk.js +105 -0
- package/dist/analyse-prepass/backends/walk.js.map +1 -0
- package/dist/analyse-prepass/index.d.ts +76 -0
- package/dist/analyse-prepass/index.d.ts.map +1 -0
- package/dist/analyse-prepass/index.js +114 -0
- package/dist/analyse-prepass/index.js.map +1 -0
- package/dist/analyse-prepass/interface.d.ts +222 -0
- package/dist/analyse-prepass/interface.d.ts.map +1 -0
- package/dist/analyse-prepass/interface.js +20 -0
- package/dist/analyse-prepass/interface.js.map +1 -0
- package/dist/libs/instance-factories/cli/templates/commander/command-generator.js +104 -0
- package/dist/libs/instance-factories/orms/templates/prisma/schema-generator.js +25 -4
- package/libs/instance-factories/cli/templates/commander/command-generator.ts +104 -0
- package/libs/instance-factories/orms/templates/prisma/schema-generator.ts +43 -5
- package/package.json +5 -1
- package/libs/instance-factories/cli/templates/commander/command-generator.d.ts +0 -14
- package/libs/instance-factories/cli/templates/commander/command-generator.js +0 -182
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/** Region markers SpecVerse-realized backends emit in behavior method bodies. */
|
|
2
|
+
const REGION_MARKERS = {
|
|
3
|
+
preconditions: /===\s*PRECONDITIONS\s*===/,
|
|
4
|
+
execute: /===\s*EXECUTE\s*===/,
|
|
5
|
+
postconditions: /===\s*POSTCONDITIONS\s*===/,
|
|
6
|
+
events: /===\s*EVENTS\s*===/,
|
|
7
|
+
};
|
|
8
|
+
/** Slice a method body into the canonical PRECONDITIONS/EXECUTE/POSTCONDITIONS/EVENTS regions. */
|
|
9
|
+
export function sliceBody(body) {
|
|
10
|
+
// Detect each marker's position in the body
|
|
11
|
+
const positions = [];
|
|
12
|
+
for (const [name, regex] of Object.entries(REGION_MARKERS)) {
|
|
13
|
+
const match = body.match(regex);
|
|
14
|
+
if (match && match.index !== undefined) {
|
|
15
|
+
positions.push({ name: name, pos: match.index });
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
if (positions.length === 0)
|
|
19
|
+
return undefined;
|
|
20
|
+
positions.sort((a, b) => a.pos - b.pos);
|
|
21
|
+
const out = {};
|
|
22
|
+
for (let i = 0; i < positions.length; i++) {
|
|
23
|
+
const { name, pos } = positions[i];
|
|
24
|
+
const next = i + 1 < positions.length ? positions[i + 1].pos : body.length;
|
|
25
|
+
out[name] = body.slice(pos, next).trim();
|
|
26
|
+
}
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
29
|
+
/** Extract event names emitted from a TS/JS method body. */
|
|
30
|
+
export function extractEmits(body) {
|
|
31
|
+
const out = new Set();
|
|
32
|
+
// Common emission patterns:
|
|
33
|
+
// eventBus.emit('Foo', ...) eventBus.publish('Foo', ...)
|
|
34
|
+
// emit('Foo', ...) this.dispatchEvent('Foo', ...)
|
|
35
|
+
// subject.next(new FooEvent()) this.bus.publish('Foo', ...)
|
|
36
|
+
// pubsub.publish('Foo', ...) this.events.emit('Foo', ...)
|
|
37
|
+
const stringEmitRegex = /(?:emit|publish|dispatchEvent|next)\s*\(\s*['"`]([^'"`]+)['"`]/g;
|
|
38
|
+
for (const m of body.matchAll(stringEmitRegex)) {
|
|
39
|
+
out.add(m[1]);
|
|
40
|
+
}
|
|
41
|
+
// For "subject.next(new FooEvent())" type patterns, capture the constructor name
|
|
42
|
+
const constructorEmitRegex = /\.next\s*\(\s*new\s+(\w+Event)\s*\(/g;
|
|
43
|
+
for (const m of body.matchAll(constructorEmitRegex)) {
|
|
44
|
+
out.add(m[1]);
|
|
45
|
+
}
|
|
46
|
+
return [...out];
|
|
47
|
+
}
|
|
48
|
+
/** Extract Prisma-style DB writes from a TS/JS method body. */
|
|
49
|
+
export function extractDbWrites(body) {
|
|
50
|
+
const out = [];
|
|
51
|
+
// Prisma: prisma.modelName.create(...)/.update(...)/.delete(...)/.upsert(...)
|
|
52
|
+
// Capture entity name (camelCase) and op
|
|
53
|
+
const prismaRegex = /\bprisma\.(\w+)\.(create|update|delete|upsert|createMany|updateMany|deleteMany)\s*\(/g;
|
|
54
|
+
for (const m of body.matchAll(prismaRegex)) {
|
|
55
|
+
const entity = m[1].charAt(0).toUpperCase() + m[1].slice(1); // pollOption → PollOption
|
|
56
|
+
const opRaw = m[2];
|
|
57
|
+
const op = opRaw.startsWith('create')
|
|
58
|
+
? 'create'
|
|
59
|
+
: opRaw.startsWith('update')
|
|
60
|
+
? 'update'
|
|
61
|
+
: opRaw.startsWith('delete')
|
|
62
|
+
? 'delete'
|
|
63
|
+
: opRaw === 'upsert'
|
|
64
|
+
? 'upsert'
|
|
65
|
+
: 'unknown';
|
|
66
|
+
out.push({ entity, op });
|
|
67
|
+
}
|
|
68
|
+
// TypeORM: repository.save() / .update() / .remove()
|
|
69
|
+
const typeormRegex = /\b(\w*[Rr]epository)\.(save|update|remove|delete|insert|upsert)\s*\(/g;
|
|
70
|
+
for (const m of body.matchAll(typeormRegex)) {
|
|
71
|
+
const repoName = m[1];
|
|
72
|
+
const entity = repoName.replace(/Repository$/i, '');
|
|
73
|
+
const opRaw = m[2];
|
|
74
|
+
const op = opRaw === 'save' || opRaw === 'insert'
|
|
75
|
+
? 'create'
|
|
76
|
+
: opRaw === 'update'
|
|
77
|
+
? 'update'
|
|
78
|
+
: opRaw === 'remove' || opRaw === 'delete'
|
|
79
|
+
? 'delete'
|
|
80
|
+
: opRaw === 'upsert'
|
|
81
|
+
? 'upsert'
|
|
82
|
+
: 'unknown';
|
|
83
|
+
if (entity)
|
|
84
|
+
out.push({ entity, op });
|
|
85
|
+
}
|
|
86
|
+
return out;
|
|
87
|
+
}
|
|
88
|
+
/** Extract external system calls from a TS/JS method body. */
|
|
89
|
+
export function extractExternalCalls(body) {
|
|
90
|
+
const out = [];
|
|
91
|
+
// HTTP: fetch / axios.X / http.request / got / undici
|
|
92
|
+
if (/\bfetch\s*\(/.test(body) || /\baxios\.\w+\s*\(/.test(body) ||
|
|
93
|
+
/\bhttp[s]?\.(request|get|post)\s*\(/.test(body) ||
|
|
94
|
+
/\bgot\.\w+\s*\(/.test(body)) {
|
|
95
|
+
out.push({ kind: 'http' });
|
|
96
|
+
}
|
|
97
|
+
// Queue: kafka / rabbit / sqs
|
|
98
|
+
if (/\bkafka\.\w+\s*\(/.test(body) || /\brabbit\w*\.\w+\s*\(/.test(body) ||
|
|
99
|
+
/\bsqs\.\w+\s*\(/.test(body)) {
|
|
100
|
+
out.push({ kind: 'queue' });
|
|
101
|
+
}
|
|
102
|
+
// Cache: redis / memcached / cache.X
|
|
103
|
+
if (/\bredis\.\w+\s*\(/.test(body) || /\bmemcached\.\w+\s*\(/.test(body) ||
|
|
104
|
+
/\bcache\.\w+\s*\(/.test(body)) {
|
|
105
|
+
out.push({ kind: 'cache' });
|
|
106
|
+
}
|
|
107
|
+
return out;
|
|
108
|
+
}
|
|
109
|
+
/** Extract throw statements (the type of error being thrown). */
|
|
110
|
+
export function extractThrows(body) {
|
|
111
|
+
const out = new Set();
|
|
112
|
+
// throw new ErrorType(...) — captures the constructor name
|
|
113
|
+
const throwNewRegex = /throw\s+new\s+(\w+)\s*\(/g;
|
|
114
|
+
for (const m of body.matchAll(throwNewRegex)) {
|
|
115
|
+
out.add(m[1]);
|
|
116
|
+
}
|
|
117
|
+
return [...out];
|
|
118
|
+
}
|
|
119
|
+
/** Find async boundaries (await / Promise.all / Promise.race). */
|
|
120
|
+
export function extractAsyncBoundaries(body) {
|
|
121
|
+
const out = [];
|
|
122
|
+
const lines = body.split('\n');
|
|
123
|
+
for (let i = 0; i < lines.length; i++) {
|
|
124
|
+
const line = lines[i];
|
|
125
|
+
if (/\bawait\b/.test(line)) {
|
|
126
|
+
if (/Promise\.all\b/.test(line)) {
|
|
127
|
+
out.push({ type: 'promise.all', line: i + 1 });
|
|
128
|
+
}
|
|
129
|
+
else if (/Promise\.race\b/.test(line)) {
|
|
130
|
+
out.push({ type: 'promise.race', line: i + 1 });
|
|
131
|
+
}
|
|
132
|
+
else if (/Promise\.allSettled\b/.test(line)) {
|
|
133
|
+
out.push({ type: 'promise.allSettled', line: i + 1 });
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
out.push({ type: 'await', line: i + 1 });
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return out;
|
|
141
|
+
}
|
|
142
|
+
/** Count branch points — if / else if / switch case / catch / ternary. */
|
|
143
|
+
export function countBranchPoints(body) {
|
|
144
|
+
let count = 0;
|
|
145
|
+
// `if (...)`, but exclude `else if` (avoids double-counting; we count the if portion)
|
|
146
|
+
count += (body.match(/\bif\s*\(/g) || []).length;
|
|
147
|
+
count += (body.match(/\bcase\s+/g) || []).length;
|
|
148
|
+
count += (body.match(/\bcatch\s*\(/g) || []).length;
|
|
149
|
+
// Ternaries: `... ? ... : ...` — count each occurrence of `?...:` (rough proxy)
|
|
150
|
+
count += (body.match(/\?\s*[^:?]+:/g) || []).length;
|
|
151
|
+
return count;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Heuristic: extract called functions from a method body via regex
|
|
155
|
+
* (fallback when call graph isn't available — grep-only backend).
|
|
156
|
+
* Returns deduplicated function names. Filters out language keywords.
|
|
157
|
+
*/
|
|
158
|
+
const KEYWORD_FILTER = new Set([
|
|
159
|
+
'if', 'for', 'while', 'switch', 'catch', 'return', 'throw', 'new',
|
|
160
|
+
'await', 'typeof', 'instanceof', 'function', 'async', 'yield',
|
|
161
|
+
'console', 'JSON', 'Object', 'Array', 'String', 'Number', 'Boolean',
|
|
162
|
+
'Math', 'Date', 'Promise', 'Error', 'Map', 'Set',
|
|
163
|
+
]);
|
|
164
|
+
export function extractCallNames(body) {
|
|
165
|
+
const out = new Set();
|
|
166
|
+
// Match `name(` or `obj.name(` — capture the identifier before `(`
|
|
167
|
+
// For chained calls (obj.method()), this captures the last identifier
|
|
168
|
+
const callRegex = /\b(\w+)\s*\(/g;
|
|
169
|
+
for (const m of body.matchAll(callRegex)) {
|
|
170
|
+
const name = m[1];
|
|
171
|
+
if (KEYWORD_FILTER.has(name))
|
|
172
|
+
continue;
|
|
173
|
+
out.add(name);
|
|
174
|
+
}
|
|
175
|
+
return [...out];
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=method-patterns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"method-patterns.js","sourceRoot":"","sources":["../../../src/analyse-prepass/backends/method-patterns.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Walk dir recursively, returning absolute file paths. */
|
|
2
|
+
export declare function walkSourceTree(dir: string): string[];
|
|
3
|
+
/** Map common file extensions to language identifiers used by the indexer. */
|
|
4
|
+
export declare function detectLanguage(filePath: string): string | null;
|
|
5
|
+
/** Convert a minimal glob (`**`, `*`, `?`) to a regex for file path matching. */
|
|
6
|
+
export declare function globToRegex(glob: string): RegExp;
|
|
7
|
+
//# sourceMappingURL=walk.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walk.d.ts","sourceRoot":"","sources":["../../../src/analyse-prepass/backends/walk.ts"],"names":[],"mappings":"AAkBA,2DAA2D;AAC3D,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CA8BpD;AAED,8EAA8E;AAC9E,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAuC9D;AAED,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQhD"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared filesystem walker — used by both grep-only and codegraph backends
|
|
3
|
+
* for `listFiles()`. The richer backends index *symbols* in their preferred
|
|
4
|
+
* languages, but the file inventory itself comes from a plain fs walk so
|
|
5
|
+
* adapters can find arbitrary file types (schema.prisma, package.json,
|
|
6
|
+
* config files, etc.).
|
|
7
|
+
*/
|
|
8
|
+
import { readdirSync, statSync } from 'fs';
|
|
9
|
+
import { join, extname } from 'path';
|
|
10
|
+
/** Common dirs to exclude from any walk. */
|
|
11
|
+
const EXCLUDE_DIRS = new Set([
|
|
12
|
+
'node_modules', '.git', '.svn', '.hg',
|
|
13
|
+
'dist', 'build', 'out', 'target', '__pycache__',
|
|
14
|
+
'.codegraph', '.gitnexus',
|
|
15
|
+
'coverage', '.next', '.nuxt',
|
|
16
|
+
]);
|
|
17
|
+
/** Walk dir recursively, returning absolute file paths. */
|
|
18
|
+
export function walkSourceTree(dir) {
|
|
19
|
+
const out = [];
|
|
20
|
+
const stack = [dir];
|
|
21
|
+
while (stack.length > 0) {
|
|
22
|
+
const cur = stack.pop();
|
|
23
|
+
let entries;
|
|
24
|
+
try {
|
|
25
|
+
entries = readdirSync(cur);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
for (const entry of entries) {
|
|
31
|
+
if (EXCLUDE_DIRS.has(entry))
|
|
32
|
+
continue;
|
|
33
|
+
// Skip dotfiles + hidden dirs (except known ones we'd want to expose later)
|
|
34
|
+
if (entry.startsWith('.'))
|
|
35
|
+
continue;
|
|
36
|
+
const full = join(cur, entry);
|
|
37
|
+
let st;
|
|
38
|
+
try {
|
|
39
|
+
st = statSync(full);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (st.isDirectory()) {
|
|
45
|
+
stack.push(full);
|
|
46
|
+
}
|
|
47
|
+
else if (st.isFile()) {
|
|
48
|
+
out.push(full);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return out;
|
|
53
|
+
}
|
|
54
|
+
/** Map common file extensions to language identifiers used by the indexer. */
|
|
55
|
+
export function detectLanguage(filePath) {
|
|
56
|
+
const ext = extname(filePath).toLowerCase();
|
|
57
|
+
switch (ext) {
|
|
58
|
+
case '.ts':
|
|
59
|
+
case '.tsx':
|
|
60
|
+
return 'typescript';
|
|
61
|
+
case '.js':
|
|
62
|
+
case '.jsx':
|
|
63
|
+
case '.mjs':
|
|
64
|
+
case '.cjs':
|
|
65
|
+
return 'javascript';
|
|
66
|
+
case '.py':
|
|
67
|
+
return 'python';
|
|
68
|
+
case '.go':
|
|
69
|
+
return 'go';
|
|
70
|
+
case '.rs':
|
|
71
|
+
return 'rust';
|
|
72
|
+
case '.java':
|
|
73
|
+
return 'java';
|
|
74
|
+
case '.kt':
|
|
75
|
+
return 'kotlin';
|
|
76
|
+
case '.swift':
|
|
77
|
+
return 'swift';
|
|
78
|
+
case '.cs':
|
|
79
|
+
return 'csharp';
|
|
80
|
+
case '.rb':
|
|
81
|
+
return 'ruby';
|
|
82
|
+
case '.php':
|
|
83
|
+
return 'php';
|
|
84
|
+
case '.c':
|
|
85
|
+
case '.h':
|
|
86
|
+
return 'c';
|
|
87
|
+
case '.cpp':
|
|
88
|
+
case '.cc':
|
|
89
|
+
case '.hpp':
|
|
90
|
+
return 'cpp';
|
|
91
|
+
default:
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/** Convert a minimal glob (`**`, `*`, `?`) to a regex for file path matching. */
|
|
96
|
+
export function globToRegex(glob) {
|
|
97
|
+
const escaped = glob.replace(/[.+^${}()|\\]/g, '\\$&');
|
|
98
|
+
const pattern = escaped
|
|
99
|
+
.replace(/\*\*/g, '__DOUBLESTAR__')
|
|
100
|
+
.replace(/\*/g, '[^/]*')
|
|
101
|
+
.replace(/__DOUBLESTAR__/g, '.*')
|
|
102
|
+
.replace(/\?/g, '[^/]');
|
|
103
|
+
return new RegExp(pattern + '$');
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=walk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walk.js","sourceRoot":"","sources":["../../../src/analyse-prepass/backends/walk.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structural pre-pass for analyse — orchestrator + public exports.
|
|
3
|
+
*
|
|
4
|
+
* Walks a source directory, extracts deterministic structural facts,
|
|
5
|
+
* translates them into SpecVerse vocabulary via per-framework adapters,
|
|
6
|
+
* and produces a `SpecVerseFacts` object suitable for injection into the
|
|
7
|
+
* analyse prompt as a structural-context preamble.
|
|
8
|
+
*
|
|
9
|
+
* Design: see specverse-self/docs/proposals/STRUCTURAL-PREPASS-FOR-ANALYSE.md
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* import { runPrepass } from '@specverse/engines/analyse-prepass';
|
|
13
|
+
* const facts = await runPrepass('/path/to/source');
|
|
14
|
+
* // facts.entities, facts.relationships, facts.lifecycles, ...
|
|
15
|
+
*/
|
|
16
|
+
export type { StructuralPrepass, Symbol, Import, Capabilities, FileFilter, ClassFilter, MethodFilter, InterfaceFilter, IndexResult, MethodFactSheet, } from './interface.js';
|
|
17
|
+
export { GrepOnlyBackend, CodeGraphBackend, GitNexusBackend, selectBackend, type BackendName, } from './backends/index.js';
|
|
18
|
+
export { extractTypeScriptPrisma, type PrismaFacts, type PrismaEntity, type PrismaField, type PrismaRelation, } from './adapters/index.js';
|
|
19
|
+
import { type BackendName } from './backends/index.js';
|
|
20
|
+
import type { StructuralPrepass } from './interface.js';
|
|
21
|
+
export interface SpecVerseFacts {
|
|
22
|
+
/** Detected entities (model candidates). */
|
|
23
|
+
entities: Array<{
|
|
24
|
+
name: string;
|
|
25
|
+
filePath: string;
|
|
26
|
+
sourceFramework: string;
|
|
27
|
+
}>;
|
|
28
|
+
/** Detected relationships between entities. */
|
|
29
|
+
relationships: Array<{
|
|
30
|
+
from: string;
|
|
31
|
+
to: string;
|
|
32
|
+
type: 'belongsTo' | 'hasMany' | 'hasOne';
|
|
33
|
+
cascade?: boolean;
|
|
34
|
+
}>;
|
|
35
|
+
/** Detected lifecycle declarations: states attached to a model's status field. */
|
|
36
|
+
lifecycles: Array<{
|
|
37
|
+
model: string;
|
|
38
|
+
field: string;
|
|
39
|
+
states: string[];
|
|
40
|
+
}>;
|
|
41
|
+
/** Provenance: which adapter(s) ran, what backend was used. */
|
|
42
|
+
meta: {
|
|
43
|
+
backend: string;
|
|
44
|
+
backendCapabilities: Record<string, boolean>;
|
|
45
|
+
adaptersRun: string[];
|
|
46
|
+
sourceDir: string;
|
|
47
|
+
durationMs: number;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export interface RunPrepassOptions {
|
|
51
|
+
/** Backend to use; defaults to 'auto' (CodeGraph if available, else grep-only). */
|
|
52
|
+
backend?: BackendName;
|
|
53
|
+
/** Pre-built backend instance (advanced; bypasses selectBackend). */
|
|
54
|
+
prepass?: StructuralPrepass;
|
|
55
|
+
/** Skip adapter selection and run only the named ones. Default = all detected. */
|
|
56
|
+
adapters?: Array<'typescript-prisma'>;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Run the structural pre-pass on a source directory.
|
|
60
|
+
*
|
|
61
|
+
* Pipeline:
|
|
62
|
+
* 1. Select / receive a backend (`StructuralPrepass`)
|
|
63
|
+
* 2. Initialize + index the source dir
|
|
64
|
+
* 3. Detect which adapters apply (e.g. schema.prisma exists → TS+Prisma)
|
|
65
|
+
* 4. Run each detected adapter to extract framework-specific facts
|
|
66
|
+
* 5. Merge facts into a single SpecVerse-vocabulary `SpecVerseFacts` object
|
|
67
|
+
*/
|
|
68
|
+
export declare function runPrepass(sourceDir: string, options?: RunPrepassOptions): Promise<SpecVerseFacts>;
|
|
69
|
+
/**
|
|
70
|
+
* Format a `SpecVerseFacts` object as a markdown block suitable for
|
|
71
|
+
* injection into the analyse prompt's user template (mirrors the format
|
|
72
|
+
* from the existing manually-extracted facts files used in §5/§6
|
|
73
|
+
* experiments).
|
|
74
|
+
*/
|
|
75
|
+
export declare function formatFactsAsMarkdown(facts: SpecVerseFacts): string;
|
|
76
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/analyse-prepass/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,YAAY,EACV,iBAAiB,EACjB,MAAM,EACN,MAAM,EACN,YAAY,EACZ,UAAU,EACV,WAAW,EACX,YAAY,EACZ,eAAe,EACf,WAAW,EACX,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,KAAK,WAAW,GACjB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,uBAAuB,EACvB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,cAAc,GACpB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAExD,MAAM,WAAW,cAAc;IAC7B,4CAA4C;IAC5C,QAAQ,EAAE,KAAK,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC,CAAC;IACH,+CAA+C;IAC/C,aAAa,EAAE,KAAK,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAC;QACzC,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC,CAAC;IACH,kFAAkF;IAClF,UAAU,EAAE,KAAK,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,EAAE,CAAC;KAClB,CAAC,CAAC;IACH,+DAA+D;IAC/D,IAAI,EAAE;QACJ,OAAO,EAAE,MAAM,CAAC;QAChB,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC7C,WAAW,EAAE,MAAM,EAAE,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED,MAAM,WAAW,iBAAiB;IAChC,mFAAmF;IACnF,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,qEAAqE;IACrE,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,kFAAkF;IAClF,QAAQ,CAAC,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAC;CACvC;AAED;;;;;;;;;GASG;AACH,wBAAsB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,cAAc,CAAC,CAyD5G;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CA2CnE"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
export { GrepOnlyBackend, CodeGraphBackend, GitNexusBackend, selectBackend, } from './backends/index.js';
|
|
2
|
+
export { extractTypeScriptPrisma, } from './adapters/index.js';
|
|
3
|
+
import { selectBackend } from './backends/index.js';
|
|
4
|
+
import { extractTypeScriptPrisma } from './adapters/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* Run the structural pre-pass on a source directory.
|
|
7
|
+
*
|
|
8
|
+
* Pipeline:
|
|
9
|
+
* 1. Select / receive a backend (`StructuralPrepass`)
|
|
10
|
+
* 2. Initialize + index the source dir
|
|
11
|
+
* 3. Detect which adapters apply (e.g. schema.prisma exists → TS+Prisma)
|
|
12
|
+
* 4. Run each detected adapter to extract framework-specific facts
|
|
13
|
+
* 5. Merge facts into a single SpecVerse-vocabulary `SpecVerseFacts` object
|
|
14
|
+
*/
|
|
15
|
+
export async function runPrepass(sourceDir, options = {}) {
|
|
16
|
+
const start = Date.now();
|
|
17
|
+
const prepass = options.prepass ?? selectBackend(options.backend ?? 'auto');
|
|
18
|
+
await prepass.init(sourceDir);
|
|
19
|
+
await prepass.index();
|
|
20
|
+
const adaptersRun = [];
|
|
21
|
+
const facts = {
|
|
22
|
+
entities: [],
|
|
23
|
+
relationships: [],
|
|
24
|
+
lifecycles: [],
|
|
25
|
+
meta: {
|
|
26
|
+
backend: prepass.constructor.name,
|
|
27
|
+
backendCapabilities: { ...prepass.capabilities },
|
|
28
|
+
adaptersRun: [],
|
|
29
|
+
sourceDir,
|
|
30
|
+
durationMs: 0,
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
// ── TypeScript + Prisma adapter ──
|
|
34
|
+
// Detect via schema.prisma presence. (Future: also TypeORM via @Entity decorators,
|
|
35
|
+
// Sequelize via Model.init calls, Drizzle via *.schema.ts, etc.)
|
|
36
|
+
const prismaSchemas = await prepass.listFiles({ glob: '**/schema.prisma' });
|
|
37
|
+
if (prismaSchemas.length > 0) {
|
|
38
|
+
adaptersRun.push('typescript-prisma');
|
|
39
|
+
const prisma = await extractTypeScriptPrisma(prepass);
|
|
40
|
+
for (const ent of prisma.entities) {
|
|
41
|
+
facts.entities.push({
|
|
42
|
+
name: ent.name,
|
|
43
|
+
filePath: ent.filePath,
|
|
44
|
+
sourceFramework: 'prisma',
|
|
45
|
+
});
|
|
46
|
+
if (ent.lifecycleStates && ent.lifecycleField) {
|
|
47
|
+
facts.lifecycles.push({
|
|
48
|
+
model: ent.name,
|
|
49
|
+
field: ent.lifecycleField,
|
|
50
|
+
states: ent.lifecycleStates,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
for (const rel of prisma.relationships) {
|
|
55
|
+
facts.relationships.push({
|
|
56
|
+
from: rel.fromModel,
|
|
57
|
+
to: rel.toModel,
|
|
58
|
+
type: rel.type,
|
|
59
|
+
cascade: rel.cascade,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// Future adapters slot in here. Each detects its applicability + runs.
|
|
64
|
+
facts.meta.adaptersRun = adaptersRun;
|
|
65
|
+
facts.meta.durationMs = Date.now() - start;
|
|
66
|
+
return facts;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Format a `SpecVerseFacts` object as a markdown block suitable for
|
|
70
|
+
* injection into the analyse prompt's user template (mirrors the format
|
|
71
|
+
* from the existing manually-extracted facts files used in §5/§6
|
|
72
|
+
* experiments).
|
|
73
|
+
*/
|
|
74
|
+
export function formatFactsAsMarkdown(facts) {
|
|
75
|
+
const lines = [];
|
|
76
|
+
lines.push('# Structural facts extracted from source via Tree-sitter + per-framework adapters');
|
|
77
|
+
lines.push('');
|
|
78
|
+
lines.push('These facts are deterministic — extracted from AST analysis');
|
|
79
|
+
lines.push('and source-pattern matching, NOT LLM judgment. Treat as ground');
|
|
80
|
+
lines.push('truth for what symbols/files exist; verify SpecVerse semantics');
|
|
81
|
+
lines.push('against the source where you can.');
|
|
82
|
+
lines.push('');
|
|
83
|
+
lines.push(`Backend: ${facts.meta.backend} | Adapters: ${facts.meta.adaptersRun.join(', ') || '(none)'}`);
|
|
84
|
+
lines.push('');
|
|
85
|
+
if (facts.entities.length > 0) {
|
|
86
|
+
lines.push('## Entities (model candidates)');
|
|
87
|
+
lines.push('');
|
|
88
|
+
for (const ent of facts.entities) {
|
|
89
|
+
lines.push(`- **${ent.name}** — declared in ${ent.filePath} (via ${ent.sourceFramework})`);
|
|
90
|
+
}
|
|
91
|
+
lines.push('');
|
|
92
|
+
}
|
|
93
|
+
if (facts.relationships.length > 0) {
|
|
94
|
+
lines.push('## Relationships');
|
|
95
|
+
lines.push('');
|
|
96
|
+
for (const r of facts.relationships) {
|
|
97
|
+
const cascade = r.cascade ? ' cascade' : '';
|
|
98
|
+
lines.push(`- ${r.from} ${r.type} ${r.to}${cascade}`);
|
|
99
|
+
}
|
|
100
|
+
lines.push('');
|
|
101
|
+
}
|
|
102
|
+
if (facts.lifecycles.length > 0) {
|
|
103
|
+
lines.push('## Lifecycle states (extracted from source enums + field declarations)');
|
|
104
|
+
lines.push('');
|
|
105
|
+
lines.push('These are the canonical lifecycle declarations found in source. Use these state names literally; do NOT invent generic synonyms (e.g. `pending` when source says `planning`).');
|
|
106
|
+
lines.push('');
|
|
107
|
+
for (const lc of facts.lifecycles) {
|
|
108
|
+
lines.push(`- **${lc.model}.${lc.field}**: states = [${lc.states.join(', ')}]`);
|
|
109
|
+
}
|
|
110
|
+
lines.push('');
|
|
111
|
+
}
|
|
112
|
+
return lines.join('\n');
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/analyse-prepass/index.ts"],"names":[],"mappings":"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"}
|