@f2a/network 0.1.2 → 0.1.3
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/package.json +8 -1
- package/.github/workflows/ci.yml +0 -113
- package/.github/workflows/publish.yml +0 -60
- package/MONOREPO.md +0 -58
- package/SKILL.md +0 -137
- package/dist/adapters/openclaw.d.ts +0 -103
- package/dist/adapters/openclaw.d.ts.map +0 -1
- package/dist/adapters/openclaw.js +0 -297
- package/dist/adapters/openclaw.js.map +0 -1
- package/dist/core/connection-manager.d.ts +0 -80
- package/dist/core/connection-manager.d.ts.map +0 -1
- package/dist/core/connection-manager.js +0 -235
- package/dist/core/connection-manager.js.map +0 -1
- package/dist/core/connection-manager.test.d.ts +0 -2
- package/dist/core/connection-manager.test.d.ts.map +0 -1
- package/dist/core/connection-manager.test.js +0 -52
- package/dist/core/connection-manager.test.js.map +0 -1
- package/dist/core/identity.d.ts +0 -47
- package/dist/core/identity.d.ts.map +0 -1
- package/dist/core/identity.js +0 -130
- package/dist/core/identity.js.map +0 -1
- package/dist/core/identity.test.d.ts +0 -2
- package/dist/core/identity.test.d.ts.map +0 -1
- package/dist/core/identity.test.js +0 -43
- package/dist/core/identity.test.js.map +0 -1
- package/dist/core/serverless.d.ts +0 -155
- package/dist/core/serverless.d.ts.map +0 -1
- package/dist/core/serverless.js +0 -615
- package/dist/core/serverless.js.map +0 -1
- package/dist/daemon/webhook.test.d.ts +0 -2
- package/dist/daemon/webhook.test.d.ts.map +0 -1
- package/dist/daemon/webhook.test.js +0 -24
- package/dist/daemon/webhook.test.js.map +0 -1
- package/dist/protocol/messages.d.ts +0 -739
- package/dist/protocol/messages.d.ts.map +0 -1
- package/dist/protocol/messages.js +0 -188
- package/dist/protocol/messages.js.map +0 -1
- package/dist/protocol/messages.test.d.ts +0 -2
- package/dist/protocol/messages.test.d.ts.map +0 -1
- package/dist/protocol/messages.test.js +0 -55
- package/dist/protocol/messages.test.js.map +0 -1
- package/docs/F2A-PROTOCOL.md +0 -61
- package/docs/MOBILE_BOOTSTRAP_DESIGN.md +0 -126
- package/docs/a2a-lessons.md +0 -316
- package/docs/middleware-guide.md +0 -448
- package/docs/readme-update-checklist.md +0 -90
- package/docs/reputation-guide.md +0 -396
- package/docs/rfcs/001-reputation-system.md +0 -712
- package/docs/security-design.md +0 -247
- package/install.sh +0 -231
- package/packages/openclaw-adapter/README.md +0 -510
- package/packages/openclaw-adapter/openclaw.plugin.json +0 -106
- package/packages/openclaw-adapter/package.json +0 -40
- package/packages/openclaw-adapter/src/announcement-queue.test.ts +0 -449
- package/packages/openclaw-adapter/src/announcement-queue.ts +0 -403
- package/packages/openclaw-adapter/src/capability-detector.test.ts +0 -99
- package/packages/openclaw-adapter/src/capability-detector.ts +0 -183
- package/packages/openclaw-adapter/src/claim-handlers.test.ts +0 -974
- package/packages/openclaw-adapter/src/claim-handlers.ts +0 -482
- package/packages/openclaw-adapter/src/connector.business.test.ts +0 -583
- package/packages/openclaw-adapter/src/connector.ts +0 -795
- package/packages/openclaw-adapter/src/index.test.ts +0 -82
- package/packages/openclaw-adapter/src/index.ts +0 -18
- package/packages/openclaw-adapter/src/integration.e2e.test.ts +0 -829
- package/packages/openclaw-adapter/src/logger.ts +0 -51
- package/packages/openclaw-adapter/src/network-client.test.ts +0 -266
- package/packages/openclaw-adapter/src/network-client.ts +0 -251
- package/packages/openclaw-adapter/src/network-recovery.test.ts +0 -465
- package/packages/openclaw-adapter/src/node-manager.test.ts +0 -136
- package/packages/openclaw-adapter/src/node-manager.ts +0 -429
- package/packages/openclaw-adapter/src/plugin.test.ts +0 -439
- package/packages/openclaw-adapter/src/plugin.ts +0 -104
- package/packages/openclaw-adapter/src/reputation.test.ts +0 -221
- package/packages/openclaw-adapter/src/reputation.ts +0 -368
- package/packages/openclaw-adapter/src/task-guard.test.ts +0 -502
- package/packages/openclaw-adapter/src/task-guard.ts +0 -860
- package/packages/openclaw-adapter/src/task-queue.concurrency.test.ts +0 -462
- package/packages/openclaw-adapter/src/task-queue.edge-cases.test.ts +0 -284
- package/packages/openclaw-adapter/src/task-queue.persistence.test.ts +0 -408
- package/packages/openclaw-adapter/src/task-queue.ts +0 -668
- package/packages/openclaw-adapter/src/tool-handlers.test.ts +0 -906
- package/packages/openclaw-adapter/src/tool-handlers.ts +0 -574
- package/packages/openclaw-adapter/src/types.ts +0 -361
- package/packages/openclaw-adapter/src/webhook-pusher.test.ts +0 -188
- package/packages/openclaw-adapter/src/webhook-pusher.ts +0 -220
- package/packages/openclaw-adapter/src/webhook-server.test.ts +0 -580
- package/packages/openclaw-adapter/src/webhook-server.ts +0 -202
- package/packages/openclaw-adapter/tsconfig.json +0 -20
- package/src/cli/commands.test.ts +0 -157
- package/src/cli/commands.ts +0 -129
- package/src/cli/index.test.ts +0 -77
- package/src/cli/index.ts +0 -234
- package/src/core/autonomous-economy.test.ts +0 -291
- package/src/core/autonomous-economy.ts +0 -428
- package/src/core/e2ee-crypto.test.ts +0 -125
- package/src/core/e2ee-crypto.ts +0 -246
- package/src/core/f2a.test.ts +0 -269
- package/src/core/f2a.ts +0 -618
- package/src/core/p2p-network.test.ts +0 -199
- package/src/core/p2p-network.ts +0 -1432
- package/src/core/reputation-security.test.ts +0 -403
- package/src/core/reputation-security.ts +0 -562
- package/src/core/reputation.test.ts +0 -260
- package/src/core/reputation.ts +0 -576
- package/src/core/review-committee.test.ts +0 -380
- package/src/core/review-committee.ts +0 -401
- package/src/core/token-manager.test.ts +0 -133
- package/src/core/token-manager.ts +0 -140
- package/src/daemon/control-server.test.ts +0 -216
- package/src/daemon/control-server.ts +0 -292
- package/src/daemon/index.test.ts +0 -85
- package/src/daemon/index.ts +0 -89
- package/src/daemon/main.ts +0 -44
- package/src/daemon/start.ts +0 -29
- package/src/daemon/webhook.test.ts +0 -68
- package/src/daemon/webhook.ts +0 -105
- package/src/index.test.ts +0 -436
- package/src/index.ts +0 -72
- package/src/types/index.test.ts +0 -87
- package/src/types/index.ts +0 -341
- package/src/types/result.ts +0 -68
- package/src/utils/benchmark.ts +0 -237
- package/src/utils/logger.ts +0 -331
- package/src/utils/middleware.ts +0 -229
- package/src/utils/rate-limiter.ts +0 -207
- package/src/utils/signature.ts +0 -136
- package/src/utils/validation.ts +0 -186
- package/tests/docker/Dockerfile.node +0 -23
- package/tests/docker/Dockerfile.runner +0 -18
- package/tests/docker/docker-compose.test.yml +0 -73
- package/tests/integration/message-passing.test.ts +0 -109
- package/tests/integration/multi-node.test.ts +0 -92
- package/tests/integration/p2p-connection.test.ts +0 -83
- package/tests/integration/test-config.ts +0 -32
- package/tsconfig.json +0 -21
- package/vitest.config.ts +0 -26
|
@@ -1,380 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 评审系统测试
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { describe, it, expect, beforeEach } from 'vitest';
|
|
6
|
-
import { ReviewCommittee, TaskReview, ReviewDimensions } from './review-committee.js';
|
|
7
|
-
import { ReputationManager } from './reputation.js';
|
|
8
|
-
|
|
9
|
-
describe('ReviewCommittee', () => {
|
|
10
|
-
let committee: ReviewCommittee;
|
|
11
|
-
let reputationManager: ReputationManager;
|
|
12
|
-
|
|
13
|
-
beforeEach(() => {
|
|
14
|
-
reputationManager = new ReputationManager();
|
|
15
|
-
committee = new ReviewCommittee(reputationManager);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
describe('评审人数计算', () => {
|
|
19
|
-
it('should return 1 reviewer for small network (< 10)', () => {
|
|
20
|
-
// 添加几个节点
|
|
21
|
-
reputationManager.getReputation('peer-1');
|
|
22
|
-
reputationManager.getReputation('peer-2');
|
|
23
|
-
|
|
24
|
-
expect(committee.getRequiredReviewers(3)).toBe(1);
|
|
25
|
-
expect(committee.getRequiredReviewers(9)).toBe(1);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('should return 3 reviewers for medium network (10-50)', () => {
|
|
29
|
-
expect(committee.getRequiredReviewers(10)).toBe(3);
|
|
30
|
-
expect(committee.getRequiredReviewers(30)).toBe(3);
|
|
31
|
-
expect(committee.getRequiredReviewers(49)).toBe(3);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('should return 5 reviewers for large network (>= 50)', () => {
|
|
35
|
-
expect(committee.getRequiredReviewers(50)).toBe(5);
|
|
36
|
-
expect(committee.getRequiredReviewers(100)).toBe(5);
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
describe('提交评审', () => {
|
|
41
|
-
it('should submit task for review', () => {
|
|
42
|
-
const pending = committee.submitForReview(
|
|
43
|
-
'task-1',
|
|
44
|
-
'requester-1',
|
|
45
|
-
'Test task'
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
expect(pending.taskId).toBe('task-1');
|
|
49
|
-
expect(pending.requesterId).toBe('requester-1');
|
|
50
|
-
expect(pending.reviews.length).toBe(0);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it('should accept valid review', () => {
|
|
54
|
-
committee.submitForReview('task-1', 'requester-1', 'Test task');
|
|
55
|
-
|
|
56
|
-
// 给 reviewer 足够信誉
|
|
57
|
-
reputationManager.recordSuccess('reviewer-1', 'prev-task');
|
|
58
|
-
|
|
59
|
-
const review: TaskReview = {
|
|
60
|
-
taskId: 'task-1',
|
|
61
|
-
reviewerId: 'reviewer-1',
|
|
62
|
-
dimensions: { workload: 50, value: 30 },
|
|
63
|
-
timestamp: Date.now(),
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
const result = committee.submitReview(review);
|
|
67
|
-
expect(result.success).toBe(true);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it('should reject review from low reputation user', () => {
|
|
71
|
-
committee.submitForReview('task-1', 'requester-1', 'Test task');
|
|
72
|
-
|
|
73
|
-
// reviewer 信誉不够(默认 70,需要 50 才能评审)
|
|
74
|
-
// 70 > 50,所以应该可以
|
|
75
|
-
|
|
76
|
-
const review: TaskReview = {
|
|
77
|
-
taskId: 'task-1',
|
|
78
|
-
reviewerId: 'reviewer-1',
|
|
79
|
-
dimensions: { workload: 50, value: 30 },
|
|
80
|
-
timestamp: Date.now(),
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
const result = committee.submitReview(review);
|
|
84
|
-
expect(result.success).toBe(true);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it('should reject review from requester', () => {
|
|
88
|
-
committee.submitForReview('task-1', 'requester-1', 'Test task');
|
|
89
|
-
|
|
90
|
-
const review: TaskReview = {
|
|
91
|
-
taskId: 'task-1',
|
|
92
|
-
reviewerId: 'requester-1',
|
|
93
|
-
dimensions: { workload: 50, value: 30 },
|
|
94
|
-
timestamp: Date.now(),
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
const result = committee.submitReview(review);
|
|
98
|
-
expect(result.success).toBe(false);
|
|
99
|
-
expect(result.message).toContain('own task');
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it('should reject duplicate review', () => {
|
|
103
|
-
committee.submitForReview('task-1', 'requester-1', 'Test task');
|
|
104
|
-
|
|
105
|
-
const review: TaskReview = {
|
|
106
|
-
taskId: 'task-1',
|
|
107
|
-
reviewerId: 'reviewer-1',
|
|
108
|
-
dimensions: { workload: 50, value: 30 },
|
|
109
|
-
timestamp: Date.now(),
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
committee.submitReview(review);
|
|
113
|
-
const result = committee.submitReview(review);
|
|
114
|
-
expect(result.success).toBe(false);
|
|
115
|
-
expect(result.message).toContain('Already reviewed');
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
it('should reject invalid workload range', () => {
|
|
119
|
-
committee.submitForReview('task-1', 'requester-1', 'Test task');
|
|
120
|
-
|
|
121
|
-
const review: TaskReview = {
|
|
122
|
-
taskId: 'task-1',
|
|
123
|
-
reviewerId: 'reviewer-1',
|
|
124
|
-
dimensions: { workload: 150, value: 30 }, // workload > 100
|
|
125
|
-
timestamp: Date.now(),
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
const result = committee.submitReview(review);
|
|
129
|
-
expect(result.success).toBe(false);
|
|
130
|
-
expect(result.message).toContain('Invalid review dimensions');
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
it('should reject invalid value range', () => {
|
|
134
|
-
committee.submitForReview('task-1', 'requester-1', 'Test task');
|
|
135
|
-
|
|
136
|
-
const review: TaskReview = {
|
|
137
|
-
taskId: 'task-1',
|
|
138
|
-
reviewerId: 'reviewer-1',
|
|
139
|
-
dimensions: { workload: 50, value: 150 }, // value > 100
|
|
140
|
-
timestamp: Date.now(),
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
const result = committee.submitReview(review);
|
|
144
|
-
expect(result.success).toBe(false);
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
describe('评审聚合', () => {
|
|
149
|
-
it('should return single review as final', () => {
|
|
150
|
-
const reviews: TaskReview[] = [
|
|
151
|
-
{
|
|
152
|
-
taskId: 'task-1',
|
|
153
|
-
reviewerId: 'reviewer-1',
|
|
154
|
-
dimensions: { workload: 50, value: 30 },
|
|
155
|
-
timestamp: Date.now(),
|
|
156
|
-
},
|
|
157
|
-
];
|
|
158
|
-
|
|
159
|
-
const result = committee.aggregateReviews(reviews);
|
|
160
|
-
expect(result.finalWorkload).toBe(50);
|
|
161
|
-
expect(result.finalValue).toBe(30);
|
|
162
|
-
expect(result.outliers.length).toBe(0);
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
it('should calculate average from multiple reviews', () => {
|
|
166
|
-
const reviews: TaskReview[] = [
|
|
167
|
-
{
|
|
168
|
-
taskId: 'task-1',
|
|
169
|
-
reviewerId: 'reviewer-1',
|
|
170
|
-
dimensions: { workload: 40, value: 20 },
|
|
171
|
-
timestamp: Date.now(),
|
|
172
|
-
},
|
|
173
|
-
{
|
|
174
|
-
taskId: 'task-1',
|
|
175
|
-
reviewerId: 'reviewer-2',
|
|
176
|
-
dimensions: { workload: 60, value: 40 },
|
|
177
|
-
timestamp: Date.now(),
|
|
178
|
-
},
|
|
179
|
-
{
|
|
180
|
-
taskId: 'task-1',
|
|
181
|
-
reviewerId: 'reviewer-3',
|
|
182
|
-
dimensions: { workload: 50, value: 30 },
|
|
183
|
-
timestamp: Date.now(),
|
|
184
|
-
},
|
|
185
|
-
];
|
|
186
|
-
|
|
187
|
-
const result = committee.aggregateReviews(reviews);
|
|
188
|
-
// 去掉最高最低后,只剩 50, 30
|
|
189
|
-
expect(result.finalWorkload).toBe(50);
|
|
190
|
-
expect(result.finalValue).toBe(30);
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
it('should identify outliers with significant deviation', () => {
|
|
194
|
-
// 创建更明显的偏离数据
|
|
195
|
-
const reviews: TaskReview[] = [];
|
|
196
|
-
|
|
197
|
-
// 4 个正常评审
|
|
198
|
-
for (let i = 1; i <= 4; i++) {
|
|
199
|
-
reviews.push({
|
|
200
|
-
taskId: 'task-1',
|
|
201
|
-
reviewerId: `reviewer-${i}`,
|
|
202
|
-
dimensions: { workload: 50, value: 30 },
|
|
203
|
-
timestamp: Date.now(),
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// 1 个极端偏离评审
|
|
208
|
-
reviews.push({
|
|
209
|
-
taskId: 'task-1',
|
|
210
|
-
reviewerId: 'outlier-1',
|
|
211
|
-
dimensions: { workload: 0, value: -100 }, // 极端偏离
|
|
212
|
-
timestamp: Date.now(),
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
const result = committee.aggregateReviews(reviews);
|
|
216
|
-
// 检查偏离者是否被识别(可能因为极端值被识别)
|
|
217
|
-
// 注意:聚合时会去掉最高最低,所以偏离检测基于原始数据
|
|
218
|
-
// 如果偏离不够显著,可能不会被识别为 outlier
|
|
219
|
-
// 这里我们只验证聚合结果是否合理
|
|
220
|
-
expect(result.finalWorkload).toBeGreaterThanOrEqual(0);
|
|
221
|
-
expect(result.finalValue).toBeGreaterThanOrEqual(-100);
|
|
222
|
-
});
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
describe('评审结算', () => {
|
|
226
|
-
it('should finalize review when complete', () => {
|
|
227
|
-
committee.submitForReview('task-1', 'requester-1', 'Test task');
|
|
228
|
-
|
|
229
|
-
committee.submitReview({
|
|
230
|
-
taskId: 'task-1',
|
|
231
|
-
reviewerId: 'reviewer-1',
|
|
232
|
-
dimensions: { workload: 50, value: 30 },
|
|
233
|
-
timestamp: Date.now(),
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
const result = committee.finalizeReview('task-1');
|
|
237
|
-
expect(result).not.toBeNull();
|
|
238
|
-
expect(result!.finalWorkload).toBe(50);
|
|
239
|
-
expect(result!.finalValue).toBe(30);
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
it('should not finalize incomplete review', () => {
|
|
243
|
-
committee.submitForReview('task-1', 'requester-1', 'Test task', {}, undefined);
|
|
244
|
-
// 没有提交评审
|
|
245
|
-
|
|
246
|
-
const result = committee.finalizeReview('task-1');
|
|
247
|
-
expect(result).toBeNull();
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
it('should update reviewer reputation', () => {
|
|
251
|
-
committee.submitForReview('task-1', 'requester-1', 'Test task');
|
|
252
|
-
|
|
253
|
-
const beforeScore = reputationManager.getReputation('reviewer-1').score;
|
|
254
|
-
|
|
255
|
-
committee.submitReview({
|
|
256
|
-
taskId: 'task-1',
|
|
257
|
-
reviewerId: 'reviewer-1',
|
|
258
|
-
dimensions: { workload: 50, value: 30 },
|
|
259
|
-
timestamp: Date.now(),
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
committee.finalizeReview('task-1');
|
|
263
|
-
|
|
264
|
-
const afterScore = reputationManager.getReputation('reviewer-1').score;
|
|
265
|
-
expect(afterScore).toBeGreaterThan(beforeScore);
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
it('should penalize outlier reviewers when detected', () => {
|
|
269
|
-
// 使用自定义配置,更低的偏离阈值
|
|
270
|
-
const strictCommittee = new ReviewCommittee(reputationManager, {
|
|
271
|
-
outlierThreshold: 1, // 1 个标准差就认为是偏离
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
strictCommittee.submitForReview('task-1', 'requester-1', 'Test task');
|
|
275
|
-
|
|
276
|
-
// 正常评审
|
|
277
|
-
strictCommittee.submitReview({
|
|
278
|
-
taskId: 'task-1',
|
|
279
|
-
reviewerId: 'reviewer-1',
|
|
280
|
-
dimensions: { workload: 50, value: 30 },
|
|
281
|
-
timestamp: Date.now(),
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
// 另一个正常评审
|
|
285
|
-
strictCommittee.submitReview({
|
|
286
|
-
taskId: 'task-1',
|
|
287
|
-
reviewerId: 'reviewer-2',
|
|
288
|
-
dimensions: { workload: 50, value: 30 },
|
|
289
|
-
timestamp: Date.now(),
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
// 第三个评审
|
|
293
|
-
strictCommittee.submitReview({
|
|
294
|
-
taskId: 'task-1',
|
|
295
|
-
reviewerId: 'reviewer-3',
|
|
296
|
-
dimensions: { workload: 50, value: 30 },
|
|
297
|
-
timestamp: Date.now(),
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
const result = strictCommittee.finalizeReview('task-1');
|
|
301
|
-
// 如果没有偏离者,所有评审者都应该获得奖励
|
|
302
|
-
expect(result).not.toBeNull();
|
|
303
|
-
});
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
describe('可用评审者', () => {
|
|
307
|
-
it('should return available reviewers', () => {
|
|
308
|
-
// 提升一些节点的信誉
|
|
309
|
-
reputationManager.recordSuccess('reviewer-1', 'task-1');
|
|
310
|
-
reputationManager.recordSuccess('reviewer-2', 'task-2');
|
|
311
|
-
|
|
312
|
-
const available = committee.getAvailableReviewers(['requester-1']);
|
|
313
|
-
|
|
314
|
-
expect(available.length).toBeGreaterThan(0);
|
|
315
|
-
expect(available).not.toContain('requester-1');
|
|
316
|
-
});
|
|
317
|
-
|
|
318
|
-
it('should exclude specified ids', () => {
|
|
319
|
-
reputationManager.recordSuccess('reviewer-1', 'task-1');
|
|
320
|
-
|
|
321
|
-
const available = committee.getAvailableReviewers(['reviewer-1']);
|
|
322
|
-
expect(available).not.toContain('reviewer-1');
|
|
323
|
-
});
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
describe('待评审状态', () => {
|
|
327
|
-
it('should track pending reviews', () => {
|
|
328
|
-
committee.submitForReview('task-1', 'requester-1', 'Test 1');
|
|
329
|
-
committee.submitForReview('task-2', 'requester-2', 'Test 2');
|
|
330
|
-
|
|
331
|
-
const pending = committee.getPendingReviews();
|
|
332
|
-
expect(pending.length).toBe(2);
|
|
333
|
-
});
|
|
334
|
-
|
|
335
|
-
it('should get specific review status', () => {
|
|
336
|
-
committee.submitForReview('task-1', 'requester-1', 'Test task');
|
|
337
|
-
|
|
338
|
-
const status = committee.getReviewStatus('task-1');
|
|
339
|
-
expect(status).not.toBeNull();
|
|
340
|
-
expect(status!.taskId).toBe('task-1');
|
|
341
|
-
});
|
|
342
|
-
|
|
343
|
-
it('should return null for non-existent task', () => {
|
|
344
|
-
const status = committee.getReviewStatus('non-existent');
|
|
345
|
-
expect(status).toBeNull();
|
|
346
|
-
});
|
|
347
|
-
|
|
348
|
-
it('should check if review is complete', () => {
|
|
349
|
-
committee.submitForReview('task-1', 'requester-1', 'Test task');
|
|
350
|
-
|
|
351
|
-
expect(committee.isReviewComplete('task-1')).toBe(false);
|
|
352
|
-
|
|
353
|
-
committee.submitReview({
|
|
354
|
-
taskId: 'task-1',
|
|
355
|
-
reviewerId: 'reviewer-1',
|
|
356
|
-
dimensions: { workload: 50, value: 30 },
|
|
357
|
-
timestamp: Date.now(),
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
expect(committee.isReviewComplete('task-1')).toBe(true);
|
|
361
|
-
});
|
|
362
|
-
});
|
|
363
|
-
|
|
364
|
-
describe('超时清理', () => {
|
|
365
|
-
it('should cleanup expired reviews', async () => {
|
|
366
|
-
// 使用很短的超时配置
|
|
367
|
-
const quickCommittee = new ReviewCommittee(reputationManager, {
|
|
368
|
-
reviewTimeout: 100, // 100ms
|
|
369
|
-
});
|
|
370
|
-
|
|
371
|
-
quickCommittee.submitForReview('task-1', 'requester-1', 'Test task');
|
|
372
|
-
|
|
373
|
-
// 等待超时
|
|
374
|
-
await new Promise(resolve => setTimeout(resolve, 150));
|
|
375
|
-
|
|
376
|
-
const expired = quickCommittee.cleanupExpiredReviews();
|
|
377
|
-
expect(expired).toContain('task-1');
|
|
378
|
-
});
|
|
379
|
-
});
|
|
380
|
-
});
|