tryassay 0.1.0

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 (93) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +553 -0
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.js +80 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/assess.d.ts +6 -0
  7. package/dist/commands/assess.js +267 -0
  8. package/dist/commands/assess.js.map +1 -0
  9. package/dist/commands/describe.d.ts +3 -0
  10. package/dist/commands/describe.js +114 -0
  11. package/dist/commands/describe.js.map +1 -0
  12. package/dist/commands/extract.d.ts +4 -0
  13. package/dist/commands/extract.js +144 -0
  14. package/dist/commands/extract.js.map +1 -0
  15. package/dist/commands/hallucinate.d.ts +3 -0
  16. package/dist/commands/hallucinate.js +100 -0
  17. package/dist/commands/hallucinate.js.map +1 -0
  18. package/dist/commands/init.d.ts +1 -0
  19. package/dist/commands/init.js +39 -0
  20. package/dist/commands/init.js.map +1 -0
  21. package/dist/commands/regenerate.d.ts +3 -0
  22. package/dist/commands/regenerate.js +158 -0
  23. package/dist/commands/regenerate.js.map +1 -0
  24. package/dist/commands/remediate.d.ts +5 -0
  25. package/dist/commands/remediate.js +155 -0
  26. package/dist/commands/remediate.js.map +1 -0
  27. package/dist/commands/report.d.ts +3 -0
  28. package/dist/commands/report.js +84 -0
  29. package/dist/commands/report.js.map +1 -0
  30. package/dist/commands/reverse.d.ts +9 -0
  31. package/dist/commands/reverse.js +115 -0
  32. package/dist/commands/reverse.js.map +1 -0
  33. package/dist/commands/verify.d.ts +4 -0
  34. package/dist/commands/verify.js +112 -0
  35. package/dist/commands/verify.js.map +1 -0
  36. package/dist/lib/anthropic.d.ts +13 -0
  37. package/dist/lib/anthropic.js +60 -0
  38. package/dist/lib/anthropic.js.map +1 -0
  39. package/dist/lib/assessment-reporter.d.ts +5 -0
  40. package/dist/lib/assessment-reporter.js +266 -0
  41. package/dist/lib/assessment-reporter.js.map +1 -0
  42. package/dist/lib/claim-extractor.d.ts +6 -0
  43. package/dist/lib/claim-extractor.js +138 -0
  44. package/dist/lib/claim-extractor.js.map +1 -0
  45. package/dist/lib/code-verifier.d.ts +7 -0
  46. package/dist/lib/code-verifier.js +265 -0
  47. package/dist/lib/code-verifier.js.map +1 -0
  48. package/dist/lib/codebase-indexer.d.ts +15 -0
  49. package/dist/lib/codebase-indexer.js +156 -0
  50. package/dist/lib/codebase-indexer.js.map +1 -0
  51. package/dist/lib/config.d.ts +7 -0
  52. package/dist/lib/config.js +38 -0
  53. package/dist/lib/config.js.map +1 -0
  54. package/dist/lib/constraint-engine.d.ts +2 -0
  55. package/dist/lib/constraint-engine.js +337 -0
  56. package/dist/lib/constraint-engine.js.map +1 -0
  57. package/dist/lib/fs-utils.d.ts +1 -0
  58. package/dist/lib/fs-utils.js +11 -0
  59. package/dist/lib/fs-utils.js.map +1 -0
  60. package/dist/lib/guided-generator.d.ts +2 -0
  61. package/dist/lib/guided-generator.js +195 -0
  62. package/dist/lib/guided-generator.js.map +1 -0
  63. package/dist/lib/inventory-extractor.d.ts +7 -0
  64. package/dist/lib/inventory-extractor.js +238 -0
  65. package/dist/lib/inventory-extractor.js.map +1 -0
  66. package/dist/lib/prompts.d.ts +3 -0
  67. package/dist/lib/prompts.js +50 -0
  68. package/dist/lib/prompts.js.map +1 -0
  69. package/dist/lib/publisher.d.ts +2 -0
  70. package/dist/lib/publisher.js +71 -0
  71. package/dist/lib/publisher.js.map +1 -0
  72. package/dist/lib/remediation-generator.d.ts +2 -0
  73. package/dist/lib/remediation-generator.js +136 -0
  74. package/dist/lib/remediation-generator.js.map +1 -0
  75. package/dist/lib/remediator.d.ts +7 -0
  76. package/dist/lib/remediator.js +209 -0
  77. package/dist/lib/remediator.js.map +1 -0
  78. package/dist/lib/report-generator.d.ts +8 -0
  79. package/dist/lib/report-generator.js +190 -0
  80. package/dist/lib/report-generator.js.map +1 -0
  81. package/dist/lib/requirements-generator.d.ts +14 -0
  82. package/dist/lib/requirements-generator.js +311 -0
  83. package/dist/lib/requirements-generator.js.map +1 -0
  84. package/dist/lib/spec-synthesizer.d.ts +2 -0
  85. package/dist/lib/spec-synthesizer.js +136 -0
  86. package/dist/lib/spec-synthesizer.js.map +1 -0
  87. package/dist/lib/system-prompts.d.ts +12 -0
  88. package/dist/lib/system-prompts.js +254 -0
  89. package/dist/lib/system-prompts.js.map +1 -0
  90. package/dist/types.d.ts +243 -0
  91. package/dist/types.js +2 -0
  92. package/dist/types.js.map +1 -0
  93. package/package.json +49 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAGvC,MAAM,SAAS,GAAG,QAAQ,CAAC;AAC3B,MAAM,WAAW,GAAG,aAAa,CAAC;AAClC,MAAM,cAAc,GAAG,YAAY,CAAC;AAEpC,MAAM,UAAU,WAAW,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IACrD,OAAO,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IACvD,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAC1D,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,cAAc,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAC5D,OAAO,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAC1D,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CACb,sDAAsD,CACvD,CAAC;IACJ,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC1C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAgB,CAAC;AACxC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAmB,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE;IAChF,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,OAAO,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAEtC,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;QAC9B,MAAM,KAAK,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC;IACD,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QAC7B,MAAM,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;AACvF,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { CodeSpec, ConstraintSet } from '../types.js';
