@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.
- package/dist/ai/analyse-runner.d.ts.map +1 -1
- package/dist/ai/analyse-runner.js +53 -1
- package/dist/ai/analyse-runner.js.map +1 -1
- package/dist/ai/prompt-runner.d.ts +39 -1
- package/dist/ai/prompt-runner.d.ts.map +1 -1
- package/dist/ai/prompt-runner.js +44 -3
- package/dist/ai/prompt-runner.js.map +1 -1
- package/dist/ai/providers/claude-cli.d.ts.map +1 -1
- package/dist/ai/providers/claude-cli.js +8 -1
- package/dist/ai/providers/claude-cli.js.map +1 -1
- package/dist/ai/skill-loader.d.ts +50 -0
- package/dist/ai/skill-loader.d.ts.map +1 -0
- package/dist/ai/skill-loader.js +96 -0
- package/dist/ai/skill-loader.js.map +1 -0
- package/dist/analyse-prepass/adapters/index.d.ts +2 -0
- package/dist/analyse-prepass/adapters/index.d.ts.map +1 -1
- package/dist/analyse-prepass/adapters/index.js +2 -0
- package/dist/analyse-prepass/adapters/index.js.map +1 -1
- package/dist/analyse-prepass/adapters/module-functions.d.ts +95 -0
- package/dist/analyse-prepass/adapters/module-functions.d.ts.map +1 -0
- package/dist/analyse-prepass/adapters/module-functions.js +358 -0
- package/dist/analyse-prepass/adapters/module-functions.js.map +1 -0
- package/dist/analyse-prepass/adapters/naming-convention-fks.d.ts +90 -0
- package/dist/analyse-prepass/adapters/naming-convention-fks.d.ts.map +1 -0
- package/dist/analyse-prepass/adapters/naming-convention-fks.js +181 -0
- package/dist/analyse-prepass/adapters/naming-convention-fks.js.map +1 -0
- package/dist/analyse-prepass/index.d.ts +8 -0
- package/dist/analyse-prepass/index.d.ts.map +1 -1
- package/dist/analyse-prepass/index.js +130 -0
- package/dist/analyse-prepass/index.js.map +1 -1
- package/dist/libs/instance-factories/cli/templates/commander/cli-entry-generator.js +11 -12
- package/dist/libs/instance-factories/cli/templates/commander/command-generator.js +2 -2
- package/dist/libs/instance-factories/controllers/templates/fastify/routes-generator.js +29 -10
- package/dist/libs/instance-factories/services/templates/prisma/ai-behaviors-generator.js +10 -9
- package/dist/libs/instance-factories/services/templates/prisma/behavior-generator.js +24 -2
- package/dist/libs/instance-factories/services/templates/prisma/controller-generator.js +28 -20
- package/dist/normalise/index.d.ts +14 -0
- package/dist/normalise/index.d.ts.map +1 -0
- package/dist/normalise/index.js +14 -0
- package/dist/normalise/index.js.map +1 -0
- package/dist/normalise/load-overrides.d.ts +43 -0
- package/dist/normalise/load-overrides.d.ts.map +1 -0
- package/dist/normalise/load-overrides.js +121 -0
- package/dist/normalise/load-overrides.js.map +1 -0
- package/dist/normalise/normalise-rules.d.ts +181 -0
- package/dist/normalise/normalise-rules.d.ts.map +1 -0
- package/dist/normalise/normalise-rules.js +79 -0
- package/dist/normalise/normalise-rules.js.map +1 -0
- package/dist/normalise/rules/cluster-module-functions.d.ts +31 -0
- package/dist/normalise/rules/cluster-module-functions.d.ts.map +1 -0
- package/dist/normalise/rules/cluster-module-functions.js +238 -0
- package/dist/normalise/rules/cluster-module-functions.js.map +1 -0
- package/dist/normalise/rules/crud-into-curved.d.ts +117 -0
- package/dist/normalise/rules/crud-into-curved.d.ts.map +1 -0
- package/dist/normalise/rules/crud-into-curved.js +303 -0
- package/dist/normalise/rules/crud-into-curved.js.map +1 -0
- package/dist/normalise/rules/drop-trivial-passthrough.d.ts +92 -0
- package/dist/normalise/rules/drop-trivial-passthrough.d.ts.map +1 -0
- package/dist/normalise/rules/drop-trivial-passthrough.js +217 -0
- package/dist/normalise/rules/drop-trivial-passthrough.js.map +1 -0
- package/dist/normalise/runner.d.ts +58 -0
- package/dist/normalise/runner.d.ts.map +1 -0
- package/dist/normalise/runner.js +114 -0
- package/dist/normalise/runner.js.map +1 -0
- package/dist/parser/import-resolver/resolver.js +1 -1
- package/dist/parser/import-resolver/resolver.js.map +1 -1
- package/dist/realize/engines/typescript-engine.js +1 -1
- package/dist/realize/engines/typescript-engine.js.map +1 -1
- package/dist/realize/index.d.ts.map +1 -1
- package/dist/realize/index.js +221 -88
- package/dist/realize/index.js.map +1 -1
- package/dist/realize/library/library.js +1 -1
- package/dist/realize/library/library.js.map +1 -1
- package/dist/realize/library/resolver.d.ts.map +1 -1
- package/dist/realize/library/resolver.js +14 -1
- package/dist/realize/library/resolver.js.map +1 -1
- package/dist/realize/owner-emit-shared.d.ts +114 -0
- package/dist/realize/owner-emit-shared.d.ts.map +1 -0
- package/dist/realize/owner-emit-shared.js +227 -0
- package/dist/realize/owner-emit-shared.js.map +1 -0
- package/dist/realize/per-action-recovery.d.ts +74 -0
- package/dist/realize/per-action-recovery.d.ts.map +1 -0
- package/dist/realize/per-action-recovery.js +268 -0
- package/dist/realize/per-action-recovery.js.map +1 -0
- package/dist/realize/per-owner-emit.d.ts +7 -58
- package/dist/realize/per-owner-emit.d.ts.map +1 -1
- package/dist/realize/per-owner-emit.js +67 -215
- package/dist/realize/per-owner-emit.js.map +1 -1
- package/dist/realize/per-owner-runner.d.ts +24 -4
- package/dist/realize/per-owner-runner.d.ts.map +1 -1
- package/dist/realize/per-owner-runner.js +77 -19
- package/dist/realize/per-owner-runner.js.map +1 -1
- package/dist/realize/post-emit-verify/diagnostics.d.ts +107 -0
- package/dist/realize/post-emit-verify/diagnostics.d.ts.map +1 -0
- package/dist/realize/post-emit-verify/diagnostics.js +148 -0
- package/dist/realize/post-emit-verify/diagnostics.js.map +1 -0
- package/dist/realize/post-emit-verify/feedback-runner.d.ts +123 -0
- package/dist/realize/post-emit-verify/feedback-runner.d.ts.map +1 -0
- package/dist/realize/post-emit-verify/feedback-runner.js +232 -0
- package/dist/realize/post-emit-verify/feedback-runner.js.map +1 -0
- package/dist/realize/post-emit-verify/index.d.ts +19 -0
- package/dist/realize/post-emit-verify/index.d.ts.map +1 -0
- package/dist/realize/post-emit-verify/index.js +18 -0
- package/dist/realize/post-emit-verify/index.js.map +1 -0
- package/dist/realize/post-emit-verify/reemit.d.ts +82 -0
- package/dist/realize/post-emit-verify/reemit.d.ts.map +1 -0
- package/dist/realize/post-emit-verify/reemit.js +124 -0
- package/dist/realize/post-emit-verify/reemit.js.map +1 -0
- package/dist/realize/post-emit-verify/types.d.ts +187 -0
- package/dist/realize/post-emit-verify/types.d.ts.map +1 -0
- package/dist/realize/post-emit-verify/types.js +28 -0
- package/dist/realize/post-emit-verify/types.js.map +1 -0
- package/dist/realize/post-emit-verify/verifier-manifest.d.ts +29 -0
- package/dist/realize/post-emit-verify/verifier-manifest.d.ts.map +1 -0
- package/dist/realize/post-emit-verify/verifier-manifest.js +57 -0
- package/dist/realize/post-emit-verify/verifier-manifest.js.map +1 -0
- package/dist/realize/post-emit-verify/verifiers/stub-completeness.d.ts +85 -0
- package/dist/realize/post-emit-verify/verifiers/stub-completeness.d.ts.map +1 -0
- package/dist/realize/post-emit-verify/verifiers/stub-completeness.js +298 -0
- package/dist/realize/post-emit-verify/verifiers/stub-completeness.js.map +1 -0
- package/dist/realize/post-emit-verify/verifiers/tsc.d.ts +24 -0
- package/dist/realize/post-emit-verify/verifiers/tsc.d.ts.map +1 -0
- package/dist/realize/post-emit-verify/verifiers/tsc.js +148 -0
- package/dist/realize/post-emit-verify/verifiers/tsc.js.map +1 -0
- package/dist/realize/realize-context-snapshot.d.ts +70 -0
- package/dist/realize/realize-context-snapshot.d.ts.map +1 -0
- package/dist/realize/realize-context-snapshot.js +96 -0
- package/dist/realize/realize-context-snapshot.js.map +1 -0
- package/dist/realize/realize-rules.d.ts +113 -0
- package/dist/realize/realize-rules.d.ts.map +1 -0
- package/dist/realize/realize-rules.js +271 -0
- package/dist/realize/realize-rules.js.map +1 -0
- package/dist/realize/structural-validator.d.ts +36 -2
- package/dist/realize/structural-validator.d.ts.map +1 -1
- package/dist/realize/structural-validator.js +50 -7
- package/dist/realize/structural-validator.js.map +1 -1
- package/libs/instance-factories/cli/templates/commander/cli-entry-generator.ts +11 -12
- package/libs/instance-factories/cli/templates/commander/command-generator.ts +2 -2
- package/libs/instance-factories/controllers/templates/fastify/routes-generator.ts +49 -15
- package/libs/instance-factories/services/templates/prisma/ai-behaviors-generator.ts +19 -3
- package/libs/instance-factories/services/templates/prisma/behavior-generator.ts +62 -2
- package/libs/instance-factories/services/templates/prisma/controller-generator.ts +47 -20
- package/package.json +9 -1
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post-emit verification framework — generic interface.
|
|
3
|
+
*
|
|
4
|
+
* SpecVerse realize emits one or more LLM-authored source files per
|
|
5
|
+
* owner (e.g. `backend/src/behaviors/<Owner>.ai.ts` for the TypeScript
|
|
6
|
+
* stack). LLM emissions sometimes carry compile errors / lint issues
|
|
7
|
+
* that don't show up at per-rule validation time (the realize-rules
|
|
8
|
+
* manifest catches forbidden APIs, missing `.js` extensions, etc., but
|
|
9
|
+
* not type mismatches or runtime semantics).
|
|
10
|
+
*
|
|
11
|
+
* A `PostEmitVerifier` runs AFTER all owners have emitted, on the
|
|
12
|
+
* fully-realized output tree. It produces structured errors that the
|
|
13
|
+
* feedback runner uses to drive a per-file re-emit pass.
|
|
14
|
+
*
|
|
15
|
+
* The interface is intentionally language-agnostic. The first
|
|
16
|
+
* implementation is `tsc` for TypeScript stacks; future verifiers can
|
|
17
|
+
* target Python (`mypy`/`ruff`), Go (`go vet`), Java (`mvn compile`),
|
|
18
|
+
* Rust (`cargo check`), etc. Each verifier knows whether it `applies`
|
|
19
|
+
* given the realized target (the manifest's stack tells you).
|
|
20
|
+
*
|
|
21
|
+
* Empirical motivation: 2026-05-13 idle-meta realize at engines 6.50.1
|
|
22
|
+
* produced 48 backend tsc errors. Two hand-crafted feedback prompts
|
|
23
|
+
* (AuthController.ai.ts + FormatNumberService.ai.ts) reduced this to
|
|
24
|
+
* 37 errors with zero regressions. Extrapolation: a full feedback
|
|
25
|
+
* sweep brings idle-meta from ~48 → ~5-10 errors per realize.
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Single error reported by a verifier. Position-optional (some
|
|
29
|
+
* verifiers — Go vet, formatters — emit errors without precise
|
|
30
|
+
* line/col).
|
|
31
|
+
*/
|
|
32
|
+
export interface VerifyError {
|
|
33
|
+
/** Path to the source file, relative to the realized output dir. */
|
|
34
|
+
file: string;
|
|
35
|
+
line?: number;
|
|
36
|
+
col?: number;
|
|
37
|
+
/** Verifier-specific code, e.g. "TS2554", "py:E501", "go:S1000". */
|
|
38
|
+
code: string;
|
|
39
|
+
/** Human-readable description, suitable for inclusion in a feedback
|
|
40
|
+
* prompt. Verifier-specific; the framework doesn't interpret it. */
|
|
41
|
+
message: string;
|
|
42
|
+
severity: 'error' | 'warning';
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Result of running a single verifier on the realized output.
|
|
46
|
+
*/
|
|
47
|
+
export interface VerifyResult {
|
|
48
|
+
/** Verifier id (matches `PostEmitVerifier.id`). */
|
|
49
|
+
verifierId: string;
|
|
50
|
+
/** Wall-time. Useful for tuning verifier order + budget. */
|
|
51
|
+
durationMs: number;
|
|
52
|
+
/** Whether the verifier ran successfully. False indicates a tool-level
|
|
53
|
+
* failure (tsc not installed, npm install needed first, etc.) — the
|
|
54
|
+
* feedback runner SKIPS the verifier when not ok, not when errors > 0. */
|
|
55
|
+
ok: boolean;
|
|
56
|
+
errors: VerifyError[];
|
|
57
|
+
/** Non-fatal warnings from the verifier itself (separate from
|
|
58
|
+
* per-error severity), e.g. "tsc emitted 200 errors but we truncated
|
|
59
|
+
* to 100". */
|
|
60
|
+
notes: string[];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Context passed to verifiers — describes the realize target so each
|
|
64
|
+
* verifier can decide whether it `applies`.
|
|
65
|
+
*
|
|
66
|
+
* Minimal for now; extends as new verifiers need additional signal.
|
|
67
|
+
*/
|
|
68
|
+
export interface VerifyContext {
|
|
69
|
+
/** Absolute path to the realized output root (the dir that contains
|
|
70
|
+
* e.g. `backend/`, `frontend/`, `tests/`). */
|
|
71
|
+
outputDir: string;
|
|
72
|
+
/** Realize target tag, e.g. 'typescript', 'python', 'go'. Set by the
|
|
73
|
+
* realize pipeline based on the manifest's primary stack. */
|
|
74
|
+
targetLanguage?: string;
|
|
75
|
+
/** Optional: explicit subpath within outputDir to verify. tsc would
|
|
76
|
+
* typically scope to `backend/`. Defaults to outputDir itself. */
|
|
77
|
+
subpath?: string;
|
|
78
|
+
/**
|
|
79
|
+
* When true (the default), verifiers MAY run dependency installation
|
|
80
|
+
* (`npm install` / `pip install` / etc.) before running their actual
|
|
81
|
+
* checks. Required for the in-pipeline `spv realize` invocation:
|
|
82
|
+
* realize emits a scaffolded project but doesn't install deps, so
|
|
83
|
+
* tsc/mypy/etc. wouldn't otherwise be available.
|
|
84
|
+
*
|
|
85
|
+
* Set to false in test harnesses or when the caller has already
|
|
86
|
+
* installed deps. Each verifier decides whether to honour the hint —
|
|
87
|
+
* a stub-only verifier might ignore it.
|
|
88
|
+
*/
|
|
89
|
+
autoInstall?: boolean;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* A verifier runs a quality check on the realized output. Each
|
|
93
|
+
* verifier is independent — the framework collects results from
|
|
94
|
+
* applicable verifiers, then the feedback runner decides what to do.
|
|
95
|
+
*
|
|
96
|
+
* Implementations must NOT throw on tool-level failures; return
|
|
97
|
+
* `{ ok: false, errors: [], notes: ['…'] }` instead. The framework
|
|
98
|
+
* surfaces notes to the user; throws crash the realize pipeline.
|
|
99
|
+
*/
|
|
100
|
+
export interface PostEmitVerifier {
|
|
101
|
+
/** Stable identifier — kebab-case. e.g. 'tsc', 'mypy', 'go-vet'. */
|
|
102
|
+
id: string;
|
|
103
|
+
/** Human-readable name for logs and audit. */
|
|
104
|
+
name: string;
|
|
105
|
+
/**
|
|
106
|
+
* Whether this verifier runs unless explicitly disabled. Mature
|
|
107
|
+
* stable verifiers ship `enabledByDefault: true` (tsc); experimental
|
|
108
|
+
* or third-party verifiers ship `false` to require an opt-in via
|
|
109
|
+
* `SPECVERSE_REALIZE_POST_VERIFY_ENABLE=<id>,<id>` env (future).
|
|
110
|
+
*
|
|
111
|
+
* Optional for backwards compatibility — missing field is treated
|
|
112
|
+
* as `true` (the original behavior).
|
|
113
|
+
*/
|
|
114
|
+
enabledByDefault?: boolean;
|
|
115
|
+
/** Predicate: does this verifier apply to the given context? */
|
|
116
|
+
applies: (ctx: VerifyContext) => boolean;
|
|
117
|
+
/** Run the verifier. MUST NOT throw on tool failure (return ok:false). */
|
|
118
|
+
verify: (ctx: VerifyContext) => Promise<VerifyResult>;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* After all verifiers have run, the feedback runner needs to map
|
|
122
|
+
* each errored file to its owning spec entity (e.g.
|
|
123
|
+
* `backend/src/behaviors/AuthController.ai.ts` → ownerName=AuthController).
|
|
124
|
+
*
|
|
125
|
+
* Each verifier MAY contribute a mapping hint via `mapFileToOwner`,
|
|
126
|
+
* but the framework falls back to a generic regex
|
|
127
|
+
* (`behaviors/(.+)\\.ai\\.ts$` for TypeScript). Verifiers for other
|
|
128
|
+
* stacks would override the mapping.
|
|
129
|
+
*/
|
|
130
|
+
export interface OwnerMapping {
|
|
131
|
+
/** Source file path (relative to outputDir). */
|
|
132
|
+
file: string;
|
|
133
|
+
/** Inferred owner name. null if the file can't be mapped (e.g.
|
|
134
|
+
* shared infrastructure files generated by the framework, not by
|
|
135
|
+
* per-owner LLM emit — those should NOT receive feedback re-emits). */
|
|
136
|
+
ownerName: string | null;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Per-error fix strategy. Phase 2 of
|
|
140
|
+
* 2026-05-13-VERIFIER-DIAGNOSTIC-TREATMENT-SPLIT — different verifier
|
|
141
|
+
* errors need different fix strategies, not a single "always reemit"
|
|
142
|
+
* path:
|
|
143
|
+
*
|
|
144
|
+
* - `auto-reemit`: include this error in the file's reemit prompt;
|
|
145
|
+
* the LLM should try to fix it. Right for tsc errors (unambiguous
|
|
146
|
+
* fix) + γ-fallback / trivial-return / empty-body stubs (LLM never
|
|
147
|
+
* produced real output the first time; a second try with focused
|
|
148
|
+
* context is high-success).
|
|
149
|
+
*
|
|
150
|
+
* - `surface-spec-gap`: do NOT reemit; surface the error to the user
|
|
151
|
+
* via the `realize-quality.json` sidecar (`specGaps` field).
|
|
152
|
+
* Right for STUB002 (LLM-throw stubs) where the LLM already
|
|
153
|
+
* signaled a context gap on the original emit — re-prompting
|
|
154
|
+
* either no-ops or hallucinates cross-file regressions (measured
|
|
155
|
+
* on idle-meta 2026-05-13 at engines 6.54.0).
|
|
156
|
+
*
|
|
157
|
+
* - `skip`: ignore entirely. Right for unmappable errors (already
|
|
158
|
+
* filtered) and for future categories the framework doesn't know
|
|
159
|
+
* how to treat.
|
|
160
|
+
*/
|
|
161
|
+
export type TreatmentStrategy = 'auto-reemit' | 'surface-spec-gap' | 'skip';
|
|
162
|
+
/**
|
|
163
|
+
* Decides how each verifier error should be treated. The default
|
|
164
|
+
* selector lives in `feedback-runner.ts::defaultTreatmentSelector`;
|
|
165
|
+
* callers may override for advanced cases (testing, custom verifiers,
|
|
166
|
+
* different LLM tolerance profiles).
|
|
167
|
+
*/
|
|
168
|
+
export type TreatmentSelector = (error: VerifyError) => TreatmentStrategy;
|
|
169
|
+
/**
|
|
170
|
+
* A single spec-level gap surfaced from a verifier error that the
|
|
171
|
+
* framework chose NOT to auto-fix. Goes into the realize-quality.json
|
|
172
|
+
* sidecar's `specGaps` array; users read it and decide whether to
|
|
173
|
+
* adjust the spec/manifest, switch providers, or hand-edit.
|
|
174
|
+
*/
|
|
175
|
+
export interface SpecGapEntry {
|
|
176
|
+
/** Owner name (e.g. "AuthController"). null when unmappable. */
|
|
177
|
+
ownerName: string | null;
|
|
178
|
+
/** Source file path, relative to outputDir. */
|
|
179
|
+
file: string;
|
|
180
|
+
line?: number;
|
|
181
|
+
col?: number;
|
|
182
|
+
/** Verifier code (e.g. "STUB002"). */
|
|
183
|
+
code: string;
|
|
184
|
+
/** Verifier-formatted message — directly suitable for user reading. */
|
|
185
|
+
message: string;
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/realize/post-emit-verify/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb;yEACqE;IACrE,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,mDAAmD;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,UAAU,EAAE,MAAM,CAAC;IACnB;;+EAE2E;IAC3E,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB;;mBAEe;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B;mDAC+C;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB;kEAC8D;IAC9D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;uEACmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;OAUG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,gBAAgB;IAC/B,oEAAoE;IACpE,EAAE,EAAE,MAAM,CAAC;IACX,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;;;OAQG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gEAAgE;IAChE,OAAO,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC;IACzC,0EAA0E;IAC1E,MAAM,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;CACvD;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,YAAY;IAC3B,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb;;4EAEwE;IACxE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,MAAM,iBAAiB,GAAG,aAAa,GAAG,kBAAkB,GAAG,MAAM,CAAC;AAE5E;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE,WAAW,KAAK,iBAAiB,CAAC;AAE1E;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,gEAAgE;IAChE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC;CACjB"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post-emit verification framework — generic interface.
|
|
3
|
+
*
|
|
4
|
+
* SpecVerse realize emits one or more LLM-authored source files per
|
|
5
|
+
* owner (e.g. `backend/src/behaviors/<Owner>.ai.ts` for the TypeScript
|
|
6
|
+
* stack). LLM emissions sometimes carry compile errors / lint issues
|
|
7
|
+
* that don't show up at per-rule validation time (the realize-rules
|
|
8
|
+
* manifest catches forbidden APIs, missing `.js` extensions, etc., but
|
|
9
|
+
* not type mismatches or runtime semantics).
|
|
10
|
+
*
|
|
11
|
+
* A `PostEmitVerifier` runs AFTER all owners have emitted, on the
|
|
12
|
+
* fully-realized output tree. It produces structured errors that the
|
|
13
|
+
* feedback runner uses to drive a per-file re-emit pass.
|
|
14
|
+
*
|
|
15
|
+
* The interface is intentionally language-agnostic. The first
|
|
16
|
+
* implementation is `tsc` for TypeScript stacks; future verifiers can
|
|
17
|
+
* target Python (`mypy`/`ruff`), Go (`go vet`), Java (`mvn compile`),
|
|
18
|
+
* Rust (`cargo check`), etc. Each verifier knows whether it `applies`
|
|
19
|
+
* given the realized target (the manifest's stack tells you).
|
|
20
|
+
*
|
|
21
|
+
* Empirical motivation: 2026-05-13 idle-meta realize at engines 6.50.1
|
|
22
|
+
* produced 48 backend tsc errors. Two hand-crafted feedback prompts
|
|
23
|
+
* (AuthController.ai.ts + FormatNumberService.ai.ts) reduced this to
|
|
24
|
+
* 37 errors with zero regressions. Extrapolation: a full feedback
|
|
25
|
+
* sweep brings idle-meta from ~48 → ~5-10 errors per realize.
|
|
26
|
+
*/
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/realize/post-emit-verify/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post-emit verifier manifest — single source of truth for which
|
|
3
|
+
* verifiers ship with the realize pipeline.
|
|
4
|
+
*
|
|
5
|
+
* Adding a new verifier: append to VERIFIERS, then it auto-runs on
|
|
6
|
+
* matching realize targets via `applies`.
|
|
7
|
+
*/
|
|
8
|
+
import type { PostEmitVerifier, VerifyContext, VerifyResult } from './types.js';
|
|
9
|
+
export declare const VERIFIERS: PostEmitVerifier[];
|
|
10
|
+
/**
|
|
11
|
+
* Run all applicable verifiers against the realized output. Verifiers
|
|
12
|
+
* run in series (most are heavyweight enough that parallel doesn't
|
|
13
|
+
* help much, and series gives predictable log output). Each verifier's
|
|
14
|
+
* tool-level failures are isolated — one failure doesn't stop the
|
|
15
|
+
* others.
|
|
16
|
+
*
|
|
17
|
+
* Verifier filtering order:
|
|
18
|
+
* 1. `enabledByDefault === false` AND id NOT in `enabledOverrides` → SKIP
|
|
19
|
+
* 2. `applies(ctx)` returns false → SKIP
|
|
20
|
+
* 3. Otherwise → run
|
|
21
|
+
*
|
|
22
|
+
* Missing `enabledByDefault` field is treated as `true` (backwards-
|
|
23
|
+
* compatible default). The `enabledOverrides` parameter lets callers
|
|
24
|
+
* opt-in to experimental verifiers at run-time without changing the
|
|
25
|
+
* manifest.
|
|
26
|
+
*/
|
|
27
|
+
export declare function runAllVerifiers(ctx: VerifyContext, enabledOverrides?: Set<string>): Promise<VerifyResult[]>;
|
|
28
|
+
export declare function findVerifier(id: string): PostEmitVerifier | undefined;
|
|
29
|
+
//# sourceMappingURL=verifier-manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verifier-manifest.d.ts","sourceRoot":"","sources":["../../../src/realize/post-emit-verify/verifier-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAIhF,eAAO,MAAM,SAAS,EAAE,gBAAgB,EAQvC,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,aAAa,EAClB,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAC7B,OAAO,CAAC,YAAY,EAAE,CAAC,CAqBzB;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAErE"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { TSC_VERIFIER } from './verifiers/tsc.js';
|
|
2
|
+
import { STUB_COMPLETENESS_VERIFIER } from './verifiers/stub-completeness.js';
|
|
3
|
+
export const VERIFIERS = [
|
|
4
|
+
TSC_VERIFIER,
|
|
5
|
+
STUB_COMPLETENESS_VERIFIER,
|
|
6
|
+
// Future:
|
|
7
|
+
// PY_MYPY_VERIFIER — `mypy --strict src/`
|
|
8
|
+
// GO_VET_VERIFIER — `go vet ./...`
|
|
9
|
+
// JAVA_MVN_VERIFIER — `mvn -q compile`
|
|
10
|
+
// RUST_CARGO_CHECK_VERIFIER — `cargo check`
|
|
11
|
+
];
|
|
12
|
+
/**
|
|
13
|
+
* Run all applicable verifiers against the realized output. Verifiers
|
|
14
|
+
* run in series (most are heavyweight enough that parallel doesn't
|
|
15
|
+
* help much, and series gives predictable log output). Each verifier's
|
|
16
|
+
* tool-level failures are isolated — one failure doesn't stop the
|
|
17
|
+
* others.
|
|
18
|
+
*
|
|
19
|
+
* Verifier filtering order:
|
|
20
|
+
* 1. `enabledByDefault === false` AND id NOT in `enabledOverrides` → SKIP
|
|
21
|
+
* 2. `applies(ctx)` returns false → SKIP
|
|
22
|
+
* 3. Otherwise → run
|
|
23
|
+
*
|
|
24
|
+
* Missing `enabledByDefault` field is treated as `true` (backwards-
|
|
25
|
+
* compatible default). The `enabledOverrides` parameter lets callers
|
|
26
|
+
* opt-in to experimental verifiers at run-time without changing the
|
|
27
|
+
* manifest.
|
|
28
|
+
*/
|
|
29
|
+
export async function runAllVerifiers(ctx, enabledOverrides) {
|
|
30
|
+
const out = [];
|
|
31
|
+
for (const v of VERIFIERS) {
|
|
32
|
+
const enabledByDefault = v.enabledByDefault !== false;
|
|
33
|
+
const explicitlyEnabled = enabledOverrides?.has(v.id) ?? false;
|
|
34
|
+
if (!enabledByDefault && !explicitlyEnabled)
|
|
35
|
+
continue;
|
|
36
|
+
if (!v.applies(ctx))
|
|
37
|
+
continue;
|
|
38
|
+
try {
|
|
39
|
+
const result = await v.verify(ctx);
|
|
40
|
+
out.push(result);
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
out.push({
|
|
44
|
+
verifierId: v.id,
|
|
45
|
+
durationMs: 0,
|
|
46
|
+
ok: false,
|
|
47
|
+
errors: [],
|
|
48
|
+
notes: [`Verifier "${v.id}" threw: ${err?.message ?? String(err)}`],
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return out;
|
|
53
|
+
}
|
|
54
|
+
export function findVerifier(id) {
|
|
55
|
+
return VERIFIERS.find((v) => v.id === id);
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=verifier-manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verifier-manifest.js","sourceRoot":"","sources":["../../../src/realize/post-emit-verify/verifier-manifest.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AAE9E,MAAM,CAAC,MAAM,SAAS,GAAuB;IAC3C,YAAY;IACZ,0BAA0B;IAC1B,UAAU;IACV,6CAA6C;IAC7C,uCAAuC;IACvC,yCAAyC;IACzC,8CAA8C;CAC/C,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,GAAkB,EAClB,gBAA8B;IAE9B,MAAM,GAAG,GAAmB,EAAE,CAAC;IAC/B,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,MAAM,gBAAgB,GAAG,CAAC,CAAC,gBAAgB,KAAK,KAAK,CAAC;QACtD,MAAM,iBAAiB,GAAG,gBAAgB,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC;QAC/D,IAAI,CAAC,gBAAgB,IAAI,CAAC,iBAAiB;YAAE,SAAS;QACtD,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;YAAE,SAAS;QAC9B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACnC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnB,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,GAAG,CAAC,IAAI,CAAC;gBACP,UAAU,EAAE,CAAC,CAAC,EAAE;gBAChB,UAAU,EAAE,CAAC;gBACb,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,EAAE;gBACV,KAAK,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,YAAY,GAAG,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;aACpE,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,EAAU;IACrC,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
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 type { PostEmitVerifier } from '../types.js';
|
|
40
|
+
/** Stub error codes — surfaced to the feedback prompt as the verifier
|
|
41
|
+
* code; the LLM doesn't see them directly but they appear in the
|
|
42
|
+
* audit sidecar + logs. */
|
|
43
|
+
export declare const STUB_CODES: {
|
|
44
|
+
readonly GAMMA_FALLBACK: "STUB001";
|
|
45
|
+
readonly LLM_THROW: "STUB002";
|
|
46
|
+
readonly TRIVIAL_RETURN: "STUB003";
|
|
47
|
+
readonly EMPTY_BODY: "STUB004";
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Find every top-level `export async function NAME(...): Promise<X> {`
|
|
51
|
+
* declaration in a file and return its name + body + start-line.
|
|
52
|
+
*
|
|
53
|
+
* Brace counting handles nested blocks and template-literal expression
|
|
54
|
+
* holes. We don't try to parse strings/regexes/comments precisely; the
|
|
55
|
+
* narrow shape of `.ai.ts` files makes this safe in practice (each
|
|
56
|
+
* function is independent and bodies don't contain `}` in odd places
|
|
57
|
+
* at the start of a line at depth 0).
|
|
58
|
+
*/
|
|
59
|
+
interface ExtractedFunction {
|
|
60
|
+
name: string;
|
|
61
|
+
body: string;
|
|
62
|
+
/** 1-based line number of the `export async function` declaration. */
|
|
63
|
+
declLine: number;
|
|
64
|
+
/** 1-based line number of the first body line (after the opening `{`). */
|
|
65
|
+
bodyStartLine: number;
|
|
66
|
+
}
|
|
67
|
+
export declare function extractAsyncFunctions(source: string): ExtractedFunction[];
|
|
68
|
+
/**
|
|
69
|
+
* Strip line + block comments and blank lines, then trim.
|
|
70
|
+
* Used to normalize bodies before stub-pattern matching.
|
|
71
|
+
*/
|
|
72
|
+
export declare function stripCommentsAndBlanks(body: string): string;
|
|
73
|
+
export interface StubMatch {
|
|
74
|
+
kind: 'gamma-fallback' | 'llm-throw' | 'trivial-return' | 'empty';
|
|
75
|
+
code: string;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Classify a function body as a stub (or not). Conservative: requires
|
|
79
|
+
* the body to be a single-statement match to avoid false positives on
|
|
80
|
+
* real bodies that happen to contain a throw deep inside a conditional.
|
|
81
|
+
*/
|
|
82
|
+
export declare function classifyBody(body: string): StubMatch | null;
|
|
83
|
+
export declare const STUB_COMPLETENESS_VERIFIER: PostEmitVerifier;
|
|
84
|
+
export {};
|
|
85
|
+
//# sourceMappingURL=stub-completeness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stub-completeness.d.ts","sourceRoot":"","sources":["../../../../src/realize/post-emit-verify/verifiers/stub-completeness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAIH,OAAO,KAAK,EACV,gBAAgB,EAIjB,MAAM,aAAa,CAAC;AAErB;;4BAE4B;AAC5B,eAAO,MAAM,UAAU;;;;;CAKb,CAAC;AAQX;;;;;;;;;GASG;AACH,UAAU,iBAAiB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,QAAQ,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAuFzE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQ3D;AAaD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,gBAAgB,GAAG,WAAW,GAAG,gBAAgB,GAAG,OAAO,CAAC;IAClE,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAwB3D;AA2CD,eAAO,MAAM,0BAA0B,EAAE,gBAoExC,CAAC"}
|