semantic-complexity 0.0.7-741984fb → 0.0.13-2aaf183b

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 (163) hide show
  1. package/dist/__tests__/analyzers.test.d.ts +5 -0
  2. package/dist/__tests__/analyzers.test.d.ts.map +1 -0
  3. package/dist/__tests__/analyzers.test.js +357 -0
  4. package/dist/__tests__/analyzers.test.js.map +1 -0
  5. package/dist/__tests__/gate.test.d.ts +5 -0
  6. package/dist/__tests__/gate.test.d.ts.map +1 -0
  7. package/dist/__tests__/gate.test.js +140 -0
  8. package/dist/__tests__/gate.test.js.map +1 -0
  9. package/dist/analyzers/bread.d.ts +63 -0
  10. package/dist/analyzers/bread.d.ts.map +1 -0
  11. package/dist/analyzers/bread.js +415 -0
  12. package/dist/analyzers/bread.js.map +1 -0
  13. package/dist/analyzers/cheese.d.ts +111 -0
  14. package/dist/analyzers/cheese.d.ts.map +1 -0
  15. package/dist/analyzers/cheese.js +881 -0
  16. package/dist/analyzers/cheese.js.map +1 -0
  17. package/dist/analyzers/ham.d.ts +33 -0
  18. package/dist/analyzers/ham.d.ts.map +1 -0
  19. package/dist/analyzers/ham.js +264 -0
  20. package/dist/analyzers/ham.js.map +1 -0
  21. package/dist/analyzers/index.d.ts +7 -0
  22. package/dist/analyzers/index.d.ts.map +1 -0
  23. package/dist/analyzers/index.js +7 -0
  24. package/dist/analyzers/index.js.map +1 -0
  25. package/dist/budget/index.d.ts +50 -0
  26. package/dist/budget/index.d.ts.map +1 -0
  27. package/dist/budget/index.js +138 -0
  28. package/dist/budget/index.js.map +1 -0
  29. package/dist/cli/index.d.ts +6 -0
  30. package/dist/cli/index.d.ts.map +1 -0
  31. package/dist/cli/index.js +103 -0
  32. package/dist/cli/index.js.map +1 -0
  33. package/dist/gate/index.d.ts +31 -0
  34. package/dist/gate/index.d.ts.map +1 -0
  35. package/dist/gate/index.js +117 -0
  36. package/dist/gate/index.js.map +1 -0
  37. package/dist/gate/waiver.d.ts +54 -0
  38. package/dist/gate/waiver.d.ts.map +1 -0
  39. package/dist/gate/waiver.js +280 -0
  40. package/dist/gate/waiver.js.map +1 -0
  41. package/dist/index.d.ts +8 -34
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +8 -49
  44. package/dist/index.js.map +1 -1
  45. package/dist/mcp/index.d.ts +5 -0
  46. package/dist/mcp/index.d.ts.map +1 -0
  47. package/dist/mcp/index.js +140 -0
  48. package/dist/mcp/index.js.map +1 -0
  49. package/dist/recommend/index.d.ts +32 -0
  50. package/dist/recommend/index.d.ts.map +1 -0
  51. package/dist/recommend/index.js +169 -0
  52. package/dist/recommend/index.js.map +1 -0
  53. package/dist/simplex/index.d.ts +26 -0
  54. package/dist/simplex/index.d.ts.map +1 -0
  55. package/dist/simplex/index.js +100 -0
  56. package/dist/simplex/index.js.map +1 -0
  57. package/dist/types/index.d.ts +39 -0
  58. package/dist/types/index.d.ts.map +1 -0
  59. package/dist/types/index.js +5 -0
  60. package/dist/types/index.js.map +1 -0
  61. package/package.json +27 -52
  62. package/LICENSE +0 -21
  63. package/README.md +0 -72
  64. package/dist/ast/index.d.ts +0 -2
  65. package/dist/ast/index.d.ts.map +0 -1
  66. package/dist/ast/index.js +0 -2
  67. package/dist/ast/index.js.map +0 -1
  68. package/dist/ast/parser.d.ts +0 -27
  69. package/dist/ast/parser.d.ts.map +0 -1
  70. package/dist/ast/parser.js +0 -273
  71. package/dist/ast/parser.js.map +0 -1
  72. package/dist/canonical/convergence.d.ts +0 -56
  73. package/dist/canonical/convergence.d.ts.map +0 -1
  74. package/dist/canonical/convergence.js +0 -149
  75. package/dist/canonical/convergence.js.map +0 -1
  76. package/dist/canonical/index.d.ts +0 -11
  77. package/dist/canonical/index.d.ts.map +0 -1
  78. package/dist/canonical/index.js +0 -11
  79. package/dist/canonical/index.js.map +0 -1
  80. package/dist/canonical/profiles.d.ts +0 -40
  81. package/dist/canonical/profiles.d.ts.map +0 -1
  82. package/dist/canonical/profiles.js +0 -182
  83. package/dist/canonical/profiles.js.map +0 -1
  84. package/dist/canonical/types.d.ts +0 -124
  85. package/dist/canonical/types.d.ts.map +0 -1
  86. package/dist/canonical/types.js +0 -46
  87. package/dist/canonical/types.js.map +0 -1
  88. package/dist/compare.d.ts +0 -31
  89. package/dist/compare.d.ts.map +0 -1
  90. package/dist/compare.js +0 -354
  91. package/dist/compare.js.map +0 -1
  92. package/dist/context/index.d.ts +0 -41
  93. package/dist/context/index.d.ts.map +0 -1
  94. package/dist/context/index.js +0 -253
  95. package/dist/context/index.js.map +0 -1
  96. package/dist/gates/delta.d.ts +0 -45
  97. package/dist/gates/delta.d.ts.map +0 -1
  98. package/dist/gates/delta.js +0 -260
  99. package/dist/gates/delta.js.map +0 -1
  100. package/dist/gates/index.d.ts +0 -9
  101. package/dist/gates/index.d.ts.map +0 -1
  102. package/dist/gates/index.js +0 -9
  103. package/dist/gates/index.js.map +0 -1
  104. package/dist/gates/types.d.ts +0 -96
  105. package/dist/gates/types.d.ts.map +0 -1
  106. package/dist/gates/types.js +0 -59
  107. package/dist/gates/types.js.map +0 -1
  108. package/dist/graph/call.d.ts +0 -63
  109. package/dist/graph/call.d.ts.map +0 -1
  110. package/dist/graph/call.js +0 -240
  111. package/dist/graph/call.js.map +0 -1
  112. package/dist/graph/dependency.d.ts +0 -52
  113. package/dist/graph/dependency.d.ts.map +0 -1
  114. package/dist/graph/dependency.js +0 -296
  115. package/dist/graph/dependency.js.map +0 -1
  116. package/dist/graph/index.d.ts +0 -3
  117. package/dist/graph/index.d.ts.map +0 -1
  118. package/dist/graph/index.js +0 -3
  119. package/dist/graph/index.js.map +0 -1
  120. package/dist/metrics/cognitive.d.ts +0 -42
  121. package/dist/metrics/cognitive.d.ts.map +0 -1
  122. package/dist/metrics/cognitive.js +0 -204
  123. package/dist/metrics/cognitive.js.map +0 -1
  124. package/dist/metrics/cyclomatic.d.ts +0 -31
  125. package/dist/metrics/cyclomatic.d.ts.map +0 -1
  126. package/dist/metrics/cyclomatic.js +0 -121
  127. package/dist/metrics/cyclomatic.js.map +0 -1
  128. package/dist/metrics/dimensional.d.ts +0 -32
  129. package/dist/metrics/dimensional.d.ts.map +0 -1
  130. package/dist/metrics/dimensional.js +0 -560
  131. package/dist/metrics/dimensional.js.map +0 -1
  132. package/dist/metrics/index.d.ts +0 -26
  133. package/dist/metrics/index.d.ts.map +0 -1
  134. package/dist/metrics/index.js +0 -120
  135. package/dist/metrics/index.js.map +0 -1
  136. package/dist/metrics/meta.d.ts +0 -90
  137. package/dist/metrics/meta.d.ts.map +0 -1
  138. package/dist/metrics/meta.js +0 -144
  139. package/dist/metrics/meta.js.map +0 -1
  140. package/dist/tensor/canonical.d.ts +0 -53
  141. package/dist/tensor/canonical.d.ts.map +0 -1
  142. package/dist/tensor/canonical.js +0 -192
  143. package/dist/tensor/canonical.js.map +0 -1
  144. package/dist/tensor/index.d.ts +0 -22
  145. package/dist/tensor/index.d.ts.map +0 -1
  146. package/dist/tensor/index.js +0 -22
  147. package/dist/tensor/index.js.map +0 -1
  148. package/dist/tensor/matrix.d.ts +0 -62
  149. package/dist/tensor/matrix.d.ts.map +0 -1
  150. package/dist/tensor/matrix.js +0 -187
  151. package/dist/tensor/matrix.js.map +0 -1
  152. package/dist/tensor/scoring.d.ts +0 -82
  153. package/dist/tensor/scoring.d.ts.map +0 -1
  154. package/dist/tensor/scoring.js +0 -233
  155. package/dist/tensor/scoring.js.map +0 -1
  156. package/dist/tensor/types.d.ts +0 -186
  157. package/dist/tensor/types.d.ts.map +0 -1
  158. package/dist/tensor/types.js +0 -15
  159. package/dist/tensor/types.js.map +0 -1
  160. package/dist/types.d.ts +0 -341
  161. package/dist/types.d.ts.map +0 -1
  162. package/dist/types.js +0 -22
  163. package/dist/types.js.map +0 -1
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Analyzer Tests
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=analyzers.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyzers.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/analyzers.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,357 @@
1
+ /**
2
+ * Analyzer Tests
3
+ */
4
+ import { describe, it } from 'node:test';
5
+ import assert from 'node:assert';
6
+ import { analyzeBread } from '../analyzers/bread.js';
7
+ import { analyzeCheese } from '../analyzers/cheese.js';
8
+ import { analyzeHam } from '../analyzers/ham.js';
9
+ describe('Bread Analyzer', () => {
10
+ it('should detect trust boundary markers', () => {
11
+ const source = `
12
+ // TRUST_BOUNDARY: API endpoint
13
+ app.get('/api/users', handler);
14
+ `;
15
+ const result = analyzeBread(source);
16
+ assert.ok(result.trustBoundaryCount > 0);
17
+ });
18
+ it('should detect hardcoded secrets', () => {
19
+ const source = `
20
+ const password = "secret123";
21
+ const api_key = "sk_live_xxx";
22
+ `;
23
+ const result = analyzeBread(source);
24
+ assert.ok(result.secretPatterns.length > 0);
25
+ assert.ok(result.secretPatterns.some(s => s.severity === 'high'));
26
+ });
27
+ it('should count hidden dependencies', () => {
28
+ const source = `
29
+ const env = process.env.NODE_ENV;
30
+ console.log(env);
31
+ `;
32
+ const result = analyzeBread(source);
33
+ assert.ok(result.hiddenDeps.env > 0);
34
+ assert.ok(result.hiddenDeps.io > 0);
35
+ });
36
+ it('should detect auth patterns', () => {
37
+ const source = `
38
+ import jwt from 'jsonwebtoken';
39
+ function verifyToken(token) {
40
+ return jwt.verify(token, secret);
41
+ }
42
+ `;
43
+ const result = analyzeBread(source);
44
+ assert.ok(result.authExplicitness > 0);
45
+ assert.ok(result.authPatterns.length > 0);
46
+ });
47
+ // TypeScript 전용 테스트
48
+ it('should detect any type usage', () => {
49
+ const source = `
50
+ function process(data: any) {
51
+ return data.value;
52
+ }
53
+ const x: any = getData();
54
+ `;
55
+ const result = analyzeBread(source);
56
+ assert.ok(result.typeSafety.anyCount >= 2);
57
+ assert.ok(result.typeSafety.safetyScore < 1.0);
58
+ });
59
+ it('should detect type assertions', () => {
60
+ const source = `
61
+ const data = response as UserData;
62
+ const value = input as any;
63
+ `;
64
+ const result = analyzeBread(source);
65
+ assert.ok(result.typeSafety.assertionCount >= 2);
66
+ assert.ok(result.typeSafety.assertionLocations.some(l => l.reason.includes('as any')));
67
+ });
68
+ it('should detect ts-ignore comments', () => {
69
+ const source = `
70
+ // @ts-ignore
71
+ const x = dangerousCall();
72
+ `;
73
+ const result = analyzeBread(source);
74
+ assert.ok(result.typeSafety.tsIgnoreCount >= 1);
75
+ });
76
+ it('should reward unknown type usage', () => {
77
+ const source = `
78
+ function process(data: unknown) {
79
+ if (typeof data === 'string') {
80
+ return data.length;
81
+ }
82
+ }
83
+ `;
84
+ const result = analyzeBread(source);
85
+ assert.ok(result.typeSafety.unknownCount >= 1);
86
+ assert.ok(result.typeSafety.safetyScore > 0.9);
87
+ });
88
+ });
89
+ describe('Cheese Analyzer', () => {
90
+ it('should calculate nesting depth', () => {
91
+ const source = `
92
+ function deep() {
93
+ if (a) {
94
+ for (let i = 0; i < 10; i++) {
95
+ while (true) {
96
+ try {
97
+ doSomething();
98
+ } catch (e) {
99
+ console.log(e);
100
+ }
101
+ }
102
+ }
103
+ }
104
+ }
105
+ `;
106
+ const result = analyzeCheese(source);
107
+ assert.ok(result.maxNesting >= 4);
108
+ });
109
+ it('should detect state×async×retry violation', () => {
110
+ const source = `
111
+ class Service {
112
+ async fetchWithRetry() {
113
+ this.count = 0;
114
+ for (let attempts = 0; attempts < 3; attempts++) {
115
+ try {
116
+ const result = await fetch('/api');
117
+ this.count++;
118
+ return result;
119
+ } catch (e) {
120
+ continue;
121
+ }
122
+ }
123
+ }
124
+ }
125
+ `;
126
+ const result = analyzeCheese(source);
127
+ assert.ok(result.stateAsyncRetry.violated);
128
+ assert.ok(result.stateAsyncRetry.count >= 2);
129
+ });
130
+ it('should detect rest parameter anti-pattern', () => {
131
+ const source = `
132
+ function process(...args: any[]) {
133
+ return args.map(x => x * 2);
134
+ }
135
+ `;
136
+ const result = analyzeCheese(source);
137
+ const hasRestPenalty = result.functions.some(f => f.antiPatterns.some(ap => ap.pattern === 'rest_params'));
138
+ assert.ok(hasRestPenalty);
139
+ });
140
+ it('should pass for simple accessible code', () => {
141
+ const source = `
142
+ function add(a: number, b: number): number {
143
+ return a + b;
144
+ }
145
+ `;
146
+ const result = analyzeCheese(source);
147
+ assert.ok(result.accessible);
148
+ assert.strictEqual(result.violations.length, 0);
149
+ });
150
+ // TypeScript 전용 테스트
151
+ it('should detect generic complexity', () => {
152
+ const source = `
153
+ type Complex<T extends Record<K, V>, K extends string, V, R extends T> = {
154
+ [P in keyof T]: T[P];
155
+ };
156
+ `;
157
+ const result = analyzeCheese(source);
158
+ assert.ok(result.typeComplexity.generics.count >= 1);
159
+ assert.ok(result.typeComplexity.generics.maxParams >= 4);
160
+ assert.ok(result.typeComplexity.generics.constrainedCount >= 2);
161
+ });
162
+ it('should detect union type complexity', () => {
163
+ const source = `
164
+ type Status = 'pending' | 'active' | 'completed' | 'cancelled' | 'failed' | 'archived';
165
+ `;
166
+ const result = analyzeCheese(source);
167
+ assert.ok(result.typeComplexity.unions.count >= 1);
168
+ assert.ok(result.typeComplexity.unions.maxMembers >= 6);
169
+ });
170
+ it('should detect conditional types', () => {
171
+ const source = `
172
+ type IsArray<T> = T extends Array<infer U> ? U : never;
173
+ type Unwrap<T> = T extends Promise<infer U> ? U : T;
174
+ `;
175
+ const result = analyzeCheese(source);
176
+ assert.ok(result.typeComplexity.conditionalTypes >= 2);
177
+ });
178
+ it('should detect mapped types', () => {
179
+ const source = `
180
+ type Readonly<T> = { readonly [K in keyof T]: T[K] };
181
+ type Partial<T> = { [K in keyof T]?: T[K] };
182
+ `;
183
+ const result = analyzeCheese(source);
184
+ assert.ok(result.typeComplexity.mappedTypes >= 2);
185
+ });
186
+ it('should detect type guards', () => {
187
+ const source = `
188
+ function isString(value: unknown): value is string {
189
+ return typeof value === 'string';
190
+ }
191
+ `;
192
+ const result = analyzeCheese(source);
193
+ assert.ok(result.typeComplexity.typeGuards >= 1);
194
+ });
195
+ });
196
+ describe('Framework Adjustment', () => {
197
+ it('should detect React framework', () => {
198
+ const source = `
199
+ import React, { useState, useEffect } from 'react';
200
+
201
+ function UserProfile({ userId }: Props) {
202
+ const [user, setUser] = useState(null);
203
+ const [loading, setLoading] = useState(true);
204
+
205
+ useEffect(() => {
206
+ fetchUser(userId).then(setUser);
207
+ }, [userId]);
208
+
209
+ return <div>{user?.name}</div>;
210
+ }
211
+ `;
212
+ const result = analyzeCheese(source);
213
+ assert.strictEqual(result.frameworkInfo.detected, 'react');
214
+ assert.ok(result.frameworkInfo.hookCount >= 2);
215
+ });
216
+ it('should apply JSX nesting weight', () => {
217
+ // Note: TypeScript parser needs proper JSX syntax
218
+ const source = `
219
+ import React from 'react';
220
+
221
+ function Component() {
222
+ // Simulating nested structure with nested functions
223
+ return nested1(() => nested2(() => nested3()));
224
+ }
225
+ `;
226
+ const result = analyzeCheese(source);
227
+ // Framework detected as React, adjustments applied
228
+ assert.strictEqual(result.frameworkInfo.detected, 'react');
229
+ assert.ok(result.adjustedNesting <= result.maxNesting);
230
+ });
231
+ it('should apply hook concept weight', () => {
232
+ const source = `
233
+ import { useState, useEffect, useMemo, useCallback } from 'react';
234
+
235
+ function useCustomHook() {
236
+ const [state, setState] = useState(null);
237
+ const [loading, setLoading] = useState(true);
238
+ const [error, setError] = useState(null);
239
+
240
+ useEffect(() => {}, []);
241
+
242
+ const memoized = useMemo(() => state, [state]);
243
+ const callback = useCallback(() => {}, []);
244
+
245
+ return { state, loading, error, memoized, callback };
246
+ }
247
+ `;
248
+ const result = analyzeCheese(source);
249
+ // Hook이 많지만 가중치 적용되어 개념 수 감소
250
+ assert.ok(result.frameworkInfo.hookCount >= 4);
251
+ const hookAdjustment = result.frameworkInfo.adjustments.find(a => a.type === 'hook');
252
+ if (hookAdjustment) {
253
+ assert.ok(hookAdjustment.adjusted < hookAdjustment.original);
254
+ }
255
+ });
256
+ it('should apply chain method weight', () => {
257
+ const source = `
258
+ import React from 'react';
259
+
260
+ function UserList({ users }: Props) {
261
+ const result = users.filter(u => u.active);
262
+ const names = result.map(u => u.name);
263
+ const sorted = names.sort();
264
+ return sorted.join(', ');
265
+ }
266
+ `;
267
+ const result = analyzeCheese(source);
268
+ // At least some chain methods detected
269
+ assert.ok(result.frameworkInfo.chainCount >= 1);
270
+ });
271
+ it('should detect Vue framework', () => {
272
+ const source = `
273
+ import { ref, computed, onMounted } from 'vue';
274
+
275
+ export default {
276
+ setup() {
277
+ const count = ref(0);
278
+ const doubled = computed(() => count.value * 2);
279
+
280
+ onMounted(() => {
281
+ console.log('mounted');
282
+ });
283
+
284
+ return { count, doubled };
285
+ }
286
+ };
287
+ `;
288
+ const result = analyzeCheese(source);
289
+ assert.strictEqual(result.frameworkInfo.detected, 'vue');
290
+ });
291
+ it('should not apply weight for non-framework code', () => {
292
+ const source = `
293
+ function calculate(a: number, b: number) {
294
+ if (a > 0) {
295
+ for (let i = 0; i < b; i++) {
296
+ console.log(i);
297
+ }
298
+ }
299
+ return a + b;
300
+ }
301
+ `;
302
+ const result = analyzeCheese(source);
303
+ assert.strictEqual(result.frameworkInfo.detected, 'none');
304
+ assert.strictEqual(result.maxNesting, result.adjustedNesting);
305
+ });
306
+ });
307
+ describe('Ham Analyzer', () => {
308
+ it('should detect critical paths', () => {
309
+ const source = `
310
+ function processPayment(amount: number) {
311
+ return charge(amount);
312
+ }
313
+
314
+ async function authenticateUser(token: string) {
315
+ return verify(token);
316
+ }
317
+
318
+ function deleteAccount(userId: string) {
319
+ return remove(userId);
320
+ }
321
+ `;
322
+ const result = analyzeHam(source);
323
+ assert.ok(result.criticalPaths.length >= 2);
324
+ assert.ok(result.criticalPaths.some(cp => cp.category === 'payment'));
325
+ assert.ok(result.criticalPaths.some(cp => cp.category === 'auth'));
326
+ });
327
+ it('should detect test framework', () => {
328
+ const testSource = `
329
+ import { describe, it, expect } from 'vitest';
330
+
331
+ describe('Payment', () => {
332
+ it('should process payment', () => {
333
+ expect(processPayment(100)).toBe(true);
334
+ });
335
+ });
336
+ `;
337
+ const result = analyzeHam('', testSource);
338
+ assert.strictEqual(result.testInfo.framework, 'vitest');
339
+ assert.ok(result.testInfo.testCount > 0);
340
+ });
341
+ it('should calculate coverage', () => {
342
+ const source = `
343
+ function processPayment() {}
344
+ function login() {}
345
+ `;
346
+ const testSource = `
347
+ describe('Payment', () => {
348
+ it('should processPayment', () => {});
349
+ });
350
+ `;
351
+ const result = analyzeHam(source, testSource);
352
+ // processPayment is tested, login is not
353
+ assert.ok(result.goldenTestCoverage >= 0);
354
+ assert.ok(result.goldenTestCoverage <= 1);
355
+ });
356
+ });
357
+ //# sourceMappingURL=analyzers.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyzers.test.js","sourceRoot":"","sources":["../../src/__tests__/analyzers.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Gate Tests
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=gate.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/gate.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Gate Tests
3
+ */
4
+ import { describe, it } from 'node:test';
5
+ import assert from 'node:assert';
6
+ import { checkGate, getThresholds, STAGE_POLICIES } from '../gate/index.js';
7
+ // Helper to create mock CheeseResult
8
+ function mockCheese(overrides = {}) {
9
+ return {
10
+ accessible: true,
11
+ reason: 'All conditions met',
12
+ violations: [],
13
+ maxNesting: 2,
14
+ adjustedNesting: 2,
15
+ functions: [],
16
+ hiddenDependencies: 0,
17
+ stateAsyncRetry: {
18
+ hasState: false,
19
+ hasAsync: false,
20
+ hasRetry: false,
21
+ axes: [],
22
+ count: 0,
23
+ violated: false,
24
+ },
25
+ config: {
26
+ nestingThreshold: 4,
27
+ conceptsPerFunction: 9,
28
+ hiddenDepThreshold: 2,
29
+ },
30
+ typeComplexity: {
31
+ generics: { count: 0, maxParams: 0, maxDepth: 0, constrainedCount: 0, penalty: 0 },
32
+ unions: { count: 0, maxMembers: 0, intersectionCount: 0, penalty: 0 },
33
+ conditionalTypes: 0,
34
+ mappedTypes: 0,
35
+ typeGuards: 0,
36
+ decoratorStacks: 0,
37
+ totalPenalty: 0,
38
+ },
39
+ frameworkInfo: {
40
+ detected: 'none',
41
+ config: {
42
+ name: 'none',
43
+ jsxNestingWeight: 1.0,
44
+ hookConceptWeight: 1.0,
45
+ chainMethodWeight: 1.0,
46
+ propsDestructureWeight: 1.0,
47
+ },
48
+ jsxNestingDepth: 0,
49
+ logicNestingDepth: 0,
50
+ hookCount: 0,
51
+ chainCount: 0,
52
+ adjustments: [],
53
+ },
54
+ ...overrides,
55
+ };
56
+ }
57
+ // Helper to create mock HamResult
58
+ function mockHam(overrides = {}) {
59
+ return {
60
+ goldenTestCoverage: 0.9,
61
+ criticalPaths: [],
62
+ untestedCriticalPaths: [],
63
+ testInfo: {
64
+ framework: 'jest',
65
+ testCount: 10,
66
+ describedFunctions: new Set(),
67
+ },
68
+ ...overrides,
69
+ };
70
+ }
71
+ describe('Gate Thresholds', () => {
72
+ it('should return different thresholds for each gate type', () => {
73
+ const poc = getThresholds('poc');
74
+ const mvp = getThresholds('mvp');
75
+ const production = getThresholds('production');
76
+ // PoC is most lenient
77
+ assert.ok(poc.nesting_max > mvp.nesting_max);
78
+ assert.ok(poc.golden_test_min < mvp.golden_test_min);
79
+ // Production is strictest
80
+ assert.ok(production.nesting_max < mvp.nesting_max);
81
+ assert.ok(production.golden_test_min > mvp.golden_test_min);
82
+ });
83
+ it('should have correct waiver policies', () => {
84
+ assert.strictEqual(STAGE_POLICIES.poc.waiver_allowed, false);
85
+ assert.strictEqual(STAGE_POLICIES.mvp.waiver_allowed, false);
86
+ assert.strictEqual(STAGE_POLICIES.production.waiver_allowed, true);
87
+ });
88
+ });
89
+ describe('Gate Check', () => {
90
+ it('should pass MVP gate for good code', () => {
91
+ const cheese = mockCheese({ maxNesting: 3, hiddenDependencies: 1 });
92
+ const ham = mockHam({ goldenTestCoverage: 0.85 });
93
+ const result = checkGate('mvp', cheese, ham);
94
+ assert.strictEqual(result.passed, true);
95
+ assert.strictEqual(result.violations.length, 0);
96
+ });
97
+ it('should fail MVP gate for deep nesting', () => {
98
+ const cheese = mockCheese({ maxNesting: 6 });
99
+ const ham = mockHam();
100
+ const result = checkGate('mvp', cheese, ham);
101
+ assert.strictEqual(result.passed, false);
102
+ assert.ok(result.violations.some(v => v.rule === 'nesting_max'));
103
+ });
104
+ it('should fail MVP gate for low test coverage', () => {
105
+ const cheese = mockCheese();
106
+ const ham = mockHam({ goldenTestCoverage: 0.5 });
107
+ const result = checkGate('mvp', cheese, ham);
108
+ assert.strictEqual(result.passed, false);
109
+ assert.ok(result.violations.some(v => v.rule === 'golden_test_min'));
110
+ });
111
+ it('should fail for state×async×retry violation', () => {
112
+ const cheese = mockCheese({
113
+ stateAsyncRetry: {
114
+ hasState: true,
115
+ hasAsync: true,
116
+ hasRetry: false,
117
+ axes: ['state', 'async'],
118
+ count: 2,
119
+ violated: true,
120
+ },
121
+ });
122
+ const ham = mockHam();
123
+ const result = checkGate('mvp', cheese, ham);
124
+ assert.strictEqual(result.passed, false);
125
+ assert.ok(result.violations.some(v => v.rule === 'state_async_retry'));
126
+ });
127
+ it('should pass PoC gate with relaxed thresholds', () => {
128
+ const cheese = mockCheese({ maxNesting: 5, hiddenDependencies: 2 });
129
+ const ham = mockHam({ goldenTestCoverage: 0.5 });
130
+ const result = checkGate('poc', cheese, ham);
131
+ assert.strictEqual(result.passed, true);
132
+ });
133
+ it('should be strict for production gate', () => {
134
+ const cheese = mockCheese({ maxNesting: 4 }); // OK for MVP, too high for production
135
+ const ham = mockHam({ goldenTestCoverage: 0.85 }); // OK for MVP, too low for production
136
+ const result = checkGate('production', cheese, ham);
137
+ assert.strictEqual(result.passed, false);
138
+ });
139
+ });
140
+ //# sourceMappingURL=gate.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate.test.js","sourceRoot":"","sources":["../../src/__tests__/gate.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * 🍞 Bread Analyzer - Security & Trust Boundary (TypeScript)
3
+ *
4
+ * 보안 구조 안정성 분석:
5
+ * - Trust boundary 탐지
6
+ * - Auth/Authz 흐름 분석
7
+ * - Secret 패턴 탐지
8
+ * - Hidden dependencies 계산
9
+ *
10
+ * TypeScript 전용 타입 안전성 분석:
11
+ * - any 타입 사용 탐지
12
+ * - Type assertion (as) 남용
13
+ * - @ts-ignore, @ts-expect-error 사용
14
+ * - Non-null assertion (!) 남용
15
+ * - unknown vs any 사용 패턴
16
+ */
17
+ export interface BreadResult {
18
+ trustBoundaryCount: number;
19
+ trustBoundaries: TrustBoundary[];
20
+ authExplicitness: number;
21
+ authPatterns: string[];
22
+ secretPatterns: SecretPattern[];
23
+ hiddenDeps: HiddenDeps;
24
+ violations: string[];
25
+ typeSafety: TypeSafetyResult;
26
+ }
27
+ export interface TypeSafetyResult {
28
+ anyCount: number;
29
+ anyLocations: TypeUnsafeLocation[];
30
+ assertionCount: number;
31
+ assertionLocations: TypeUnsafeLocation[];
32
+ nonNullAssertionCount: number;
33
+ tsIgnoreCount: number;
34
+ tsIgnoreLocations: TypeUnsafeLocation[];
35
+ unknownCount: number;
36
+ safetyScore: number;
37
+ }
38
+ export interface TypeUnsafeLocation {
39
+ line: number;
40
+ column: number;
41
+ code: string;
42
+ reason: string;
43
+ }
44
+ export interface TrustBoundary {
45
+ name: string;
46
+ line: number;
47
+ boundaryType: 'marker' | 'api' | 'auth' | 'network' | 'data';
48
+ description: string;
49
+ }
50
+ export interface SecretPattern {
51
+ line: number;
52
+ patternType: string;
53
+ snippet: string;
54
+ severity: 'high' | 'medium' | 'low';
55
+ }
56
+ export interface HiddenDeps {
57
+ global: number;
58
+ env: number;
59
+ io: number;
60
+ total: number;
61
+ }
62
+ export declare function analyzeBread(source: string, _filePath?: string): BreadResult;
63
+ //# sourceMappingURL=bread.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bread.d.ts","sourceRoot":"","sources":["../../src/analyzers/bread.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAQH,MAAM,WAAW,WAAW;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe,EAAE,aAAa,EAAE,CAAC;IACjC,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,UAAU,EAAE,UAAU,CAAC;IACvB,UAAU,EAAE,MAAM,EAAE,CAAC;IAGrB,UAAU,EAAE,gBAAgB,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,kBAAkB,EAAE,CAAC;IACnC,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,kBAAkB,EAAE,CAAC;IACzC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,kBAAkB,EAAE,CAAC;IACxC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;IAC7D,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;CACrC;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf;AAgJD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,WAAW,CA6B5E"}