@boyingliu01/xp-gate 0.8.9 → 0.8.11
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.
- package/lib/init.js +36 -0
- package/mock-policy/AGENTS.md +94 -0
- package/mock-policy/__tests__/config.test.ts +292 -0
- package/mock-policy/__tests__/integration.test.ts +600 -0
- package/mock-policy/__tests__/mock-decision-engine.test.ts +231 -0
- package/mock-policy/__tests__/scope-scanner.test.ts +535 -0
- package/mock-policy/config.ts +106 -0
- package/mock-policy/gate-m3.ts +233 -0
- package/mock-policy/mock-decision-engine.ts +155 -0
- package/mock-policy/schema.ts +22 -0
- package/mock-policy/scope-scanner.ts +288 -0
- package/mock-policy/types.ts +65 -0
- package/mutation/AGENTS.md +73 -0
- package/mutation/__tests__/detect-ai-test.test.ts +152 -0
- package/mutation/__tests__/gate-m.test.ts +194 -0
- package/mutation/detect-ai-test.ts +128 -0
- package/mutation/gate-m.ts +619 -0
- package/mutation/init-baseline.ts +192 -0
- package/mutation/stryker-types.ts +14 -0
- package/mutation/types.ts +70 -0
- package/mutation/update-baseline.ts +160 -0
- package/package.json +5 -2
- package/plugins/claude-code/.claude-plugin/plugin.json +2 -2
- package/plugins/claude-code/skills/delphi-review/AGENTS.md +7 -7
- package/plugins/claude-code/skills/delphi-review/INSTALL.md +1 -1
- package/plugins/claude-code/skills/delphi-review/SKILL.md +12 -12
- package/plugins/claude-code/skills/delphi-review/references/code-walkthrough.md +1 -1
- package/plugins/claude-code/skills/sprint-flow/AGENTS.md +7 -7
- package/plugins/claude-code/skills/sprint-flow/SKILL.md +1 -1
- package/plugins/claude-code/skills/sprint-flow/references/force-levels.md +1 -1
- package/plugins/claude-code/skills/sprint-flow/references/phase-3-review.md +2 -2
- package/plugins/claude-code/skills/test-specification-alignment/AGENTS.md +3 -3
- package/plugins/opencode/package.json +1 -1
- package/plugins/opencode/skills/delphi-review/AGENTS.md +7 -7
- package/plugins/opencode/skills/delphi-review/INSTALL.md +1 -1
- package/plugins/opencode/skills/delphi-review/SKILL.md +12 -12
- package/plugins/opencode/skills/delphi-review/references/code-walkthrough.md +1 -1
- package/plugins/opencode/skills/sprint-flow/AGENTS.md +7 -7
- package/plugins/opencode/skills/sprint-flow/SKILL.md +1 -1
- package/plugins/opencode/skills/sprint-flow/references/force-levels.md +1 -1
- package/plugins/opencode/skills/sprint-flow/references/phase-3-review.md +2 -2
- package/plugins/opencode/skills/test-specification-alignment/AGENTS.md +3 -3
- package/plugins/qoder/plugin.json +1 -1
- package/plugins/qoder/skills/delphi-review/AGENTS.md +7 -7
- package/plugins/qoder/skills/delphi-review/INSTALL.md +1 -1
- package/plugins/qoder/skills/delphi-review/SKILL.md +12 -12
- package/plugins/qoder/skills/delphi-review/references/code-walkthrough.md +1 -1
- package/plugins/qoder/skills/sprint-flow/AGENTS.md +7 -7
- package/plugins/qoder/skills/sprint-flow/SKILL.md +51 -1
- package/plugins/qoder/skills/sprint-flow/references/force-levels.md +1 -1
- package/plugins/qoder/skills/sprint-flow/references/phase-3-review.md +2 -2
- package/plugins/qoder/skills/test-specification-alignment/AGENTS.md +3 -3
- package/principles/AGENTS.md +111 -0
- package/principles/__tests__/analyzer.test.ts +343 -0
- package/principles/__tests__/baseline-storage.test.ts +187 -0
- package/principles/__tests__/baseline.test.ts +328 -0
- package/principles/__tests__/boy-scout-integration.test.ts +264 -0
- package/principles/__tests__/boy-scout.test.ts +646 -0
- package/principles/__tests__/config.test.ts +78 -0
- package/principles/__tests__/index.test.ts +81 -0
- package/principles/__tests__/lint-baseline.test.ts +314 -0
- package/principles/__tests__/reporter.test.ts +832 -0
- package/principles/__tests__/types.test.ts +101 -0
- package/principles/adapters/__tests__/base.test.ts +95 -0
- package/principles/adapters/__tests__/cpp.test.ts +290 -0
- package/principles/adapters/__tests__/dart.test.ts +84 -0
- package/principles/adapters/__tests__/go.test.ts +68 -0
- package/principles/adapters/__tests__/java.test.ts +68 -0
- package/principles/adapters/__tests__/kotlin.test.ts +76 -0
- package/principles/adapters/__tests__/objectivec.test.ts +453 -0
- package/principles/adapters/__tests__/python.test.ts +84 -0
- package/principles/adapters/__tests__/swift.test.ts +68 -0
- package/principles/adapters/__tests__/typescript.test.ts +116 -0
- package/principles/adapters/base.ts +124 -0
- package/principles/adapters/cpp.ts +115 -0
- package/principles/adapters/dart.ts +44 -0
- package/principles/adapters/go.ts +55 -0
- package/principles/adapters/java.ts +56 -0
- package/principles/adapters/kotlin.ts +54 -0
- package/principles/adapters/objectivec.ts +82 -0
- package/principles/adapters/python.ts +83 -0
- package/principles/adapters/swift.ts +40 -0
- package/principles/adapters/typescript.ts +66 -0
- package/principles/analyzer.ts +190 -0
- package/principles/baseline.ts +273 -0
- package/principles/boy-scout.ts +416 -0
- package/principles/config.ts +118 -0
- package/principles/index.ts +87 -0
- package/principles/lint-baseline.ts +385 -0
- package/principles/reporter.ts +188 -0
- package/principles/rules/__tests__/clean-code/code-duplication.test.ts +84 -0
- package/principles/rules/__tests__/clean-code/deep-nesting.test.ts +74 -0
- package/principles/rules/__tests__/clean-code/god-class.test.ts +111 -0
- package/principles/rules/__tests__/clean-code/large-file.test.ts +73 -0
- package/principles/rules/__tests__/clean-code/long-function.test.ts +83 -0
- package/principles/rules/__tests__/clean-code/magic-numbers.test.ts +68 -0
- package/principles/rules/__tests__/clean-code/many-exports.test.ts +118 -0
- package/principles/rules/__tests__/clean-code/missing-error-handling.test.ts +173 -0
- package/principles/rules/__tests__/clean-code/too-many-params.test.ts +60 -0
- package/principles/rules/__tests__/clean-code/unused-imports.test.ts +107 -0
- package/principles/rules/__tests__/index.test.ts +49 -0
- package/principles/rules/__tests__/solid/dip.test.ts +121 -0
- package/principles/rules/__tests__/solid/isp.test.ts +60 -0
- package/principles/rules/__tests__/solid/lsp.test.ts +184 -0
- package/principles/rules/__tests__/solid/ocp.test.ts +69 -0
- package/principles/rules/__tests__/solid/srp.test.ts +89 -0
- package/principles/rules/clean-code/code-duplication.ts +31 -0
- package/principles/rules/clean-code/deep-nesting.ts +38 -0
- package/principles/rules/clean-code/god-class.ts +54 -0
- package/principles/rules/clean-code/large-file.ts +34 -0
- package/principles/rules/clean-code/long-function.ts +47 -0
- package/principles/rules/clean-code/magic-numbers.ts +59 -0
- package/principles/rules/clean-code/many-exports.ts +40 -0
- package/principles/rules/clean-code/missing-error-handling.ts +33 -0
- package/principles/rules/clean-code/too-many-params.ts +35 -0
- package/principles/rules/clean-code/unused-imports.ts +33 -0
- package/principles/rules/index.ts +61 -0
- package/principles/rules/solid/dip.ts +47 -0
- package/principles/rules/solid/isp.ts +37 -0
- package/principles/rules/solid/lsp.ts +79 -0
- package/principles/rules/solid/ocp.ts +40 -0
- package/principles/rules/solid/srp.ts +44 -0
- package/principles/types.ts +27 -0
- package/skills/delphi-review/AGENTS.md +7 -7
- package/skills/delphi-review/INSTALL.md +1 -1
- package/skills/delphi-review/SKILL.md +12 -12
- package/skills/delphi-review/references/code-walkthrough.md +1 -1
- package/skills/sprint-flow/AGENTS.md +7 -7
- package/skills/sprint-flow/SKILL.md +1 -1
- package/skills/sprint-flow/references/force-levels.md +1 -1
- package/skills/sprint-flow/references/phase-3-review.md +2 -2
- package/skills/test-specification-alignment/AGENTS.md +3 -3
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import MockDecisionEngine from '../mock-decision-engine';
|
|
3
|
+
import type { ProjectScope, MockPolicyConfig, TestLayer } from '../types';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @test MockDecisionEngine decision logic
|
|
7
|
+
* @intent Verify all decision paths for unit, integration, and e2e layers
|
|
8
|
+
* @covers MockDecisionEngine.decide
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const baseScope: ProjectScope = {
|
|
12
|
+
implementedModules: ['src/utils/helper', 'src/core/service'],
|
|
13
|
+
unimplementedModules: ['src/feature/pending-module'],
|
|
14
|
+
externalPackages: ['lodash', 'express', 'axios'],
|
|
15
|
+
projectBoundary: ['src/**'],
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const defaultConfig: MockPolicyConfig = {
|
|
19
|
+
version: 1,
|
|
20
|
+
layers: {
|
|
21
|
+
unit: {
|
|
22
|
+
mockPolicy: 'lenient',
|
|
23
|
+
requireRealForImplemented: false,
|
|
24
|
+
allowExternalMock: true,
|
|
25
|
+
requirePendingRemoval: false,
|
|
26
|
+
maxMockDensity: 100,
|
|
27
|
+
},
|
|
28
|
+
integration: {
|
|
29
|
+
mockPolicy: 'strict',
|
|
30
|
+
requireRealForImplemented: true,
|
|
31
|
+
allowExternalMock: true,
|
|
32
|
+
requirePendingRemoval: true,
|
|
33
|
+
maxMockDensity: 30,
|
|
34
|
+
},
|
|
35
|
+
e2e: {
|
|
36
|
+
mockPolicy: 'strict',
|
|
37
|
+
requireRealForImplemented: true,
|
|
38
|
+
allowExternalMock: false,
|
|
39
|
+
requirePendingRemoval: false,
|
|
40
|
+
maxMockDensity: 0,
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
projectBoundary: ['src/**'],
|
|
44
|
+
severity: 'warning',
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
describe('MockDecisionEngine', () => {
|
|
48
|
+
describe('e2e layer — always return real', () => {
|
|
49
|
+
it('returns real for any import in e2e', () => {
|
|
50
|
+
const engine = new MockDecisionEngine(baseScope, defaultConfig);
|
|
51
|
+
const decision = engine.decide('lodash', 'e2e');
|
|
52
|
+
expect(decision.strategy).toBe('real');
|
|
53
|
+
expect(decision.layer).toBe('e2e');
|
|
54
|
+
expect(decision.reason).toContain('E2E tests must use real dependencies');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('returns real for internal imports in e2e', () => {
|
|
58
|
+
const engine = new MockDecisionEngine(baseScope, defaultConfig);
|
|
59
|
+
const decision = engine.decide('src/core/service', 'e2e');
|
|
60
|
+
expect(decision.strategy).toBe('real');
|
|
61
|
+
expect(decision.reason).toContain('E2E');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('returns real for pending imports in e2e', () => {
|
|
65
|
+
const engine = new MockDecisionEngine(baseScope, defaultConfig);
|
|
66
|
+
const decision = engine.decide('src/feature/pending-module', 'e2e');
|
|
67
|
+
expect(decision.strategy).toBe('real');
|
|
68
|
+
expect(decision.reason).toContain('E2E');
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
describe('unit layer with lenient policy — always mock', () => {
|
|
73
|
+
it('returns mock for external dependencies', () => {
|
|
74
|
+
const engine = new MockDecisionEngine(baseScope, defaultConfig);
|
|
75
|
+
const decision = engine.decide('lodash', 'unit');
|
|
76
|
+
expect(decision.strategy).toBe('mock');
|
|
77
|
+
expect(decision.layer).toBe('unit');
|
|
78
|
+
expect(decision.reason).toContain('lenient policy');
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('returns mock for internal dependencies', () => {
|
|
82
|
+
const engine = new MockDecisionEngine(baseScope, defaultConfig);
|
|
83
|
+
const decision = engine.decide('src/utils/helper', 'unit');
|
|
84
|
+
expect(decision.strategy).toBe('mock');
|
|
85
|
+
expect(decision.reason).toContain('lenient policy');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('returns mock for pending dependencies', () => {
|
|
89
|
+
const engine = new MockDecisionEngine(baseScope, defaultConfig);
|
|
90
|
+
const decision = engine.decide('src/feature/pending-module', 'unit');
|
|
91
|
+
expect(decision.strategy).toBe('mock');
|
|
92
|
+
expect(decision.reason).toContain('lenient policy');
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
describe('unit layer with strict policy — applies integration rules', () => {
|
|
97
|
+
const strictUnitConfig: MockPolicyConfig = {
|
|
98
|
+
...defaultConfig,
|
|
99
|
+
layers: {
|
|
100
|
+
...defaultConfig.layers,
|
|
101
|
+
unit: {
|
|
102
|
+
mockPolicy: 'strict',
|
|
103
|
+
requireRealForImplemented: true,
|
|
104
|
+
allowExternalMock: true,
|
|
105
|
+
requirePendingRemoval: true,
|
|
106
|
+
maxMockDensity: 50,
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
it('returns real for internal+implemented when requireRealForImplemented is true', () => {
|
|
112
|
+
const engine = new MockDecisionEngine(baseScope, strictUnitConfig);
|
|
113
|
+
const decision = engine.decide('src/utils/helper', 'unit');
|
|
114
|
+
expect(decision.strategy).toBe('real');
|
|
115
|
+
expect(decision.reason).toContain('real implementation');
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('returns mock for internal unimplemented when not matched as implemented', () => {
|
|
119
|
+
const engine = new MockDecisionEngine(baseScope, strictUnitConfig);
|
|
120
|
+
const decision = engine.decide('src/utils/unknown-module', 'unit');
|
|
121
|
+
// Falls through to default: unknown scope → mock for safety
|
|
122
|
+
expect(decision.strategy).toBe('mock');
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
describe('integration layer', () => {
|
|
127
|
+
it('returns real for internal+implemented when requireRealForImplemented is true', () => {
|
|
128
|
+
const engine = new MockDecisionEngine(baseScope, defaultConfig);
|
|
129
|
+
const decision = engine.decide('src/utils/helper', 'integration');
|
|
130
|
+
expect(decision.strategy).toBe('real');
|
|
131
|
+
expect(decision.layer).toBe('integration');
|
|
132
|
+
expect(decision.reason).toContain('real implementation');
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('returns real for internal+implemented (src/core/service)', () => {
|
|
136
|
+
const engine = new MockDecisionEngine(baseScope, defaultConfig);
|
|
137
|
+
const decision = engine.decide('src/core/service', 'integration');
|
|
138
|
+
expect(decision.strategy).toBe('real');
|
|
139
|
+
expect(decision.reason).toContain('real implementation');
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('returns mock for external dependencies when allowExternalMock is true', () => {
|
|
143
|
+
const engine = new MockDecisionEngine(baseScope, defaultConfig);
|
|
144
|
+
const decision = engine.decide('lodash', 'integration');
|
|
145
|
+
expect(decision.strategy).toBe('mock');
|
|
146
|
+
expect(decision.reason).toContain('External dependency');
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('returns mock for axios (external)', () => {
|
|
150
|
+
const engine = new MockDecisionEngine(baseScope, defaultConfig);
|
|
151
|
+
const decision = engine.decide('axios', 'integration');
|
|
152
|
+
expect(decision.strategy).toBe('mock');
|
|
153
|
+
expect(decision.reason).toContain('External dependency');
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('returns mock for express (external)', () => {
|
|
157
|
+
const engine = new MockDecisionEngine(baseScope, defaultConfig);
|
|
158
|
+
const decision = engine.decide('express', 'integration');
|
|
159
|
+
expect(decision.strategy).toBe('mock');
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('returns mock with pendingRemoval for pending dependencies when requirePendingRemoval is true', () => {
|
|
163
|
+
const engine = new MockDecisionEngine(baseScope, defaultConfig);
|
|
164
|
+
const decision = engine.decide('src/feature/pending-module', 'integration');
|
|
165
|
+
expect(decision.strategy).toBe('mock');
|
|
166
|
+
expect(decision.pendingRemoval).toBeDefined();
|
|
167
|
+
expect(decision.pendingRemoval!.ticket).toBe('src/feature/pending-module');
|
|
168
|
+
expect(decision.pendingRemoval!.reason).toContain('not yet implemented');
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('returns real for external when allowExternalMock is disabled', () => {
|
|
172
|
+
const noExternalMockConfig: MockPolicyConfig = {
|
|
173
|
+
...defaultConfig,
|
|
174
|
+
layers: {
|
|
175
|
+
...defaultConfig.layers,
|
|
176
|
+
integration: {
|
|
177
|
+
...defaultConfig.layers.integration,
|
|
178
|
+
allowExternalMock: false,
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
const engine = new MockDecisionEngine(baseScope, noExternalMockConfig);
|
|
183
|
+
const decision = engine.decide('lodash', 'integration');
|
|
184
|
+
expect(decision.strategy).toBe('real');
|
|
185
|
+
expect(decision.reason).toContain('allowExternalMock is disabled');
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it('returns mock for unknown dependencies (falls to external)', () => {
|
|
189
|
+
const engine = new MockDecisionEngine(baseScope, defaultConfig);
|
|
190
|
+
const decision = engine.decide('some-unknown-package', 'integration');
|
|
191
|
+
expect(decision.strategy).toBe('mock');
|
|
192
|
+
expect(decision.reason).toContain('External dependency');
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
describe('unknown layer — falls back to unit behavior', () => {
|
|
197
|
+
it('treats unknown layer like unit — applies lenient mock for all deps', () => {
|
|
198
|
+
const engine = new MockDecisionEngine(baseScope, defaultConfig);
|
|
199
|
+
const decision = engine.decide('lodash', 'unknown' as TestLayer);
|
|
200
|
+
expect(decision.strategy).toBe('mock');
|
|
201
|
+
// Falls back to unit layer rules (lenient → all mocked per policy)
|
|
202
|
+
expect(decision.reason).toContain('should be mocked');
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
describe('edge cases', () => {
|
|
207
|
+
it('handles empty implementedModules gracefully', () => {
|
|
208
|
+
const emptyImplementedScope: ProjectScope = {
|
|
209
|
+
...baseScope,
|
|
210
|
+
implementedModules: [],
|
|
211
|
+
};
|
|
212
|
+
const engine = new MockDecisionEngine(emptyImplementedScope, defaultConfig);
|
|
213
|
+
const decision = engine.decide('src/utils/helper', 'integration');
|
|
214
|
+
// Not matched as implemented, external, or pending → falls to unknown → mock
|
|
215
|
+
expect(decision.strategy).toBe('mock');
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it('handles empty externalPackages gracefully', () => {
|
|
219
|
+
const noExternalScope: ProjectScope = {
|
|
220
|
+
...baseScope,
|
|
221
|
+
externalPackages: [],
|
|
222
|
+
};
|
|
223
|
+
const engine = new MockDecisionEngine(noExternalScope, defaultConfig);
|
|
224
|
+
const decision = engine.decide('lodash', 'integration');
|
|
225
|
+
// lodash is a bare import, classifyDependency routes to external via
|
|
226
|
+
// isExternalImport (not matched in externalPackages list), allowExternalMock=true → mock
|
|
227
|
+
expect(decision.strategy).toBe('mock');
|
|
228
|
+
expect(decision.reason).toContain('External dependency');
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
});
|