tryassay 0.22.2 → 0.25.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 (44) hide show
  1. package/dist/cli.js +38 -1
  2. package/dist/cli.js.map +1 -1
  3. package/dist/commands/assess.js +73 -6
  4. package/dist/commands/assess.js.map +1 -1
  5. package/dist/commands/suppress.d.ts +17 -0
  6. package/dist/commands/suppress.js +119 -0
  7. package/dist/commands/suppress.js.map +1 -0
  8. package/dist/lib/__tests__/claim-id.test.d.ts +1 -0
  9. package/dist/lib/__tests__/claim-id.test.js +24 -0
  10. package/dist/lib/__tests__/claim-id.test.js.map +1 -0
  11. package/dist/lib/__tests__/gap-matcher.test.d.ts +1 -0
  12. package/dist/lib/__tests__/gap-matcher.test.js +291 -0
  13. package/dist/lib/__tests__/gap-matcher.test.js.map +1 -0
  14. package/dist/lib/__tests__/gap-suppression.test.d.ts +1 -0
  15. package/dist/lib/__tests__/gap-suppression.test.js +168 -0
  16. package/dist/lib/__tests__/gap-suppression.test.js.map +1 -0
  17. package/dist/lib/__tests__/output-dir-migration.test.d.ts +1 -0
  18. package/dist/lib/__tests__/output-dir-migration.test.js +33 -0
  19. package/dist/lib/__tests__/output-dir-migration.test.js.map +1 -0
  20. package/dist/lib/__tests__/overrides.test.d.ts +1 -0
  21. package/dist/lib/__tests__/overrides.test.js +55 -0
  22. package/dist/lib/__tests__/overrides.test.js.map +1 -0
  23. package/dist/lib/assessment-reporter.js +4 -1
  24. package/dist/lib/assessment-reporter.js.map +1 -1
  25. package/dist/lib/claim-id.d.ts +1 -0
  26. package/dist/lib/claim-id.js +6 -0
  27. package/dist/lib/claim-id.js.map +1 -0
  28. package/dist/lib/gap-matcher.d.ts +63 -0
  29. package/dist/lib/gap-matcher.js +268 -0
  30. package/dist/lib/gap-matcher.js.map +1 -0
  31. package/dist/lib/intent-extractor.d.ts +5 -0
  32. package/dist/lib/intent-extractor.js +18 -3
  33. package/dist/lib/intent-extractor.js.map +1 -1
  34. package/dist/lib/intent-types.d.ts +11 -0
  35. package/dist/lib/llm-provider.js +36 -7
  36. package/dist/lib/llm-provider.js.map +1 -1
  37. package/dist/lib/output-dir.d.ts +4 -0
  38. package/dist/lib/output-dir.js +19 -0
  39. package/dist/lib/output-dir.js.map +1 -0
  40. package/dist/lib/overrides.d.ts +27 -0
  41. package/dist/lib/overrides.js +81 -0
  42. package/dist/lib/overrides.js.map +1 -0
  43. package/dist/types.d.ts +12 -0
  44. package/package.json +3 -2
