tryassay 0.23.0 → 0.27.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 (38) hide show
  1. package/dist/cli.js +31 -6
  2. package/dist/cli.js.map +1 -1
  3. package/dist/commands/assess.d.ts +1 -0
  4. package/dist/commands/assess.js +143 -8
  5. package/dist/commands/assess.js.map +1 -1
  6. package/dist/commands/config-cmd.d.ts +5 -0
  7. package/dist/commands/config-cmd.js +35 -0
  8. package/dist/commands/config-cmd.js.map +1 -0
  9. package/dist/commands/suppress.d.ts +7 -0
  10. package/dist/commands/suppress.js +66 -1
  11. package/dist/commands/suppress.js.map +1 -1
  12. package/dist/lib/__tests__/gap-matcher.test.d.ts +1 -0
  13. package/dist/lib/__tests__/gap-matcher.test.js +291 -0
  14. package/dist/lib/__tests__/gap-matcher.test.js.map +1 -0
  15. package/dist/lib/__tests__/gap-suppression.test.d.ts +1 -0
  16. package/dist/lib/__tests__/gap-suppression.test.js +168 -0
  17. package/dist/lib/__tests__/gap-suppression.test.js.map +1 -0
  18. package/dist/lib/gap-matcher.d.ts +63 -0
  19. package/dist/lib/gap-matcher.js +268 -0
  20. package/dist/lib/gap-matcher.js.map +1 -0
  21. package/dist/lib/intent-extractor.d.ts +5 -0
  22. package/dist/lib/intent-extractor.js +18 -3
  23. package/dist/lib/intent-extractor.js.map +1 -1
  24. package/dist/lib/intent-types.d.ts +11 -0
  25. package/dist/lib/overrides.d.ts +18 -0
  26. package/dist/lib/overrides.js +49 -0
  27. package/dist/lib/overrides.js.map +1 -1
  28. package/dist/lib/publisher.d.ts +19 -1
  29. package/dist/lib/publisher.js +62 -8
  30. package/dist/lib/publisher.js.map +1 -1
  31. package/dist/lib/telemetry.d.ts +39 -0
  32. package/dist/lib/telemetry.js +69 -0
  33. package/dist/lib/telemetry.js.map +1 -0
  34. package/dist/lib/user-config.d.ts +17 -0
  35. package/dist/lib/user-config.js +34 -0
  36. package/dist/lib/user-config.js.map +1 -0
  37. package/dist/types.d.ts +1 -0
  38. package/package.json +1 -1
