@specverse/engines 6.42.3 → 6.60.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 (143) hide show
  1. package/dist/ai/analyse-runner.d.ts.map +1 -1
  2. package/dist/ai/analyse-runner.js +53 -1
  3. package/dist/ai/analyse-runner.js.map +1 -1
  4. package/dist/ai/prompt-runner.d.ts +39 -1
  5. package/dist/ai/prompt-runner.d.ts.map +1 -1
  6. package/dist/ai/prompt-runner.js +44 -3
  7. package/dist/ai/prompt-runner.js.map +1 -1
  8. package/dist/ai/providers/claude-cli.d.ts.map +1 -1
  9. package/dist/ai/providers/claude-cli.js +8 -1
  10. package/dist/ai/providers/claude-cli.js.map +1 -1
  11. package/dist/ai/skill-loader.d.ts +50 -0
  12. package/dist/ai/skill-loader.d.ts.map +1 -0
  13. package/dist/ai/skill-loader.js +96 -0
  14. package/dist/ai/skill-loader.js.map +1 -0
  15. package/dist/analyse-prepass/adapters/index.d.ts +2 -0
  16. package/dist/analyse-prepass/adapters/index.d.ts.map +1 -1
  17. package/dist/analyse-prepass/adapters/index.js +2 -0
  18. package/dist/analyse-prepass/adapters/index.js.map +1 -1
  19. package/dist/analyse-prepass/adapters/module-functions.d.ts +95 -0
  20. package/dist/analyse-prepass/adapters/module-functions.d.ts.map +1 -0
  21. package/dist/analyse-prepass/adapters/module-functions.js +358 -0
  22. package/dist/analyse-prepass/adapters/module-functions.js.map +1 -0
  23. package/dist/analyse-prepass/adapters/naming-convention-fks.d.ts +90 -0
  24. package/dist/analyse-prepass/adapters/naming-convention-fks.d.ts.map +1 -0
  25. package/dist/analyse-prepass/adapters/naming-convention-fks.js +181 -0
  26. package/dist/analyse-prepass/adapters/naming-convention-fks.js.map +1 -0
  27. package/dist/analyse-prepass/index.d.ts +8 -0
  28. package/dist/analyse-prepass/index.d.ts.map +1 -1
  29. package/dist/analyse-prepass/index.js +130 -0
  30. package/dist/analyse-prepass/index.js.map +1 -1
  31. package/dist/libs/instance-factories/cli/templates/commander/cli-entry-generator.js +11 -12
  32. package/dist/libs/instance-factories/cli/templates/commander/command-generator.js +2 -2
  33. package/dist/libs/instance-factories/controllers/templates/fastify/routes-generator.js +29 -10
  34. package/dist/libs/instance-factories/services/templates/prisma/ai-behaviors-generator.js +10 -9
  35. package/dist/libs/instance-factories/services/templates/prisma/behavior-generator.js +24 -2
  36. package/dist/libs/instance-factories/services/templates/prisma/controller-generator.js +28 -20
  37. package/dist/normalise/index.d.ts +14 -0
  38. package/dist/normalise/index.d.ts.map +1 -0
  39. package/dist/normalise/index.js +14 -0
  40. package/dist/normalise/index.js.map +1 -0
  41. package/dist/normalise/load-overrides.d.ts +43 -0
  42. package/dist/normalise/load-overrides.d.ts.map +1 -0
  43. package/dist/normalise/load-overrides.js +121 -0
  44. package/dist/normalise/load-overrides.js.map +1 -0
  45. package/dist/normalise/normalise-rules.d.ts +181 -0
  46. package/dist/normalise/normalise-rules.d.ts.map +1 -0
  47. package/dist/normalise/normalise-rules.js +79 -0
  48. package/dist/normalise/normalise-rules.js.map +1 -0
  49. package/dist/normalise/rules/cluster-module-functions.d.ts +31 -0
  50. package/dist/normalise/rules/cluster-module-functions.d.ts.map +1 -0
  51. package/dist/normalise/rules/cluster-module-functions.js +238 -0
  52. package/dist/normalise/rules/cluster-module-functions.js.map +1 -0
  53. package/dist/normalise/rules/crud-into-curved.d.ts +117 -0
  54. package/dist/normalise/rules/crud-into-curved.d.ts.map +1 -0
  55. package/dist/normalise/rules/crud-into-curved.js +303 -0
  56. package/dist/normalise/rules/crud-into-curved.js.map +1 -0
  57. package/dist/normalise/rules/drop-trivial-passthrough.d.ts +92 -0
  58. package/dist/normalise/rules/drop-trivial-passthrough.d.ts.map +1 -0
  59. package/dist/normalise/rules/drop-trivial-passthrough.js +217 -0
  60. package/dist/normalise/rules/drop-trivial-passthrough.js.map +1 -0
  61. package/dist/normalise/runner.d.ts +58 -0
  62. package/dist/normalise/runner.d.ts.map +1 -0
  63. package/dist/normalise/runner.js +114 -0
  64. package/dist/normalise/runner.js.map +1 -0
  65. package/dist/parser/import-resolver/resolver.js +1 -1
  66. package/dist/parser/import-resolver/resolver.js.map +1 -1
  67. package/dist/realize/engines/typescript-engine.js +1 -1
  68. package/dist/realize/engines/typescript-engine.js.map +1 -1
  69. package/dist/realize/index.d.ts.map +1 -1
  70. package/dist/realize/index.js +221 -88
  71. package/dist/realize/index.js.map +1 -1
  72. package/dist/realize/library/library.js +1 -1
  73. package/dist/realize/library/library.js.map +1 -1
  74. package/dist/realize/library/resolver.d.ts.map +1 -1
  75. package/dist/realize/library/resolver.js +14 -1
  76. package/dist/realize/library/resolver.js.map +1 -1
  77. package/dist/realize/owner-emit-shared.d.ts +114 -0
  78. package/dist/realize/owner-emit-shared.d.ts.map +1 -0
  79. package/dist/realize/owner-emit-shared.js +227 -0
  80. package/dist/realize/owner-emit-shared.js.map +1 -0
  81. package/dist/realize/per-action-recovery.d.ts +74 -0
  82. package/dist/realize/per-action-recovery.d.ts.map +1 -0
  83. package/dist/realize/per-action-recovery.js +268 -0
  84. package/dist/realize/per-action-recovery.js.map +1 -0
  85. package/dist/realize/per-owner-emit.d.ts +7 -58
  86. package/dist/realize/per-owner-emit.d.ts.map +1 -1
  87. package/dist/realize/per-owner-emit.js +67 -215
  88. package/dist/realize/per-owner-emit.js.map +1 -1
  89. package/dist/realize/per-owner-runner.d.ts +24 -4
  90. package/dist/realize/per-owner-runner.d.ts.map +1 -1
  91. package/dist/realize/per-owner-runner.js +77 -19
  92. package/dist/realize/per-owner-runner.js.map +1 -1
  93. package/dist/realize/post-emit-verify/diagnostics.d.ts +107 -0
  94. package/dist/realize/post-emit-verify/diagnostics.d.ts.map +1 -0
  95. package/dist/realize/post-emit-verify/diagnostics.js +148 -0
  96. package/dist/realize/post-emit-verify/diagnostics.js.map +1 -0
  97. package/dist/realize/post-emit-verify/feedback-runner.d.ts +123 -0
  98. package/dist/realize/post-emit-verify/feedback-runner.d.ts.map +1 -0
  99. package/dist/realize/post-emit-verify/feedback-runner.js +232 -0
  100. package/dist/realize/post-emit-verify/feedback-runner.js.map +1 -0
  101. package/dist/realize/post-emit-verify/index.d.ts +19 -0
  102. package/dist/realize/post-emit-verify/index.d.ts.map +1 -0
  103. package/dist/realize/post-emit-verify/index.js +18 -0
  104. package/dist/realize/post-emit-verify/index.js.map +1 -0
  105. package/dist/realize/post-emit-verify/reemit.d.ts +82 -0
  106. package/dist/realize/post-emit-verify/reemit.d.ts.map +1 -0
  107. package/dist/realize/post-emit-verify/reemit.js +124 -0
  108. package/dist/realize/post-emit-verify/reemit.js.map +1 -0
  109. package/dist/realize/post-emit-verify/types.d.ts +187 -0
  110. package/dist/realize/post-emit-verify/types.d.ts.map +1 -0
  111. package/dist/realize/post-emit-verify/types.js +28 -0
  112. package/dist/realize/post-emit-verify/types.js.map +1 -0
  113. package/dist/realize/post-emit-verify/verifier-manifest.d.ts +29 -0
  114. package/dist/realize/post-emit-verify/verifier-manifest.d.ts.map +1 -0
  115. package/dist/realize/post-emit-verify/verifier-manifest.js +57 -0
  116. package/dist/realize/post-emit-verify/verifier-manifest.js.map +1 -0
  117. package/dist/realize/post-emit-verify/verifiers/stub-completeness.d.ts +85 -0
  118. package/dist/realize/post-emit-verify/verifiers/stub-completeness.d.ts.map +1 -0
  119. package/dist/realize/post-emit-verify/verifiers/stub-completeness.js +298 -0
  120. package/dist/realize/post-emit-verify/verifiers/stub-completeness.js.map +1 -0
  121. package/dist/realize/post-emit-verify/verifiers/tsc.d.ts +24 -0
  122. package/dist/realize/post-emit-verify/verifiers/tsc.d.ts.map +1 -0
  123. package/dist/realize/post-emit-verify/verifiers/tsc.js +148 -0
  124. package/dist/realize/post-emit-verify/verifiers/tsc.js.map +1 -0
  125. package/dist/realize/realize-context-snapshot.d.ts +70 -0
  126. package/dist/realize/realize-context-snapshot.d.ts.map +1 -0
  127. package/dist/realize/realize-context-snapshot.js +96 -0
  128. package/dist/realize/realize-context-snapshot.js.map +1 -0
  129. package/dist/realize/realize-rules.d.ts +113 -0
  130. package/dist/realize/realize-rules.d.ts.map +1 -0
  131. package/dist/realize/realize-rules.js +271 -0
  132. package/dist/realize/realize-rules.js.map +1 -0
  133. package/dist/realize/structural-validator.d.ts +36 -2
  134. package/dist/realize/structural-validator.d.ts.map +1 -1
  135. package/dist/realize/structural-validator.js +50 -7
  136. package/dist/realize/structural-validator.js.map +1 -1
  137. package/libs/instance-factories/cli/templates/commander/cli-entry-generator.ts +11 -12
  138. package/libs/instance-factories/cli/templates/commander/command-generator.ts +2 -2
  139. package/libs/instance-factories/controllers/templates/fastify/routes-generator.ts +49 -15
  140. package/libs/instance-factories/services/templates/prisma/ai-behaviors-generator.ts +19 -3
  141. package/libs/instance-factories/services/templates/prisma/behavior-generator.ts +62 -2
  142. package/libs/instance-factories/services/templates/prisma/controller-generator.ts +47 -20
  143. package/package.json +9 -1
