@liangjie559567/ultrapower 5.0.21 → 5.0.23
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-plugin/plugin.json +1 -1
- package/commands/ax-analyze-error.md +0 -1
- package/commands/ax-context.md +0 -1
- package/commands/ax-decompose.md +0 -1
- package/commands/ax-draft.md +0 -1
- package/commands/ax-evolution.md +0 -1
- package/commands/ax-evolve.md +0 -1
- package/commands/ax-export.md +0 -1
- package/commands/ax-implement.md +0 -1
- package/commands/ax-knowledge.md +0 -1
- package/commands/ax-reflect.md +0 -1
- package/commands/ax-review.md +0 -1
- package/commands/ax-rollback.md +0 -1
- package/commands/ax-status.md +0 -1
- package/commands/ax-suspend.md +0 -1
- package/commands/brainstorm.md +0 -1
- package/commands/execute-plan.md +0 -1
- package/commands/write-plan.md +0 -1
- package/dist/__tests__/validateMode.test.d.ts +2 -0
- package/dist/__tests__/validateMode.test.d.ts.map +1 -0
- package/dist/__tests__/validateMode.test.js +100 -0
- package/dist/__tests__/validateMode.test.js.map +1 -0
- package/dist/lib/validateMode.d.ts +49 -0
- package/dist/lib/validateMode.d.ts.map +1 -0
- package/dist/lib/validateMode.js +68 -0
- package/dist/lib/validateMode.js.map +1 -0
- package/docs/CLAUDE.md +1 -1
- package/docs/prd/ultrapower-standards-draft.md +191 -0
- package/docs/prd/ultrapower-standards-rough.md +560 -0
- package/docs/reviews/ultrapower-standards/review_critic.md +230 -0
- package/docs/reviews/ultrapower-standards/review_domain.md +243 -0
- package/docs/reviews/ultrapower-standards/review_product.md +102 -0
- package/docs/reviews/ultrapower-standards/review_tech.md +142 -0
- package/docs/reviews/ultrapower-standards/review_ux.md +110 -0
- package/docs/reviews/ultrapower-standards/summary.md +85 -0
- package/docs/standards/README.md +85 -0
- package/docs/standards/agent-lifecycle.md +445 -0
- package/docs/standards/anti-patterns.md +365 -0
- package/docs/standards/audit-report.md +388 -0
- package/docs/standards/contribution-guide.md +208 -0
- package/docs/standards/hook-execution-order.md +320 -0
- package/docs/standards/runtime-protection.md +336 -0
- package/docs/standards/state-machine.md +316 -0
- package/docs/standards/templates/agent-template.md +63 -0
- package/docs/standards/templates/hook-template.md +74 -0
- package/docs/standards/templates/skill-template.md +48 -0
- package/docs/standards/user-guide.md +290 -0
- package/docs/tasks/ultrapower-standards/manifest.md +441 -0
- package/package.json +1 -1
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
# ultrapower 全链路规范体系 — 现有实现审计报告
|
|
2
|
+
|
|
3
|
+
> **状态**: 完成
|
|
4
|
+
> **版本**: ultrapower v5.0.22
|
|
5
|
+
> **审计日期**: 2026-02-26
|
|
6
|
+
> **审计范围**: T-01a(Hook/Bridge)+ T-01b(Mode/Agent/State)
|
|
7
|
+
> **产出用途**: 作为 T-02 至 T-09 所有 P0 规范文档的真理之源
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 目录
|
|
12
|
+
|
|
13
|
+
1. [T-01a:Hook/Bridge 审计](#t-01a-hookbridge-审计)
|
|
14
|
+
- 1.1 HookType 完整枚举(15 类)
|
|
15
|
+
- 1.2 Stop 阶段优先级链
|
|
16
|
+
- 1.3 Hook 失败降级策略
|
|
17
|
+
- 1.4 bridge-normalize.ts 白名单覆盖范围
|
|
18
|
+
2. [T-01b:Mode/Agent/State 审计](#t-01b-modeagentstate-审计)
|
|
19
|
+
- 2.1 关键常量
|
|
20
|
+
- 2.2 SubagentStopInput.success 废弃说明
|
|
21
|
+
- 2.3 Windows rename 语义差异
|
|
22
|
+
- 2.4 状态文件并发保护级别对照表
|
|
23
|
+
3. [差异点汇总](#差异点汇总)
|
|
24
|
+
4. [对后续规范任务的影响](#对后续规范任务的影响)
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## T-01a:Hook/Bridge 审计
|
|
29
|
+
|
|
30
|
+
### 1.1 HookType 完整枚举(15 类)
|
|
31
|
+
|
|
32
|
+
来源:`src/hooks/bridge.ts`
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
type HookType =
|
|
36
|
+
| "keyword-detector" // UserPromptSubmit 阶段
|
|
37
|
+
| "stop-continuation" // Stop 阶段(最低优先级)
|
|
38
|
+
| "ralph" // Stop 阶段(最高优先级)
|
|
39
|
+
| "persistent-mode" // Stop 阶段(含 ultrawork,次优先级)
|
|
40
|
+
| "session-start" // Session 生命周期
|
|
41
|
+
| "session-end" // Session 生命周期(敏感)
|
|
42
|
+
| "pre-tool-use" // 工具调用生命周期
|
|
43
|
+
| "post-tool-use" // 工具调用生命周期
|
|
44
|
+
| "autopilot" // Agent 生命周期
|
|
45
|
+
| "subagent-start" // Agent 生命周期
|
|
46
|
+
| "subagent-stop" // Agent 生命周期
|
|
47
|
+
| "pre-compact" // 系统维护
|
|
48
|
+
| "setup-init" // 系统维护(敏感)
|
|
49
|
+
| "setup-maintenance" // 系统维护(敏感)
|
|
50
|
+
| "permission-request"; // 系统维护(敏感,不可静默降级)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**分类表(六个阶段):**
|
|
54
|
+
|
|
55
|
+
| 阶段 | HookType | 必需字段 | 敏感级别 |
|
|
56
|
+
|------|----------|----------|----------|
|
|
57
|
+
| UserPromptSubmit | keyword-detector | `[]`(默认) | 普通 |
|
|
58
|
+
| Stop(P1,最高) | ralph | `[]`(默认) | 普通 |
|
|
59
|
+
| Stop(P1.5) | persistent-mode(含 ultrawork) | `[]`(默认) | 普通 |
|
|
60
|
+
| Stop(P2,最低) | stop-continuation | `[]`(默认) | 普通 |
|
|
61
|
+
| Session 生命周期 | session-start | `[]`(默认) | 普通 |
|
|
62
|
+
| Session 生命周期 | session-end | `["sessionId", "directory"]` | **敏感** |
|
|
63
|
+
| 工具调用生命周期 | pre-tool-use | `[]`(默认) | 普通 |
|
|
64
|
+
| 工具调用生命周期 | post-tool-use | `[]`(默认) | 普通 |
|
|
65
|
+
| Agent 生命周期 | autopilot | `[]`(默认) | 普通 |
|
|
66
|
+
| Agent 生命周期 | subagent-start | `["sessionId", "directory"]` | 普通 |
|
|
67
|
+
| Agent 生命周期 | subagent-stop | `["sessionId", "directory"]` | 普通 |
|
|
68
|
+
| 系统维护 | pre-compact | `["sessionId", "directory"]` | 普通 |
|
|
69
|
+
| 系统维护 | setup-init | `["sessionId", "directory"]` | **敏感** |
|
|
70
|
+
| 系统维护 | setup-maintenance | `["sessionId", "directory"]` | **敏感** |
|
|
71
|
+
| 系统维护 | permission-request | `["sessionId", "directory", "toolName"]` | **敏感,不可静默降级** |
|
|
72
|
+
|
|
73
|
+
**终止开关:**
|
|
74
|
+
- `DISABLE_OMC` 环境变量:禁用所有 hooks
|
|
75
|
+
- `OMC_SKIP_HOOKS` 环境变量:按逗号分隔名称跳过特定 hooks
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
### 1.2 Stop 阶段优先级链
|
|
80
|
+
|
|
81
|
+
来源:`src/hooks/persistent-mode/index.ts`
|
|
82
|
+
|
|
83
|
+
**实际代码中的优先级(与 PRD 注释存在差异,见差异点 D-02):**
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
Ralph(P1,最高优先级)
|
|
87
|
+
↓ 未处理时
|
|
88
|
+
Autopilot(P1.5,次优先级)
|
|
89
|
+
↓ 未处理时
|
|
90
|
+
Ultrawork/persistent-mode(P2,最低优先级)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**互斥规则:** 高优先级 hook 处理后,低优先级 hook 不得重复处理同一 Stop 事件。
|
|
94
|
+
|
|
95
|
+
**Ralph 自动扩展:** 当 ralph 达到 max_iterations 限制时,自动追加 +10 次迭代(`MAX_TODO_CONTINUATION_ATTEMPTS = 5`)。
|
|
96
|
+
|
|
97
|
+
**重要:** `createHookOutput()` 函数**始终**返回 `{ continue: true }`,这是设计决策(软执行,不阻塞用户工作流):
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
export function createHookOutput(result: PersistentModeResult): {
|
|
101
|
+
continue: boolean; message?: string;
|
|
102
|
+
} {
|
|
103
|
+
return { continue: true, message: result.message || undefined };
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
### 1.3 Hook 失败降级策略
|
|
110
|
+
|
|
111
|
+
来源:`src/hooks/bridge.ts`
|
|
112
|
+
|
|
113
|
+
**通用策略(静默降级):**
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
try {
|
|
117
|
+
// hook 执行逻辑
|
|
118
|
+
} catch (error) {
|
|
119
|
+
return { continue: true }; // 静默降级,不阻塞用户工作流
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**例外:permission-request(不可静默降级)**
|
|
124
|
+
|
|
125
|
+
permission-request 是安全边界,失败时**理论上**不应静默降级。但当前代码实现中,`createHookOutput()` 对所有类型统一返回 `{ continue: true }`(见差异点 D-05)。
|
|
126
|
+
|
|
127
|
+
**规范要求(待实现):** permission-request 类型失败时必须阻塞,不得返回 `{ continue: true }`。
|
|
128
|
+
|
|
129
|
+
**Hook 超时处理(当前代码未见明确超时限制):**
|
|
130
|
+
- 规范要求:PreToolUse hook 超时(默认 5s)时,Claude 继续执行工具调用(不阻塞)
|
|
131
|
+
- 规范要求:PostToolUse hook 超时时,状态写入标记为"待重试",不回滚已执行的工具调用
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
### 1.4 bridge-normalize.ts 白名单覆盖范围
|
|
136
|
+
|
|
137
|
+
来源:`src/hooks/bridge-normalize.ts`
|
|
138
|
+
|
|
139
|
+
**敏感 Hook 白名单(严格过滤,未知字段被丢弃):**
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
const SENSITIVE_HOOKS = new Set([
|
|
143
|
+
'permission-request',
|
|
144
|
+
'setup-init',
|
|
145
|
+
'setup-maintenance',
|
|
146
|
+
'session-end'
|
|
147
|
+
]);
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**当前覆盖:4 类**(见差异点 D-01:PRD 说 3 类,实际是 4 类)
|
|
151
|
+
|
|
152
|
+
**非敏感 Hook 处理(透传,仅记录 debug 警告):**
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
function filterPassthrough(input, hookType) {
|
|
156
|
+
const isSensitive = hookType != null && SENSITIVE_HOOKS.has(hookType);
|
|
157
|
+
if (isSensitive) {
|
|
158
|
+
// 严格白名单:只允许 KNOWN_FIELDS,丢弃其他字段
|
|
159
|
+
} else {
|
|
160
|
+
// 非敏感:未知字段透传,仅记录 debug 警告(见差异点 D-06)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**规范要求(待实现):** 将白名单扩展至全部 15 类 HookType,每类明确必需字段和禁止字段。
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## T-01b:Mode/Agent/State 审计
|
|
170
|
+
|
|
171
|
+
### 2.1 关键常量
|
|
172
|
+
|
|
173
|
+
**来源:`src/hooks/subagent-tracker/index.ts`**
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
export const COST_LIMIT_USD = 1.0; // 成本限制:1.0 美元
|
|
177
|
+
export const DEADLOCK_CHECK_THRESHOLD = 3; // 死锁检测:连续 3 次相同工具调用
|
|
178
|
+
const STALE_THRESHOLD_MS = 5 * 60 * 1000; // Agent stale 阈值:5 分钟
|
|
179
|
+
const WRITE_DEBOUNCE_MS = 100; // 写入防抖:100ms
|
|
180
|
+
const MAX_FLUSH_RETRIES = 3; // 最大刷新重试次数
|
|
181
|
+
const LOCK_TIMEOUT_MS = 5000; // 锁超时:5 秒
|
|
182
|
+
const MAX_COMPLETED_AGENTS = 100; // 最大已完成 agent 记录数
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
**来源:`src/hooks/mode-registry/index.ts`**
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
const STALE_MARKER_THRESHOLD = 60 * 60 * 1000; // 模式 stale marker 阈值:1 小时
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
**注意:** 两个"stale"阈值用途不同(见差异点 D-09):
|
|
192
|
+
- `STALE_MARKER_THRESHOLD`(1 小时):用于模式状态文件的 stale marker 检测
|
|
193
|
+
- `STALE_THRESHOLD_MS`(5 分钟):用于 agent 运行状态的 stale 检测
|
|
194
|
+
|
|
195
|
+
**来源:`src/hooks/mode-registry/index.ts`**
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
// 8 个注册模式(见差异点 D-03:PRD 说 7 个,实际 8 个)
|
|
199
|
+
const MODE_CONFIGS = {
|
|
200
|
+
autopilot, ultrapilot, swarm, pipeline, team, ralph, ultrawork, ultraqa
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
// 互斥模式(见差异点 D-04)
|
|
204
|
+
const EXCLUSIVE_MODES = ['autopilot', 'ultrapilot', 'swarm', 'pipeline'];
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**Agent 边界情况矩阵(来源:subagent-tracker/index.ts):**
|
|
208
|
+
|
|
209
|
+
| 边界情况 | 触发条件 | 处理策略 |
|
|
210
|
+
|---------|---------|---------|
|
|
211
|
+
| 超时 | `STALE_THRESHOLD_MS = 5 * 60 * 1000`(5 分钟) | 标记为 stale,触发清理 |
|
|
212
|
+
| 孤儿状态 | 父 session 结束但 agent 仍在运行 | session-end hook 触发孤儿检测,强制 SHUTDOWN |
|
|
213
|
+
| 成本超限 | `COST_LIMIT_USD = 1.0` | 触发强制终止,记录到 last-tool-error.json |
|
|
214
|
+
| 死锁检测 | `DEADLOCK_CHECK_THRESHOLD = 3`(连续 3 次相同工具调用) | 触发 AgentIntervention,中断执行 |
|
|
215
|
+
|
|
216
|
+
**AgentIntervention 类型:**
|
|
217
|
+
```typescript
|
|
218
|
+
type AgentInterventionType = "timeout" | "deadlock" | "excessive_cost" | "file_conflict";
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
### 2.2 SubagentStopInput.success 废弃说明
|
|
224
|
+
|
|
225
|
+
来源:`src/hooks/subagent-tracker/index.ts`,第 ~102 行
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
export interface SubagentStopInput {
|
|
229
|
+
session_id: string;
|
|
230
|
+
transcript_path: string;
|
|
231
|
+
cwd: string;
|
|
232
|
+
permission_mode: string;
|
|
233
|
+
hook_event_name: "SubagentStop";
|
|
234
|
+
agent_id: string;
|
|
235
|
+
agent_type: string;
|
|
236
|
+
output?: string;
|
|
237
|
+
/** @deprecated The SDK does not provide a success field. Use inferred status instead. */
|
|
238
|
+
success?: boolean;
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
**推断机制(当前实现):**
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
const succeeded = input.success !== false;
|
|
246
|
+
// 当 success 为 undefined 时,默认推断为成功(true)
|
|
247
|
+
// 只有明确传入 false 时才视为失败
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
**规范要求:** 实现者不得假设可以直接读取 `success` 字段,必须使用推断机制。
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
### 2.3 Windows rename 语义差异
|
|
255
|
+
|
|
256
|
+
来源:`src/lib/atomic-write.ts`
|
|
257
|
+
|
|
258
|
+
**原子写入完整流程:**
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
export function atomicWriteFileSync(filePath: string, content: string): void {
|
|
262
|
+
ensureDirSync(dir);
|
|
263
|
+
// 1. 独占创建临时文件(wx 标志 = O_CREAT|O_EXCL|O_WRONLY,权限 0o600)
|
|
264
|
+
const tmpPath = path.join(dir, `.${base}.tmp.${randomUUID()}`);
|
|
265
|
+
const fd = fs.openSync(tmpPath, 'wx', 0o600);
|
|
266
|
+
// 2. 写入内容
|
|
267
|
+
fs.writeSync(fd, content, 0, 'utf8');
|
|
268
|
+
// 3. fsync 落盘
|
|
269
|
+
fs.fsyncSync(fd);
|
|
270
|
+
fs.closeSync(fd);
|
|
271
|
+
// 4. rename 替换(原子操作)
|
|
272
|
+
fs.renameSync(tmpPath, filePath);
|
|
273
|
+
// 5. 目录级 fsync(best-effort,Windows 上可能失败,已捕获异常)
|
|
274
|
+
try {
|
|
275
|
+
const dirFd = fs.openSync(dir, 'r');
|
|
276
|
+
fs.fsyncSync(dirFd);
|
|
277
|
+
fs.closeSync(dirFd);
|
|
278
|
+
} catch {
|
|
279
|
+
// Some platforms don't support directory fsync - that's okay
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
**Windows 平台差异:**
|
|
285
|
+
- Windows 上 `fs.rename` 使用 `MoveFileExW with MOVEFILE_REPLACE_EXISTING`
|
|
286
|
+
- 当目标文件被其他进程持有时会**失败**(不同于 POSIX 的原子替换语义)
|
|
287
|
+
- 代码已处理此情况:目录级 fsync 失败时静默捕获异常
|
|
288
|
+
- **规范要求:** 实现者不得假设 Windows 和 POSIX 的 rename 行为一致
|
|
289
|
+
|
|
290
|
+
**文件权限:** 所有原子写入文件权限为 `0o600`(仅所有者可读写)
|
|
291
|
+
|
|
292
|
+
**safeReadJson 行为:**
|
|
293
|
+
```typescript
|
|
294
|
+
export function safeReadJson<T>(filePath: string): T | null {
|
|
295
|
+
// ENOENT 或 JSON.parse 失败时返回 null(不崩溃)
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
### 2.4 状态文件并发保护级别对照表
|
|
302
|
+
|
|
303
|
+
来源:`src/hooks/subagent-tracker/index.ts`、`src/lib/atomic-write.ts`
|
|
304
|
+
|
|
305
|
+
| 状态文件 | 并发保护机制 | 保护级别 |
|
|
306
|
+
|---------|------------|---------|
|
|
307
|
+
| `subagent-tracking.json` | debounce(100ms)+ flushInProgress Set + mergeTrackerStates + 文件锁(PID:timestamp) | **最高**(四层保护) |
|
|
308
|
+
| `team-state.json` | atomicWriteJsonSync | 中(原子写入,无 debounce) |
|
|
309
|
+
| `ralph-state.json` | atomicWriteJsonSync | 中(原子写入,无 debounce) |
|
|
310
|
+
| `autopilot-state.json` | atomicWriteJsonSync | 中(原子写入,无 debounce) |
|
|
311
|
+
| 其他 `*-state.json` | atomicWriteJsonSync | 中(原子写入,无 debounce) |
|
|
312
|
+
| subagent-tracker 内部即时写入 | `writeFileSync`(直接写入,见差异点 D-07) | **低**(无原子保护) |
|
|
313
|
+
|
|
314
|
+
**subagent-tracking.json 锁机制详情:**
|
|
315
|
+
- 锁文件格式:`PID:timestamp`
|
|
316
|
+
- stale 检测:锁持有超过 5 秒,或持有进程已死亡
|
|
317
|
+
- 等待机制:`Atomics.wait`(syncSleep)
|
|
318
|
+
- 锁超时:`LOCK_TIMEOUT_MS = 5000`(5 秒)
|
|
319
|
+
|
|
320
|
+
**mergeTrackerStates 合并策略:**
|
|
321
|
+
- 计数器(tool_calls、cost 等):取 `Math.max`
|
|
322
|
+
- 同一 agent_id 的状态:newer timestamp wins
|
|
323
|
+
|
|
324
|
+
**规范目标:**
|
|
325
|
+
- v1:明确记录此不一致性(本文档已完成)
|
|
326
|
+
- v2:统一为 debounce + atomic 双层保护
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## 差异点汇总
|
|
331
|
+
|
|
332
|
+
以下差异点均为 PRD/manifest 描述与实际代码实现之间的不符项。
|
|
333
|
+
|
|
334
|
+
| 编号 | 差异描述 | PRD/manifest 描述 | 实际代码 | 影响任务 |
|
|
335
|
+
|------|---------|------------------|---------|---------|
|
|
336
|
+
| D-01 | 敏感 hook 数量 | "3 类(permission-request、setup、session-end)" | 4 类(setup 拆分为 setup-init + setup-maintenance) | T-03a、T-04a |
|
|
337
|
+
| D-02 | Stop 阶段优先级链 | "Ralph > Ultrawork > Todo-Continuation" | Ralph > Autopilot > Ultrawork(Todo-Continuation 已移除) | T-04b |
|
|
338
|
+
| D-03 | 合法 mode 数量 | "7 个合法值" | 8 个(包含 swarm) | T-03b、T-07 |
|
|
339
|
+
| D-04 | 互斥模式范围 | "autopilot 与 ultrapilot 互斥" | EXCLUSIVE_MODES = ['autopilot', 'ultrapilot', 'swarm', 'pipeline'](4 个互斥) | T-05 |
|
|
340
|
+
| D-05 | permission-request 失败处理 | "不可静默降级,失败时必须阻塞" | `createHookOutput()` 对所有类型统一返回 `{ continue: true }` | T-03a、T-04b |
|
|
341
|
+
| D-06 | 非敏感 hook 未知字段处理 | "未知字段被丢弃" | 非敏感 hook 的未知字段透传,仅记录 debug 警告 | T-03a |
|
|
342
|
+
| D-07 | subagent-tracker 内部写入 | "所有状态文件写入必须使用 atomicWriteJsonSync" | `writeTrackingStateImmediate` 使用 `writeFileSync` 直接写入 | T-03b |
|
|
343
|
+
| D-08 | DEADLOCK_CHECK_THRESHOLD 使用位置 | 在 subagent-tracker 中使用 | 在 subagent-tracker 中定义并导出,但未在该文件内使用(由外部调用方使用) | T-06 |
|
|
344
|
+
| D-09 | stale 阈值含义 | 未区分两种 stale 阈值 | 两个不同概念:mode stale(1 小时)vs agent stale(5 分钟) | T-05、T-06 |
|
|
345
|
+
| D-10 | 死锁检测未实现 | "DEADLOCK_CHECK_THRESHOLD 用于死锁检测" | 常量已定义并导出,但死锁检测逻辑未在代码中实现 | T-06 |
|
|
346
|
+
|
|
347
|
+
**差异点数量:10 个**(满足验收条件:差异点数量 ≥ 0)
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
## 对后续规范任务的影响
|
|
352
|
+
|
|
353
|
+
### T-02(规范体系入口 README.md)
|
|
354
|
+
- 无直接影响,按原计划执行
|
|
355
|
+
|
|
356
|
+
### T-03a(Hook 输入防护规范)
|
|
357
|
+
- **D-01**:敏感 hook 白名单应为 4 类,不是 3 类
|
|
358
|
+
- **D-05**:permission-request 当前实现未阻塞,规范需明确要求修复
|
|
359
|
+
- **D-06**:非敏感 hook 未知字段透传,规范需明确要求扩展白名单至 15 类
|
|
360
|
+
|
|
361
|
+
### T-03b(State/Mode 防护规范)
|
|
362
|
+
- **D-03**:validateMode 白名单应包含 8 个合法值(含 swarm)
|
|
363
|
+
- **D-07**:`writeTrackingStateImmediate` 使用直接写入,规范需记录此不一致性
|
|
364
|
+
|
|
365
|
+
### T-04a(HookType 枚举与路由规范)
|
|
366
|
+
- **D-01**:setup 类型需拆分为 setup-init 和 setup-maintenance 分别描述
|
|
367
|
+
|
|
368
|
+
### T-04b(执行顺序与优先级规范)
|
|
369
|
+
- **D-02**:Stop 阶段优先级链需更新为 Ralph > Autopilot > Ultrawork
|
|
370
|
+
- **D-05**:permission-request 失败处理需明确当前实现与规范要求的差距
|
|
371
|
+
|
|
372
|
+
### T-05(状态机规范)
|
|
373
|
+
- **D-04**:互斥模式规则需更新为 4 个互斥模式
|
|
374
|
+
- **D-09**:需区分 mode stale(1 小时)和 agent stale(5 分钟)两个概念
|
|
375
|
+
|
|
376
|
+
### T-06(Agent 生命周期规范)
|
|
377
|
+
- **D-08**:DEADLOCK_CHECK_THRESHOLD 的实际使用位置需进一步确认
|
|
378
|
+
- **D-09**:agent stale 阈值(5 分钟)与 mode stale 阈值(1 小时)需分别说明
|
|
379
|
+
|
|
380
|
+
### T-07(validateMode.ts 实现)
|
|
381
|
+
- **D-03**:VALID_MODES 应包含 8 个值:`['autopilot', 'ultrapilot', 'team', 'pipeline', 'ralph', 'ultrawork', 'ultraqa', 'swarm']`
|
|
382
|
+
|
|
383
|
+
### T-08a/T-08b(用户指南)
|
|
384
|
+
- **D-04**:autopilot 与 ultrapilot 互斥说明需扩展为 4 个互斥模式的说明
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
*审计报告完成。本文档作为 T-02 至 T-09 所有 P0 规范文档的真理之源,后续规范编写必须以本报告为准,不得凭空撰写。*
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# 贡献规范
|
|
2
|
+
|
|
3
|
+
> **ultrapower-version**: 5.0.21
|
|
4
|
+
> **优先级**: P1(推荐遵守)
|
|
5
|
+
> **真理之源**: `docs/standards/audit-report.md`
|
|
6
|
+
> **覆盖范围**: T-10(贡献者工作流 + 质量门禁)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 目录
|
|
11
|
+
|
|
12
|
+
1. [贡献前准备](#1-贡献前准备)
|
|
13
|
+
2. [分支策略](#2-分支策略)
|
|
14
|
+
3. [代码规范](#3-代码规范)
|
|
15
|
+
4. [质量门禁](#4-质量门禁)
|
|
16
|
+
5. [文档更新要求](#5-文档更新要求)
|
|
17
|
+
6. [PR 提交流程](#6-pr-提交流程)
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 1. 贡献前准备
|
|
22
|
+
|
|
23
|
+
### 1.1 环境要求
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
node >= 18
|
|
27
|
+
npm >= 9
|
|
28
|
+
TypeScript >= 5.0
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### 1.2 安装依赖
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 1.3 验证环境
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm run build # TypeScript 编译
|
|
41
|
+
npm test # 运行测试套件
|
|
42
|
+
npm run lint # ESLint 检查
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 2. 分支策略
|
|
48
|
+
|
|
49
|
+
**默认基础分支:`dev`**(不是 `main`)
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# 从 dev 创建功能分支
|
|
53
|
+
git checkout dev
|
|
54
|
+
git pull origin dev
|
|
55
|
+
git checkout -b feat/your-feature-name
|
|
56
|
+
|
|
57
|
+
# 使用 worktree 隔离(推荐)
|
|
58
|
+
git worktree add ../ultrapower-feat -b feat/your-feature-name dev
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**禁止**:直接向 `main` 提交或创建以 `main` 为目标的 PR。
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## 3. 代码规范
|
|
66
|
+
|
|
67
|
+
### 3.1 TypeScript 规范
|
|
68
|
+
|
|
69
|
+
- 所有公共 API 必须有 JSDoc 注释
|
|
70
|
+
- 使用 `as const` 定义枚举类型常量
|
|
71
|
+
- 安全边界函数必须接受 `unknown` 类型参数
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
// ✅ 正确示例
|
|
75
|
+
/**
|
|
76
|
+
* 校验 mode 参数,防止路径遍历。
|
|
77
|
+
* @param mode - 待校验的输入
|
|
78
|
+
* @returns 若为合法 mode 则返回 true
|
|
79
|
+
*/
|
|
80
|
+
export function validateMode(mode: unknown): mode is ValidMode {
|
|
81
|
+
return typeof mode === 'string' && (VALID_MODES as readonly string[]).includes(mode);
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 3.2 安全规范
|
|
86
|
+
|
|
87
|
+
- mode 参数用于路径构建前必须调用 `assertValidMode()`
|
|
88
|
+
- 禁止直接字符串插值未校验的用户输入到文件路径
|
|
89
|
+
- 详见 `docs/standards/runtime-protection.md` §2.4
|
|
90
|
+
|
|
91
|
+
### 3.3 提交信息规范
|
|
92
|
+
|
|
93
|
+
格式:`type(scope): description`(英文)
|
|
94
|
+
|
|
95
|
+
| type | 用途 |
|
|
96
|
+
|------|------|
|
|
97
|
+
| `feat` | 新功能 |
|
|
98
|
+
| `fix` | Bug 修复 |
|
|
99
|
+
| `docs` | 文档更新 |
|
|
100
|
+
| `refactor` | 重构(不改变行为) |
|
|
101
|
+
| `test` | 测试相关 |
|
|
102
|
+
| `chore` | 构建/工具链 |
|
|
103
|
+
|
|
104
|
+
示例:
|
|
105
|
+
```
|
|
106
|
+
feat(validateMode): add path traversal protection for mode parameter
|
|
107
|
+
fix(subagent-tracker): use inferred success status instead of deprecated field
|
|
108
|
+
docs(standards): add anti-patterns guide
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## 4. 质量门禁
|
|
114
|
+
|
|
115
|
+
所有 PR 合并前必须通过以下门禁:
|
|
116
|
+
|
|
117
|
+
### 4.1 CI Gate(必须)
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
tsc --noEmit # 零类型错误
|
|
121
|
+
npm run build # 构建成功
|
|
122
|
+
npm test # 所有测试通过
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### 4.2 安全检查(必须)
|
|
126
|
+
|
|
127
|
+
- 无未校验的 mode 参数路径拼接
|
|
128
|
+
- 无 `SubagentStopInput.success` 直接读取
|
|
129
|
+
- 无敏感信息写入状态文件
|
|
130
|
+
|
|
131
|
+
### 4.3 文档同步(必须)
|
|
132
|
+
|
|
133
|
+
修改以下内容时,对应文档必须同步更新:
|
|
134
|
+
|
|
135
|
+
| 修改内容 | 必须更新 |
|
|
136
|
+
|---------|---------|
|
|
137
|
+
| `agents/*.md` | `src/agents/definitions.ts`、`docs/REFERENCE.md` |
|
|
138
|
+
| `skills/*/SKILL.md` | `commands/*.md`(镜像) |
|
|
139
|
+
| `src/hooks/*` | `src/hooks/index.ts`、`src/hooks/bridge.ts` |
|
|
140
|
+
| 新执行模式 | `src/lib/validateMode.ts` 的 `VALID_MODES` |
|
|
141
|
+
| 工具定义 | `src/tools/index.ts`、`docs/REFERENCE.md` |
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## 5. 文档更新要求
|
|
146
|
+
|
|
147
|
+
### 5.1 新增执行模式
|
|
148
|
+
|
|
149
|
+
新增 mode 时必须同步更新:
|
|
150
|
+
|
|
151
|
+
1. `src/lib/validateMode.ts` — 将新 mode 加入 `VALID_MODES`
|
|
152
|
+
2. `src/__tests__/validateMode.test.ts` — 更新测试中的期望数量和值
|
|
153
|
+
3. `docs/standards/state-machine.md` — 更新状态文件路径表
|
|
154
|
+
4. `docs/CLAUDE.md` — 更新 `state_write` 支持的模式列表
|
|
155
|
+
5. `AGENTS.md` — 更新执行模式表
|
|
156
|
+
|
|
157
|
+
### 5.2 新增 Agent
|
|
158
|
+
|
|
159
|
+
新增 agent 时必须同步更新:
|
|
160
|
+
|
|
161
|
+
1. `agents/<name>.md` — agent 提示模板
|
|
162
|
+
2. `src/agents/definitions.ts` — agent 定义注册
|
|
163
|
+
3. `docs/REFERENCE.md` — agent 列表
|
|
164
|
+
4. `AGENTS.md` — agent 概览表
|
|
165
|
+
|
|
166
|
+
### 5.3 差异点记录
|
|
167
|
+
|
|
168
|
+
发现代码与规范不一致时:
|
|
169
|
+
|
|
170
|
+
1. 在 `docs/standards/audit-report.md` 中记录新差异点(D-XX 格式)
|
|
171
|
+
2. 在对应规范文档的"差异点说明"章节引用
|
|
172
|
+
3. 在 `docs/standards/anti-patterns.md` 中添加对应反模式
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## 6. PR 提交流程
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
# 1. 确保基于最新 dev
|
|
180
|
+
git fetch origin
|
|
181
|
+
git rebase origin/dev
|
|
182
|
+
|
|
183
|
+
# 2. 运行质量门禁
|
|
184
|
+
tsc --noEmit && npm run build && npm test
|
|
185
|
+
|
|
186
|
+
# 3. 创建 PR(目标分支必须是 dev)
|
|
187
|
+
gh pr create --base dev \
|
|
188
|
+
--title "feat(scope): description" \
|
|
189
|
+
--body "## 变更说明\n\n## 测试验证\n\n## 文档更新"
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**PR 描述模板**:
|
|
193
|
+
|
|
194
|
+
```markdown
|
|
195
|
+
## 变更说明
|
|
196
|
+
<!-- 简述本次变更的目的和内容 -->
|
|
197
|
+
|
|
198
|
+
## 测试验证
|
|
199
|
+
<!-- 列出运行的测试命令和结果 -->
|
|
200
|
+
- [ ] `tsc --noEmit` 通过
|
|
201
|
+
- [ ] `npm run build` 通过
|
|
202
|
+
- [ ] `npm test` 通过
|
|
203
|
+
|
|
204
|
+
## 文档更新
|
|
205
|
+
<!-- 列出同步更新的文档 -->
|
|
206
|
+
- [ ] 相关规范文档已更新
|
|
207
|
+
- [ ] AGENTS.md 已更新(如适用)
|
|
208
|
+
```
|