claude-flow-novice 2.15.6 → 2.15.8
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/.claude/cfn-extras/agents/google-sheets/google-sheets-coordinator.md +1 -1
- package/.claude/cfn-extras/docs/GOOGLE_SHEETS_CFN_LOOP.md +13 -11
- package/.claude/skills/cfn-loop-orchestration/helpers/gate-check.sh +39 -577
- package/.claude/skills/cfn-loop-orchestration/helpers/parse-test-results.sh +49 -270
- package/.claude/skills/cfn-loop-orchestration/src/helpers/consensus.ts +87 -0
- package/.claude/skills/cfn-loop-orchestration/src/helpers/deliverable-verifier.ts +103 -0
- package/.claude/skills/cfn-loop-orchestration/src/helpers/gate-check.ts +115 -0
- package/.claude/skills/cfn-loop-orchestration/src/helpers/iteration-manager.ts +45 -0
- package/.claude/skills/cfn-loop-orchestration/src/helpers/parse-test-results.ts +372 -0
- package/.claude/skills/cfn-loop-orchestration/src/helpers/timeout-calculator.ts +41 -0
- package/.claude/skills/cfn-loop-orchestration/tests/consensus.test.ts +142 -0
- package/.claude/skills/cfn-loop-orchestration/tests/deliverable-verifier.test.ts +197 -0
- package/.claude/skills/cfn-loop-orchestration/tests/gate-check.test.ts +325 -0
- package/.claude/skills/cfn-loop-orchestration/tests/iteration-manager.test.ts +132 -0
- package/.claude/skills/cfn-loop-orchestration/tests/parse-test-results.test.ts +382 -0
- package/.claude/skills/cfn-loop-orchestration/tests/timeout-calculator.test.ts +118 -0
- package/.claude/skills/cfn-redis-coordination/coverage/clover.xml +1447 -0
- package/.claude/skills/cfn-redis-coordination/coverage/coverage-final.json +13 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/agent-logger.ts.html +1423 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/agent-recovery.ts.html +1447 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/base.css +224 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/block-navigation.js +87 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/completion-reporter.ts.html +1273 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/context-manager.ts.html +1066 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/favicon.png +0 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/index.html +281 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/mode-detector.ts.html +550 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/prettify.css +1 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/prettify.js +2 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/redis-client.ts.html +2047 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/result-collector.ts.html +1396 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/sorter.js +210 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/swarm-manager.ts.html +1567 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/task-analyzer.ts.html +1297 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/task-executor.ts.html +1354 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/types.ts.html +790 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov-report/waiting-coordinator.ts.html +1846 -0
- package/.claude/skills/cfn-redis-coordination/coverage/lcov.info +2650 -0
- package/.claude/skills/cfn-redis-coordination/dist/task-analyzer.js +1 -1
- package/.claude/skills/cfn-redis-coordination/src/task-analyzer.ts +1 -1
- package/.claude/skills/cfn-redis-coordination/tests/coordination.test.ts +18 -9
- package/claude-assets/agents/cfn-dev-team/coordinators/cfn-frontend-coordinator.md +13 -72
- package/claude-assets/agents/cfn-dev-team/coordinators/cfn-v3-coordinator.md +5 -65
- package/claude-assets/agents/cfn-dev-team/coordinators/consensus-builder.md +465 -508
- package/claude-assets/agents/cfn-dev-team/coordinators/handoff-coordinator.md +733 -743
- package/claude-assets/agents/cfn-dev-team/coordinators/multi-sprint-coordinator.md +13 -79
- package/claude-assets/agents/cfn-dev-team/dev-ops/docker-specialist.md +13 -18
- package/claude-assets/agents/cfn-dev-team/dev-ops/kubernetes-specialist.md +13 -18
- package/claude-assets/agents/cfn-dev-team/developers/api-gateway-specialist.md +13 -18
- package/claude-assets/agents/cfn-dev-team/developers/backend-developer.md +15 -17
- package/claude-assets/agents/cfn-dev-team/developers/data/data-engineer.md +15 -17
- package/claude-assets/agents/cfn-dev-team/developers/database/database-architect.md +15 -14
- package/claude-assets/agents/cfn-dev-team/developers/frontend/mobile-dev.md +15 -17
- package/claude-assets/agents/cfn-dev-team/developers/frontend/react-frontend-engineer.md +15 -17
- package/claude-assets/agents/cfn-dev-team/developers/frontend/typescript-specialist.md +15 -17
- package/claude-assets/agents/cfn-dev-team/developers/frontend/ui-designer.md +23 -30
- package/claude-assets/agents/cfn-dev-team/developers/graphql-specialist.md +13 -18
- package/claude-assets/agents/cfn-dev-team/developers/rust-developer.md +13 -18
- package/claude-assets/agents/cfn-dev-team/reviewers/code-reviewer.md +312 -317
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/code-quality-validator.md +23 -20
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/perf-analyzer.md +23 -20
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/performance-benchmarker.md +23 -20
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/security-specialist.md +23 -20
- package/claude-assets/agents/cfn-dev-team/testers/api-testing-specialist.md +15 -20
- package/claude-assets/agents/cfn-dev-team/testers/chaos-engineering-specialist.md +15 -20
- package/claude-assets/agents/cfn-dev-team/testers/contract-tester.md +718 -737
- package/claude-assets/agents/cfn-dev-team/testers/integration-tester.md +817 -828
- package/claude-assets/agents/cfn-dev-team/testers/interaction-tester.md +15 -20
- package/claude-assets/agents/cfn-dev-team/testers/load-testing-specialist.md +8 -9
- package/claude-assets/agents/cfn-dev-team/testers/mutation-testing-specialist.md +668 -684
- package/claude-assets/agents/cfn-dev-team/testers/playwright-tester.md +15 -20
- package/claude-assets/agents/cfn-dev-team/testers/tester.md +248 -253
- package/claude-assets/agents/cfn-dev-team/utility/epic-creator.md +13 -18
- package/claude-assets/agents/cfn-dev-team/utility/memory-leak-specialist.md +13 -18
- package/claude-assets/agents/cfn-dev-team/utility/z-ai-specialist.md +13 -18
- package/claude-assets/cfn-extras/agents/google-sheets/google-sheets-coordinator.md +1 -1
- package/claude-assets/cfn-extras/docs/GOOGLE_SHEETS_CFN_LOOP.md +13 -11
- package/claude-assets/skills/cfn-loop-orchestration/helpers/gate-check.sh +39 -577
- package/claude-assets/skills/cfn-loop-orchestration/helpers/parse-test-results.sh +49 -270
- package/claude-assets/skills/cfn-loop-orchestration/src/helpers/consensus.ts +87 -0
- package/claude-assets/skills/cfn-loop-orchestration/src/helpers/deliverable-verifier.ts +103 -0
- package/claude-assets/skills/cfn-loop-orchestration/src/helpers/gate-check.ts +115 -0
- package/claude-assets/skills/cfn-loop-orchestration/src/helpers/iteration-manager.ts +45 -0
- package/claude-assets/skills/cfn-loop-orchestration/src/helpers/parse-test-results.ts +372 -0
- package/claude-assets/skills/cfn-loop-orchestration/src/helpers/timeout-calculator.ts +41 -0
- package/claude-assets/skills/cfn-loop-orchestration/tests/consensus.test.ts +142 -0
- package/claude-assets/skills/cfn-loop-orchestration/tests/deliverable-verifier.test.ts +197 -0
- package/claude-assets/skills/cfn-loop-orchestration/tests/gate-check.test.ts +325 -0
- package/claude-assets/skills/cfn-loop-orchestration/tests/iteration-manager.test.ts +132 -0
- package/claude-assets/skills/cfn-loop-orchestration/tests/parse-test-results.test.ts +382 -0
- package/claude-assets/skills/cfn-loop-orchestration/tests/timeout-calculator.test.ts +118 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/clover.xml +1447 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/coverage-final.json +13 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/agent-logger.ts.html +1423 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/agent-recovery.ts.html +1447 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/base.css +224 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/block-navigation.js +87 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/completion-reporter.ts.html +1273 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/context-manager.ts.html +1066 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/favicon.png +0 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/index.html +281 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/mode-detector.ts.html +550 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/prettify.css +1 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/prettify.js +2 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/redis-client.ts.html +2047 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/result-collector.ts.html +1396 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/sorter.js +210 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/swarm-manager.ts.html +1567 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/task-analyzer.ts.html +1297 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/task-executor.ts.html +1354 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/types.ts.html +790 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov-report/waiting-coordinator.ts.html +1846 -0
- package/claude-assets/skills/cfn-redis-coordination/coverage/lcov.info +2650 -0
- package/claude-assets/skills/cfn-redis-coordination/dist/task-analyzer.js +1 -1
- package/claude-assets/skills/cfn-redis-coordination/src/task-analyzer.ts +1 -1
- package/claude-assets/skills/cfn-redis-coordination/tests/coordination.test.ts +18 -9
- package/dist/agents/agent-loader.js +165 -146
- package/dist/agents/agent-loader.js.map +1 -1
- package/package.json +1 -1
- package/scripts/clean-agent-profiles.sh +112 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deliverable Verifier Tests
|
|
3
|
+
* Tests for verifying expected deliverables exist (prevents "consensus on vapor")
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { verifyDeliverables } from '../src/helpers/deliverable-verifier';
|
|
7
|
+
|
|
8
|
+
describe('deliverable-verifier', () => {
|
|
9
|
+
describe('file existence verification', () => {
|
|
10
|
+
it('should verify existing files', () => {
|
|
11
|
+
const result = verifyDeliverables({
|
|
12
|
+
files: ['package.json', 'tsconfig.json']
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
expect(result.verified).toBe(true);
|
|
16
|
+
expect(result.missing).toEqual([]);
|
|
17
|
+
expect(result.found).toContain('package.json');
|
|
18
|
+
expect(result.found).toContain('tsconfig.json');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should detect missing files', () => {
|
|
22
|
+
const result = verifyDeliverables({
|
|
23
|
+
files: ['nonexistent-file-12345.txt']
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
expect(result.verified).toBe(false);
|
|
27
|
+
expect(result.missing).toContain('nonexistent-file-12345.txt');
|
|
28
|
+
expect(result.found).toEqual([]);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('should detect partial missing files', () => {
|
|
32
|
+
const result = verifyDeliverables({
|
|
33
|
+
files: ['package.json', 'nonexistent.txt', 'tsconfig.json']
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
expect(result.verified).toBe(false);
|
|
37
|
+
expect(result.missing).toEqual(['nonexistent.txt']);
|
|
38
|
+
expect(result.found).toContain('package.json');
|
|
39
|
+
expect(result.found).toContain('tsconfig.json');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should handle empty file list', () => {
|
|
43
|
+
const result = verifyDeliverables({
|
|
44
|
+
files: []
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
expect(result.verified).toBe(true);
|
|
48
|
+
expect(result.missing).toEqual([]);
|
|
49
|
+
expect(result.found).toEqual([]);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
describe('file type validation', () => {
|
|
54
|
+
it('should verify TypeScript files', () => {
|
|
55
|
+
const result = verifyDeliverables({
|
|
56
|
+
files: ['src/helpers/gate-check.ts'],
|
|
57
|
+
expectedTypes: ['.ts']
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
expect(result.verified).toBe(true);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('should verify shell script files', () => {
|
|
64
|
+
const result = verifyDeliverables({
|
|
65
|
+
files: ['helpers/consensus.sh'],
|
|
66
|
+
expectedTypes: ['.sh']
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
expect(result.verified).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('should reject wrong file types', () => {
|
|
73
|
+
const result = verifyDeliverables({
|
|
74
|
+
files: ['package.json'],
|
|
75
|
+
expectedTypes: ['.ts']
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
expect(result.verified).toBe(false);
|
|
79
|
+
expect(result.typeErrors).toContain('package.json');
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('should allow multiple file types', () => {
|
|
83
|
+
const result = verifyDeliverables({
|
|
84
|
+
files: ['package.json', 'tsconfig.json'],
|
|
85
|
+
expectedTypes: ['.json', '.ts']
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
expect(result.verified).toBe(true);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe('git change detection', () => {
|
|
93
|
+
it('should detect when files are created', () => {
|
|
94
|
+
const result = verifyDeliverables({
|
|
95
|
+
files: [],
|
|
96
|
+
requireGitChanges: true
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// This test depends on actual git state, so we check structure
|
|
100
|
+
expect(result).toHaveProperty('gitChanges');
|
|
101
|
+
expect(typeof result.gitChanges).toBe('number');
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('should fail when no changes and changes required', () => {
|
|
105
|
+
// Mock scenario: implementation task with no files
|
|
106
|
+
const result = verifyDeliverables({
|
|
107
|
+
files: [],
|
|
108
|
+
requireGitChanges: true,
|
|
109
|
+
taskType: 'implementation'
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// If no files specified and git has no changes, should fail for implementation
|
|
113
|
+
if (result.gitChanges === 0) {
|
|
114
|
+
expect(result.verified).toBe(false);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
describe('task type keyword detection', () => {
|
|
120
|
+
it('should detect implementation keywords', () => {
|
|
121
|
+
const keywords = ['create', 'build', 'implement', 'add', 'generate'];
|
|
122
|
+
|
|
123
|
+
keywords.forEach(keyword => {
|
|
124
|
+
const result = verifyDeliverables({
|
|
125
|
+
files: [],
|
|
126
|
+
taskType: keyword,
|
|
127
|
+
requireGitChanges: true
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// Should require git changes for implementation keywords
|
|
131
|
+
expect(result).toHaveProperty('requiresChanges');
|
|
132
|
+
if (result.requiresChanges) {
|
|
133
|
+
expect(result.gitChanges).toBeGreaterThan(-1); // Check git changes were counted
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('should not require changes for read-only tasks', () => {
|
|
139
|
+
const result = verifyDeliverables({
|
|
140
|
+
files: [],
|
|
141
|
+
taskType: 'analyze',
|
|
142
|
+
requireGitChanges: false
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
expect(result.verified).toBe(true);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
describe('consensus on vapor prevention', () => {
|
|
150
|
+
it('should fail if implementation task has no deliverables', () => {
|
|
151
|
+
const result = verifyDeliverables({
|
|
152
|
+
files: [],
|
|
153
|
+
taskType: 'implement authentication',
|
|
154
|
+
requireGitChanges: true
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// If git has changes, this should pass; otherwise fail
|
|
158
|
+
if (result.gitChanges === 0) {
|
|
159
|
+
expect(result.verified).toBe(false);
|
|
160
|
+
expect(result.reason).toContain('vapor');
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('should pass if implementation task has deliverables', () => {
|
|
165
|
+
const result = verifyDeliverables({
|
|
166
|
+
files: ['package.json'], // Existing file as proxy
|
|
167
|
+
taskType: 'implement feature'
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
expect(result.verified).toBe(true);
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
describe('verification reporting', () => {
|
|
175
|
+
it('should provide detailed results', () => {
|
|
176
|
+
const result = verifyDeliverables({
|
|
177
|
+
files: ['package.json', 'missing.txt']
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
expect(result).toHaveProperty('verified');
|
|
181
|
+
expect(result).toHaveProperty('files');
|
|
182
|
+
expect(result).toHaveProperty('missing');
|
|
183
|
+
expect(result).toHaveProperty('found');
|
|
184
|
+
expect(result.files).toEqual(['package.json', 'missing.txt']);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('should track all requested files', () => {
|
|
188
|
+
const requestedFiles = ['file1.ts', 'file2.ts', 'file3.ts'];
|
|
189
|
+
const result = verifyDeliverables({
|
|
190
|
+
files: requestedFiles
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
expect(result.files).toEqual(requestedFiles);
|
|
194
|
+
expect(result.found.length + result.missing.length).toBe(requestedFiles.length);
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
});
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import { gateCheck, GateCheckResult, Mode } from '../src/helpers/gate-check';
|
|
2
|
+
|
|
3
|
+
describe('gateCheck', () => {
|
|
4
|
+
describe('Basic gate logic', () => {
|
|
5
|
+
it('should pass gate when pass rate >= threshold', () => {
|
|
6
|
+
const result = gateCheck({
|
|
7
|
+
passRate: 0.96,
|
|
8
|
+
threshold: 0.95,
|
|
9
|
+
mode: 'standard',
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
expect(result.passed).toBe(true);
|
|
13
|
+
expect(result.passRate).toBe(0.96);
|
|
14
|
+
expect(result.threshold).toBe(0.95);
|
|
15
|
+
expect(result.mode).toBe('standard');
|
|
16
|
+
expect(result.reason).toContain('0.96');
|
|
17
|
+
expect(result.reason).toContain('0.95');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should fail gate when pass rate < threshold', () => {
|
|
21
|
+
const result = gateCheck({
|
|
22
|
+
passRate: 0.85,
|
|
23
|
+
threshold: 0.95,
|
|
24
|
+
mode: 'standard',
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
expect(result.passed).toBe(false);
|
|
28
|
+
expect(result.passRate).toBe(0.85);
|
|
29
|
+
expect(result.threshold).toBe(0.95);
|
|
30
|
+
expect(result.gap).toBeCloseTo(0.10, 2);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should pass gate when pass rate equals threshold', () => {
|
|
34
|
+
const result = gateCheck({
|
|
35
|
+
passRate: 0.95,
|
|
36
|
+
threshold: 0.95,
|
|
37
|
+
mode: 'standard',
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
expect(result.passed).toBe(true);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should handle perfect pass rate', () => {
|
|
44
|
+
const result = gateCheck({
|
|
45
|
+
passRate: 1.0,
|
|
46
|
+
threshold: 0.95,
|
|
47
|
+
mode: 'standard',
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
expect(result.passed).toBe(true);
|
|
51
|
+
expect(result.gap).toBeCloseTo(-0.05, 2);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('should handle zero pass rate', () => {
|
|
55
|
+
const result = gateCheck({
|
|
56
|
+
passRate: 0.0,
|
|
57
|
+
threshold: 0.95,
|
|
58
|
+
mode: 'standard',
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
expect(result.passed).toBe(false);
|
|
62
|
+
expect(result.gap).toBeCloseTo(0.95, 2);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe('Mode-specific thresholds', () => {
|
|
67
|
+
it('should use MVP threshold (0.70)', () => {
|
|
68
|
+
const result = gateCheck({
|
|
69
|
+
passRate: 0.75,
|
|
70
|
+
mode: 'mvp',
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
expect(result.threshold).toBe(0.70);
|
|
74
|
+
expect(result.passed).toBe(true);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('should use Standard threshold (0.95)', () => {
|
|
78
|
+
const result = gateCheck({
|
|
79
|
+
passRate: 0.96,
|
|
80
|
+
mode: 'standard',
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
expect(result.threshold).toBe(0.95);
|
|
84
|
+
expect(result.passed).toBe(true);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('should use Enterprise threshold (0.98)', () => {
|
|
88
|
+
const result = gateCheck({
|
|
89
|
+
passRate: 0.99,
|
|
90
|
+
mode: 'enterprise',
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
expect(result.threshold).toBe(0.98);
|
|
94
|
+
expect(result.passed).toBe(true);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should fail MVP mode when below 0.70', () => {
|
|
98
|
+
const result = gateCheck({
|
|
99
|
+
passRate: 0.65,
|
|
100
|
+
mode: 'mvp',
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
expect(result.passed).toBe(false);
|
|
104
|
+
expect(result.threshold).toBe(0.70);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('should fail Standard mode when below 0.95', () => {
|
|
108
|
+
const result = gateCheck({
|
|
109
|
+
passRate: 0.90,
|
|
110
|
+
mode: 'standard',
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
expect(result.passed).toBe(false);
|
|
114
|
+
expect(result.threshold).toBe(0.95);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('should fail Enterprise mode when below 0.98', () => {
|
|
118
|
+
const result = gateCheck({
|
|
119
|
+
passRate: 0.97,
|
|
120
|
+
mode: 'enterprise',
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
expect(result.passed).toBe(false);
|
|
124
|
+
expect(result.threshold).toBe(0.98);
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
describe('Custom threshold override', () => {
|
|
129
|
+
it('should use custom threshold when provided', () => {
|
|
130
|
+
const result = gateCheck({
|
|
131
|
+
passRate: 0.88,
|
|
132
|
+
threshold: 0.85,
|
|
133
|
+
mode: 'standard',
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
expect(result.threshold).toBe(0.85);
|
|
137
|
+
expect(result.passed).toBe(true);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('should override mode threshold with custom value', () => {
|
|
141
|
+
const result = gateCheck({
|
|
142
|
+
passRate: 0.92,
|
|
143
|
+
threshold: 0.90,
|
|
144
|
+
mode: 'enterprise', // Would be 0.98 without override
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
expect(result.threshold).toBe(0.90);
|
|
148
|
+
expect(result.passed).toBe(true);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
describe('Gap calculation', () => {
|
|
153
|
+
it('should calculate gap correctly when failing', () => {
|
|
154
|
+
const result = gateCheck({
|
|
155
|
+
passRate: 0.80,
|
|
156
|
+
threshold: 0.95,
|
|
157
|
+
mode: 'standard',
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
expect(result.gap).toBeCloseTo(0.15, 2);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('should have zero gap when passing exactly at threshold', () => {
|
|
164
|
+
const result = gateCheck({
|
|
165
|
+
passRate: 0.95,
|
|
166
|
+
threshold: 0.95,
|
|
167
|
+
mode: 'standard',
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
expect(result.gap).toBeCloseTo(0.0, 2);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('should have negative gap when exceeding threshold', () => {
|
|
174
|
+
const result = gateCheck({
|
|
175
|
+
passRate: 1.0,
|
|
176
|
+
threshold: 0.95,
|
|
177
|
+
mode: 'standard',
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
expect(result.gap).toBeCloseTo(-0.05, 2);
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
describe('Reason generation', () => {
|
|
185
|
+
it('should provide clear reason for passing', () => {
|
|
186
|
+
const result = gateCheck({
|
|
187
|
+
passRate: 0.98,
|
|
188
|
+
threshold: 0.95,
|
|
189
|
+
mode: 'standard',
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
expect(result.reason).toMatch(/pass/i);
|
|
193
|
+
expect(result.reason).toContain('0.98');
|
|
194
|
+
expect(result.reason).toContain('0.95');
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it('should provide clear reason for failing', () => {
|
|
198
|
+
const result = gateCheck({
|
|
199
|
+
passRate: 0.85,
|
|
200
|
+
threshold: 0.95,
|
|
201
|
+
mode: 'standard',
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
expect(result.reason).toMatch(/fail/i);
|
|
205
|
+
expect(result.reason).toContain('0.85');
|
|
206
|
+
expect(result.reason).toContain('0.95');
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it('should include mode in reason', () => {
|
|
210
|
+
const result = gateCheck({
|
|
211
|
+
passRate: 0.96,
|
|
212
|
+
mode: 'standard',
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
expect(result.reason).toMatch(/standard/i);
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
describe('Edge cases', () => {
|
|
220
|
+
it('should handle very small differences', () => {
|
|
221
|
+
const result = gateCheck({
|
|
222
|
+
passRate: 0.9501,
|
|
223
|
+
threshold: 0.95,
|
|
224
|
+
mode: 'standard',
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
expect(result.passed).toBe(true);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it('should handle floating point precision', () => {
|
|
231
|
+
const result = gateCheck({
|
|
232
|
+
passRate: 0.9499999,
|
|
233
|
+
threshold: 0.95,
|
|
234
|
+
mode: 'standard',
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
expect(result.passed).toBe(false);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('should handle threshold at boundaries', () => {
|
|
241
|
+
const result1 = gateCheck({
|
|
242
|
+
passRate: 1.0,
|
|
243
|
+
threshold: 1.0,
|
|
244
|
+
mode: 'standard',
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
const result2 = gateCheck({
|
|
248
|
+
passRate: 0.0,
|
|
249
|
+
threshold: 0.0,
|
|
250
|
+
mode: 'standard',
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
expect(result1.passed).toBe(true);
|
|
254
|
+
expect(result2.passed).toBe(true);
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
describe('Type safety', () => {
|
|
259
|
+
it('should enforce Mode type', () => {
|
|
260
|
+
const modes: Mode[] = ['mvp', 'standard', 'enterprise'];
|
|
261
|
+
|
|
262
|
+
modes.forEach((mode) => {
|
|
263
|
+
const result = gateCheck({
|
|
264
|
+
passRate: 1.0,
|
|
265
|
+
mode,
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
expect(result.mode).toBe(mode);
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it('should return properly typed GateCheckResult', () => {
|
|
273
|
+
const result: GateCheckResult = gateCheck({
|
|
274
|
+
passRate: 0.96,
|
|
275
|
+
mode: 'standard',
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
// Type assertions
|
|
279
|
+
expect(typeof result.passed).toBe('boolean');
|
|
280
|
+
expect(typeof result.passRate).toBe('number');
|
|
281
|
+
expect(typeof result.threshold).toBe('number');
|
|
282
|
+
expect(typeof result.mode).toBe('string');
|
|
283
|
+
expect(typeof result.reason).toBe('string');
|
|
284
|
+
expect(typeof result.gap).toBe('number');
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
describe('Default mode', () => {
|
|
289
|
+
it('should default to standard mode when mode not specified', () => {
|
|
290
|
+
const result = gateCheck({
|
|
291
|
+
passRate: 0.96,
|
|
292
|
+
mode: 'standard',
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
expect(result.mode).toBe('standard');
|
|
296
|
+
expect(result.threshold).toBe(0.95);
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
describe('Boundary testing', () => {
|
|
301
|
+
it('should handle MVP boundary (0.70)', () => {
|
|
302
|
+
const pass = gateCheck({ passRate: 0.70, mode: 'mvp' });
|
|
303
|
+
const fail = gateCheck({ passRate: 0.6999, mode: 'mvp' });
|
|
304
|
+
|
|
305
|
+
expect(pass.passed).toBe(true);
|
|
306
|
+
expect(fail.passed).toBe(false);
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
it('should handle Standard boundary (0.95)', () => {
|
|
310
|
+
const pass = gateCheck({ passRate: 0.95, mode: 'standard' });
|
|
311
|
+
const fail = gateCheck({ passRate: 0.9499, mode: 'standard' });
|
|
312
|
+
|
|
313
|
+
expect(pass.passed).toBe(true);
|
|
314
|
+
expect(fail.passed).toBe(false);
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
it('should handle Enterprise boundary (0.98)', () => {
|
|
318
|
+
const pass = gateCheck({ passRate: 0.98, mode: 'enterprise' });
|
|
319
|
+
const fail = gateCheck({ passRate: 0.9799, mode: 'enterprise' });
|
|
320
|
+
|
|
321
|
+
expect(pass.passed).toBe(true);
|
|
322
|
+
expect(fail.passed).toBe(false);
|
|
323
|
+
});
|
|
324
|
+
});
|
|
325
|
+
});
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Iteration Manager Tests
|
|
3
|
+
* Tests for managing CFN Loop iteration transitions and feedback
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { prepareIteration, wakeAgents } from '../src/helpers/iteration-manager';
|
|
7
|
+
|
|
8
|
+
describe('iteration-manager', () => {
|
|
9
|
+
describe('prepareIteration', () => {
|
|
10
|
+
it('should increment iteration number', () => {
|
|
11
|
+
const result = prepareIteration({
|
|
12
|
+
currentIteration: 1,
|
|
13
|
+
feedback: { issues: ['Fix tests'] }
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
expect(result.nextIteration).toBe(2);
|
|
17
|
+
expect(result.feedback).toBeDefined();
|
|
18
|
+
expect(result.feedback.issues).toEqual(['Fix tests']);
|
|
19
|
+
expect(result.timestamp).toMatch(/^\d{4}-\d{2}-\d{2}T/); // ISO format
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('should handle iteration 0 to 1 transition', () => {
|
|
23
|
+
const result = prepareIteration({
|
|
24
|
+
currentIteration: 0,
|
|
25
|
+
feedback: { message: 'Initial iteration' }
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
expect(result.nextIteration).toBe(1);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('should handle high iteration numbers', () => {
|
|
32
|
+
const result = prepareIteration({
|
|
33
|
+
currentIteration: 15,
|
|
34
|
+
feedback: {}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
expect(result.nextIteration).toBe(16);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should preserve feedback structure', () => {
|
|
41
|
+
const complexFeedback = {
|
|
42
|
+
issues: ['Issue 1', 'Issue 2'],
|
|
43
|
+
suggestions: ['Suggestion 1'],
|
|
44
|
+
metadata: { validator: 'code-reviewer', confidence: 0.85 }
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const result = prepareIteration({
|
|
48
|
+
currentIteration: 3,
|
|
49
|
+
feedback: complexFeedback
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
expect(result.feedback).toEqual(complexFeedback);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('should allow empty feedback', () => {
|
|
56
|
+
const result = prepareIteration({
|
|
57
|
+
currentIteration: 2,
|
|
58
|
+
feedback: {}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
expect(result.nextIteration).toBe(3);
|
|
62
|
+
expect(result.feedback).toEqual({});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should generate valid timestamp', () => {
|
|
66
|
+
const result = prepareIteration({
|
|
67
|
+
currentIteration: 1,
|
|
68
|
+
feedback: {}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const timestamp = new Date(result.timestamp);
|
|
72
|
+
expect(timestamp.toString()).not.toBe('Invalid Date');
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
describe('wakeAgents', () => {
|
|
77
|
+
it('should prepare wake signals for single agent', () => {
|
|
78
|
+
const result = wakeAgents(['backend-dev-001']);
|
|
79
|
+
|
|
80
|
+
expect(result.signals).toHaveLength(1);
|
|
81
|
+
expect(result.signals[0]).toContain('backend-dev-001');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('should prepare wake signals for multiple agents', () => {
|
|
85
|
+
const agentIds = ['backend-dev-001', 'code-reviewer-002', 'tester-003'];
|
|
86
|
+
const result = wakeAgents(agentIds);
|
|
87
|
+
|
|
88
|
+
expect(result.signals).toHaveLength(3);
|
|
89
|
+
expect(result.signals[0]).toContain('backend-dev-001');
|
|
90
|
+
expect(result.signals[1]).toContain('code-reviewer-002');
|
|
91
|
+
expect(result.signals[2]).toContain('tester-003');
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('should handle empty agent list', () => {
|
|
95
|
+
const result = wakeAgents([]);
|
|
96
|
+
|
|
97
|
+
expect(result.signals).toEqual([]);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('should generate unique signals for each agent', () => {
|
|
101
|
+
const agentIds = ['agent-1', 'agent-2', 'agent-3'];
|
|
102
|
+
const result = wakeAgents(agentIds);
|
|
103
|
+
|
|
104
|
+
const uniqueSignals = new Set(result.signals);
|
|
105
|
+
expect(uniqueSignals.size).toBe(3);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('should include agent ID in each signal', () => {
|
|
109
|
+
const agentIds = ['test-agent-123'];
|
|
110
|
+
const result = wakeAgents(agentIds);
|
|
111
|
+
|
|
112
|
+
expect(result.signals[0]).toContain('test-agent-123');
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
describe('integration: prepareIteration + wakeAgents', () => {
|
|
117
|
+
it('should support iteration workflow', () => {
|
|
118
|
+
// Prepare next iteration
|
|
119
|
+
const iteration = prepareIteration({
|
|
120
|
+
currentIteration: 2,
|
|
121
|
+
feedback: { issues: ['Fix validation'] }
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
expect(iteration.nextIteration).toBe(3);
|
|
125
|
+
|
|
126
|
+
// Wake agents for next iteration
|
|
127
|
+
const wake = wakeAgents(['dev-1', 'validator-1']);
|
|
128
|
+
|
|
129
|
+
expect(wake.signals).toHaveLength(2);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
});
|