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,100 @@
1
+ import { readdir, mkdir, writeFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { readConfig, getIterationsDir } from '../lib/config.js';
4
+ import { exists } from '../lib/fs-utils.js';
5
+ import { streamHallucination } from '../lib/anthropic.js';
6
+ const VALID_TYPES = ['tos', 'api-docs', 'user-manual'];
7
+ function countSections(content) {
8
+ // Count markdown headings (## or ###) as sections
9
+ const headings = content.match(/^#{1,3}\s+.+$/gm);
10
+ return headings?.length ?? 0;
11
+ }
12
+ function estimateClaims(content) {
13
+ // Heuristic: count sentences with specific numbers, named technologies,
14
+ // or declarative statements about capabilities
15
+ const sentences = content.split(/[.!]\s+/);
16
+ let claims = 0;
17
+ for (const sentence of sentences) {
18
+ const hasNumber = /\d+/.test(sentence);
19
+ const hasDeclarative = /\b(is|are|will|provides?|supports?|includes?|requires?|limits?|allows?|ensures?|stores?|encrypts?|processes?|retains?)\b/i.test(sentence);
20
+ const hasSpecific = /\b(GB|MB|TB|ms|seconds?|minutes?|hours?|days?|%|per|AES|SHA|RSA|SSL|TLS|HTTPS|OAuth|JWT|REST|GraphQL)\b/i.test(sentence);
21
+ if (hasNumber || (hasDeclarative && hasSpecific)) {
22
+ claims++;
23
+ }
24
+ }
25
+ return claims;
26
+ }
27
+ async function getNextIteration(iterDir) {
28
+ if (!(await exists(iterDir))) {
29
+ return 1;
30
+ }
31
+ const entries = await readdir(iterDir, { withFileTypes: true });
32
+ const nums = entries
33
+ .filter(e => e.isDirectory())
34
+ .map(e => parseInt(e.name, 10))
35
+ .filter(n => !isNaN(n));
36
+ return nums.length === 0 ? 1 : Math.max(...nums) + 1;
37
+ }
38
+ export async function hallucinateCommand(options) {
39
+ const type = (options.type ?? 'tos');
40
+ if (!VALID_TYPES.includes(type)) {
41
+ console.error(` Error: Invalid type "${type}". Must be one of: ${VALID_TYPES.join(', ')}`);
42
+ process.exit(1);
43
+ }
44
+ let config;
45
+ try {
46
+ config = await readConfig();
47
+ }
48
+ catch (err) {
49
+ console.error(` Error: ${err instanceof Error ? err.message : err}`);
50
+ process.exit(1);
51
+ }
52
+ const iterDir = getIterationsDir();
53
+ const iteration = await getNextIteration(iterDir);
54
+ console.log(`\n Assay — Hallucinating ${type} (iteration ${iteration})`);
55
+ console.log(` Project: ${config.projectName}`);
56
+ console.log(` ─────────────────────────────────────\n`);
57
+ let result;
58
+ const startTime = Date.now();
59
+ try {
60
+ result = await streamHallucination(config, type);
61
+ }
62
+ catch (err) {
63
+ console.error(`\n Error: ${err instanceof Error ? err.message : err}`);
64
+ process.exit(1);
65
+ }
66
+ const durationMs = Date.now() - startTime;
67
+ // Create iteration directory only after successful generation
68
+ const iterPath = join(iterDir, String(iteration));
69
+ await mkdir(iterPath, { recursive: true });
70
+ // Save hallucinated document
71
+ const docPath = join(iterPath, `hallucinated-${type}.md`);
72
+ await writeFile(docPath, result.content, 'utf-8');
73
+ // Compute stats
74
+ const sectionCount = countSections(result.content);
75
+ const estimatedClaims = estimateClaims(result.content);
76
+ // Save metadata
77
+ const meta = {
78
+ type,
79
+ iteration,
80
+ model: 'claude-sonnet-4-5-20250929',
81
+ inputTokens: result.inputTokens,
82
+ outputTokens: result.outputTokens,
83
+ sectionCount,
84
+ estimatedClaims,
85
+ generatedAt: new Date().toISOString(),
86
+ durationMs,
87
+ };
88
+ const metaPath = join(iterPath, 'meta.json');
89
+ await writeFile(metaPath, JSON.stringify(meta, null, 2) + '\n', 'utf-8');
90
+ // Print summary
91
+ console.log(`\n ─────────────────────────────────────`);
92
+ console.log(` Saved: .assay/iterations/${iteration}/hallucinated-${type}.md`);
93
+ console.log(` Meta: .assay/iterations/${iteration}/meta.json`);
94
+ console.log(`\n Sections: ${sectionCount}`);
95
+ console.log(` Estimated claims: ${estimatedClaims}`);
96
+ console.log(` Input tokens: ${result.inputTokens.toLocaleString()}`);
97
+ console.log(` Output tokens: ${result.outputTokens.toLocaleString()}`);
98
+ console.log(` Duration: ${(durationMs / 1000).toFixed(1)}s\n`);
99
+ }
100
+ //# sourceMappingURL=hallucinate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hallucinate.js","sourceRoot":"","sources":["../../src/commands/hallucinate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function initCommand(): Promise<void>;
@@ -0,0 +1,39 @@
1
+ import { configExists, writeConfig } from '../lib/config.js';
2
+ import { prompt, confirm, closePrompts } from '../lib/prompts.js';
3
+ export async function initCommand() {
4
+ console.log('\n Assay — Project Initialization\n');
5
+ if (await configExists()) {
6
+ const overwrite = await confirm(' .assay/config.json already exists. Overwrite?');
7
+ if (!overwrite) {
8
+ console.log(' Aborted.');
9
+ return;
10
+ }
11
+ }
12
+ const projectName = await prompt(' Project name');
13
+ if (!projectName) {
14
+ console.error(' Error: Project name is required.');
15
+ process.exit(1);
16
+ }
17
+ const description = await prompt(' Description (what does it do?)');
18
+ if (!description) {
19
+ console.error(' Error: Description is required.');
20
+ process.exit(1);
21
+ }
22
+ const techStack = await prompt(' Tech stack', 'TypeScript, Node.js');
23
+ const targetAudience = await prompt(' Target audience', 'developers');
24
+ closePrompts();
25
+ const config = {
26
+ projectName,
27
+ description,
28
+ techStack,
29
+ targetAudience,
30
+ createdAt: new Date().toISOString(),
31
+ };
32
+ await writeConfig(config);
33
+ console.log('\n Created:');
34
+ console.log(' .assay/config.json');
35
+ console.log(' .assay/iterations/');
36
+ console.log('\n Tip: Add .assay/ to your .gitignore');
37
+ console.log(`\n Next: Run \`assay hallucinate\` to generate your first hallucinated spec.\n`);
38
+ }
39
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGlE,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;IAEpD,IAAI,MAAM,YAAY,EAAE,EAAE,CAAC;QACzB,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,iDAAiD,CAAC,CAAC;QACnF,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC1B,OAAO;QACT,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACnD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,kCAAkC,CAAC,CAAC;IACrE,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,cAAc,EAAE,qBAAqB,CAAC,CAAC;IACtE,MAAM,cAAc,GAAG,MAAM,MAAM,CAAC,mBAAmB,EAAE,YAAY,CAAC,CAAC;IAEvE,YAAY,EAAE,CAAC;IAEf,MAAM,MAAM,GAAgB;QAC1B,WAAW;QACX,WAAW;QACX,SAAS;QACT,cAAc;QACd,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;IAEF,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC;IAE1B,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC5B,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IACtC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IACtC,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,iFAAiF,CAAC,CAAC;AACjG,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function regenerateCommand(options: {
2
+ iteration?: string;
3
+ }): Promise<void>;
@@ -0,0 +1,158 @@
1
+ import { readdir, readFile, mkdir, writeFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { readConfig, getIterationsDir } from '../lib/config.js';
4
+ import { exists } from '../lib/fs-utils.js';
5
+ import { streamRegeneration } from '../lib/anthropic.js';
6
+ const VALID_TYPES = ['tos', 'api-docs', 'user-manual'];
7
+ async function findLatestIteration(iterDir) {
8
+ if (!(await exists(iterDir)))
9
+ return null;
10
+ const entries = await readdir(iterDir, { withFileTypes: true });
11
+ const nums = entries
12
+ .filter((e) => e.isDirectory())
13
+ .map((e) => parseInt(e.name, 10))
14
+ .filter((n) => !isNaN(n));
15
+ return nums.length === 0 ? null : Math.max(...nums);
16
+ }
17
+ async function findHallucinatedDoc(iterPath) {
18
+ const entries = await readdir(iterPath);
19
+ const doc = entries.find((e) => e.startsWith('hallucinated-') && e.endsWith('.md'));
20
+ if (!doc)
21
+ return null;
22
+ const type = doc.replace('hallucinated-', '').replace('.md', '');
23
+ if (!VALID_TYPES.includes(type))
24
+ return null;
25
+ return { path: join(iterPath, doc), type };
26
+ }
27
+ function countSections(content) {
28
+ const headings = content.match(/^#{1,3}\s+.+$/gm);
29
+ return headings?.length ?? 0;
30
+ }
31
+ function estimateClaims(content) {
32
+ const sentences = content.split(/[.!]\s+/);
33
+ let claims = 0;
34
+ for (const sentence of sentences) {
35
+ const hasNumber = /\d+/.test(sentence);
36
+ const hasDeclarative = /\b(is|are|will|provides?|supports?|includes?|requires?|limits?|allows?|ensures?|stores?|encrypts?|processes?|retains?)\b/i.test(sentence);
37
+ const hasSpecific = /\b(GB|MB|TB|ms|seconds?|minutes?|hours?|days?|%|per|AES|SHA|RSA|SSL|TLS|HTTPS|OAuth|JWT|REST|GraphQL)\b/i.test(sentence);
38
+ if (hasNumber || (hasDeclarative && hasSpecific)) {
39
+ claims++;
40
+ }
41
+ }
42
+ return claims;
43
+ }
44
+ export async function regenerateCommand(options) {
45
+ const iterDir = getIterationsDir();
46
+ // Determine source iteration
47
+ let sourceIteration;
48
+ if (options.iteration) {
49
+ sourceIteration = parseInt(options.iteration, 10);
50
+ if (isNaN(sourceIteration)) {
51
+ console.error(` Error: Invalid iteration "${options.iteration}".`);
52
+ process.exit(1);
53
+ }
54
+ }
55
+ else {
56
+ const latest = await findLatestIteration(iterDir);
57
+ if (latest === null) {
58
+ console.error(' Error: No iterations found. Run the full pipeline first:');
59
+ console.error(' assay hallucinate → assay extract → assay verify');
60
+ process.exit(1);
61
+ }
62
+ sourceIteration = latest;
63
+ }
64
+ const sourcePath = join(iterDir, String(sourceIteration));
65
+ // Verify all required files exist
66
+ const claimsPath = join(sourcePath, 'claims.json');
67
+ const verificationPath = join(sourcePath, 'verification.json');
68
+ if (!(await exists(claimsPath))) {
69
+ console.error(` Error: No claims.json found for iteration ${sourceIteration}.`);
70
+ console.error(' Run `assay extract` first.');
71
+ process.exit(1);
72
+ }
73
+ if (!(await exists(verificationPath))) {
74
+ console.error(` Error: No verification.json found for iteration ${sourceIteration}.`);
75
+ console.error(' Run `assay verify` first.');
76
+ process.exit(1);
77
+ }
78
+ const doc = await findHallucinatedDoc(sourcePath);
79
+ if (!doc) {
80
+ console.error(` Error: No hallucinated-*.md found in iteration ${sourceIteration}.`);
81
+ process.exit(1);
82
+ }
83
+ // Read all inputs
84
+ let config;
85
+ try {
86
+ config = await readConfig();
87
+ }
88
+ catch (err) {
89
+ console.error(` Error: ${err instanceof Error ? err.message : err}`);
90
+ process.exit(1);
91
+ }
92
+ const priorDocument = await readFile(doc.path, 'utf-8');
93
+ const extraction = JSON.parse(await readFile(claimsPath, 'utf-8'));
94
+ const verification = JSON.parse(await readFile(verificationPath, 'utf-8'));
95
+ const { verdicts } = verification;
96
+ const total = verification.verifications.length;
97
+ const assessed = total - verdicts.na;
98
+ const score = assessed > 0
99
+ ? ((verdicts.pass + verdicts.partial * 0.5) / assessed) * 100
100
+ : 0;
101
+ const nextIteration = sourceIteration + 1;
102
+ console.log(`\n Assay — Regenerating ${doc.type} (iteration ${sourceIteration} → ${nextIteration})`);
103
+ console.log(` Project: ${config.projectName}`);
104
+ console.log(` Prior compliance: ${score.toFixed(1)}% (${verdicts.pass} pass, ${verdicts.partial} partial, ${verdicts.fail} fail)`);
105
+ console.log(` ─────────────────────────────────────\n`);
106
+ const ctx = {
107
+ config,
108
+ type: doc.type,
109
+ priorDocument,
110
+ extraction,
111
+ verification,
112
+ };
113
+ let result;
114
+ const startTime = Date.now();
115
+ try {
116
+ result = await streamRegeneration(ctx);
117
+ }
118
+ catch (err) {
119
+ console.error(`\n Error: ${err instanceof Error ? err.message : err}`);
120
+ process.exit(1);
121
+ }
122
+ const durationMs = Date.now() - startTime;
123
+ // Create next iteration directory
124
+ const nextPath = join(iterDir, String(nextIteration));
125
+ await mkdir(nextPath, { recursive: true });
126
+ // Save regenerated document
127
+ const docPath = join(nextPath, `hallucinated-${doc.type}.md`);
128
+ await writeFile(docPath, result.content, 'utf-8');
129
+ // Compute stats
130
+ const sectionCount = countSections(result.content);
131
+ const estimatedClaimCount = estimateClaims(result.content);
132
+ // Save metadata
133
+ const meta = {
134
+ type: doc.type,
135
+ iteration: nextIteration,
136
+ model: 'claude-sonnet-4-5-20250929',
137
+ inputTokens: result.inputTokens,
138
+ outputTokens: result.outputTokens,
139
+ sectionCount,
140
+ estimatedClaims: estimatedClaimCount,
141
+ generatedAt: new Date().toISOString(),
142
+ durationMs,
143
+ };
144
+ const metaPath = join(nextPath, 'meta.json');
145
+ await writeFile(metaPath, JSON.stringify(meta, null, 2) + '\n', 'utf-8');
146
+ // Print summary
147
+ console.log(`\n ─────────────────────────────────────`);
148
+ console.log(` Saved: .assay/iterations/${nextIteration}/hallucinated-${doc.type}.md`);
149
+ console.log(` Meta: .assay/iterations/${nextIteration}/meta.json`);
150
+ console.log(`\n Sections: ${sectionCount}`);
151
+ console.log(` Estimated claims: ${estimatedClaimCount}`);
152
+ console.log(` Input tokens: ${result.inputTokens.toLocaleString()}`);
153
+ console.log(` Output tokens: ${result.outputTokens.toLocaleString()}`);
154
+ console.log(` Duration: ${(durationMs / 1000).toFixed(1)}s`);
155
+ console.log(`\n The convergence loop continues.`);
156
+ console.log(` Next: Run \`assay extract -i ${nextIteration}\` → \`assay verify\` → \`assay report\`\n`);
157
+ }
158
+ //# sourceMappingURL=regenerate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regenerate.js","sourceRoot":"","sources":["../../src/commands/regenerate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare function remediateCommand(options: {
2
+ iteration?: string;
3
+ repo?: string;
4
+ threshold?: string;
5
+ }): Promise<void>;
@@ -0,0 +1,155 @@
1
+ import { readdir, readFile, writeFile } from 'node:fs/promises';
2
+ import { join, resolve } from 'node:path';
3
+ import { readConfig, getIterationsDir } from '../lib/config.js';
4
+ import { exists } from '../lib/fs-utils.js';
5
+ import { indexCodebase } from '../lib/codebase-indexer.js';
6
+ import { generateRemediationTasks } from '../lib/remediator.js';
7
+ import { generateRemediationReport } from '../lib/remediation-generator.js';
8
+ async function findLatestIteration(iterDir) {
9
+ if (!(await exists(iterDir)))
10
+ return null;
11
+ const entries = await readdir(iterDir, { withFileTypes: true });
12
+ const nums = entries
13
+ .filter((e) => e.isDirectory())
14
+ .map((e) => parseInt(e.name, 10))
15
+ .filter((n) => !isNaN(n));
16
+ return nums.length === 0 ? null : Math.max(...nums);
17
+ }
18
+ export async function remediateCommand(options) {
19
+ const iterDir = getIterationsDir();
20
+ const repoPath = resolve(options.repo || '.');
21
+ const threshold = parseFloat(options.threshold || '95');
22
+ // Determine iteration
23
+ let iteration;
24
+ if (options.iteration) {
25
+ iteration = parseInt(options.iteration, 10);
26
+ if (isNaN(iteration)) {
27
+ console.error(` Error: Invalid iteration "${options.iteration}".`);
28
+ process.exit(1);
29
+ }
30
+ }
31
+ else {
32
+ const latest = await findLatestIteration(iterDir);
33
+ if (latest === null) {
34
+ console.error(' Error: No iterations found. Run the full pipeline first:');
35
+ console.error(' assay hallucinate → assay extract → assay verify');
36
+ process.exit(1);
37
+ }
38
+ iteration = latest;
39
+ }
40
+ const iterPath = join(iterDir, String(iteration));
41
+ const claimsPath = join(iterPath, 'claims.json');
42
+ const verificationPath = join(iterPath, 'verification.json');
43
+ if (!(await exists(claimsPath))) {
44
+ console.error(` Error: No claims.json found for iteration ${iteration}.`);
45
+ console.error(' Run `assay extract` first.');
46
+ process.exit(1);
47
+ }
48
+ if (!(await exists(verificationPath))) {
49
+ console.error(` Error: No verification.json found for iteration ${iteration}.`);
50
+ console.error(' Run `assay verify` first.');
51
+ process.exit(1);
52
+ }
53
+ // Read inputs
54
+ const extraction = JSON.parse(await readFile(claimsPath, 'utf-8'));
55
+ const verification = JSON.parse(await readFile(verificationPath, 'utf-8'));
56
+ // Compute current score
57
+ const { verdicts, verifications } = verification;
58
+ const total = verifications.length;
59
+ const assessed = total - verdicts.na;
60
+ const currentScore = assessed > 0
61
+ ? ((verdicts.pass + verdicts.partial * 0.5) / assessed) * 100
62
+ : 0;
63
+ // Check convergence
64
+ if (currentScore >= threshold) {
65
+ console.log(`\n Assay — Remediation (iteration ${iteration})`);
66
+ console.log(` ─────────────────────────────────────`);
67
+ console.log(`\n CONVERGED: Compliance score ${currentScore.toFixed(1)}% >= ${threshold}% threshold.`);
68
+ console.log(` No remediation tasks needed.\n`);
69
+ return;
70
+ }
71
+ // Read config for project name
72
+ let projectName;
73
+ try {
74
+ const config = await readConfig();
75
+ projectName = config.projectName;
76
+ }
77
+ catch {
78
+ // Config is optional for display purposes
79
+ }
80
+ console.log(`\n Assay — Generating remediation tasks (iteration ${iteration})`);
81
+ console.log(` Codebase: ${repoPath}`);
82
+ console.log(` Score: ${currentScore.toFixed(1)}% (target: ${threshold}%)`);
83
+ console.log(` Gap: ${(threshold - currentScore).toFixed(1)} points`);
84
+ console.log(` ─────────────────────────────────────\n`);
85
+ // Filter verifications
86
+ const failVerifications = verifications.filter((v) => v.verdict === 'FAIL');
87
+ const partialVerifications = verifications.filter((v) => v.verdict === 'PARTIAL');
88
+ console.log(` Claims to remediate: ${failVerifications.length} FAIL, ${partialVerifications.length} PARTIAL\n`);
89
+ // Index codebase
90
+ console.log(` Indexing codebase...`);
91
+ const index = await indexCodebase(repoPath);
92
+ console.log(` ${index.summary.split('\n').join('\n ')}\n`);
93
+ // Generate remediation tasks
94
+ const startTime = Date.now();
95
+ const { tasks, inputTokens, outputTokens } = await generateRemediationTasks(failVerifications, partialVerifications, extraction.claims, index, (msg) => console.log(` ${msg}`));
96
+ const durationMs = Date.now() - startTime;
97
+ // Build plan
98
+ const tasksBySeverity = { critical: 0, high: 0, medium: 0, low: 0 };
99
+ for (const t of tasks) {
100
+ tasksBySeverity[t.severity]++;
101
+ }
102
+ const plan = {
103
+ iteration,
104
+ codebasePath: repoPath,
105
+ currentScore,
106
+ targetScore: threshold,
107
+ totalTasks: tasks.length,
108
+ tasksByVerdict: {
109
+ fail: tasks.filter((t) => t.verdict === 'FAIL').length,
110
+ partial: tasks.filter((t) => t.verdict === 'PARTIAL').length,
111
+ },
112
+ tasksBySeverity,
113
+ tasks,
114
+ generatedAt: new Date().toISOString(),
115
+ inputTokens,
116
+ outputTokens,
117
+ durationMs,
118
+ };
119
+ // Write outputs
120
+ const jsonPath = join(iterPath, 'remediation.json');
121
+ const mdPath = join(iterPath, 'remediation.md');
122
+ await writeFile(jsonPath, JSON.stringify(plan, null, 2) + '\n', 'utf-8');
123
+ const report = generateRemediationReport(plan, projectName);
124
+ await writeFile(mdPath, report, 'utf-8');
125
+ // Print summary
126
+ console.log(`\n ─────────────────────────────────────`);
127
+ console.log(` Saved: .assay/iterations/${iteration}/remediation.json`);
128
+ console.log(` Saved: .assay/iterations/${iteration}/remediation.md`);
129
+ console.log(`\n Remediation Tasks: ${tasks.length}`);
130
+ console.log(` FAIL tasks: ${plan.tasksByVerdict.fail}`);
131
+ console.log(` PARTIAL tasks: ${plan.tasksByVerdict.partial}`);
132
+ console.log(`\n By severity:`);
133
+ if (tasksBySeverity.critical > 0)
134
+ console.log(` Critical: ${tasksBySeverity.critical}`);
135
+ if (tasksBySeverity.high > 0)
136
+ console.log(` High: ${tasksBySeverity.high}`);
137
+ if (tasksBySeverity.medium > 0)
138
+ console.log(` Medium: ${tasksBySeverity.medium}`);
139
+ if (tasksBySeverity.low > 0)
140
+ console.log(` Low: ${tasksBySeverity.low}`);
141
+ // Show top priority tasks
142
+ const topTasks = tasks.slice(0, 3);
143
+ if (topTasks.length > 0) {
144
+ console.log(`\n Top priority tasks:`);
145
+ for (const t of topTasks) {
146
+ console.log(` ${t.id} [${t.severity}] ${t.title}`);
147
+ console.log(` → ${t.targetFiles.join(', ')}`);
148
+ }
149
+ }
150
+ console.log(`\n Input tokens: ${inputTokens.toLocaleString()}`);
151
+ console.log(` Output tokens: ${outputTokens.toLocaleString()}`);
152
+ console.log(` Duration: ${(durationMs / 1000).toFixed(1)}s`);
153
+ console.log(`\n Fix the tasks above, then re-verify: \`assay verify → assay report\`\n`);
154
+ }
155
+ //# sourceMappingURL=remediate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remediate.js","sourceRoot":"","sources":["../../src/commands/remediate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function reportCommand(options: {
2
+ iteration?: string;
3
+ }): Promise<void>;
@@ -0,0 +1,84 @@
1
+ import { readdir, readFile, writeFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { getIterationsDir, readConfig } from '../lib/config.js';
4
+ import { exists } from '../lib/fs-utils.js';
5
+ import { generateGapReport } from '../lib/report-generator.js';
6
+ async function findLatestIteration(iterDir) {
7
+ if (!(await exists(iterDir)))
8
+ return null;
9
+ const entries = await readdir(iterDir, { withFileTypes: true });
10
+ const nums = entries
11
+ .filter((e) => e.isDirectory())
12
+ .map((e) => parseInt(e.name, 10))
13
+ .filter((n) => !isNaN(n));
14
+ return nums.length === 0 ? null : Math.max(...nums);
15
+ }
16
+ export async function reportCommand(options) {
17
+ const iterDir = getIterationsDir();
18
+ // Determine iteration
19
+ let iteration;
20
+ if (options.iteration) {
21
+ iteration = parseInt(options.iteration, 10);
22
+ if (isNaN(iteration)) {
23
+ console.error(` Error: Invalid iteration "${options.iteration}".`);
24
+ process.exit(1);
25
+ }
26
+ }
27
+ else {
28
+ const latest = await findLatestIteration(iterDir);
29
+ if (latest === null) {
30
+ console.error(' Error: No iterations found.');
31
+ process.exit(1);
32
+ }
33
+ iteration = latest;
34
+ }
35
+ const iterPath = join(iterDir, String(iteration));
36
+ const claimsPath = join(iterPath, 'claims.json');
37
+ const verificationPath = join(iterPath, 'verification.json');
38
+ if (!(await exists(claimsPath))) {
39
+ console.error(` Error: No claims.json found for iteration ${iteration}.`);
40
+ console.error(' Run `assay extract` first.');
41
+ process.exit(1);
42
+ }
43
+ if (!(await exists(verificationPath))) {
44
+ console.error(` Error: No verification.json found for iteration ${iteration}.`);
45
+ console.error(' Run `assay verify` first.');
46
+ process.exit(1);
47
+ }
48
+ const extraction = JSON.parse(await readFile(claimsPath, 'utf-8'));
49
+ const verification = JSON.parse(await readFile(verificationPath, 'utf-8'));
50
+ // Try to get project name from config
51
+ let projectName;
52
+ try {
53
+ const config = await readConfig();
54
+ projectName = config.projectName;
55
+ }
56
+ catch {
57
+ // Config not required for report
58
+ }
59
+ console.log(`\n Assay — Generating gap report (iteration ${iteration})`);
60
+ console.log(` ─────────────────────────────────────\n`);
61
+ const report = generateGapReport({
62
+ extraction,
63
+ verification,
64
+ projectName,
65
+ });
66
+ const reportPath = join(iterPath, 'gap-report.md');
67
+ await writeFile(reportPath, report, 'utf-8');
68
+ const { verdicts } = verification;
69
+ const total = verification.verifications.length;
70
+ const assessed = total - verdicts.na;
71
+ const score = assessed > 0
72
+ ? ((verdicts.pass + verdicts.partial * 0.5) / assessed) * 100
73
+ : 0;
74
+ console.log(` Saved: .assay/iterations/${iteration}/gap-report.md`);
75
+ console.log(`\n Report Summary:`);
76
+ console.log(` Total claims: ${total}`);
77
+ console.log(` PASS: ${verdicts.pass}`);
78
+ console.log(` PARTIAL: ${verdicts.partial}`);
79
+ console.log(` FAIL: ${verdicts.fail}`);
80
+ console.log(` N/A: ${verdicts.na}`);
81
+ console.log(` Compliance score: ${score.toFixed(1)}%`);
82
+ console.log(`\n The gap report is ready for delivery.\n`);
83
+ }
84
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/commands/report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ interface ReverseOptions {
2
+ task?: string;
3
+ taskFile?: string;
4
+ lang: string;
5
+ output?: string;
6
+ verbose?: boolean;
7
+ }
8
+ export declare function reverseCommand(options: ReverseOptions): Promise<void>;
9
+ export {};