xp-gate 0.5.1
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/adapter-common.sh +192 -0
- package/adapters/cpp.sh +76 -0
- package/adapters/dart.sh +41 -0
- package/adapters/flutter.sh +41 -0
- package/adapters/go.sh +59 -0
- package/adapters/iac.sh +189 -0
- package/adapters/java.sh +191 -0
- package/adapters/kotlin.sh +77 -0
- package/adapters/objectivec.sh +38 -0
- package/adapters/powershell.sh +138 -0
- package/adapters/python.sh +104 -0
- package/adapters/shell.sh +55 -0
- package/adapters/swift.sh +44 -0
- package/adapters/typescript.sh +61 -0
- package/bin/xp-gate.js +157 -0
- package/hooks/adapter-common.sh +192 -0
- package/hooks/pre-commit +1667 -0
- package/hooks/pre-push +395 -0
- package/lib/__tests__/detect-deps.test.js +209 -0
- package/lib/__tests__/doctor.test.js +448 -0
- package/lib/__tests__/download-skill.test.js +281 -0
- package/lib/__tests__/init.test.js +327 -0
- package/lib/__tests__/install-skill.test.js +326 -0
- package/lib/__tests__/migrate.test.js +212 -0
- package/lib/__tests__/rollback.test.js +183 -0
- package/lib/__tests__/ui-detector.test.ts +200 -0
- package/lib/__tests__/uninstall-skill.test.js +189 -0
- package/lib/__tests__/uninstall.test.js +589 -0
- package/lib/__tests__/update-skill.test.js +276 -0
- package/lib/detect-deps.js +157 -0
- package/lib/doctor.js +370 -0
- package/lib/download-skill.js +96 -0
- package/lib/init.js +367 -0
- package/lib/install-skill.js +184 -0
- package/lib/migrate.js +120 -0
- package/lib/rollback.js +78 -0
- package/lib/ui-detector.ts +99 -0
- package/lib/uninstall-skill.js +69 -0
- package/lib/uninstall.js +401 -0
- package/lib/update-skill.js +90 -0
- package/package.json +39 -0
- package/plugins/claude-code/.claude-plugin/plugin.json +21 -0
- package/plugins/claude-code/bin/delphi-review-guard.sh +68 -0
- package/plugins/claude-code/bin/xp-gate-check +47 -0
- package/plugins/claude-code/hooks/hooks.json +37 -0
- package/skills/delphi-review/.delphi-config.json.example +45 -0
- package/skills/delphi-review/AGENTS.md +54 -0
- package/skills/delphi-review/INSTALL.md +152 -0
- package/skills/delphi-review/SKILL.md +371 -0
- package/skills/delphi-review/evals/evals.json +82 -0
- package/skills/delphi-review/opencode.json.delphi.example +56 -0
- package/skills/delphi-review/references/code-walkthrough.md +486 -0
- package/skills/ralph-loop/SKILL.md +330 -0
- package/skills/ralph-loop/evals/evals.json +311 -0
- package/skills/ralph-loop/evolution-history.json +59 -0
- package/skills/ralph-loop/evolution-log.md +16 -0
- package/skills/ralph-loop/references/components/memory.md +55 -0
- package/skills/ralph-loop/references/components/middleware.md +54 -0
- package/skills/ralph-loop/references/components/skill-invocations.md +39 -0
- package/skills/ralph-loop/references/components/system-prompt.md +24 -0
- package/skills/ralph-loop/references/components/tool-descriptions.md +32 -0
- package/skills/ralph-loop/references/phase-2-build-ralph.md +89 -0
- package/skills/ralph-loop/templates/progress-log.md +36 -0
- package/skills/sprint-flow/SKILL.md +600 -0
- package/skills/sprint-flow/evals/evals.json +78 -0
- package/skills/sprint-flow/evolution-history.json +39 -0
- package/skills/sprint-flow/evolution-log.md +23 -0
- package/skills/sprint-flow/references/components/memory.md +87 -0
- package/skills/sprint-flow/references/components/middleware.md +72 -0
- package/skills/sprint-flow/references/components/skill-invocations.md +104 -0
- package/skills/sprint-flow/references/components/system-prompt.md +27 -0
- package/skills/sprint-flow/references/components/tool-descriptions.md +96 -0
- package/skills/sprint-flow/references/phase-0-think.md +115 -0
- package/skills/sprint-flow/references/phase-1-plan.md +178 -0
- package/skills/sprint-flow/references/phase-2-build.md +198 -0
- package/skills/sprint-flow/references/phase-3-review.md +213 -0
- package/skills/sprint-flow/references/phase-4-uat.md +125 -0
- package/skills/sprint-flow/references/phase-5-feedback.md +100 -0
- package/skills/sprint-flow/references/phase-6-ship.md +193 -0
- package/skills/sprint-flow/references/phase-7-land.md +140 -0
- package/skills/sprint-flow/references/phase-8-cleanup.md +192 -0
- package/skills/sprint-flow/templates/emergent-issues-template.md +120 -0
- package/skills/sprint-flow/templates/pain-document-template.md +115 -0
- package/skills/sprint-flow/templates/sprint-summary-template.md +120 -0
- package/skills/test-specification-alignment/AGENTS.md +59 -0
- package/skills/test-specification-alignment/SKILL.md +605 -0
- package/skills/test-specification-alignment/evals/evals.json +75 -0
- package/skills/test-specification-alignment/references/alignment-verification-algorithm.md +493 -0
- package/skills/test-specification-alignment/references/phase2-constraint-enforcement.md +431 -0
- package/skills/test-specification-alignment/references/specification-format.md +348 -0
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
# Specification YAML 格式规范
|
|
2
|
+
|
|
3
|
+
## 标准格式
|
|
4
|
+
|
|
5
|
+
```yaml
|
|
6
|
+
specification:
|
|
7
|
+
id: "SPEC-XXX-XXX"
|
|
8
|
+
name: "模块/功能名称"
|
|
9
|
+
version: "1.0.0"
|
|
10
|
+
|
|
11
|
+
# 需求列表
|
|
12
|
+
requirements:
|
|
13
|
+
- id: "REQ-XXX-001"
|
|
14
|
+
description: "需求描述"
|
|
15
|
+
priority: "MUST" | "SHOULD" | "MAY"
|
|
16
|
+
|
|
17
|
+
# 验收标准 (Gherkin 格式)
|
|
18
|
+
acceptance_criteria:
|
|
19
|
+
- id: "AC-XXX-001-01"
|
|
20
|
+
given: "前置条件"
|
|
21
|
+
when: "触发动作"
|
|
22
|
+
then: "期望结果"
|
|
23
|
+
|
|
24
|
+
- id: "AC-XXX-001-02"
|
|
25
|
+
given: "..."
|
|
26
|
+
when: "..."
|
|
27
|
+
then: "..."
|
|
28
|
+
|
|
29
|
+
# 边界条件
|
|
30
|
+
edge_cases:
|
|
31
|
+
- "边界条件1"
|
|
32
|
+
- "边界条件2"
|
|
33
|
+
|
|
34
|
+
# 安全考虑
|
|
35
|
+
security_considerations:
|
|
36
|
+
- "安全要点1"
|
|
37
|
+
|
|
38
|
+
# 测试覆盖要求
|
|
39
|
+
test_coverage_requirements:
|
|
40
|
+
unit: true
|
|
41
|
+
integration: true
|
|
42
|
+
e2e: false
|
|
43
|
+
|
|
44
|
+
# 设计决策
|
|
45
|
+
design_decisions:
|
|
46
|
+
- id: "DD-XXX-001"
|
|
47
|
+
description: "设计决策描述"
|
|
48
|
+
rationale: "决策理由"
|
|
49
|
+
alternatives_considered:
|
|
50
|
+
- "备选方案1"
|
|
51
|
+
- "备选方案2"
|
|
52
|
+
|
|
53
|
+
# API 契约
|
|
54
|
+
api_contracts:
|
|
55
|
+
- endpoint: "POST /api/xxx"
|
|
56
|
+
description: "API 描述"
|
|
57
|
+
request:
|
|
58
|
+
body:
|
|
59
|
+
field1: "type"
|
|
60
|
+
field2: "type"
|
|
61
|
+
response:
|
|
62
|
+
success:
|
|
63
|
+
status: 200
|
|
64
|
+
body:
|
|
65
|
+
field1: "type"
|
|
66
|
+
failure:
|
|
67
|
+
status: 400
|
|
68
|
+
body:
|
|
69
|
+
error: "string"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 完整示例:用户认证模块
|
|
75
|
+
|
|
76
|
+
```yaml
|
|
77
|
+
specification:
|
|
78
|
+
id: "SPEC-AUTH-001"
|
|
79
|
+
name: "User Authentication Module"
|
|
80
|
+
version: "1.0.0"
|
|
81
|
+
|
|
82
|
+
requirements:
|
|
83
|
+
# REQ-1: 用户登录
|
|
84
|
+
- id: "REQ-AUTH-001"
|
|
85
|
+
description: "用户使用正确的用户名和密码可以成功登录"
|
|
86
|
+
priority: "MUST"
|
|
87
|
+
|
|
88
|
+
acceptance_criteria:
|
|
89
|
+
- id: "AC-AUTH-001-01"
|
|
90
|
+
given: "用户存在且密码正确"
|
|
91
|
+
when: "用户提交登录表单"
|
|
92
|
+
then: "系统返回 200 状态码和有效 JWT token"
|
|
93
|
+
|
|
94
|
+
- id: "AC-AUTH-001-02"
|
|
95
|
+
given: "用户存在且密码正确"
|
|
96
|
+
when: "用户提交登录表单"
|
|
97
|
+
then: "返回的 token 过期时间 >= 1小时"
|
|
98
|
+
|
|
99
|
+
- id: "AC-AUTH-001-03"
|
|
100
|
+
given: "用户存在且密码正确"
|
|
101
|
+
when: "用户提交登录表单"
|
|
102
|
+
then: "token 包含用户 ID 和角色信息"
|
|
103
|
+
|
|
104
|
+
edge_cases:
|
|
105
|
+
- "密码包含特殊字符 (@#$%^&*)"
|
|
106
|
+
- "用户名包含空格"
|
|
107
|
+
- "并发登录请求"
|
|
108
|
+
- "超长用户名 (>100字符)"
|
|
109
|
+
- "超长密码 (>200字符)"
|
|
110
|
+
|
|
111
|
+
security_considerations:
|
|
112
|
+
- "密码不能明文传输"
|
|
113
|
+
- "使用 HTTPS"
|
|
114
|
+
- "登录失败不暴露用户是否存在"
|
|
115
|
+
- "记录登录日志"
|
|
116
|
+
|
|
117
|
+
test_coverage_requirements:
|
|
118
|
+
unit: true
|
|
119
|
+
integration: true
|
|
120
|
+
e2e: true
|
|
121
|
+
|
|
122
|
+
# REQ-2: 登录失败
|
|
123
|
+
- id: "REQ-AUTH-002"
|
|
124
|
+
description: "用户使用错误的密码登录失败"
|
|
125
|
+
priority: "MUST"
|
|
126
|
+
|
|
127
|
+
acceptance_criteria:
|
|
128
|
+
- id: "AC-AUTH-002-01"
|
|
129
|
+
given: "用户存在但密码错误"
|
|
130
|
+
when: "用户提交登录表单"
|
|
131
|
+
then: "系统返回 401 状态码"
|
|
132
|
+
|
|
133
|
+
- id: "AC-AUTH-002-02"
|
|
134
|
+
given: "密码错误次数 >= 3"
|
|
135
|
+
when: "用户尝试登录"
|
|
136
|
+
then: "账户被锁定 15 分钟"
|
|
137
|
+
|
|
138
|
+
- id: "AC-AUTH-002-03"
|
|
139
|
+
given: "用户不存在"
|
|
140
|
+
when: "用户提交登录表单"
|
|
141
|
+
then: "系统返回 401 状态码(不暴露用户不存在)"
|
|
142
|
+
|
|
143
|
+
edge_cases:
|
|
144
|
+
- "密码错误 2 次后第 3 次正确"
|
|
145
|
+
- "锁定期间尝试登录"
|
|
146
|
+
- "锁定时间边界 (14分59秒, 15分00秒, 15分01秒)"
|
|
147
|
+
|
|
148
|
+
security_considerations:
|
|
149
|
+
- "不暴露具体错误原因(用户不存在 vs 密码错误)"
|
|
150
|
+
- "防暴力破解"
|
|
151
|
+
|
|
152
|
+
# REQ-3: Token 刷新
|
|
153
|
+
- id: "REQ-AUTH-003"
|
|
154
|
+
description: "用户可以刷新过期的 token"
|
|
155
|
+
priority: "SHOULD"
|
|
156
|
+
|
|
157
|
+
acceptance_criteria:
|
|
158
|
+
- id: "AC-AUTH-003-01"
|
|
159
|
+
given: "用户有有效的 refresh token"
|
|
160
|
+
when: "用户请求刷新 token"
|
|
161
|
+
then: "系统返回新的 access token"
|
|
162
|
+
|
|
163
|
+
- id: "AC-AUTH-003-02"
|
|
164
|
+
given: "用户的 refresh token 已过期"
|
|
165
|
+
when: "用户请求刷新 token"
|
|
166
|
+
then: "系统返回 401 状态码,要求重新登录"
|
|
167
|
+
|
|
168
|
+
design_decisions:
|
|
169
|
+
- id: "DD-AUTH-001"
|
|
170
|
+
description: "使用 JWT 进行身份认证"
|
|
171
|
+
rationale: "无状态,支持分布式部署,减少数据库查询"
|
|
172
|
+
alternatives_considered:
|
|
173
|
+
- "Session-based auth: 需要分布式 session 存储"
|
|
174
|
+
- "API Key: 不适合用户登录场景"
|
|
175
|
+
|
|
176
|
+
- id: "DD-AUTH-002"
|
|
177
|
+
description: "密码使用 bcrypt 哈希存储"
|
|
178
|
+
rationale: "安全性高,计算成本可调,防彩虹表"
|
|
179
|
+
|
|
180
|
+
- id: "DD-AUTH-003"
|
|
181
|
+
description: "双 token 机制 (access + refresh)"
|
|
182
|
+
rationale: "平衡安全性和用户体验,access token 短期有效"
|
|
183
|
+
|
|
184
|
+
api_contracts:
|
|
185
|
+
- endpoint: "POST /api/auth/login"
|
|
186
|
+
description: "用户登录"
|
|
187
|
+
request:
|
|
188
|
+
body:
|
|
189
|
+
username: "string (required, 1-100 chars)"
|
|
190
|
+
password: "string (required, 1-200 chars)"
|
|
191
|
+
response:
|
|
192
|
+
success:
|
|
193
|
+
status: 200
|
|
194
|
+
body:
|
|
195
|
+
token: "string (JWT)"
|
|
196
|
+
refreshToken: "string"
|
|
197
|
+
expiresIn: "number (seconds)"
|
|
198
|
+
failure:
|
|
199
|
+
status: 401
|
|
200
|
+
body:
|
|
201
|
+
error: "Invalid credentials"
|
|
202
|
+
attemptsRemaining: "number (optional)"
|
|
203
|
+
|
|
204
|
+
- endpoint: "POST /api/auth/logout"
|
|
205
|
+
description: "用户登出"
|
|
206
|
+
request:
|
|
207
|
+
headers:
|
|
208
|
+
Authorization: "Bearer <token>"
|
|
209
|
+
response:
|
|
210
|
+
success:
|
|
211
|
+
status: 200
|
|
212
|
+
body:
|
|
213
|
+
message: "Logged out successfully"
|
|
214
|
+
|
|
215
|
+
- endpoint: "POST /api/auth/refresh"
|
|
216
|
+
description: "刷新 token"
|
|
217
|
+
request:
|
|
218
|
+
body:
|
|
219
|
+
refreshToken: "string"
|
|
220
|
+
response:
|
|
221
|
+
success:
|
|
222
|
+
status: 200
|
|
223
|
+
body:
|
|
224
|
+
token: "string (new JWT)"
|
|
225
|
+
expiresIn: "number"
|
|
226
|
+
failure:
|
|
227
|
+
status: 401
|
|
228
|
+
body:
|
|
229
|
+
error: "Invalid or expired refresh token"
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## 测试标签格式
|
|
235
|
+
|
|
236
|
+
### TypeScript/JavaScript
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
/**
|
|
240
|
+
* @test REQ-AUTH-001
|
|
241
|
+
* @intent 验证用户使用正确凭据可以成功登录
|
|
242
|
+
* @covers AC-AUTH-001-01, AC-AUTH-001-02, AC-AUTH-001-03
|
|
243
|
+
* @edge_cases password_with_special_chars, concurrent_login
|
|
244
|
+
*/
|
|
245
|
+
describe('REQ-AUTH-001: User Login', () => {
|
|
246
|
+
test('AC-AUTH-001-01: returns 200 and valid token', async () => {
|
|
247
|
+
// Given: 用户存在且密码正确
|
|
248
|
+
const user = await createTestUser({ password: 'correctpassword' });
|
|
249
|
+
|
|
250
|
+
// When: 用户提交登录表单
|
|
251
|
+
const response = await request(app)
|
|
252
|
+
.post('/api/auth/login')
|
|
253
|
+
.send({ username: user.username, password: 'correctpassword' });
|
|
254
|
+
|
|
255
|
+
// Then: 系统返回 200 状态码和有效 JWT token
|
|
256
|
+
expect(response.status).toBe(200);
|
|
257
|
+
expect(response.body.token).toBeDefined();
|
|
258
|
+
expect(() => jwt.verify(response.body.token, JWT_SECRET)).not.toThrow();
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Python (pytest)
|
|
264
|
+
|
|
265
|
+
```python
|
|
266
|
+
# @test REQ-AUTH-001
|
|
267
|
+
# @intent 验证用户使用正确凭据可以成功登录
|
|
268
|
+
# @covers AC-AUTH-001-01, AC-AUTH-001-02
|
|
269
|
+
# @edge_cases password_with_special_chars, concurrent_login
|
|
270
|
+
class Test_REQ_AUTH_001_UserLogin:
|
|
271
|
+
"""
|
|
272
|
+
REQ-AUTH-001: 用户登录测试
|
|
273
|
+
|
|
274
|
+
@test REQ-AUTH-001
|
|
275
|
+
@intent 验证用户使用正确凭据可以成功登录
|
|
276
|
+
"""
|
|
277
|
+
|
|
278
|
+
def test_AC_AUTH_001_01_returns_200_and_token(self):
|
|
279
|
+
"""AC-AUTH-001-01: 返回 200 和有效 token"""
|
|
280
|
+
# Given: 用户存在且密码正确
|
|
281
|
+
user = create_test_user(password='correctpassword')
|
|
282
|
+
|
|
283
|
+
# When: 用户提交登录表单
|
|
284
|
+
response = client.post('/api/auth/login', json={
|
|
285
|
+
'username': user.username,
|
|
286
|
+
'password': 'correctpassword'
|
|
287
|
+
})
|
|
288
|
+
|
|
289
|
+
# Then: 系统返回 200 状态码和有效 JWT token
|
|
290
|
+
assert response.status_code == 200
|
|
291
|
+
assert 'token' in response.json
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Go
|
|
295
|
+
|
|
296
|
+
```go
|
|
297
|
+
// @test REQ-AUTH-001
|
|
298
|
+
// @intent 验证用户使用正确凭据可以成功登录
|
|
299
|
+
// @covers AC-AUTH-001-01, AC-AUTH-001-02
|
|
300
|
+
// @edge_cases password_with_special_chars, concurrent_login
|
|
301
|
+
func Test_REQ_AUTH_001_UserLogin(t *testing.T) {
|
|
302
|
+
// AC-AUTH-001-01: 返回 200 和有效 token
|
|
303
|
+
|
|
304
|
+
// Given: 用户存在且密码正确
|
|
305
|
+
user := createTestUser(t, "correctpassword")
|
|
306
|
+
|
|
307
|
+
// When: 用户提交登录表单
|
|
308
|
+
resp := httptest.NewRecorder()
|
|
309
|
+
req := httptest.NewRequest("POST", "/api/auth/login",
|
|
310
|
+
strings.NewReader(fmt.Sprintf(`{"username":"%s","password":"correctpassword"}`, user.Username)))
|
|
311
|
+
router.ServeHTTP(resp, req)
|
|
312
|
+
|
|
313
|
+
// Then: 系统返回 200 状态码和有效 JWT token
|
|
314
|
+
assert.Equal(t, 200, resp.Code)
|
|
315
|
+
// ... 更多断言
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## 必需字段检查清单
|
|
322
|
+
|
|
323
|
+
### Specification 层级
|
|
324
|
+
|
|
325
|
+
- [ ] `specification.id` - 唯一标识符
|
|
326
|
+
- [ ] `specification.name` - 模块名称
|
|
327
|
+
- [ ] `specification.version` - 版本号
|
|
328
|
+
- [ ] `specification.requirements` - 需求列表 (至少 1 个)
|
|
329
|
+
|
|
330
|
+
### Requirement 层级
|
|
331
|
+
|
|
332
|
+
- [ ] `requirements[].id` - REQ-XXX-XXX 格式
|
|
333
|
+
- [ ] `requirements[].description` - 需求描述
|
|
334
|
+
- [ ] `requirements[].priority` - MUST/SHOULD/MAY
|
|
335
|
+
- [ ] `requirements[].acceptance_criteria` - 验收标准 (至少 1 个)
|
|
336
|
+
|
|
337
|
+
### Acceptance Criteria 层级
|
|
338
|
+
|
|
339
|
+
- [ ] `acceptance_criteria[].id` - AC-XXX-XXX-XX 格式
|
|
340
|
+
- [ ] `acceptance_criteria[].given` - 前置条件
|
|
341
|
+
- [ ] `acceptance_criteria[].when` - 触发动作
|
|
342
|
+
- [ ] `acceptance_criteria[].then` - 期望结果
|
|
343
|
+
|
|
344
|
+
### 测试标签层级
|
|
345
|
+
|
|
346
|
+
- [ ] `@test REQ-XXX-XXX` - 关联 requirement
|
|
347
|
+
- [ ] `@intent 描述` - 测试意图
|
|
348
|
+
- [ ] `@covers AC-XXX-XX` - 覆盖的 AC (推荐)
|