@@ -0,0 +1,298 @@
1
+ /**
2
+ * Stub-completeness verifier — detects placeholder/stub bodies in
3
+ * emitted `.ai.ts` files and reports them as VerifyErrors so the
4
+ * existing feedback runner re-emits real bodies.
5
+ *
6
+ * Why this exists:
7
+ * The tsc verifier catches code that DOESN'T COMPILE. It says nothing
8
+ * about code that compiles but ships no behavior — the dominant
9
+ * failure mode for smaller/open LLMs on per-owner emit:
10
+ * - Engine γ-stubs (LLM declined → fallback placeholder file)
11
+ * - LLM-emitted throw stubs ("not implemented", "TODO: ...")
12
+ * - LLM-emitted trivial returns (`return null as any`)
13
+ *
14
+ * Empirical at 2026-05-13:
15
+ * - idle-meta Ollama: 58% real-LLM fill, 80 tsc errors → 0 tsc
16
+ * errors looks clean but 42% of bodies are stubs.
17
+ * - idle-meta MarrBox: 69% real-LLM fill, 40 → ? tsc errors,
18
+ * 31% bodies still stubs.
19
+ *
20
+ * Reporting stubs as VerifyErrors lets the feedback runner re-emit
21
+ * them with a targeted prompt. The existing rollback machinery
22
+ * prevents regressions if the LLM can't do better.
23
+ *
24
+ * Design:
25
+ * - Regex-only — no TS compiler API import. The `.ai.ts` files have
26
+ * a narrow shape: top-level `export async function NAME(...):
27
+ * Promise<X> { ... }` declarations. Brace-balanced extraction with
28
+ * a single line scanner is enough.
29
+ * - Conservative: ONLY flags single-statement bodies that match
30
+ * stub patterns. A real function body with a stub-shaped throw
31
+ * inside a conditional is NOT flagged.
32
+ * - Severity `warning` not `error` — these don't break the build,
33
+ * but the feedback runner counts them as errors-to-fix.
34
+ *
35
+ * Initial release: `enabledByDefault: false` — opt in via
36
+ * `SPECVERSE_REALIZE_POST_VERIFY_ENABLE=stub-completeness`. Once the
37
+ * empirical hit-rate is measured we flip default-on.
38
+ */
39
+ import { existsSync, readdirSync, readFileSync, statSync } from 'fs';
40
+ import { join, relative } from 'path';
41
+ /** Stub error codes — surfaced to the feedback prompt as the verifier
42
+ * code; the LLM doesn't see them directly but they appear in the
43
+ * audit sidecar + logs. */
44
+ export const STUB_CODES = {
45
+ GAMMA_FALLBACK: 'STUB001', // engine wrote the placeholder file
46
+ LLM_THROW: 'STUB002', // LLM emitted "throw not implemented"
47
+ TRIVIAL_RETURN: 'STUB003', // LLM emitted `return null|undefined|{}|[]`
48
+ EMPTY_BODY: 'STUB004', // body is whitespace/comments only
49
+ };
50
+ /** Resolve the behaviors directory tsc + this verifier scan. */
51
+ function resolveBehaviorsDir(ctx) {
52
+ const sub = ctx.subpath ?? 'backend';
53
+ return join(ctx.outputDir, sub, 'src', 'behaviors');
54
+ }
55
+ export function extractAsyncFunctions(source) {
56
+ const lines = source.split('\n');
57
+ const out = [];
58
+ // Pattern: line starts (after optional `export ` + `async `) with
59
+ // `async function NAME(`. We accept `export async function` (the
60
+ // canonical case) plus the alternate `async function NAME(...){...}`
61
+ // followed by `export { NAME as ... }` re-export form used for
62
+ // reserved-word action names in the engine γ-fallback file.
63
+ const declRe = /^(export\s+)?async\s+function\s+(\w+)\s*\(/;
64
+ for (let i = 0; i < lines.length; i++) {
65
+ const line = lines[i];
66
+ const m = declRe.exec(line);
67
+ if (!m)
68
+ continue;
69
+ const name = m[2];
70
+ // Walk forward to find the first `{` that opens the body. Skip
71
+ // anything inside the parameter list / return-type annotation.
72
+ let openIdx = -1;
73
+ let parenDepth = 0;
74
+ let lineCursor = i;
75
+ let colCursor = m.index + m[0].length; // just past `(`
76
+ // We've consumed up to the `(` of params; start at depth 1.
77
+ parenDepth = 1;
78
+ scanHeader: while (lineCursor < lines.length) {
79
+ const s = lines[lineCursor];
80
+ while (colCursor < s.length) {
81
+ const ch = s[colCursor];
82
+ if (parenDepth > 0) {
83
+ if (ch === '(')
84
+ parenDepth++;
85
+ else if (ch === ')')
86
+ parenDepth--;
87
+ }
88
+ else {
89
+ // After params closed: look for `{`.
90
+ if (ch === '{') {
91
+ openIdx = colCursor;
92
+ break scanHeader;
93
+ }
94
+ }
95
+ colCursor++;
96
+ }
97
+ lineCursor++;
98
+ colCursor = 0;
99
+ }
100
+ if (openIdx === -1)
101
+ continue;
102
+ // Now brace-count forward from just past `{` until we hit the
103
+ // matching `}`.
104
+ let depth = 1;
105
+ let bodyStartLineIdx = lineCursor;
106
+ let bodyStartColIdx = openIdx + 1;
107
+ let endLineIdx = -1;
108
+ let endColIdx = -1;
109
+ walkBody: for (let li = lineCursor; li < lines.length; li++) {
110
+ const s = lines[li];
111
+ const startCol = li === lineCursor ? openIdx + 1 : 0;
112
+ for (let ci = startCol; ci < s.length; ci++) {
113
+ const ch = s[ci];
114
+ if (ch === '{')
115
+ depth++;
116
+ else if (ch === '}') {
117
+ depth--;
118
+ if (depth === 0) {
119
+ endLineIdx = li;
120
+ endColIdx = ci;
121
+ break walkBody;
122
+ }
123
+ }
124
+ }
125
+ }
126
+ if (endLineIdx === -1)
127
+ continue; // unbalanced; bail on this fn
128
+ // Slice the body content (exclusive of the outer braces).
129
+ let body;
130
+ if (bodyStartLineIdx === endLineIdx) {
131
+ body = lines[bodyStartLineIdx].slice(bodyStartColIdx, endColIdx);
132
+ }
133
+ else {
134
+ const first = lines[bodyStartLineIdx].slice(bodyStartColIdx);
135
+ const middle = lines.slice(bodyStartLineIdx + 1, endLineIdx).join('\n');
136
+ const last = lines[endLineIdx].slice(0, endColIdx);
137
+ body = [first, middle, last].filter((x) => x !== '').join('\n');
138
+ }
139
+ out.push({
140
+ name,
141
+ body,
142
+ declLine: i + 1,
143
+ bodyStartLine: bodyStartLineIdx + 1,
144
+ });
145
+ // Skip past the end so we don't re-scan content inside the body.
146
+ i = endLineIdx;
147
+ }
148
+ return out;
149
+ }
150
+ /**
151
+ * Strip line + block comments and blank lines, then trim.
152
+ * Used to normalize bodies before stub-pattern matching.
153
+ */
154
+ export function stripCommentsAndBlanks(body) {
155
+ // Block comments first (greedy, multi-line capable).
156
+ let s = body.replace(/\/\*[\s\S]*?\*\//g, '');
157
+ // Line comments.
158
+ s = s.replace(/(^|\n)\s*\/\/[^\n]*/g, (_, p1) => p1 ?? '');
159
+ // Collapse multiple newlines + trim.
160
+ s = s.split('\n').map((l) => l.trimEnd()).filter((l) => l.trim() !== '').join('\n').trim();
161
+ return s;
162
+ }
163
+ // γ-fallback engine placeholders. Two producers:
164
+ // - per-owner-runner.renderFallbackPlaceholderFile → "(per-owner emit fell back)"
165
+ // - per-action-recovery.renderActionGammaStub → "(per-action recovery fell back)"
166
+ // Both are ENGINE placeholders (STUB001, auto-reemit-eligible), NOT the
167
+ // LLM's own "not implemented" throw (STUB002, surface-spec-gap).
168
+ const GAMMA_FALLBACK_RE = /^throw new Error\s*\(\s*["'`].*?not implemented \((?:per-owner emit|per-action recovery) fell back\).*?["'`]\s*\)\s*;?$/s;
169
+ const LLM_THROW_RE = /^throw new Error\s*\(\s*["'`][^"'`]*\b(not\s+implement\w*|not\s+yet|todo|placeholder|stub|requires|fallback|missing|unimplement\w*)\b[^"'`]*["'`]\s*\)\s*;?$/is;
170
+ const TRIVIAL_RETURN_RE = /^return\s+(?:null|undefined|\{\s*\}|\[\s*\])(\s+as\s+\w+)?\s*;?$/s;
171
+ /**
172
+ * Classify a function body as a stub (or not). Conservative: requires
173
+ * the body to be a single-statement match to avoid false positives on
174
+ * real bodies that happen to contain a throw deep inside a conditional.
175
+ */
176
+ export function classifyBody(body) {
177
+ const stripped = stripCommentsAndBlanks(body);
178
+ if (stripped === '') {
179
+ return { kind: 'empty', code: STUB_CODES.EMPTY_BODY };
180
+ }
181
+ // Single-statement check: count semicolons + ensure no control-flow
182
+ // keywords at the top level. We don't try to detect every multi-
183
+ // statement function; instead, we use the simplest signal — if the
184
+ // stripped body matches a single-statement stub regex end-to-end,
185
+ // it's a stub.
186
+ if (GAMMA_FALLBACK_RE.test(stripped)) {
187
+ return { kind: 'gamma-fallback', code: STUB_CODES.GAMMA_FALLBACK };
188
+ }
189
+ if (LLM_THROW_RE.test(stripped)) {
190
+ return { kind: 'llm-throw', code: STUB_CODES.LLM_THROW };
191
+ }
192
+ if (TRIVIAL_RETURN_RE.test(stripped)) {
193
+ return { kind: 'trivial-return', code: STUB_CODES.TRIVIAL_RETURN };
194
+ }
195
+ return null;
196
+ }
197
+ /** Render a feedback-prompt-friendly message for a stub match. */
198
+ function messageFor(kind, fnName) {
199
+ switch (kind) {
200
+ case 'gamma-fallback':
201
+ return (`Function '${fnName}' is a γ-stub placeholder (per-owner emit fell back). ` +
202
+ `Emit a real implementation per the [PRE-BAKED] action contract in the spec.`);
203
+ case 'llm-throw':
204
+ return (`Function '${fnName}' has a placeholder body that throws 'not implemented' ` +
205
+ `(or similar). Emit a real implementation per the [PRE-BAKED] action contract.`);
206
+ case 'trivial-return':
207
+ return (`Function '${fnName}' returns a trivial placeholder (null/undefined/{}). ` +
208
+ `Emit a real implementation per the [PRE-BAKED] action contract.`);
209
+ case 'empty':
210
+ return (`Function '${fnName}' has an empty body. ` +
211
+ `Emit a real implementation per the [PRE-BAKED] action contract.`);
212
+ }
213
+ }
214
+ /** Recursively list `*.ai.ts` files under a directory. Defensive — the
215
+ * behaviors dir is normally flat but engines may add subdirs later. */
216
+ function listAiTsFiles(dir) {
217
+ if (!existsSync(dir))
218
+ return [];
219
+ const out = [];
220
+ for (const name of readdirSync(dir)) {
221
+ const p = join(dir, name);
222
+ let st;
223
+ try {
224
+ st = statSync(p);
225
+ }
226
+ catch {
227
+ continue;
228
+ }
229
+ if (st.isDirectory())
230
+ out.push(...listAiTsFiles(p));
231
+ else if (st.isFile() && p.endsWith('.ai.ts'))
232
+ out.push(p);
233
+ }
234
+ return out;
235
+ }
236
+ export const STUB_COMPLETENESS_VERIFIER = {
237
+ id: 'stub-completeness',
238
+ name: 'Stub Body Completeness',
239
+ // Default-on as of engines 6.56.0 (Phase 2 of
240
+ // 2026-05-13-VERIFIER-DIAGNOSTIC-TREATMENT-SPLIT). Safe to flip
241
+ // because the feedback runner's defaultTreatmentSelector routes
242
+ // STUB002 to surface-spec-gap (no reemit), preventing the cross-
243
+ // file regressions measured at engines 6.54.0 on idle-meta.
244
+ // STUB001/003/004 still auto-reemit (high-success on γ-fallback
245
+ // recovery, measured at engines 6.54.0 on nestjs-billing: 7/7 fixed).
246
+ enabledByDefault: true,
247
+ applies: (ctx) => {
248
+ if (ctx.targetLanguage && ctx.targetLanguage !== 'typescript')
249
+ return false;
250
+ const dir = resolveBehaviorsDir(ctx);
251
+ return existsSync(dir) && listAiTsFiles(dir).length > 0;
252
+ },
253
+ verify: async (ctx) => {
254
+ const start = Date.now();
255
+ const dir = resolveBehaviorsDir(ctx);
256
+ const files = listAiTsFiles(dir);
257
+ const errors = [];
258
+ const notes = [];
259
+ let totalFunctions = 0;
260
+ let totalStubs = 0;
261
+ for (const absFile of files) {
262
+ let source;
263
+ try {
264
+ source = readFileSync(absFile, 'utf8');
265
+ }
266
+ catch (e) {
267
+ notes.push(`could not read ${absFile}: ${e?.message ?? String(e)}`);
268
+ continue;
269
+ }
270
+ const fns = extractAsyncFunctions(source);
271
+ totalFunctions += fns.length;
272
+ for (const fn of fns) {
273
+ const match = classifyBody(fn.body);
274
+ if (!match)
275
+ continue;
276
+ totalStubs++;
277
+ errors.push({
278
+ file: relative(ctx.outputDir, absFile),
279
+ line: fn.declLine,
280
+ col: 1,
281
+ severity: 'warning',
282
+ code: match.code,
283
+ message: messageFor(match.kind, fn.name),
284
+ });
285
+ }
286
+ }
287
+ notes.push(`scanned ${files.length} .ai.ts file(s), ${totalFunctions} function(s); ` +
288
+ `flagged ${totalStubs} stub(s)`);
289
+ return {
290
+ verifierId: 'stub-completeness',
291
+ durationMs: Date.now() - start,
292
+ ok: true,
293
+ errors,
294
+ notes,
295
+ };
296
+ },
297
+ };
298
+ //# sourceMappingURL=stub-completeness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stub-completeness.js","sourceRoot":"","sources":["../../../../src/realize/post-emit-verify/verifiers/stub-completeness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AACrE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAQtC;;4BAE4B;AAC5B,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,cAAc,EAAE,SAAS,EAAG,oCAAoC;IAChE,SAAS,EAAE,SAAS,EAAQ,sCAAsC;IAClE,cAAc,EAAE,SAAS,EAAG,4CAA4C;IACxE,UAAU,EAAE,SAAS,EAAO,mCAAmC;CACvD,CAAC;AAEX,gEAAgE;AAChE,SAAS,mBAAmB,CAAC,GAAkB;IAC7C,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,IAAI,SAAS,CAAC;IACrC,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC;AACtD,CAAC;AAqBD,MAAM,UAAU,qBAAqB,CAAC,MAAc;IAClD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,GAAG,GAAwB,EAAE,CAAC;IACpC,kEAAkE;IAClE,iEAAiE;IACjE,qEAAqE;IACrE,+DAA+D;IAC/D,4DAA4D;IAC5D,MAAM,MAAM,GAAG,4CAA4C,CAAC;IAE5D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;QACvB,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;QAEnB,+DAA+D;QAC/D,+DAA+D;QAC/D,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC;QACjB,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,IAAI,SAAS,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAE,gBAAgB;QACxD,4DAA4D;QAC5D,UAAU,GAAG,CAAC,CAAC;QAEf,UAAU,EAAE,OAAO,UAAU,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YAC7C,MAAM,CAAC,GAAG,KAAK,CAAC,UAAU,CAAE,CAAC;YAC7B,OAAO,SAAS,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC;gBAC5B,MAAM,EAAE,GAAG,CAAC,CAAC,SAAS,CAAE,CAAC;gBACzB,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;oBACnB,IAAI,EAAE,KAAK,GAAG;wBAAE,UAAU,EAAE,CAAC;yBACxB,IAAI,EAAE,KAAK,GAAG;wBAAE,UAAU,EAAE,CAAC;gBACpC,CAAC;qBAAM,CAAC;oBACN,qCAAqC;oBACrC,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;wBAAC,OAAO,GAAG,SAAS,CAAC;wBAAC,MAAM,UAAU,CAAC;oBAAC,CAAC;gBAC5D,CAAC;gBACD,SAAS,EAAE,CAAC;YACd,CAAC;YACD,UAAU,EAAE,CAAC;YACb,SAAS,GAAG,CAAC,CAAC;QAChB,CAAC;QACD,IAAI,OAAO,KAAK,CAAC,CAAC;YAAE,SAAS;QAE7B,8DAA8D;QAC9D,gBAAgB;QAChB,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,IAAI,gBAAgB,GAAG,UAAU,CAAC;QAClC,IAAI,eAAe,GAAG,OAAO,GAAG,CAAC,CAAC;QAClC,IAAI,UAAU,GAAG,CAAC,CAAC,CAAC;QACpB,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC;QAEnB,QAAQ,EAAE,KAAK,IAAI,EAAE,GAAG,UAAU,EAAE,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;YAC5D,MAAM,CAAC,GAAG,KAAK,CAAC,EAAE,CAAE,CAAC;YACrB,MAAM,QAAQ,GAAG,EAAE,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACrD,KAAK,IAAI,EAAE,GAAG,QAAQ,EAAE,EAAE,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;gBAC5C,MAAM,EAAE,GAAG,CAAC,CAAC,EAAE,CAAE,CAAC;gBAClB,IAAI,EAAE,KAAK,GAAG;oBAAE,KAAK,EAAE,CAAC;qBACnB,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;oBACpB,KAAK,EAAE,CAAC;oBACR,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;wBAAC,UAAU,GAAG,EAAE,CAAC;wBAAC,SAAS,GAAG,EAAE,CAAC;wBAAC,MAAM,QAAQ,CAAC;oBAAC,CAAC;gBACvE,CAAC;YACH,CAAC;QACH,CAAC;QACD,IAAI,UAAU,KAAK,CAAC,CAAC;YAAE,SAAS,CAAE,8BAA8B;QAEhE,0DAA0D;QAC1D,IAAI,IAAY,CAAC;QACjB,IAAI,gBAAgB,KAAK,UAAU,EAAE,CAAC;YACpC,IAAI,GAAG,KAAK,CAAC,gBAAgB,CAAE,CAAC,KAAK,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC;QACpE,CAAC;aAAM,CAAC;YACN,MAAM,KAAK,GAAG,KAAK,CAAC,gBAAgB,CAAE,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;YAC9D,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,gBAAgB,GAAG,CAAC,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACxE,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAE,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;YACpD,IAAI,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClE,CAAC;QAED,GAAG,CAAC,IAAI,CAAC;YACP,IAAI;YACJ,IAAI;YACJ,QAAQ,EAAE,CAAC,GAAG,CAAC;YACf,aAAa,EAAE,gBAAgB,GAAG,CAAC;SACpC,CAAC,CAAC;QAEH,iEAAiE;QACjE,CAAC,GAAG,UAAU,CAAC;IACjB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAY;IACjD,qDAAqD;IACrD,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;IAC9C,iBAAiB;IACjB,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3D,qCAAqC;IACrC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3F,OAAO,CAAC,CAAC;AACX,CAAC;AAED,iDAAiD;AACjD,oFAAoF;AACpF,yFAAyF;AACzF,wEAAwE;AACxE,iEAAiE;AACjE,MAAM,iBAAiB,GAAG,0HAA0H,CAAC;AAErJ,MAAM,YAAY,GAAG,gKAAgK,CAAC;AAEtL,MAAM,iBAAiB,GAAG,mEAAmE,CAAC;AAO9F;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,QAAQ,GAAG,sBAAsB,CAAC,IAAI,CAAC,CAAC;IAE9C,IAAI,QAAQ,KAAK,EAAE,EAAE,CAAC;QACpB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,CAAC,UAAU,EAAE,CAAC;IACxD,CAAC;IAED,oEAAoE;IACpE,iEAAiE;IACjE,mEAAmE;IACnE,kEAAkE;IAClE,eAAe;IAEf,IAAI,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrC,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,UAAU,CAAC,cAAc,EAAE,CAAC;IACrE,CAAC;IACD,IAAI,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,CAAC,SAAS,EAAE,CAAC;IAC3D,CAAC;IACD,IAAI,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrC,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,UAAU,CAAC,cAAc,EAAE,CAAC;IACrE,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,kEAAkE;AAClE,SAAS,UAAU,CAAC,IAAuB,EAAE,MAAc;IACzD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,gBAAgB;YACnB,OAAO,CACL,aAAa,MAAM,wDAAwD;gBAC3E,6EAA6E,CAC9E,CAAC;QACJ,KAAK,WAAW;YACd,OAAO,CACL,aAAa,MAAM,yDAAyD;gBAC5E,+EAA+E,CAChF,CAAC;QACJ,KAAK,gBAAgB;YACnB,OAAO,CACL,aAAa,MAAM,uDAAuD;gBAC1E,iEAAiE,CAClE,CAAC;QACJ,KAAK,OAAO;YACV,OAAO,CACL,aAAa,MAAM,uBAAuB;gBAC1C,iEAAiE,CAClE,CAAC;IACN,CAAC;AACH,CAAC;AAED;wEACwE;AACxE,SAAS,aAAa,CAAC,GAAW;IAChC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;QACpC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC1B,IAAI,EAAE,CAAC;QACP,IAAI,CAAC;YAAC,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,SAAS;QAAC,CAAC;QAC7C,IAAI,EAAE,CAAC,WAAW,EAAE;YAAE,GAAG,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;aAC/C,IAAI,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,CAAC,MAAM,0BAA0B,GAAqB;IAC1D,EAAE,EAAE,mBAAmB;IACvB,IAAI,EAAE,wBAAwB;IAC9B,8CAA8C;IAC9C,gEAAgE;IAChE,gEAAgE;IAChE,iEAAiE;IACjE,4DAA4D;IAC5D,gEAAgE;IAChE,sEAAsE;IACtE,gBAAgB,EAAE,IAAI;IAEtB,OAAO,EAAE,CAAC,GAAkB,EAAW,EAAE;QACvC,IAAI,GAAG,CAAC,cAAc,IAAI,GAAG,CAAC,cAAc,KAAK,YAAY;YAAE,OAAO,KAAK,CAAC;QAC5E,MAAM,GAAG,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;QACrC,OAAO,UAAU,CAAC,GAAG,CAAC,IAAI,aAAa,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,EAAE,KAAK,EAAE,GAAkB,EAAyB,EAAE;QAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;QACrC,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,MAAM,GAAkB,EAAE,CAAC;QACjC,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,IAAI,cAAc,GAAG,CAAC,CAAC;QACvB,IAAI,UAAU,GAAG,CAAC,CAAC;QAEnB,KAAK,MAAM,OAAO,IAAI,KAAK,EAAE,CAAC;YAC5B,IAAI,MAAc,CAAC;YACnB,IAAI,CAAC;gBACH,MAAM,GAAG,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACzC,CAAC;YAAC,OAAO,CAAM,EAAE,CAAC;gBAChB,KAAK,CAAC,IAAI,CAAC,kBAAkB,OAAO,KAAK,CAAC,EAAE,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACpE,SAAS;YACX,CAAC;YAED,MAAM,GAAG,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;YAC1C,cAAc,IAAI,GAAG,CAAC,MAAM,CAAC;YAE7B,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;gBACrB,MAAM,KAAK,GAAG,YAAY,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;gBACpC,IAAI,CAAC,KAAK;oBAAE,SAAS;gBACrB,UAAU,EAAE,CAAC;gBACb,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC;oBACtC,IAAI,EAAE,EAAE,CAAC,QAAQ;oBACjB,GAAG,EAAE,CAAC;oBACN,QAAQ,EAAE,SAAS;oBACnB,IAAI,EAAE,KAAK,CAAC,IAAI;oBAChB,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC;iBACzC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,KAAK,CAAC,IAAI,CACR,WAAW,KAAK,CAAC,MAAM,oBAAoB,cAAc,gBAAgB;YACzE,WAAW,UAAU,UAAU,CAChC,CAAC;QAEF,OAAO;YACL,UAAU,EAAE,mBAAmB;YAC/B,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;YAC9B,EAAE,EAAE,IAAI;YACR,MAAM;YACN,KAAK;SACN,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * TypeScript verifier — runs `tsc --noEmit` on the realized backend
3
+ * tree, parses error output, and returns structured `VerifyError`s.
4
+ *
5
+ * The first concrete implementation of the `PostEmitVerifier` interface.
6
+ * Used for any TypeScript realize target (the default stack today).
7
+ *
8
+ * Design notes:
9
+ * - We rely on the realized project's own `node_modules/.bin/tsc`
10
+ * and `tsconfig.json` (installed by the realize-emit step).
11
+ * The framework doesn't bundle a tsc — the user's project owns
12
+ * its own TypeScript version.
13
+ * - `applies` checks for the presence of `tsconfig.json` in
14
+ * `<outputDir>/<subpath>/`. Future stacks (e.g. a Java target)
15
+ * would have their own verifier with their own `applies`.
16
+ * - Output parsing matches the standard tsc message format:
17
+ * `path/to/file.ts(line,col): error TSXXXX: Message text.`
18
+ * - tsc tool-failure (binary missing, install needed) → ok=false
19
+ * + notes explain. The feedback runner skips the verifier; the
20
+ * realize pipeline does NOT crash.
21
+ */
22
+ import type { PostEmitVerifier } from '../types.js';
23
+ export declare const TSC_VERIFIER: PostEmitVerifier;
24
+ //# sourceMappingURL=tsc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tsc.d.ts","sourceRoot":"","sources":["../../../../src/realize/post-emit-verify/verifiers/tsc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAKH,OAAO,KAAK,EACV,gBAAgB,EAIjB,MAAM,aAAa,CAAC;AAcrB,eAAO,MAAM,YAAY,EAAE,gBA8H1B,CAAC"}
@@ -0,0 +1,148 @@
1
+ /**
2
+ * TypeScript verifier — runs `tsc --noEmit` on the realized backend
3
+ * tree, parses error output, and returns structured `VerifyError`s.
4
+ *
5
+ * The first concrete implementation of the `PostEmitVerifier` interface.
6
+ * Used for any TypeScript realize target (the default stack today).
7
+ *
8
+ * Design notes:
9
+ * - We rely on the realized project's own `node_modules/.bin/tsc`
10
+ * and `tsconfig.json` (installed by the realize-emit step).
11
+ * The framework doesn't bundle a tsc — the user's project owns
12
+ * its own TypeScript version.
13
+ * - `applies` checks for the presence of `tsconfig.json` in
14
+ * `<outputDir>/<subpath>/`. Future stacks (e.g. a Java target)
15
+ * would have their own verifier with their own `applies`.
16
+ * - Output parsing matches the standard tsc message format:
17
+ * `path/to/file.ts(line,col): error TSXXXX: Message text.`
18
+ * - tsc tool-failure (binary missing, install needed) → ok=false
19
+ * + notes explain. The feedback runner skips the verifier; the
20
+ * realize pipeline does NOT crash.
21
+ */
22
+ import { existsSync } from 'fs';
23
+ import { join, relative } from 'path';
24
+ import { spawnSync } from 'child_process';
25
+ const TSC_LINE_RE = /^(.+?)\((\d+),(\d+)\):\s+(error|warning)\s+(TS\d+):\s+(.+)$/;
26
+ /**
27
+ * Resolve the directory tsc should run in. Defaults to
28
+ * `<outputDir>/backend` (the canonical SpecVerse TypeScript target).
29
+ * Caller can override via `ctx.subpath`.
30
+ */
31
+ function resolveSubpath(ctx) {
32
+ if (ctx.subpath)
33
+ return join(ctx.outputDir, ctx.subpath);
34
+ return join(ctx.outputDir, 'backend');
35
+ }
36
+ export const TSC_VERIFIER = {
37
+ id: 'tsc',
38
+ name: 'TypeScript Compiler',
39
+ enabledByDefault: true,
40
+ applies: (ctx) => {
41
+ if (ctx.targetLanguage && ctx.targetLanguage !== 'typescript')
42
+ return false;
43
+ const dir = resolveSubpath(ctx);
44
+ return existsSync(join(dir, 'tsconfig.json'));
45
+ },
46
+ verify: async (ctx) => {
47
+ const dir = resolveSubpath(ctx);
48
+ const start = Date.now();
49
+ const notes = [];
50
+ // Auto-install deps if needed. The realize pipeline emits a
51
+ // scaffolded project tree (package.json + tsconfig.json) but does
52
+ // not run `npm install`, so node_modules/.bin/tsc is missing on
53
+ // first verify. Without auto-install the framework would silently
54
+ // no-op default-on (after the engines 6.52 flip). Run `npm install`
55
+ // once when:
56
+ // - `package.json` exists
57
+ // - `node_modules/.bin/tsc` is missing
58
+ // - `ctx.autoInstall !== false` (defaults to true)
59
+ // Bounded by a 5-min timeout — pathological dep trees fail loudly
60
+ // rather than hang the realize pipeline.
61
+ const localTsc = join(dir, 'node_modules', '.bin', 'tsc');
62
+ const pkgJson = join(dir, 'package.json');
63
+ const autoInstall = ctx.autoInstall !== false;
64
+ if (!existsSync(localTsc) && existsSync(pkgJson) && autoInstall) {
65
+ const installResult = spawnSync('npm', ['install', '--no-audit', '--no-fund', '--silent'], {
66
+ cwd: dir,
67
+ encoding: 'utf8',
68
+ maxBuffer: 50 * 1024 * 1024,
69
+ timeout: 5 * 60_000,
70
+ });
71
+ if (installResult.error || installResult.status !== 0) {
72
+ return {
73
+ verifierId: 'tsc',
74
+ durationMs: Date.now() - start,
75
+ ok: false,
76
+ errors: [],
77
+ notes: [
78
+ `tsc verifier auto-install failed in ${dir}: ${installResult.error?.message ?? `npm exit ${installResult.status}`}. Hint: run \`npm install\` manually before realize, or set ctx.autoInstall=false.`,
79
+ ],
80
+ };
81
+ }
82
+ notes.push(`auto-installed deps in ${dir} for tsc verifier`);
83
+ }
84
+ // Locate the project-local tsc. Fall back to PATH `npx tsc` only if
85
+ // node_modules/.bin/tsc isn't installed yet.
86
+ let cmd;
87
+ let args;
88
+ if (existsSync(localTsc)) {
89
+ cmd = localTsc;
90
+ args = ['--noEmit'];
91
+ }
92
+ else {
93
+ cmd = 'npx';
94
+ args = ['--no-install', 'tsc', '--noEmit'];
95
+ }
96
+ const result = spawnSync(cmd, args, {
97
+ cwd: dir,
98
+ encoding: 'utf8',
99
+ maxBuffer: 50 * 1024 * 1024, // 50MB — error output on a heavy
100
+ // realize can be megabytes.
101
+ });
102
+ const durationMs = Date.now() - start;
103
+ if (result.error) {
104
+ return {
105
+ verifierId: 'tsc',
106
+ durationMs,
107
+ ok: false,
108
+ errors: [],
109
+ notes: [
110
+ ...notes,
111
+ `tsc could not be invoked: ${result.error.message}. ` +
112
+ `Hint: run \`npm install\` in ${dir} before realizing, or ensure ` +
113
+ `tsc is on PATH.`,
114
+ ],
115
+ };
116
+ }
117
+ const combined = (result.stdout ?? '') + (result.stderr ?? '');
118
+ const errors = [];
119
+ // tsc reports file paths relative to its CWD (the subpath). Convert
120
+ // those to paths relative to outputDir so the feedback runner's
121
+ // `join(outputDir, file)` resolves correctly.
122
+ const subpathRel = relative(ctx.outputDir, dir);
123
+ const toOutputRel = (file) => subpathRel === '' ? file : `${subpathRel}/${file}`;
124
+ for (const line of combined.split('\n')) {
125
+ const m = TSC_LINE_RE.exec(line.trimEnd());
126
+ if (!m)
127
+ continue;
128
+ errors.push({
129
+ file: toOutputRel(m[1]),
130
+ line: parseInt(m[2], 10),
131
+ col: parseInt(m[3], 10),
132
+ severity: m[4],
133
+ code: m[5],
134
+ message: m[6],
135
+ });
136
+ }
137
+ return {
138
+ verifierId: 'tsc',
139
+ durationMs,
140
+ // ok: true even when errors > 0 — that's the EXPECTED path.
141
+ // ok: false reserved for tool-level failures (binary missing, etc.).
142
+ ok: true,
143
+ errors,
144
+ notes,
145
+ };
146
+ },
147
+ };
148
+ //# sourceMappingURL=tsc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tsc.js","sourceRoot":"","sources":["../../../../src/realize/post-emit-verify/verifiers/tsc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAQ1C,MAAM,WAAW,GAAG,6DAA6D,CAAC;AAElF;;;;GAIG;AACH,SAAS,cAAc,CAAC,GAAkB;IACxC,IAAI,GAAG,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACzD,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAqB;IAC5C,EAAE,EAAE,KAAK;IACT,IAAI,EAAE,qBAAqB;IAC3B,gBAAgB,EAAE,IAAI;IAEtB,OAAO,EAAE,CAAC,GAAkB,EAAW,EAAE;QACvC,IAAI,GAAG,CAAC,cAAc,IAAI,GAAG,CAAC,cAAc,KAAK,YAAY;YAAE,OAAO,KAAK,CAAC;QAC5E,MAAM,GAAG,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QAChC,OAAO,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,EAAE,KAAK,EAAE,GAAkB,EAAyB,EAAE;QAC1D,MAAM,GAAG,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QAChC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,4DAA4D;QAC5D,kEAAkE;QAClE,gEAAgE;QAChE,kEAAkE;QAClE,oEAAoE;QACpE,aAAa;QACb,4BAA4B;QAC5B,yCAAyC;QACzC,qDAAqD;QACrD,kEAAkE;QAClE,yCAAyC;QACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QAC1C,MAAM,WAAW,GAAG,GAAG,CAAC,WAAW,KAAK,KAAK,CAAC;QAC9C,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,UAAU,CAAC,OAAO,CAAC,IAAI,WAAW,EAAE,CAAC;YAChE,MAAM,aAAa,GAAG,SAAS,CAC7B,KAAK,EACL,CAAC,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,CAAC,EAClD;gBACE,GAAG,EAAE,GAAG;gBACR,QAAQ,EAAE,MAAM;gBAChB,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;gBAC3B,OAAO,EAAE,CAAC,GAAG,MAAM;aACpB,CACF,CAAC;YACF,IAAI,aAAa,CAAC,KAAK,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACtD,OAAO;oBACL,UAAU,EAAE,KAAK;oBACjB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;oBAC9B,EAAE,EAAE,KAAK;oBACT,MAAM,EAAE,EAAE;oBACV,KAAK,EAAE;wBACL,uCAAuC,GAAG,KACxC,aAAa,CAAC,KAAK,EAAE,OAAO,IAAI,YAAY,aAAa,CAAC,MAAM,EAClE,oFAAoF;qBACrF;iBACF,CAAC;YACJ,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,0BAA0B,GAAG,mBAAmB,CAAC,CAAC;QAC/D,CAAC;QAED,oEAAoE;QACpE,6CAA6C;QAC7C,IAAI,GAAW,CAAC;QAChB,IAAI,IAAc,CAAC;QACnB,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,GAAG,GAAG,QAAQ,CAAC;YACf,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,GAAG,GAAG,KAAK,CAAC;YACZ,IAAI,GAAG,CAAC,cAAc,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE;YAClC,GAAG,EAAE,GAAG;YACR,QAAQ,EAAE,MAAM;YAChB,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAG,iCAAiC;YAChC,4BAA4B;SAC5D,CAAC,CAAC;QAEH,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QAEtC,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,OAAO;gBACL,UAAU,EAAE,KAAK;gBACjB,UAAU;gBACV,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,EAAE;gBACV,KAAK,EAAE;oBACL,GAAG,KAAK;oBACR,6BAA6B,MAAM,CAAC,KAAK,CAAC,OAAO,IAAI;wBACrD,gCAAgC,GAAG,+BAA+B;wBAClE,iBAAiB;iBAClB;aACF,CAAC;QACJ,CAAC;QAED,MAAM,QAAQ,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;QAC/D,MAAM,MAAM,GAAkB,EAAE,CAAC;QAEjC,oEAAoE;QACpE,gEAAgE;QAChE,8CAA8C;QAC9C,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAChD,MAAM,WAAW,GAAG,CAAC,IAAY,EAAU,EAAE,CAC3C,UAAU,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,UAAU,IAAI,IAAI,EAAE,CAAC;QAErD,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACxC,MAAM,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;YAC3C,IAAI,CAAC,CAAC;gBAAE,SAAS;YACjB,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC;gBACxB,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC;gBACzB,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC;gBACxB,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAyB;gBACtC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAE;gBACX,OAAO,EAAE,CAAC,CAAC,CAAC,CAAE;aACf,CAAC,CAAC;QACL,CAAC;QAED,OAAO;YACL,UAAU,EAAE,KAAK;YACjB,UAAU;YACV,4DAA4D;YAC5D,qEAAqE;YACrE,EAAE,EAAE,IAAI;YACR,MAAM;YACN,KAAK;SACN,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Per-owner realize-context snapshot.
3
+ *
4
+ * Phase 3 of 2026-05-13-VERIFIER-DIAGNOSTIC-TREATMENT-SPLIT.
5
+ *
6
+ * The per-owner emit prompt has TARGET RUNTIME, [PRE-BAKED] step bullets,
7
+ * cross-service operation signatures, available capabilities, library
8
+ * whitelist — everything the LLM needs to emit a real action body. The
9
+ * post-emit feedback runner's `buildLlmReemit` historically had NONE of
10
+ * this; the reemit prompt provided only the previous bad output + the
11
+ * verifier errors.
12
+ *
13
+ * Empirical consequence: sonnet still bridged the gap via inference;
14
+ * smaller models (Ollama qwen3-coder:30b, MarrBox) drifted further from
15
+ * the realize-emit skill's contract, introducing cross-file tsc
16
+ * regressions when asked to fix STUB002 stubs (measured 2026-05-13 at
17
+ * engines 6.54.0 on idle-meta).
18
+ *
19
+ * Phase 3 closes the gap by SNAPSHOTTING the per-owner context to disk
20
+ * at emit time and READING it at reemit time. The snapshot lives at
21
+ * `<outputDir>/.realize-context/<OwnerName>.md` and contains a compact
22
+ * markdown blob — directly embeddable in the reemit user prompt.
23
+ *
24
+ * Decoupling: the snapshot writer (called from per-owner-runner)
25
+ * doesn't know about reemit; the snapshot loader (called from reemit
26
+ * factory) doesn't know about per-owner-emit. They share only the
27
+ * file layout convention.
28
+ */
29
+ /** Input data for snapshotting an owner's realize context. Mirrors the
30
+ * subset of PerOwnerEmitRequest that's directly useful for fixing
31
+ * bodies — TARGET RUNTIME + per-action [PRE-BAKED] scaffolding +
32
+ * cross-service signatures + available capabilities. */
33
+ export interface OwnerRealizeContext {
34
+ ownerName: string;
35
+ /** e.g. "Node.js (backend)" — short, structurally useful for choosing
36
+ * imports + identifying forbidden APIs. */
37
+ targetRuntime: string;
38
+ /** The full per-action scaffolding rendered by `buildPerActionScaffolding`
39
+ * — already formatted with `[PRE-BAKED] "<step>" → <snippet>` blocks
40
+ * and `[WRITE] "<step>"` markers. Reusing the same render keeps the
41
+ * reemit prompt aligned with the original per-owner prompt. */
42
+ perActionScaffolding: string;
43
+ /** AVAILABLE SPEC SURFACE — signatures of cross-service operations.
44
+ * Empty-fallback formatted by the per-owner-runner. */
45
+ availableSpecSurface: string;
46
+ /** AVAILABLE CAPABILITIES — clients / repos the LLM may call. */
47
+ availableCapabilities: string;
48
+ /** AVAILABLE CLIENTS — generated client classes the LLM may instantiate. */
49
+ availableClients: string;
50
+ }
51
+ /**
52
+ * Render the context as a compact markdown blob suitable for direct
53
+ * embedding in the reemit prompt body. Mirrors the section headings
54
+ * used in the per-owner-emit prompt template so the LLM sees the same
55
+ * structural cues.
56
+ */
57
+ export declare function formatContextSnapshot(ctx: OwnerRealizeContext): string;
58
+ /**
59
+ * Persist a context snapshot to disk. Best-effort — caller should
60
+ * never crash on snapshot failure (the reemit prompt degrades to the
61
+ * pre-Phase-3 behavior cleanly).
62
+ */
63
+ export declare function writeContextSnapshot(outputDir: string, ctx: OwnerRealizeContext): void;
64
+ /**
65
+ * Load a previously-written snapshot. Returns the raw markdown blob,
66
+ * or `null` if no snapshot exists for the owner. Callers (the reemit
67
+ * factory) include the blob in the prompt body when present.
68
+ */
69
+ export declare function loadContextSnapshot(outputDir: string, ownerName: string): string | null;
70
+ //# sourceMappingURL=realize-context-snapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realize-context-snapshot.d.ts","sourceRoot":"","sources":["../../src/realize/realize-context-snapshot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAOH;;;yDAGyD;AACzD,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB;gDAC4C;IAC5C,aAAa,EAAE,MAAM,CAAC;IACtB;;;oEAGgE;IAChE,oBAAoB,EAAE,MAAM,CAAC;IAC7B;4DACwD;IACxD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,iEAAiE;IACjE,qBAAqB,EAAE,MAAM,CAAC;IAC9B,4EAA4E;IAC5E,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,mBAAmB,GAAG,MAAM,CAmBtE;AAQD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,mBAAmB,GACvB,IAAI,CASN;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,IAAI,CAQf"}