@@ -0,0 +1,4 @@
1
+ export declare function migrateOutputDir(basePath: string): Promise<{
2
+ migrated: boolean;
3
+ message?: string;
4
+ }>;
@@ -0,0 +1,19 @@
1
+ import { rename, stat } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ const OLD_DIR = '.assay-assessment';
4
+ const NEW_DIR = '.assay';
5
+ export async function migrateOutputDir(basePath) {
6
+ const oldPath = join(basePath, OLD_DIR);
7
+ const newPath = join(basePath, NEW_DIR);
8
+ const oldExists = await stat(oldPath).then(() => true).catch(() => false);
9
+ const newExists = await stat(newPath).then(() => true).catch(() => false);
10
+ if (oldExists && !newExists) {
11
+ await rename(oldPath, newPath);
12
+ return { migrated: true, message: `Migrated ${OLD_DIR}/ to ${NEW_DIR}/` };
13
+ }
14
+ if (oldExists && newExists) {
15
+ return { migrated: false, message: `Found both ${OLD_DIR}/ and ${NEW_DIR}/. Using ${NEW_DIR}/.` };
16
+ }
17
+ return { migrated: false };
18
+ }
19
+ //# sourceMappingURL=output-dir.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output-dir.js","sourceRoot":"","sources":["../../src/lib/output-dir.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,OAAO,GAAG,mBAAmB,CAAC;AACpC,MAAM,OAAO,GAAG,QAAQ,CAAC;AAEzB,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAAgB;IACrD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACxC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAExC,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;IAC1E,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;IAE1E,IAAI,SAAS,IAAI,CAAC,SAAS,EAAE,CAAC;QAC5B,MAAM,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC/B,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,OAAO,QAAQ,OAAO,GAAG,EAAE,CAAC;IAC5E,CAAC;IAED,IAAI,SAAS,IAAI,SAAS,EAAE,CAAC;QAC3B,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,cAAc,OAAO,SAAS,OAAO,YAAY,OAAO,IAAI,EAAE,CAAC;IACpG,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { OverridesConfig } from '../types.js';
2
+ import type { IntentGapType } from './intent-types.js';
3
+ import type { GapLike, GapMatchResult } from './gap-matcher.js';
4
+ export declare function loadOverrides(basePath: string): Promise<OverridesConfig>;
5
+ export declare function saveOverrides(basePath: string, overrides: OverridesConfig): Promise<void>;
6
+ export declare function addSuppression(basePath: string, entry: {
7
+ claimId: string;
8
+ file: string;
9
+ claim: string;
10
+ reason: string;
11
+ }): Promise<void>;
12
+ export declare function addGapSuppression(basePath: string, entry: {
13
+ gapId: string;
14
+ type: IntentGapType;
15
+ description: string;
16
+ reason: string;
17
+ evidence?: string;
18
+ matchAnchors?: string[];
19
+ matchTokens?: string[];
20
+ }): Promise<void>;
21
+ export declare function buildSuppressedGapIdSet(overrides: OverridesConfig): Set<string>;
22
+ /**
23
+ * Check if a gap is suppressed — tries exact ID match first,
24
+ * falls back to pattern matching if no exact match found.
25
+ * Returns the match result or null if not suppressed.
26
+ */
27
+ export declare function isGapSuppressed(gap: GapLike, overrides: OverridesConfig): GapMatchResult | null;
@@ -0,0 +1,81 @@
1
+ import { readFile, writeFile, mkdir } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { matchGapToSuppression } from './gap-matcher.js';
4
+ const ASSAY_DIR = '.assay';
5
+ const OVERRIDES_FILE = 'overrides.json';
6
+ export async function loadOverrides(basePath) {
7
+ const filePath = join(basePath, ASSAY_DIR, OVERRIDES_FILE);
8
+ try {
9
+ const content = await readFile(filePath, 'utf-8');
10
+ return JSON.parse(content);
11
+ }
12
+ catch {
13
+ return { suppressions: [] };
14
+ }
15
+ }
16
+ export async function saveOverrides(basePath, overrides) {
17
+ const dirPath = join(basePath, ASSAY_DIR);
18
+ await mkdir(dirPath, { recursive: true });
19
+ await writeFile(join(dirPath, OVERRIDES_FILE), JSON.stringify(overrides, null, 2));
20
+ }
21
+ export async function addSuppression(basePath, entry) {
22
+ const overrides = await loadOverrides(basePath);
23
+ const exists = overrides.suppressions.some((s) => s.claimId === entry.claimId);
24
+ if (exists)
25
+ return;
26
+ overrides.suppressions.push({
27
+ ...entry,
28
+ suppressedAt: new Date().toISOString(),
29
+ suppressedBy: 'manual',
30
+ });
31
+ await saveOverrides(basePath, overrides);
32
+ }
33
+ export async function addGapSuppression(basePath, entry) {
34
+ const overrides = await loadOverrides(basePath);
35
+ if (!overrides.gapSuppressions) {
36
+ overrides.gapSuppressions = [];
37
+ }
38
+ const exists = overrides.gapSuppressions.some((s) => s.gapId === entry.gapId);
39
+ if (exists)
40
+ return;
41
+ overrides.gapSuppressions.push({
42
+ ...entry,
43
+ suppressedAt: new Date().toISOString(),
44
+ });
45
+ await saveOverrides(basePath, overrides);
46
+ }
47
+ export function buildSuppressedGapIdSet(overrides) {
48
+ return new Set((overrides.gapSuppressions ?? []).map((s) => s.gapId));
49
+ }
50
+ /**
51
+ * Check if a gap is suppressed — tries exact ID match first,
52
+ * falls back to pattern matching if no exact match found.
53
+ * Returns the match result or null if not suppressed.
54
+ */
55
+ export function isGapSuppressed(gap, overrides) {
56
+ const suppressions = overrides.gapSuppressions ?? [];
57
+ if (suppressions.length === 0)
58
+ return null;
59
+ // Fast path: exact ID match
60
+ if (gap.gapId) {
61
+ const exact = suppressions.find((s) => s.gapId === gap.gapId);
62
+ if (exact) {
63
+ return {
64
+ confidence: 'exact',
65
+ score: 1.0,
66
+ suppressionGapId: exact.gapId,
67
+ matchedAnchors: [],
68
+ matchedTokens: [],
69
+ };
70
+ }
71
+ }
72
+ // Fallback: pattern matching
73
+ for (const supp of suppressions) {
74
+ const result = matchGapToSuppression(gap, supp);
75
+ if (result && result.confidence !== 'exact') {
76
+ return result;
77
+ }
78
+ }
79
+ return null;
80
+ }
81
+ //# sourceMappingURL=overrides.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overrides.js","sourceRoot":"","sources":["../../src/lib/overrides.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -35,6 +35,18 @@ export interface ExtractionResult {
35
35
  testableClaims: number;
36
36
  extractedAt: string;
37
37
  }
38
+ export interface ClaimSuppression {
39
+ claimId: string;
40
+ file: string;
41
+ claim: string;
42
+ reason: string;
43
+ suppressedAt: string;
44
+ suppressedBy: 'manual' | 'pattern';
45
+ }
46
+ export interface OverridesConfig {
47
+ suppressions: ClaimSuppression[];
48
+ gapSuppressions?: import('./lib/intent-types.js').IntentGapSuppression[];
49
+ }
38
50
  export type Verdict = 'PASS' | 'PARTIAL' | 'FAIL' | 'N/A';
39
51
  export interface Evidence {
40
52
  file: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tryassay",
3
- "version": "0.22.2",
3
+ "version": "0.25.0",
4
4
  "description": "AI code verification CLI — find bugs that tests miss, linters ignore, and code review overlooks",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -49,7 +49,8 @@
49
49
  "@upstash/ratelimit": "^2.0.8",
50
50
  "@upstash/redis": "^1.36.2",
51
51
  "commander": "^13.1.0",
52
- "openai": "^6.22.0"
52
+ "openai": "^6.22.0",
53
+ "stripe": "^20.4.1"
53
54
  },
54
55
  "devDependencies": {
55
56
  "@types/node": "^22.0.0",