2
+ export declare function generateConstraints(task: string, language: string, specs: CodeSpec[], onProgress?: (msg: string) => void): Promise<ConstraintSet>;
@@ -0,0 +1,337 @@
1
+ import { getClient, MODEL } from './anthropic.js';
2
+ // ---------------------------------------------------------------------------
3
+ // Domain patterns — embedded knowledge from Assay benchmark findings
4
+ // ---------------------------------------------------------------------------
5
+ const DOMAIN_PATTERNS = [
6
+ {
7
+ triggers: ['sql', 'query', 'database', 'db'],
8
+ constraints: [
9
+ { type: 'must', description: 'Use parameterized queries, never string concatenation for SQL' },
10
+ { type: 'must-not', description: 'Never build SQL with template literals or string concatenation', pattern: '`SELECT * FROM ${table} WHERE id = ${id}`' },
11
+ ],
12
+ },
13
+ {
14
+ triggers: ['password', 'auth', 'login', 'credentials'],
15
+ constraints: [
16
+ { type: 'must', description: 'Use bcrypt or argon2 for password hashing, never MD5/SHA1' },
17
+ { type: 'must-not', description: 'Never store passwords in plaintext or use weak hashing' },
18
+ ],
19
+ },
20
+ {
21
+ triggers: ['counter', 'increment', 'shared', 'concurrent'],
22
+ constraints: [
23
+ { type: 'must', description: 'Use atomic operations or transactions for shared state updates' },
24
+ { type: 'must-not', description: 'Never use read-then-write pattern for counters without locking', pattern: 'const count = await getCount(); await setCount(count + 1);' },
25
+ ],
26
+ },
27
+ {
28
+ triggers: ['api', 'fetch', 'request', 'http'],
29
+ constraints: [
30
+ { type: 'must', description: 'Handle HTTP errors explicitly (check response.ok or status code)' },
31
+ { type: 'must-not', description: 'Never ignore HTTP error responses or assume success' },
32
+ { type: 'prefer', description: 'Include timeout configuration for HTTP requests' },
33
+ ],
34
+ },
35
+ {
36
+ triggers: ['array', 'list', 'collection', 'filter', 'map', 'reduce'],
37
+ constraints: [
38
+ { type: 'must', description: 'Handle empty array/collection edge case' },
39
+ { type: 'prefer', description: 'Use Set for O(1) lookups instead of nested array iterations' },
40
+ ],
41
+ },
42
+ {
43
+ triggers: ['parse', 'json', 'input', 'user input', 'form'],
44
+ constraints: [
45
+ { type: 'must', description: 'Validate and sanitize all external input before processing' },
46
+ { type: 'must', description: 'Wrap JSON.parse in try-catch' },
47
+ ],
48
+ },
49
+ {
50
+ triggers: ['file', 'path', 'directory', 'fs'],
51
+ constraints: [
52
+ { type: 'must', description: 'Check file/directory existence before operations' },
53
+ { type: 'must', description: 'Handle file operation errors (ENOENT, EACCES, etc.)' },
54
+ ],
55
+ },
56
+ {
57
+ triggers: ['regex', 'pattern', 'match'],
58
+ constraints: [
59
+ { type: 'must-not', description: 'Never use regex with /g flag in repeated calls without resetting lastIndex (JavaScript)' },
60
+ ],
61
+ },
62
+ {
63
+ triggers: ['float', 'decimal', 'money', 'price', 'calculation'],
64
+ constraints: [
65
+ { type: 'must-not', description: 'Never compare floating point numbers with strict equality', pattern: 'if (a === 0.3)' },
66
+ { type: 'prefer', description: 'Use epsilon comparison for floating point: Math.abs(a - b) < Number.EPSILON' },
67
+ ],
68
+ },
69
+ {
70
+ triggers: ['sort', 'order', 'rank', 'compare'],
71
+ constraints: [
72
+ { type: 'must', description: 'Provide an explicit comparator for numeric sorts (JavaScript default sort is lexicographic)', pattern: 'array.sort()' },
73
+ { type: 'must', description: 'Ensure sort comparator is consistent (if a < b then b > a)' },
74
+ ],
75
+ },
76
+ {
77
+ triggers: ['async', 'await', 'promise', 'callback'],
78
+ constraints: [
79
+ { type: 'must', description: 'Handle promise rejections with try-catch or .catch()' },
80
+ { type: 'must-not', description: 'Never fire-and-forget promises without error handling' },
81
+ { type: 'prefer', description: 'Use Promise.allSettled instead of Promise.all when partial failures are acceptable' },
82
+ ],
83
+ },
84
+ {
85
+ triggers: ['cache', 'memo', 'memoize', 'store'],
86
+ constraints: [
87
+ { type: 'must', description: 'Include cache invalidation or TTL mechanism' },
88
+ { type: 'must-not', description: 'Never allow unbounded cache growth without eviction policy' },
89
+ ],
90
+ },
91
+ {
92
+ triggers: ['recursive', 'recursion', 'tree', 'graph', 'traverse'],
93
+ constraints: [
94
+ { type: 'must', description: 'Include a base case that terminates recursion' },
95
+ { type: 'prefer', description: 'Guard against circular references in graph/tree traversal' },
96
+ { type: 'prefer', description: 'Consider stack depth limits for deep recursion; use iteration if depth is unbounded' },
97
+ ],
98
+ },
99
+ {
100
+ triggers: ['string', 'text', 'substring', 'split', 'join'],
101
+ constraints: [
102
+ { type: 'must', description: 'Handle empty string edge case' },
103
+ { type: 'prefer', description: 'Consider Unicode/multi-byte characters when indexing strings' },
104
+ ],
105
+ },
106
+ {
107
+ triggers: ['date', 'time', 'timestamp', 'schedule', 'cron'],
108
+ constraints: [
109
+ { type: 'must', description: 'Handle timezone conversions explicitly, do not assume UTC' },
110
+ { type: 'must-not', description: 'Never construct dates from string concatenation without validation' },
111
+ ],
112
+ },
113
+ {
114
+ triggers: ['divide', 'division', 'ratio', 'percentage', 'average'],
115
+ constraints: [
116
+ { type: 'must', description: 'Check for division by zero before dividing' },
117
+ ],
118
+ },
119
+ {
120
+ triggers: ['env', 'environment', 'config', 'secret', 'token'],
121
+ constraints: [
122
+ { type: 'must', description: 'Validate that required environment variables are set before using them' },
123
+ { type: 'must-not', description: 'Never log or expose secrets/tokens in error messages or console output' },
124
+ ],
125
+ },
126
+ {
127
+ triggers: ['stream', 'pipe', 'buffer', 'socket', 'websocket'],
128
+ constraints: [
129
+ { type: 'must', description: 'Handle stream error events to prevent unhandled exceptions' },
130
+ { type: 'must', description: 'Clean up resources (close streams/sockets) in error and completion paths' },
131
+ ],
132
+ },
133
+ ];
134
+ // ---------------------------------------------------------------------------
135
+ // LLM-based constraint derivation from specs
136
+ // ---------------------------------------------------------------------------
137
+ const CONSTRAINT_SYSTEM_PROMPT = `You are a constraint generator for code generation. Given a set of formal specifications that code must satisfy, produce generation constraints that PREVENT common failures.
138
+
139
+ CONSTRAINT RULES:
140
+
141
+ 1. For each specification, produce 1-2 constraints that guide the code generator:
142
+ - correctness spec → "must" constraint with specific implementation guidance
143
+ - security spec → "must-not" constraint with anti-pattern example
144
+ - edge-case spec → "must" constraint for boundary handling
145
+ - error-handling spec → "must" constraint for explicit error paths
146
+ - type-safety spec → "must-not" constraint against unsafe coercions
147
+ - performance spec → "prefer" constraint with recommended approach
148
+
149
+ 2. Each constraint must have:
150
+ - type: "must" | "must-not" | "prefer"
151
+ - description: Clear guidance for the code generator (1-2 sentences)
152
+ - pattern: (optional) A short code snippet showing the anti-pattern (for must-not) or expected pattern (for must)
153
+
154
+ 3. Be SPECIFIC and ACTIONABLE:
155
+ - GOOD: "Must handle the case where input array is empty by returning an empty array"
156
+ - GOOD: "Must-not use indexOf for existence checks on large arrays; use Set or Map"
157
+ - BAD: "Must be correct" (too vague)
158
+ - BAD: "Must handle errors" (not actionable)
159
+
160
+ 4. Do NOT duplicate: If two specs would produce the same constraint, only include it once.
161
+
162
+ OUTPUT FORMAT:
163
+ Return ONLY a JSON array of constraint objects. No markdown fences, no commentary.
164
+ [
165
+ {
166
+ "type": "must",
167
+ "description": "...",
168
+ "pattern": "..."
169
+ }
170
+ ]`;
171
+ const VALID_TYPES = ['must', 'must-not', 'prefer'];
172
+ function validateConstraint(raw) {
173
+ if (!raw.description || typeof raw.description !== 'string')
174
+ return null;
175
+ const type = VALID_TYPES.includes(raw.type)
176
+ ? raw.type
177
+ : 'must';
178
+ return {
179
+ type,
180
+ description: raw.description.trim(),
181
+ pattern: typeof raw.pattern === 'string' ? raw.pattern.trim() : undefined,
182
+ };
183
+ }
184
+ // ---------------------------------------------------------------------------
185
+ // Domain pattern matching
186
+ // ---------------------------------------------------------------------------
187
+ function matchDomainPatterns(task) {
188
+ const taskLower = task.toLowerCase();
189
+ const matched = [];
190
+ const seen = new Set();
191
+ for (const pattern of DOMAIN_PATTERNS) {
192
+ const triggered = pattern.triggers.some((t) => taskLower.includes(t));
193
+ if (!triggered)
194
+ continue;
195
+ for (const c of pattern.constraints) {
196
+ // Deduplicate by description
197
+ if (seen.has(c.description))
198
+ continue;
199
+ seen.add(c.description);
200
+ matched.push({
201
+ type: c.type,
202
+ description: c.description,
203
+ pattern: c.pattern,
204
+ source: 'domain',
205
+ });
206
+ }
207
+ }
208
+ return matched;
209
+ }
210
+ // ---------------------------------------------------------------------------
211
+ // JSON parsing helpers (same pattern as claim-extractor / spec-synthesizer)
212
+ // ---------------------------------------------------------------------------
213
+ function stripCodeFences(text) {
214
+ let jsonText = text.trim();
215
+ // Remove opening code fence
216
+ if (jsonText.startsWith('```')) {
217
+ const firstNewline = jsonText.indexOf('\n');
218
+ if (firstNewline !== -1) {
219
+ jsonText = jsonText.slice(firstNewline + 1);
220
+ }
221
+ }
222
+ // Remove closing code fence
223
+ const lastFence = jsonText.lastIndexOf('```');
224
+ if (lastFence !== -1) {
225
+ jsonText = jsonText.slice(0, lastFence);
226
+ }
227
+ return jsonText.trim();
228
+ }
229
+ function repairTruncatedArray(jsonText, onProgress) {
230
+ if (jsonText.endsWith(']'))
231
+ return jsonText;
232
+ const lastCloseBrace = jsonText.lastIndexOf('}');
233
+ if (lastCloseBrace !== -1) {
234
+ onProgress?.('Note: Response was truncated. Recovered partial constraints.');
235
+ return jsonText.slice(0, lastCloseBrace + 1) + '\n]';
236
+ }
237
+ return jsonText;
238
+ }
239
+ // ---------------------------------------------------------------------------
240
+ // Spec-derived constraints via LLM
241
+ // ---------------------------------------------------------------------------
242
+ async function deriveSpecConstraints(specs, task, language, onProgress) {
243
+ if (specs.length === 0) {
244
+ return { constraints: [], inputTokens: 0, outputTokens: 0 };
245
+ }
246
+ const client = getClient();
247
+ onProgress?.('Deriving spec constraints via Claude (streaming)...');
248
+ const specsText = specs
249
+ .map((s) => `[${s.id}] (${s.category}, ${s.severity}) ${s.description}\n Assertion: ${s.assertion}`)
250
+ .join('\n\n');
251
+ const stream = client.messages.stream({
252
+ model: MODEL,
253
+ max_tokens: 8_000,
254
+ system: CONSTRAINT_SYSTEM_PROMPT,
255
+ messages: [
256
+ {
257
+ role: 'user',
258
+ content: `Generate constraints for the following coding task and specifications.\n\nLanguage: ${language}\nTask: ${task}\n\nSpecifications:\n${specsText}`,
259
+ },
260
+ ],
261
+ });
262
+ let rawText = '';
263
+ stream.on('text', (text) => {
264
+ rawText += text;
265
+ });
266
+ const finalMessage = await stream.finalMessage();
267
+ onProgress?.('Parsing constraint results...');
268
+ let jsonText = stripCodeFences(rawText);
269
+ jsonText = repairTruncatedArray(jsonText, onProgress);
270
+ let parsed;
271
+ try {
272
+ parsed = JSON.parse(jsonText);
273
+ }
274
+ catch {
275
+ throw new Error(`Failed to parse Claude's constraint response as JSON.\n` +
276
+ `First 200 chars: ${jsonText.slice(0, 200)}`);
277
+ }
278
+ if (!Array.isArray(parsed)) {
279
+ throw new Error('Expected a JSON array of constraints from Claude.');
280
+ }
281
+ const constraints = [];
282
+ for (const raw of parsed) {
283
+ const validated = validateConstraint(raw);
284
+ if (validated) {
285
+ constraints.push({
286
+ ...validated,
287
+ source: 'spec',
288
+ });
289
+ }
290
+ }
291
+ return {
292
+ constraints,
293
+ inputTokens: finalMessage.usage.input_tokens,
294
+ outputTokens: finalMessage.usage.output_tokens,
295
+ };
296
+ }
297
+ // ---------------------------------------------------------------------------
298
+ // Main export
299
+ // ---------------------------------------------------------------------------
300
+ export async function generateConstraints(task, language, specs, onProgress) {
301
+ // 1. Match domain patterns
302
+ onProgress?.('Matching domain patterns...');
303
+ const domainConstraints = matchDomainPatterns(task);
304
+ onProgress?.(`Matched ${domainConstraints.length} domain constraint(s).`);
305
+ // 2. Derive spec constraints via LLM
306
+ const { constraints: specConstraints, inputTokens, outputTokens } = await deriveSpecConstraints(specs, task, language, onProgress);
307
+ onProgress?.(`Derived ${specConstraints.length} spec constraint(s).`);
308
+ // 3. Merge and deduplicate (domain first, then spec-derived)
309
+ const allConstraints = [...domainConstraints, ...specConstraints];
310
+ const seen = new Set();
311
+ const deduped = [];
312
+ for (const c of allConstraints) {
313
+ const key = c.description.toLowerCase();
314
+ if (seen.has(key))
315
+ continue;
316
+ seen.add(key);
317
+ deduped.push(c);
318
+ }
319
+ // 4. Number all constraints CON-001, CON-002, etc.
320
+ const numbered = deduped.map((c, i) => ({
321
+ id: `CON-${String(i + 1).padStart(3, '0')}`,
322
+ type: c.type,
323
+ description: c.description,
324
+ pattern: c.pattern,
325
+ source: c.source,
326
+ }));
327
+ onProgress?.(`Total: ${numbered.length} constraint(s) after deduplication.`);
328
+ return {
329
+ task,
330
+ constraints: numbered,
331
+ totalConstraints: numbered.length,
332
+ generatedAt: new Date().toISOString(),
333
+ inputTokens,
334
+ outputTokens,
335
+ };
336
+ }
337
+ //# sourceMappingURL=constraint-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constraint-engine.js","sourceRoot":"","sources":["../../src/lib/constraint-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function exists(path: string): Promise<boolean>;
@@ -0,0 +1,11 @@
1
+ import { access } from 'node:fs/promises';
2
+ export async function exists(path) {
3
+ try {
4
+ await access(path);
5
+ return true;
6
+ }
7
+ catch {
8
+ return false;
9
+ }
10
+ }
11
+ //# sourceMappingURL=fs-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-utils.js","sourceRoot":"","sources":["../../src/lib/fs-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAY;IACvC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { CodeSpec, GenerationConstraint, GeneratedCode } from '../types.js';
2
+ export declare function generateWithConstraints(task: string, language: string, specs: CodeSpec[], constraints: GenerationConstraint[], onProgress?: (msg: string) => void): Promise<GeneratedCode>;
@@ -0,0 +1,195 @@
1
+ import { getClient, MODEL } from './anthropic.js';
2
+ const MAX_TOKENS = 16_000;
3
+ function buildGenerationSystemPrompt(language, specs, constraints) {
4
+ const specLines = specs.map((s) => {
5
+ return `[${s.id}] (${s.severity}/${s.category}): ${s.description}\n Assertion: ${s.assertion}`;
6
+ });
7
+ const musts = constraints.filter((c) => c.type === 'must');
8
+ const mustNots = constraints.filter((c) => c.type === 'must-not');
9
+ const prefers = constraints.filter((c) => c.type === 'prefer');
10
+ let constraintBlock = '';
11
+ if (musts.length > 0) {
12
+ constraintBlock += 'MUST DO:\n';
13
+ constraintBlock += musts
14
+ .map((c) => `- ${c.id}: ${c.description}${c.pattern ? `\n Example: ${c.pattern}` : ''}`)
15
+ .join('\n');
16
+ constraintBlock += '\n\n';
17
+ }
18
+ if (mustNots.length > 0) {
19
+ constraintBlock += 'MUST NOT DO:\n';
20
+ constraintBlock += mustNots
21
+ .map((c) => `- ${c.id}: ${c.description}${c.pattern ? `\n Bad example: ${c.pattern}` : ''}`)
22
+ .join('\n');
23
+ constraintBlock += '\n\n';
24
+ }
25
+ if (prefers.length > 0) {
26
+ constraintBlock += 'PREFER:\n';
27
+ constraintBlock += prefers
28
+ .map((c) => `- ${c.id}: ${c.description}${c.pattern ? `\n Example: ${c.pattern}` : ''}`)
29
+ .join('\n');
30
+ constraintBlock += '\n';
31
+ }
32
+ return `You are an expert programmer. Generate production-quality ${language} code.
33
+
34
+ SPECIFICATIONS — Your code MUST satisfy ALL of these:
35
+ ${specLines.join('\n')}
36
+
37
+ CONSTRAINTS:
38
+ ${constraintBlock}
39
+ OUTPUT RULES:
40
+ - Return ONLY the code
41
+ - No markdown code fences
42
+ - No explanations before or after the code
43
+ - Include all necessary imports
44
+ - Include type annotations
45
+ - The code should be complete and runnable`;
46
+ }
47
+ const VERIFICATION_SYSTEM_PROMPT = `You are a code reviewer verifying generated code against specifications. For each specification, determine whether the code satisfies it.
48
+
49
+ OUTPUT FORMAT:
50
+ Return ONLY a JSON array. No markdown fences, no commentary. Each element:
51
+ {
52
+ "specId": "SPEC-001",
53
+ "status": "satisfied" | "partial" | "unsatisfied" | "unknown",
54
+ "reasoning": "Brief explanation of why the code does or does not satisfy this spec"
55
+ }
56
+
57
+ STATUS MEANINGS:
58
+ - satisfied: The code clearly and correctly implements this specification
59
+ - partial: The code addresses this specification but incompletely or with caveats
60
+ - unsatisfied: The code does not implement this specification or violates it
61
+ - unknown: Cannot determine from static analysis alone (e.g., runtime/performance specs)`;
62
+ function stripCodeFences(text) {
63
+ let result = text.trim();
64
+ // Remove opening code fence (```language or just ```)
65
+ if (result.startsWith('```')) {
66
+ const firstNewline = result.indexOf('\n');
67
+ if (firstNewline !== -1) {
68
+ result = result.slice(firstNewline + 1);
69
+ }
70
+ }
71
+ // Remove closing code fence
72
+ const lastFence = result.lastIndexOf('```');
73
+ if (lastFence !== -1) {
74
+ result = result.slice(0, lastFence);
75
+ }
76
+ return result.trim();
77
+ }
78
+ const VALID_STATUSES = [
79
+ 'satisfied', 'partial', 'unsatisfied', 'unknown',
80
+ ];
81
+ function validateVerification(raw, specs) {
82
+ if (!raw.specId || typeof raw.specId !== 'string')
83
+ return null;
84
+ if (!raw.reasoning || typeof raw.reasoning !== 'string')
85
+ return null;
86
+ // Verify the specId references a real spec
87
+ const matchesSpec = specs.some((s) => s.id === raw.specId);
88
+ if (!matchesSpec)
89
+ return null;
90
+ const status = VALID_STATUSES.includes(raw.status)
91
+ ? raw.status
92
+ : 'unknown';
93
+ return {
94
+ specId: raw.specId,
95
+ status,
96
+ reasoning: raw.reasoning.trim(),
97
+ };
98
+ }
99
+ function parseVerificationJson(rawText, specs, onProgress) {
100
+ let jsonText = stripCodeFences(rawText);
101
+ // If response was truncated (no closing ]), try to repair
102
+ if (!jsonText.endsWith(']')) {
103
+ const lastCloseBrace = jsonText.lastIndexOf('}');
104
+ if (lastCloseBrace !== -1) {
105
+ jsonText = jsonText.slice(0, lastCloseBrace + 1) + '\n]';
106
+ onProgress?.('Note: Verification response was truncated. Recovered partial results.');
107
+ }
108
+ }
109
+ let parsed;
110
+ try {
111
+ parsed = JSON.parse(jsonText);
112
+ }
113
+ catch {
114
+ onProgress?.('Warning: Failed to parse self-verification JSON. Returning empty results.');
115
+ return [];
116
+ }
117
+ if (!Array.isArray(parsed)) {
118
+ onProgress?.('Warning: Self-verification response was not an array. Returning empty results.');
119
+ return [];
120
+ }
121
+ const results = [];
122
+ for (const item of parsed) {
123
+ const validated = validateVerification(item, specs);
124
+ if (validated) {
125
+ results.push(validated);
126
+ }
127
+ }
128
+ return results;
129
+ }
130
+ export async function generateWithConstraints(task, language, specs, constraints, onProgress) {
131
+ const client = getClient();
132
+ let totalInputTokens = 0;
133
+ let totalOutputTokens = 0;
134
+ // ── Step 1: Guided code generation (streaming) ──
135
+ onProgress?.('Generating code with spec-aware constraints (streaming)...');
136
+ const systemPrompt = buildGenerationSystemPrompt(language, specs, constraints);
137
+ const stream = client.messages.stream({
138
+ model: MODEL,
139
+ max_tokens: MAX_TOKENS,
140
+ system: systemPrompt,
141
+ messages: [
142
+ {
143
+ role: 'user',
144
+ content: `Generate ${language} code for the following task:\n\n${task}`,
145
+ },
146
+ ],
147
+ });
148
+ let rawCode = '';
149
+ stream.on('text', (text) => {
150
+ rawCode += text;
151
+ });
152
+ const genMessage = await stream.finalMessage();
153
+ totalInputTokens += genMessage.usage.input_tokens;
154
+ totalOutputTokens += genMessage.usage.output_tokens;
155
+ const code = stripCodeFences(rawCode);
156
+ onProgress?.(`Code generated (${totalOutputTokens} tokens). Running self-verification...`);
157
+ // ── Step 2: Self-verification (non-streaming) ──
158
+ const specList = specs
159
+ .map((s) => `[${s.id}] (${s.severity}/${s.category}): ${s.description}\n Assertion: ${s.assertion}`)
160
+ .join('\n');
161
+ const verifyResponse = await client.messages.create({
162
+ model: MODEL,
163
+ max_tokens: 8_000,
164
+ system: VERIFICATION_SYSTEM_PROMPT,
165
+ messages: [
166
+ {
167
+ role: 'user',
168
+ content: `Verify the following code against the specifications below.\n\nCODE:\n${code}\n\nSPECIFICATIONS:\n${specList}`,
169
+ },
170
+ ],
171
+ });
172
+ totalInputTokens += verifyResponse.usage.input_tokens;
173
+ totalOutputTokens += verifyResponse.usage.output_tokens;
174
+ const verifyText = verifyResponse.content
175
+ .filter((block) => block.type === 'text')
176
+ .map((block) => block.text)
177
+ .join('');
178
+ const selfVerification = parseVerificationJson(verifyText, specs, onProgress);
179
+ const satisfiedCount = selfVerification.filter((v) => v.status === 'satisfied').length;
180
+ onProgress?.(`Self-verification complete: ${satisfiedCount}/${specs.length} specs satisfied.`);
181
+ return {
182
+ task,
183
+ code,
184
+ language,
185
+ specs,
186
+ constraints,
187
+ selfVerification,
188
+ satisfiedCount,
189
+ totalSpecs: specs.length,
190
+ generatedAt: new Date().toISOString(),
191
+ inputTokens: totalInputTokens,
192
+ outputTokens: totalOutputTokens,
193
+ };
194
+ }
195
+ //# sourceMappingURL=guided-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guided-generator.js","sourceRoot":"","sources":["../../src/lib/guided-generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { CodebaseIndex } from './codebase-indexer.js';
2
+ import type { AssessmentInventory } from '../types.js';
3
+ export declare function extractInventory(index: CodebaseIndex, onProgress?: (msg: string) => void): Promise<{
4
+ inventory: AssessmentInventory;
5
+ inputTokens: number;
6
+ outputTokens: number;
7
+ }>;