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,311 @@
1
+ import { getClient, MODEL } from './anthropic.js';
2
+ import { readFileContent } from './codebase-indexer.js';
3
+ import { dirname, resolve } from 'node:path';
4
+ /**
5
+ * Maximum number of imported files to follow (1 level deep).
6
+ */
7
+ const MAX_IMPORTS = 10;
8
+ /**
9
+ * Maximum characters to include per imported file.
10
+ */
11
+ const MAX_IMPORT_CHARS = 3000;
12
+ /**
13
+ * Maximum characters for the main component file.
14
+ */
15
+ const MAX_COMPONENT_CHARS = 10_000;
16
+ const REQUIREMENT_SYSTEM_PROMPT = `You are a requirements analyst. Given a route definition and the source code for its component (plus any imported modules), generate a structured requirement document.
17
+
18
+ INSTRUCTIONS:
19
+
20
+ 1. BEHAVIORS: Identify all observable behaviors the component implements.
21
+ - Data loading patterns (pagination, filtering, sorting, search)
22
+ - User interactions (forms, buttons, modals, dialogs, tabs)
23
+ - Data mutations (create, update, delete operations)
24
+ - Permission/guard checks
25
+ - Error handling and loading states
26
+ - Navigation behavior (links, redirects)
27
+ - Real-time updates (subscriptions, polling)
28
+
29
+ 2. SCAFFOLDING FLAGS: Detect any incomplete or placeholder code.
30
+ - TODO / FIXME comments (include the line content)
31
+ - "Coming Soon", "Placeholder", "Mock" text in rendered UI
32
+ - Empty event handlers: onClick={() => {}}, onClick={undefined}, onChange={() => {}}
33
+ - Hardcoded or mock data (arrays of fake data, MOCK_ prefixed constants)
34
+ - console.log("TODO") or console.log("FIXME")
35
+ - Disabled features with no path to enable
36
+ - Stub functions that return null, undefined, or empty objects
37
+ - setTimeout used to fake async operations
38
+
39
+ 3. TABLES: Identify database tables referenced (from queries, API calls, hook names).
40
+
41
+ 4. ROLES: Identify required roles/permissions (from guards, permission checks, role conditionals).
42
+
43
+ OUTPUT FORMAT:
44
+ Return ONLY a JSON object (no markdown fences, no commentary):
45
+ {
46
+ "behaviors": [
47
+ "Lists all invoices with server-side pagination",
48
+ "Supports search filtering by invoice number and customer name"
49
+ ],
50
+ "scaffoldingFlags": [
51
+ "TODO comment at line 45: '// TODO: implement export'",
52
+ "'Coming Soon' text for export feature",
53
+ "Empty onClick handler on 'Generate Report' button"
54
+ ],
55
+ "tables": ["invoices", "customers", "payments"],
56
+ "roles": ["admin", "finance_manager"]
57
+ }
58
+
59
+ Rules:
60
+ - behaviors: Each entry is a single sentence describing one observable behavior. Be specific.
61
+ - scaffoldingFlags: Each entry describes the exact scaffolding issue with location if possible.
62
+ - tables: Database table names only. Derive from query strings, Supabase .from() calls, Prisma model references, API endpoint patterns.
63
+ - roles: Role/permission names. Derive from guard checks, role conditionals, permission constants.
64
+ - If no scaffolding is found, return an empty array (do NOT invent flags).
65
+ - If you cannot determine tables or roles, return empty arrays.
66
+ - Be thorough in behaviors — capture every user-facing interaction.`;
67
+ /**
68
+ * Supported code extensions for import resolution.
69
+ */
70
+ const RESOLVABLE_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx'];
71
+ /**
72
+ * Extract relative import paths from source code.
73
+ * Returns raw import specifiers (e.g., './hooks/useInvoices', '@/lib/utils').
74
+ */
75
+ function extractImportPaths(source) {
76
+ const relative = [];
77
+ const aliased = [];
78
+ // Relative imports
79
+ const relRegex = /import\s+.*?\s+from\s+['"](\.\.?\/[^'"]+)['"]/g;
80
+ let match;
81
+ while ((match = relRegex.exec(source)) !== null) {
82
+ relative.push(match[1]);
83
+ }
84
+ // Alias imports (@/...)
85
+ const aliasRegex = /import\s+.*?\s+from\s+['"]@\/([^'"]+)['"]/g;
86
+ while ((match = aliasRegex.exec(source)) !== null) {
87
+ aliased.push(match[1]);
88
+ }
89
+ return { relative, aliased };
90
+ }
91
+ /**
92
+ * Resolve an import specifier to a file path that exists in the codebase index.
93
+ * Handles missing extensions and index files.
94
+ */
95
+ function resolveImportPath(specifier, componentDir, fileTree) {
96
+ // Normalize the path relative to project root
97
+ const basePath = specifier.startsWith('@/')
98
+ ? `src/${specifier.slice(2)}`
99
+ : resolve(componentDir, specifier).replace(/^\//, '');
100
+ // Try exact match first
101
+ if (fileTree.has(basePath))
102
+ return basePath;
103
+ // Try adding extensions
104
+ for (const ext of RESOLVABLE_EXTENSIONS) {
105
+ if (fileTree.has(basePath + ext))
106
+ return basePath + ext;
107
+ }
108
+ // Try index files (e.g., ./hooks -> ./hooks/index.ts)
109
+ for (const ext of RESOLVABLE_EXTENSIONS) {
110
+ const indexPath = `${basePath}/index${ext}`;
111
+ if (fileTree.has(indexPath))
112
+ return indexPath;
113
+ }
114
+ return null;
115
+ }
116
+ /**
117
+ * Gather imported file contents for a component (1 level deep).
118
+ * Returns a map of relative path -> file content (truncated).
119
+ */
120
+ async function gatherImportedFiles(componentPath, componentSource, index) {
121
+ const imports = new Map();
122
+ const fileTreeSet = new Set(index.fileTree);
123
+ const componentDir = dirname(componentPath);
124
+ const { relative, aliased } = extractImportPaths(componentSource);
125
+ // Combine all import specifiers
126
+ const allSpecifiers = [
127
+ ...relative,
128
+ ...aliased.map((a) => `@/${a}`),
129
+ ];
130
+ let count = 0;
131
+ for (const specifier of allSpecifiers) {
132
+ if (count >= MAX_IMPORTS)
133
+ break;
134
+ const resolved = resolveImportPath(specifier, componentDir, fileTreeSet);
135
+ if (!resolved || imports.has(resolved))
136
+ continue;
137
+ const content = await readFileContent(index.rootPath, resolved);
138
+ if (content) {
139
+ const truncated = content.length > MAX_IMPORT_CHARS
140
+ ? content.slice(0, MAX_IMPORT_CHARS) + '\n[... truncated]'
141
+ : content;
142
+ imports.set(resolved, truncated);
143
+ count++;
144
+ }
145
+ }
146
+ return imports;
147
+ }
148
+ /**
149
+ * Parse the JSON response from Claude, handling code fences and truncation.
150
+ */
151
+ function parseRequirementResponse(rawText) {
152
+ let jsonText = rawText.trim();
153
+ // Remove opening code fence
154
+ if (jsonText.startsWith('```')) {
155
+ const firstNewline = jsonText.indexOf('\n');
156
+ if (firstNewline !== -1) {
157
+ jsonText = jsonText.slice(firstNewline + 1);
158
+ }
159
+ }
160
+ // Remove closing code fence
161
+ const lastFence = jsonText.lastIndexOf('```');
162
+ if (lastFence !== -1) {
163
+ jsonText = jsonText.slice(0, lastFence);
164
+ }
165
+ jsonText = jsonText.trim();
166
+ // Handle truncation: close unclosed structures
167
+ if (!jsonText.endsWith('}')) {
168
+ const lastCloseBrace = jsonText.lastIndexOf('}');
169
+ if (lastCloseBrace !== -1) {
170
+ jsonText = jsonText.slice(0, lastCloseBrace + 1);
171
+ let openBraces = 0;
172
+ let openBrackets = 0;
173
+ for (const ch of jsonText) {
174
+ if (ch === '{')
175
+ openBraces++;
176
+ if (ch === '}')
177
+ openBraces--;
178
+ if (ch === '[')
179
+ openBrackets++;
180
+ if (ch === ']')
181
+ openBrackets--;
182
+ }
183
+ let suffix = '';
184
+ for (let i = 0; i < openBrackets; i++)
185
+ suffix += ']';
186
+ for (let i = 0; i < openBraces; i++)
187
+ suffix += '}';
188
+ jsonText += suffix;
189
+ }
190
+ }
191
+ let parsed;
192
+ try {
193
+ parsed = JSON.parse(jsonText);
194
+ }
195
+ catch {
196
+ throw new Error(`Failed to parse requirement response as JSON.\n` +
197
+ `First 300 chars: ${jsonText.slice(0, 300)}`);
198
+ }
199
+ const obj = parsed;
200
+ return {
201
+ behaviors: Array.isArray(obj.behaviors) ? obj.behaviors.map(String) : [],
202
+ scaffoldingFlags: Array.isArray(obj.scaffoldingFlags)
203
+ ? obj.scaffoldingFlags.map(String)
204
+ : [],
205
+ tables: Array.isArray(obj.tables) ? obj.tables.map(String) : [],
206
+ roles: Array.isArray(obj.roles) ? obj.roles.map(String) : [],
207
+ };
208
+ }
209
+ /**
210
+ * Generate a structured requirement for a single route.
211
+ *
212
+ * Reads the route's component file, follows 1 level of imports to gather
213
+ * related code (hooks, utilities), and sends all context to Claude to
214
+ * produce a RouteRequirement with behaviors and scaffolding flags.
215
+ */
216
+ export async function generateRequirement(route, index, onProgress) {
217
+ const client = getClient();
218
+ // Read the main component file
219
+ onProgress?.(` Reading component: ${route.component}`);
220
+ const componentSource = await readFileContent(index.rootPath, route.component);
221
+ if (!componentSource) {
222
+ // Component file not found -- return a minimal requirement with a flag
223
+ return {
224
+ requirement: {
225
+ id: '',
226
+ route: route.path,
227
+ domain: route.domain,
228
+ component: route.component,
229
+ guard: route.guard,
230
+ roles: route.roles ?? [],
231
+ tables: route.tables ?? [],
232
+ behaviors: [],
233
+ scaffoldingFlags: [`Component file not found: ${route.component}`],
234
+ },
235
+ inputTokens: 0,
236
+ outputTokens: 0,
237
+ };
238
+ }
239
+ // Truncate very large component files for the prompt
240
+ const componentContent = componentSource.length > MAX_COMPONENT_CHARS
241
+ ? componentSource.slice(0, MAX_COMPONENT_CHARS) + '\n[... truncated]'
242
+ : componentSource;
243
+ // Follow 1 level of imports
244
+ onProgress?.(` Resolving imports for ${route.component}...`);
245
+ const importedFiles = await gatherImportedFiles(route.component, componentSource, index);
246
+ // Build imported files context
247
+ let importsContext = '';
248
+ if (importedFiles.size > 0) {
249
+ onProgress?.(` Found ${importedFiles.size} imported file(s)`);
250
+ for (const [path, content] of importedFiles) {
251
+ importsContext += `\n--- IMPORTED: ${path} ---\n${content}\n`;
252
+ }
253
+ }
254
+ // Build the user message
255
+ const userMessage = [
256
+ `Analyze this route and its component code to generate a structured requirement.`,
257
+ ``,
258
+ `ROUTE INFORMATION:`,
259
+ `- Path: ${route.path}`,
260
+ `- Component: ${route.component}`,
261
+ `- Domain: ${route.domain}`,
262
+ route.guard ? `- Guard: ${route.guard}` : null,
263
+ route.roles?.length ? `- Known roles: ${route.roles.join(', ')}` : null,
264
+ route.tables?.length ? `- Known tables: ${route.tables.join(', ')}` : null,
265
+ ``,
266
+ `COMPONENT SOURCE:`,
267
+ `--- FILE: ${route.component} ---`,
268
+ componentContent,
269
+ importsContext ? `\nIMPORTED MODULES:${importsContext}` : null,
270
+ ]
271
+ .filter(Boolean)
272
+ .join('\n');
273
+ onProgress?.(` Sending to Claude for requirement generation...`);
274
+ const response = await client.messages.create({
275
+ model: MODEL,
276
+ max_tokens: 4_000,
277
+ system: REQUIREMENT_SYSTEM_PROMPT,
278
+ messages: [
279
+ {
280
+ role: 'user',
281
+ content: userMessage,
282
+ },
283
+ ],
284
+ });
285
+ const rawText = response.content
286
+ .filter((b) => b.type === 'text')
287
+ .map((b) => b.text)
288
+ .join('');
289
+ const parsed = parseRequirementResponse(rawText);
290
+ // Merge Claude's findings with inventory data.
291
+ // Claude may discover additional tables/roles beyond what inventory found.
292
+ const mergedTables = Array.from(new Set([...(route.tables ?? []), ...parsed.tables]));
293
+ const mergedRoles = Array.from(new Set([...(route.roles ?? []), ...parsed.roles]));
294
+ const requirement = {
295
+ id: '', // Caller assigns sequential IDs
296
+ route: route.path,
297
+ domain: route.domain,
298
+ component: route.component,
299
+ guard: route.guard,
300
+ roles: mergedRoles,
301
+ tables: mergedTables,
302
+ behaviors: parsed.behaviors,
303
+ scaffoldingFlags: parsed.scaffoldingFlags,
304
+ };
305
+ return {
306
+ requirement,
307
+ inputTokens: response.usage.input_tokens,
308
+ outputTokens: response.usage.output_tokens,
309
+ };
310
+ }
311
+ //# sourceMappingURL=requirements-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requirements-generator.js","sourceRoot":"","sources":["../../src/lib/requirements-generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { SpecSynthesisResult } from '../types.js';
2
+ export declare function synthesizeSpecs(task: string, language: string, onProgress?: (msg: string) => void): Promise<SpecSynthesisResult>;
@@ -0,0 +1,136 @@
1
+ import { getClient, MODEL } from './anthropic.js';
2
+ const SYNTHESIS_SYSTEM_PROMPT = `You are a formal specification synthesizer. Given a coding task description and target programming language, you generate a comprehensive set of formal specifications that any correct implementation MUST satisfy.
3
+
4
+ SYNTHESIS RULES:
5
+
6
+ 1. Generate 10-30 specifications covering ALL of these categories:
7
+ - correctness: Happy-path behavior, expected outputs for standard inputs
8
+ - edge-case: Boundary values, empty inputs, maximum values, off-by-one scenarios
9
+ - error-handling: Invalid inputs, missing data, exception behavior
10
+ - security: Injection, overflow, unauthorized access, input sanitization
11
+ - type-safety: Type constraints, null/undefined handling, coercion traps
12
+ - performance: Time/space complexity, resource limits, scaling behavior
13
+
14
+ 2. Each specification must have:
15
+ - id: Sequential "SPEC-001", "SPEC-002", etc.
16
+ - category: One of correctness, edge-case, error-handling, security, type-safety, performance
17
+ - severity: How bad is it if the code violates this spec?
18
+ - critical: Would be a bug causing incorrect results or crashes
19
+ - high: Significant quality issue, data loss, or security flaw
20
+ - medium: Best practice violation, poor robustness
21
+ - low: Nice-to-have, minor optimization
22
+ - description: Clear statement of what the code must do or guarantee
23
+ - assertion: A specific, testable assertion (pseudocode or natural language test case) that can be verified programmatically against the generated code
24
+ - rationale: Why this specification matters
25
+
26
+ 3. Assertions must be SPECIFIC and TESTABLE:
27
+ - GOOD: "sorted([3,1,2]) returns [1,2,3]"
28
+ - GOOD: "rateLimiter(100, '1m').check('user1') returns { allowed: true, remaining: 99 }"
29
+ - GOOD: "Passing null as input throws TypeError with message containing 'expected string'"
30
+ - BAD: "Function works correctly" (too vague)
31
+ - BAD: "Handles errors" (not testable)
32
+
33
+ 4. Prioritize CRITICAL specs first, then HIGH, then MEDIUM, then LOW.
34
+
35
+ 5. Think adversarially: What inputs would break a naive implementation? What edge cases do developers commonly miss?
36
+
37
+ OUTPUT FORMAT:
38
+ Return ONLY a JSON array of specification objects. No markdown fences, no commentary.`;
39
+ const VALID_CATEGORIES = [
40
+ 'correctness', 'security', 'performance', 'error-handling', 'edge-case', 'type-safety',
41
+ ];
42
+ const VALID_SEVERITIES = [
43
+ 'critical', 'high', 'medium', 'low',
44
+ ];
45
+ function validateSpec(raw, index) {
46
+ if (!raw.description || typeof raw.description !== 'string')
47
+ return null;
48
+ if (!raw.assertion || typeof raw.assertion !== 'string')
49
+ return null;
50
+ const category = VALID_CATEGORIES.includes(raw.category)
51
+ ? raw.category
52
+ : 'correctness';
53
+ const severity = VALID_SEVERITIES.includes(raw.severity)
54
+ ? raw.severity
55
+ : 'medium';
56
+ return {
57
+ id: raw.id || `SPEC-${String(index + 1).padStart(3, '0')}`,
58
+ category,
59
+ severity,
60
+ description: raw.description.trim(),
61
+ assertion: raw.assertion.trim(),
62
+ rationale: typeof raw.rationale === 'string' ? raw.rationale.trim() : 'No rationale provided',
63
+ };
64
+ }
65
+ export async function synthesizeSpecs(task, language, onProgress) {
66
+ const client = getClient();
67
+ onProgress?.('Sending task to Claude for spec synthesis (streaming)...');
68
+ const stream = client.messages.stream({
69
+ model: MODEL,
70
+ max_tokens: 16_000,
71
+ system: SYNTHESIS_SYSTEM_PROMPT,
72
+ messages: [
73
+ {
74
+ role: 'user',
75
+ content: `Generate formal specifications for the following coding task.\n\nLanguage: ${language}\n\nTask:\n${task}`,
76
+ },
77
+ ],
78
+ });
79
+ let rawText = '';
80
+ stream.on('text', (text) => {
81
+ rawText += text;
82
+ });
83
+ const finalMessage = await stream.finalMessage();
84
+ onProgress?.('Parsing synthesis results...');
85
+ // Strip markdown code fences if present
86
+ let jsonText = rawText.trim();
87
+ // Remove opening code fence
88
+ if (jsonText.startsWith('```')) {
89
+ const firstNewline = jsonText.indexOf('\n');
90
+ if (firstNewline !== -1) {
91
+ jsonText = jsonText.slice(firstNewline + 1);
92
+ }
93
+ }
94
+ // Remove closing code fence
95
+ const lastFence = jsonText.lastIndexOf('```');
96
+ if (lastFence !== -1) {
97
+ jsonText = jsonText.slice(0, lastFence);
98
+ }
99
+ jsonText = jsonText.trim();
100
+ // If response was truncated (no closing ]), try to repair by closing the array
101
+ if (!jsonText.endsWith(']')) {
102
+ const lastCloseBrace = jsonText.lastIndexOf('}');
103
+ if (lastCloseBrace !== -1) {
104
+ jsonText = jsonText.slice(0, lastCloseBrace + 1) + '\n]';
105
+ onProgress?.('Note: Response was truncated. Recovered partial specs.');
106
+ }
107
+ }
108
+ let parsed;
109
+ try {
110
+ parsed = JSON.parse(jsonText);
111
+ }
112
+ catch {
113
+ throw new Error(`Failed to parse Claude's spec synthesis response as JSON.\n` +
114
+ `First 200 chars: ${jsonText.slice(0, 200)}`);
115
+ }
116
+ if (!Array.isArray(parsed)) {
117
+ throw new Error('Expected a JSON array of specs from Claude.');
118
+ }
119
+ const specs = [];
120
+ for (let i = 0; i < parsed.length; i++) {
121
+ const validated = validateSpec(parsed[i], i);
122
+ if (validated) {
123
+ specs.push(validated);
124
+ }
125
+ }
126
+ return {
127
+ task,
128
+ language,
129
+ specs,
130
+ totalSpecs: specs.length,
131
+ synthesizedAt: new Date().toISOString(),
132
+ inputTokens: finalMessage.usage.input_tokens,
133
+ outputTokens: finalMessage.usage.output_tokens,
134
+ };
135
+ }
136
+ //# sourceMappingURL=spec-synthesizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec-synthesizer.js","sourceRoot":"","sources":["../../src/lib/spec-synthesizer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { AssayConfig, HallucinationType, VerificationReport, ExtractionResult } from '../types.js';
2
+ export declare function getSystemPrompt(type: HallucinationType, config: AssayConfig): string;
3
+ export declare function getUserPrompt(type: HallucinationType, config: AssayConfig): string;
4
+ export interface RegenerationContext {
5
+ config: AssayConfig;
6
+ type: HallucinationType;
7
+ priorDocument: string;
8
+ extraction: ExtractionResult;
9
+ verification: VerificationReport;
10
+ }
11
+ export declare function getRegenerationSystemPrompt(ctx: RegenerationContext): string;
12
+ export declare function getRegenerationUserPrompt(ctx: RegenerationContext): string;