@@ -0,0 +1,39 @@
1
+ export interface TelemetryEvent {
2
+ event_type: 'assess_complete' | 'assess_error';
3
+ package_version: string;
4
+ node_version: string;
5
+ os_platform: string;
6
+ os_arch: string;
7
+ repo_name?: string;
8
+ frameworks?: string[];
9
+ file_count?: number;
10
+ claim_count?: number;
11
+ bug_count?: number;
12
+ score?: number;
13
+ duration_ms?: number;
14
+ top_bug_categories?: Array<{
15
+ category: string;
16
+ count: number;
17
+ }>;
18
+ error_code?: string;
19
+ session_id: string;
20
+ }
21
+ /**
22
+ * Check if telemetry is enabled.
23
+ * Disabled by ASSAY_TELEMETRY=0 env var or --no-telemetry CLI flag.
24
+ */
25
+ export declare function isTelemetryEnabled(): boolean;
26
+ /**
27
+ * Show first-run telemetry notice (once per project).
28
+ * Creates .assay/telemetry-notice-shown marker file.
29
+ */
30
+ export declare function showTelemetryNotice(targetPath: string): Promise<void>;
31
+ /**
32
+ * Fire-and-forget telemetry event.
33
+ * Never blocks the CLI, never throws.
34
+ */
35
+ export declare function sendTelemetryEvent(data: Omit<TelemetryEvent, 'session_id'>): void;
36
+ /**
37
+ * Get package version from package.json.
38
+ */
39
+ export declare function getPackageVersion(): Promise<string>;
@@ -0,0 +1,69 @@
1
+ import { readFile, writeFile, mkdir } from 'node:fs/promises';
2
+ import { resolve } from 'node:path';
3
+ import { randomUUID } from 'node:crypto';
4
+ const TELEMETRY_URL = 'https://api.trylucid.dev/api/v1/telemetry';
5
+ const TELEMETRY_TIMEOUT_MS = 3_000;
6
+ /**
7
+ * Check if telemetry is enabled.
8
+ * Disabled by ASSAY_TELEMETRY=0 env var or --no-telemetry CLI flag.
9
+ */
10
+ export function isTelemetryEnabled() {
11
+ return process.env.ASSAY_TELEMETRY !== '0';
12
+ }
13
+ /**
14
+ * Show first-run telemetry notice (once per project).
15
+ * Creates .assay/telemetry-notice-shown marker file.
16
+ */
17
+ export async function showTelemetryNotice(targetPath) {
18
+ const markerPath = resolve(targetPath, '.assay', 'telemetry-notice-shown');
19
+ try {
20
+ await readFile(markerPath);
21
+ return; // Already shown
22
+ }
23
+ catch {
24
+ // Not shown yet
25
+ }
26
+ console.log('\n Note: Assay collects anonymous usage stats (no code or file paths).' +
27
+ '\n Disable: ASSAY_TELEMETRY=0 or --no-telemetry\n');
28
+ try {
29
+ await mkdir(resolve(targetPath, '.assay'), { recursive: true });
30
+ await writeFile(markerPath, new Date().toISOString());
31
+ }
32
+ catch {
33
+ // Non-critical — skip silently
34
+ }
35
+ }
36
+ /**
37
+ * Fire-and-forget telemetry event.
38
+ * Never blocks the CLI, never throws.
39
+ */
40
+ export function sendTelemetryEvent(data) {
41
+ const payload = {
42
+ ...data,
43
+ session_id: randomUUID(),
44
+ };
45
+ const controller = new AbortController();
46
+ const timeout = setTimeout(() => controller.abort(), TELEMETRY_TIMEOUT_MS);
47
+ fetch(TELEMETRY_URL, {
48
+ method: 'POST',
49
+ headers: { 'Content-Type': 'application/json' },
50
+ body: JSON.stringify(payload),
51
+ signal: controller.signal,
52
+ })
53
+ .catch(() => { }) // Silently ignore failures
54
+ .finally(() => clearTimeout(timeout));
55
+ }
56
+ /**
57
+ * Get package version from package.json.
58
+ */
59
+ export async function getPackageVersion() {
60
+ try {
61
+ const pkgPath = new URL('../../package.json', import.meta.url);
62
+ const pkg = JSON.parse(await readFile(pkgPath, 'utf-8'));
63
+ return pkg.version || 'unknown';
64
+ }
65
+ catch {
66
+ return 'unknown';
67
+ }
68
+ }
69
+ //# sourceMappingURL=telemetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../src/lib/telemetry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,aAAa,GAAG,2CAA2C,CAAC;AAClE,MAAM,oBAAoB,GAAG,KAAK,CAAC;AAoBnC;;;GAGG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,GAAG,CAAC;AAC7C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,UAAkB;IAC1D,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,EAAE,QAAQ,EAAE,wBAAwB,CAAC,CAAC;IAC3E,IAAI,CAAC;QACH,MAAM,QAAQ,CAAC,UAAU,CAAC,CAAC;QAC3B,OAAO,CAAC,gBAAgB;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,gBAAgB;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,CACT,yEAAyE;QACzE,oDAAoD,CACrD,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChE,MAAM,SAAS,CAAC,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,+BAA+B;IACjC,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAwC;IACzE,MAAM,OAAO,GAAmB;QAC9B,GAAG,IAAI;QACP,UAAU,EAAE,UAAU,EAAE;KACzB,CAAC;IAEF,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,oBAAoB,CAAC,CAAC;IAE3E,KAAK,CAAC,aAAa,EAAE;QACnB,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;QAC7B,MAAM,EAAE,UAAU,CAAC,MAAM;KAC1B,CAAC;SACC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,2BAA2B;SAC3C,OAAO,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,oBAAoB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QACzD,OAAO,GAAG,CAAC,OAAO,IAAI,SAAS,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
@@ -0,0 +1,17 @@
1
+ export interface UserConfig {
2
+ email?: string;
3
+ email_hash?: string;
4
+ api_key?: string;
5
+ }
6
+ export interface Identity {
7
+ email_hash?: string;
8
+ api_key?: string;
9
+ }
10
+ export declare function loadUserConfig(): Promise<UserConfig>;
11
+ export declare function saveUserConfig(config: UserConfig): Promise<void>;
12
+ export declare function hashEmail(email: string): string;
13
+ /**
14
+ * Resolve identity from config + environment.
15
+ * Priority: ASSAY_API_KEY env > config api_key > config email_hash
16
+ */
17
+ export declare function getIdentity(config: UserConfig): Identity;
@@ -0,0 +1,34 @@
1
+ import { readFile, writeFile, mkdir } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { homedir } from 'node:os';
4
+ import { createHash } from 'node:crypto';
5
+ const CONFIG_DIR = join(homedir(), '.assay');
6
+ const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
7
+ export async function loadUserConfig() {
8
+ try {
9
+ const data = await readFile(CONFIG_FILE, 'utf-8');
10
+ return JSON.parse(data);
11
+ }
12
+ catch {
13
+ return {};
14
+ }
15
+ }
16
+ export async function saveUserConfig(config) {
17
+ await mkdir(CONFIG_DIR, { recursive: true });
18
+ await writeFile(CONFIG_FILE, JSON.stringify(config, null, 2) + '\n');
19
+ }
20
+ export function hashEmail(email) {
21
+ return createHash('sha256').update(email.toLowerCase().trim()).digest('hex');
22
+ }
23
+ /**
24
+ * Resolve identity from config + environment.
25
+ * Priority: ASSAY_API_KEY env > config api_key > config email_hash
26
+ */
27
+ export function getIdentity(config) {
28
+ const envKey = process.env.ASSAY_API_KEY;
29
+ return {
30
+ api_key: envKey || config.api_key,
31
+ email_hash: config.email_hash,
32
+ };
33
+ }
34
+ //# sourceMappingURL=user-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-config.js","sourceRoot":"","sources":["../../src/lib/user-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,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC7C,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAapD,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAe,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,MAAkB;IACrD,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,MAAM,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC/E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,MAAkB;IAC5C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;IACzC,OAAO;QACL,OAAO,EAAE,MAAM,IAAI,MAAM,CAAC,OAAO;QACjC,UAAU,EAAE,MAAM,CAAC,UAAU;KAC9B,CAAC;AACJ,CAAC"}
package/dist/types.d.ts CHANGED
@@ -45,6 +45,7 @@ export interface ClaimSuppression {
45
45
  }
46
46
  export interface OverridesConfig {
47
47
  suppressions: ClaimSuppression[];
48
+ gapSuppressions?: import('./lib/intent-types.js').IntentGapSuppression[];
48
49
  }
49
50
  export type Verdict = 'PASS' | 'PARTIAL' | 'FAIL' | 'N/A';
50
51
  export interface Evidence {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tryassay",
3
- "version": "0.23.0",
3
+ "version": "0.27.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",