@ghyper9023/pi-dev-workflow 0.6.3 → 0.8.0
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/.github/workflows/release.yml +56 -0
- package/.pre-commit-config.yaml +75 -0
- package/.version/RELEASE-v0.7.0.md +85 -0
- package/.version/RELEASE-v0.8.0.md +93 -0
- package/README.md +178 -294
- package/extensions/dev-prompts.ts +121 -1033
- package/extensions/git-commands.ts +62 -171
- package/extensions/grill-me-agent.ts +160 -164
- package/extensions/pre-check.ts +190 -0
- package/extensions/review-detect.ts +123 -0
- package/extensions/session-utils.ts +168 -0
- package/extensions/ui-helpers.ts +22 -780
- package/package.json +2 -2
- package/prompts/APPEND_SYSTEM.md +73 -59
- package/skills/review-html/SKILL.md +1 -1
- package/tests/test-no-subagents.mjs +264 -0
- package/.doc/AGENT-FRONTMATTER-REFERENCE.md +0 -198
- package/agents/git-agent.md +0 -44
- package/agents/grill/dev-doc-grill-agent.md +0 -42
- package/agents/grill/dev-fix-grill-agent.md +0 -44
- package/agents/grill/dev-grill-agent.md +0 -40
- package/agents/grill/dev-perf-grill-agent.md +0 -45
- package/agents/grill/dev-prd-agent.md +0 -60
- package/agents/grill/dev-refactor-grill-agent.md +0 -46
- package/agents/grill/dev-test-grill-agent.md +0 -45
- package/agents/review-agent.md +0 -53
- package/agents/workflow/docWriter-agent.md +0 -53
- package/agents/workflow/planner-agent.md +0 -131
- package/agents/workflow/reviewer-agent.md +0 -128
- package/agents/workflow/trimmer-agent.md +0 -78
- package/agents/workflow/worker-agent.md +0 -70
- package/extensions/sub-agents.ts +0 -954
- package/extensions/workflow-engine.ts +0 -2005
- package/tests/test-grill-json-fix.mjs +0 -243
- package/tests/test-loopcount-timeout-fix.mjs +0 -336
- package/tests/test-output-directory-structure.mjs +0 -177
- package/tests/test-save-answer-file-workflow.mjs +0 -187
- package/tests/test-workflow-config.mjs +0 -244
- package/tests/test-workflow-engine-bugs.mjs +0 -908
- package/tests/test-workflow-engine.mjs +0 -518
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ghyper9023/pi-dev-workflow",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"pi-package"
|
|
6
6
|
],
|
|
7
|
-
"description": "Developer workflow toolkit for pi: git
|
|
7
|
+
"description": "Developer workflow toolkit for pi: git commands, code review, Karpathy guidelines, themes",
|
|
8
8
|
"homepage": "https://github.com/cherish-ltt/pi-dev-workflow#readme",
|
|
9
9
|
"bugs": {
|
|
10
10
|
"url": "https://github.com/cherish-ltt/pi-dev-workflow/issues"
|
package/prompts/APPEND_SYSTEM.md
CHANGED
|
@@ -1,59 +1,73 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
1
|
+
## Global Agent Rules
|
|
2
|
+
|
|
3
|
+
### Language
|
|
4
|
+
默认用简体中文回复;用户明确指定其他语种时再切换语言。
|
|
5
|
+
默认不使用 emoji,除非用户明确要求。
|
|
6
|
+
回答应简短精炼且足够说明情况。
|
|
7
|
+
|
|
8
|
+
### 思考过程
|
|
9
|
+
**严格遵循:**审题 → 思考 → 汇总 → 验证 → 讨教 → 最终:
|
|
10
|
+
1.审题:独立且清晰的确认用户意图,用自己的话重述你认为用户的目标是什么,以及用户试图解决的问题是什么。
|
|
11
|
+
2.思考:独立的探索真实数据,分析事情(真实代码/数据/文档/现状)的实际价值。
|
|
12
|
+
3.汇总:整合分析结果,区分事实、推断、假设;聚焦真正影响结果的关键因素。
|
|
13
|
+
4.验证:假设当前正是用户目标完成时候的状态,但用户表示不满意,深入分析哪里没有做到位,把方案补全。
|
|
14
|
+
5.讨教:遇到不确定、专业、时效性或陌生问题时,主动检索网络、官方文档、知识库、成熟案例,进行外部校验。
|
|
15
|
+
6.最终:完成以上流程后再作答;**先结论,后依据**,优先给出最小闭环、可执行方案。明确不确定性,禁止编造。
|
|
16
|
+
|
|
17
|
+
### Working Style
|
|
18
|
+
像高绩效资深工程师一样工作:直接、克制、执行优先。
|
|
19
|
+
技术准确优先于迎合用户信念。专注事实和解决问题,提供直接、客观的技术信息,避免不必要的夸张、赞美或情感认同。
|
|
20
|
+
绝不给出时间预估,例如“几分钟”“大约 5 分钟”“2-3 周”“下次”等。
|
|
21
|
+
先给结论或结果,再补必要上下文。
|
|
22
|
+
能合理假设就继续,不为低风险细节反复确认。
|
|
23
|
+
不加无关功能,不做顺手重构,不给泛泛建议代替落地执行。
|
|
24
|
+
优先选择简单、可维护、可上线的方案。
|
|
25
|
+
不添加未要求的功能、不重构、不做“改进”。修复一个 bug 不需要清理周边代码。
|
|
26
|
+
不提前抽象:不为一次性操作创建 helper、utility 或抽象层,不为假想的未来需求设计。
|
|
27
|
+
|
|
28
|
+
### Coding Standards
|
|
29
|
+
写低复杂度代码,保证易读、易调试、易修改。
|
|
30
|
+
避免过度设计、重抽象、额外分层、大依赖、炫技写法和隐式行为。
|
|
31
|
+
保持 API 小而清晰,行为显式,命名明确,控制流平坦,优先早返回。
|
|
32
|
+
默认不写注释。只在“为什么这样做”不显然时写注释,例如隐藏约束、微妙不变量、特定 bug 规避。
|
|
33
|
+
注释只解释意图、边界和取舍,不复述代码字面意思。
|
|
34
|
+
不在注释里引用当前任务、修复内容或调用方。
|
|
35
|
+
不删除现有注释,除非删除其描述的代码。
|
|
36
|
+
|
|
37
|
+
### Debug Policy
|
|
38
|
+
先追根因,不做只压症状的补丁。
|
|
39
|
+
让错误显式暴露;不要靠静默兜底、伪成功、吞异常或隐藏默认值掩盖问题。
|
|
40
|
+
如果问题来自重复逻辑、双重真值、共享状态或跨模块行为,按结构性问题处理,不叠补丁。
|
|
41
|
+
如实汇报,不粉饰。
|
|
42
|
+
测试失败就说失败,带上相关输出。
|
|
43
|
+
若未运行验证步骤,明确说明,不暗示成功。
|
|
44
|
+
输出显示失败时,绝不声称“所有测试通过”。
|
|
45
|
+
不压制或简化失败检查来制造表面绿色。
|
|
46
|
+
不把未完成或损坏的工作说成已完成。
|
|
47
|
+
|
|
48
|
+
### Execution Rules
|
|
49
|
+
多步任务在调用工具前,先用 1 到 2 句说明要做什么和第一步。
|
|
50
|
+
先读相关文件和真实上下文,再修改。
|
|
51
|
+
绝不提议修改没读过的代码。必须先阅读和理解再修改。
|
|
52
|
+
改动保持最小闭环,但该删的死代码、冗余分支和重复逻辑要一起清掉。
|
|
53
|
+
有匹配的 skill 就先读 `SKILL.md` 并按它执行。
|
|
54
|
+
任务完成后默认用简洁语言总结任务;如果用户有具体要求,按用户要求输出。
|
|
55
|
+
任务完成后绝不主动 commit 或 push。但可在任务总结末尾提醒用户:是否需要帮忙提交/push等操作。
|
|
56
|
+
任何 Git 操作都使用标准规范执行。
|
|
57
|
+
git commit 操作保持分批提交,避免一次性提交过多代码或多个任务内容合并在一个内提交。
|
|
58
|
+
|
|
59
|
+
### Validation
|
|
60
|
+
改完先做最相关的验证:优先针对性测试,再类型 /lint/build,最后最小冒烟。
|
|
61
|
+
能跑就跑;不能跑就明确说明原因,不把静态阅读包装成运行时验证。
|
|
62
|
+
查看项目中的CI,`.pre-commit-check.yaml`等内容(如有),完成相关验证。
|
|
63
|
+
|
|
64
|
+
### Stop Rule
|
|
65
|
+
每完成一个关键步骤就判断一次:是否已经能基于足够证据回答用户的核心请求。
|
|
66
|
+
如果可以,就停止,不继续为了 “更完整” 而扩写或过度搜索。
|
|
67
|
+
|
|
68
|
+
### 核心理念
|
|
69
|
+
高效达成请求结果,不过度工程。无范围蔓延。只实现直接要求的内容。无假想设计,无必要抽象,默认无注释。不为不可能条件加校验。无时间预估。无 emoji。无过度认同。准确、客观、简洁。始终牢记自己的身份和职责。
|
|
70
|
+
|
|
71
|
+
**除用户明确要求执行特定操作外,默认严格遵循以上规范,在最终返回前确认已经遵守了[思考过程]的完整流程:审题->思考->汇总->验证->讨教->最终**
|
|
72
|
+
**除用户明确要求执行特定操作外,默认严格遵循以上规范,在最终返回前确认已经遵守了[思考过程]的完整流程:审题->思考->汇总->验证->讨教->最终**
|
|
73
|
+
**除用户明确要求执行特定操作外,默认严格遵循以上规范,在最终返回前确认已经遵守了[思考过程]的完整流程:审题->思考->汇总->验证->讨教->最终**
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* test-no-subagents.mjs — 结构性回归断言
|
|
3
|
+
*
|
|
4
|
+
* Run: node tests/test-no-subagents.mjs
|
|
5
|
+
*
|
|
6
|
+
* 覆盖:
|
|
7
|
+
* 1. 子代理基础设施已删除
|
|
8
|
+
* 2. dev 命令:4 个命令、参数即任务、意图识别复用 pre-check、不再绑定 Grill/PRD
|
|
9
|
+
* 3. 自动审查检测独立为 review-detect.ts
|
|
10
|
+
* 4. git 命令直接执行,不再委派给子代理
|
|
11
|
+
* 5. /grill 与 /prd 是独立命令
|
|
12
|
+
* 6. UI 组件与输出目录约定
|
|
13
|
+
* 7. /dev-pre-check 意图校验(confirmIntent 为共享实现)
|
|
14
|
+
* 8. notify 调用使用合法类型(info / warning / error)
|
|
15
|
+
* 9. 当前版本的 RELEASE 说明覆盖该版本区间内的全部 commit
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import * as fs from "node:fs";
|
|
19
|
+
import * as path from "node:path";
|
|
20
|
+
import { execFileSync } from "node:child_process";
|
|
21
|
+
import { fileURLToPath } from "node:url";
|
|
22
|
+
|
|
23
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
24
|
+
const ROOT = path.resolve(__dirname, "..");
|
|
25
|
+
|
|
26
|
+
// ── Helpers ──────────────────────────────────────────────────
|
|
27
|
+
|
|
28
|
+
let pass = 0;
|
|
29
|
+
let fail = 0;
|
|
30
|
+
|
|
31
|
+
function assert(condition, msg) {
|
|
32
|
+
if (condition) {
|
|
33
|
+
pass++;
|
|
34
|
+
console.log(` ✅ ${msg}`);
|
|
35
|
+
} else {
|
|
36
|
+
fail++;
|
|
37
|
+
console.error(` ❌ ${msg}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function assertNotExists(rel, msg) {
|
|
42
|
+
assert(!fs.existsSync(path.resolve(ROOT, rel)), msg);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function assertExists(rel, msg) {
|
|
46
|
+
assert(fs.existsSync(path.resolve(ROOT, rel)), msg);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function assertIncludes(rel, substr, msg) {
|
|
50
|
+
const src = fs.readFileSync(path.resolve(ROOT, rel), "utf-8");
|
|
51
|
+
assert(src.includes(substr), msg);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function assertNotIncludes(rel, substr, msg) {
|
|
55
|
+
const src = fs.readFileSync(path.resolve(ROOT, rel), "utf-8");
|
|
56
|
+
assert(!src.includes(substr), msg);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ═══════════════════════════════════════════════════════════════
|
|
60
|
+
// 1. 子代理基础设施已删除
|
|
61
|
+
// ═══════════════════════════════════════════════════════════════
|
|
62
|
+
|
|
63
|
+
console.log("📋 子代理基础设施\n");
|
|
64
|
+
|
|
65
|
+
assertNotExists("extensions/sub-agents.ts", "extensions/sub-agents.ts 已删除");
|
|
66
|
+
assertNotExists("extensions/workflow-engine.ts", "extensions/workflow-engine.ts 已删除");
|
|
67
|
+
assertExists("extensions/session-utils.ts", "extensions/session-utils.ts 提供共享的等待/会话工具");
|
|
68
|
+
assertNotExists("agents/", "agents/ 目录已删除");
|
|
69
|
+
assertNotExists(".doc/AGENT-FRONTMATTER-REFERENCE.md", "AGENT-FRONTMATTER-REFERENCE.md 已删除");
|
|
70
|
+
|
|
71
|
+
// ═══════════════════════════════════════════════════════════════
|
|
72
|
+
// 2. dev 命令:4 个命令,参数即任务,意图识别复用 pre-check
|
|
73
|
+
// ═══════════════════════════════════════════════════════════════
|
|
74
|
+
|
|
75
|
+
console.log("\n📋 dev-prompts.ts\n");
|
|
76
|
+
|
|
77
|
+
assertNotIncludes("extensions/dev-prompts.ts", "./sub-agents", "不再引入 sub-agents");
|
|
78
|
+
assertNotIncludes("extensions/dev-prompts.ts", "./workflow-engine", "不再引入 workflow-engine");
|
|
79
|
+
assertNotIncludes("extensions/dev-prompts.ts", "./grill-me-agent", "不再绑定 Grill/PRD 运行时");
|
|
80
|
+
assertNotIncludes("extensions/dev-prompts.ts", "runGrillPhase", "不再触发 Grill 追问");
|
|
81
|
+
assertNotIncludes("extensions/dev-prompts.ts", "runPRDPhase", "不再触发 PRD 生成");
|
|
82
|
+
assertNotIncludes("extensions/dev-prompts.ts", "WizardQuestion", "向导式提问已移除");
|
|
83
|
+
assertIncludes("extensions/dev-prompts.ts", 'import { confirmIntent } from "./pre-check"', "意图识别复用 pre-check");
|
|
84
|
+
assertIncludes("extensions/dev-prompts.ts", "uiTaskArg(ctx, args", "任务原文来自命令参数,缺省才弹输入框");
|
|
85
|
+
assertIncludes("extensions/dev-prompts.ts", "detectProjectDefaults", "默认验收标准来自项目探测");
|
|
86
|
+
assertIncludes("extensions/dev-prompts.ts", "defaultAcceptanceItems", "默认验收标准按条目生成");
|
|
87
|
+
assertIncludes("extensions/dev-prompts.ts", "## 身份与职责", "提示词包含身份与职责段");
|
|
88
|
+
assertIncludes("extensions/dev-prompts.ts", "## 已确认的任务意图", "提示词携带已确认的意图");
|
|
89
|
+
assertIncludes("extensions/dev-prompts.ts", "## 验收标准", "提示词包含默认验收标准段");
|
|
90
|
+
assertIncludes("extensions/dev-prompts.ts", "pi.sendUserMessage(prompt", "组装后的提示词直接发送给当前代理");
|
|
91
|
+
|
|
92
|
+
for (const cmd of ["dev-feat", "dev-fix", "dev-refactor", "dev-test"]) {
|
|
93
|
+
assertIncludes("extensions/dev-prompts.ts", `registerDev(pi, "${cmd}"`, `注册 /${cmd}`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
for (const cmd of ["dev-doc", "dev-perf", "dev-style", "dev-security", "dev-chore", "dev-explain", "dev-compare"]) {
|
|
97
|
+
assertNotIncludes("extensions/dev-prompts.ts", `"${cmd}"`, `/${cmd} 已移除`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// ═══════════════════════════════════════════════════════════════
|
|
101
|
+
// 3. 自动审查检测独立为 review-detect.ts
|
|
102
|
+
// ═══════════════════════════════════════════════════════════════
|
|
103
|
+
|
|
104
|
+
console.log("\n📋 review-detect.ts\n");
|
|
105
|
+
|
|
106
|
+
assertExists("extensions/review-detect.ts", "自动审查检测独立成扩展");
|
|
107
|
+
assertNotIncludes("extensions/review-detect.ts", "./sub-agents", "不再引入 sub-agents");
|
|
108
|
+
assertIncludes("extensions/review-detect.ts", 'pi.on("input"', "拦截带审查意图的输入");
|
|
109
|
+
assertIncludes("extensions/review-detect.ts", 'event.source === "extension"', "过滤扩展注入消息,防止递归");
|
|
110
|
+
assertIncludes("extensions/review-detect.ts", "expandPromptTemplates: true", "skill 命令展开执行");
|
|
111
|
+
assertIncludes("extensions/review-detect.ts", '"pi-review"', "自动审查仍查找 pi-review/ 输出目录");
|
|
112
|
+
|
|
113
|
+
// ═══════════════════════════════════════════════════════════════
|
|
114
|
+
// 4. Git 命令直接执行,不再委派给子代理
|
|
115
|
+
// ═══════════════════════════════════════════════════════════════
|
|
116
|
+
|
|
117
|
+
console.log("\n📋 git-commands.ts\n");
|
|
118
|
+
|
|
119
|
+
assertNotIncludes("extensions/git-commands.ts", "./sub-agents", "不再引入 sub-agents");
|
|
120
|
+
assertNotIncludes("extensions/git-commands.ts", "spawnSubagent", "不再 spawn 子进程");
|
|
121
|
+
assertIncludes("extensions/git-commands.ts", "分批提交", "空消息时交由主代理分批提交");
|
|
122
|
+
assertIncludes("extensions/git-commands.ts", "pi.exec(\"git\"", "通过 pi.exec 直接执行 git");
|
|
123
|
+
assertIncludes("extensions/git-commands.ts", "git-commit", "保留 /git-commit 命令");
|
|
124
|
+
assertIncludes("extensions/git-commands.ts", "git-push", "保留 /git-push 命令");
|
|
125
|
+
assertIncludes("extensions/git-commands.ts", "git-commit-push", "保留 /git-commit-push 命令");
|
|
126
|
+
|
|
127
|
+
// ═══════════════════════════════════════════════════════════════
|
|
128
|
+
// 5. Grill / PRD 是独立命令,运行在当前代理中
|
|
129
|
+
// ═══════════════════════════════════════════════════════════════
|
|
130
|
+
|
|
131
|
+
console.log("\n📋 grill-me-agent.ts\n");
|
|
132
|
+
|
|
133
|
+
assertNotIncludes("extensions/grill-me-agent.ts", "./sub-agents", "不再引入 sub-agents");
|
|
134
|
+
assertNotIncludes("extensions/grill-me-agent.ts", "spawnSubagent", "不再 spawn 子进程");
|
|
135
|
+
assertNotIncludes("extensions/grill-me-agent.ts", "recoverFromBackup", "断点恢复随向导一并移除");
|
|
136
|
+
assertIncludes("extensions/grill-me-agent.ts", 'registerCommand("grill"', "注册独立 /grill 命令");
|
|
137
|
+
assertIncludes("extensions/grill-me-agent.ts", 'registerCommand("prd"', "注册独立 /prd 命令");
|
|
138
|
+
assertIncludes("extensions/grill-me-agent.ts", "pollFor", "轮询等待当前代理产物后读取结果");
|
|
139
|
+
assertIncludes("extensions/grill-me-agent.ts", "GRILL_ANSWERS_DIRNAME = \"answers\"", "保留 answers 子目录");
|
|
140
|
+
assertIncludes("extensions/grill-me-agent.ts", "GRILL_QUESTIONS_DIRNAME = \"questions\"", "保留 questions 子目录");
|
|
141
|
+
|
|
142
|
+
// ═══════════════════════════════════════════════════════════════
|
|
143
|
+
// 6. UI 组件与输出目录约定
|
|
144
|
+
// ═══════════════════════════════════════════════════════════════
|
|
145
|
+
|
|
146
|
+
console.log("\n📋 输出目录与 UI 组件\n");
|
|
147
|
+
|
|
148
|
+
const reviewSkill = fs.readFileSync(path.resolve(ROOT, "skills/review-html/SKILL.md"), "utf-8");
|
|
149
|
+
assert(reviewSkill.includes(".pi-dev-output/pi-review/html/"), "review-html 仍写入 pi-review/html/");
|
|
150
|
+
|
|
151
|
+
assertIncludes("extensions/session-utils.ts", "detectProjectDefaults", "项目探测(语言/测试/lint/pre-commit/CI)");
|
|
152
|
+
assertIncludes("extensions/session-utils.ts", "defaultAcceptanceItems", "生成默认验收标准条目");
|
|
153
|
+
assertIncludes("extensions/ui-helpers.ts", "export function uiSelect", "保留 uiSelect");
|
|
154
|
+
assertIncludes("extensions/ui-helpers.ts", "export function uiConfirm", "保留 uiConfirm");
|
|
155
|
+
assertIncludes("extensions/ui-helpers.ts", "export function uiInput", "保留 uiInput");
|
|
156
|
+
assertIncludes("extensions/ui-helpers.ts", "export async function uiTaskArg", "命令参数与输入框二选一取任务文本");
|
|
157
|
+
assertNotIncludes("extensions/ui-helpers.ts", "updateWorkflowWidget", "移除工作流 widget");
|
|
158
|
+
assertNotIncludes("extensions/ui-helpers.ts", "sendWorkflowResult", "移除工作流结果消息");
|
|
159
|
+
assertNotIncludes("extensions/ui-helpers.ts", "WorkflowStepWidgetState", "移除工作流状态类型");
|
|
160
|
+
|
|
161
|
+
// ═══════════════════════════════════════════════════════════════
|
|
162
|
+
// 7. /dev-pre-check 独立意图校验扩展
|
|
163
|
+
// ═══════════════════════════════════════════════════════════════
|
|
164
|
+
|
|
165
|
+
console.log("\n📋 pre-check.ts\n");
|
|
166
|
+
|
|
167
|
+
assertExists("extensions/pre-check.ts", "提供独立的 pre-check 扩展");
|
|
168
|
+
assertIncludes("extensions/pre-check.ts", 'registerCommand("dev-pre-check"', "注册 /dev-pre-check 命令");
|
|
169
|
+
assertIncludes("extensions/pre-check.ts", "export async function confirmIntent", "导出共享的意图确认循环");
|
|
170
|
+
assertIncludes("extensions/pre-check.ts", "用自己的话重述你认为用户的目标是什么,以及用户试图解决的问题是什么", "固定指令:用自己的话重述目标与问题");
|
|
171
|
+
assertIncludes("extensions/pre-check.ts", "[pre-check] 任务意图校验:只复述,不执行", "意图校验提示词声明只复述不执行");
|
|
172
|
+
assertIncludes("extensions/pre-check.ts", "禁止修改、创建、删除任何文件", "约束禁止任何实质改动");
|
|
173
|
+
assertIncludes("extensions/pre-check.ts", "pi.sendUserMessage(buildExecutionPrompt", "确认通过后才发送执行提示词");
|
|
174
|
+
assertIncludes("extensions/pre-check.ts", "buildExecutionPrompt(originalPrompt: string, intent: string)", "执行提示词携带已确认的意图复述");
|
|
175
|
+
assertIncludes("extensions/pre-check.ts", "ctx.isIdle()", "以代理空闲作为复述完成信号之一");
|
|
176
|
+
assertIncludes("extensions/pre-check.ts", "pollFor", "轮询等待复述产物");
|
|
177
|
+
assertNotIncludes("extensions/pre-check.ts", "./dev-prompts", "不依赖 /dev-* 命令实现");
|
|
178
|
+
assertNotIncludes("extensions/pre-check.ts", "./grill-me-agent", "不依赖 Grill/PRD 运行时");
|
|
179
|
+
assertNotIncludes("extensions/dev-prompts.ts", "dev-pre-check", "dev-prompts 不注册覆盖 pre-check 的命令");
|
|
180
|
+
|
|
181
|
+
// ═══════════════════════════════════════════════════════════════
|
|
182
|
+
// 8. notify 调用使用合法类型
|
|
183
|
+
// ═══════════════════════════════════════════════════════════════
|
|
184
|
+
|
|
185
|
+
console.log("\n📋 notify 类型\n");
|
|
186
|
+
|
|
187
|
+
const NOTIFY_TYPES = ["info", "warning", "error"];
|
|
188
|
+
const badNotify = [];
|
|
189
|
+
for (const file of fs.readdirSync(path.resolve(ROOT, "extensions"))) {
|
|
190
|
+
if (!file.endsWith(".ts")) continue;
|
|
191
|
+
const lines = fs.readFileSync(path.resolve(ROOT, "extensions", file), "utf-8").split("\n");
|
|
192
|
+
for (const line of lines) {
|
|
193
|
+
const matched = line.match(/\.notify\(.*,\s*"([^"]+)"\s*\)/);
|
|
194
|
+
if (matched && !NOTIFY_TYPES.includes(matched[1])) badNotify.push(`${file} → ${matched[1]}`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
assert(
|
|
198
|
+
badNotify.length === 0,
|
|
199
|
+
badNotify.length === 0 ? "所有 notify 调用使用合法类型(info / warning / error)" : `非法 notify 类型: ${badNotify.join(", ")}`,
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
// ═══════════════════════════════════════════════════════════════
|
|
203
|
+
// 9. 版本说明覆盖该版本全部 commit
|
|
204
|
+
// ═══════════════════════════════════════════════════════════════
|
|
205
|
+
|
|
206
|
+
console.log("\n📋 版本说明\n");
|
|
207
|
+
|
|
208
|
+
function git(args) {
|
|
209
|
+
return execFileSync("git", args, { cwd: ROOT, encoding: "utf-8" }).trim();
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const version = JSON.parse(fs.readFileSync(path.resolve(ROOT, "package.json"), "utf-8")).version;
|
|
213
|
+
const releaseDoc = `.version/RELEASE-v${version}.md`;
|
|
214
|
+
assertExists(releaseDoc, `存在 ${releaseDoc}`);
|
|
215
|
+
|
|
216
|
+
const docText = fs.readFileSync(path.resolve(ROOT, releaseDoc), "utf-8");
|
|
217
|
+
const listed = docText
|
|
218
|
+
.split("\n")
|
|
219
|
+
.map((line) => line.match(/^[0-9a-f]{7,40}\b/)?.[0])
|
|
220
|
+
.filter(Boolean);
|
|
221
|
+
assert(listed.length > 0, "Commit History 至少列出一条 commit");
|
|
222
|
+
|
|
223
|
+
const unknown = listed.filter((h) => {
|
|
224
|
+
try {
|
|
225
|
+
git(["rev-parse", "--verify", "--quiet", `${h}^{commit}`]);
|
|
226
|
+
return false;
|
|
227
|
+
} catch {
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
assert(unknown.length === 0, `列出的 commit 都真实存在(${unknown.join(", ") || "无缺失"})`);
|
|
232
|
+
|
|
233
|
+
// 以文档中最新的一条 commit 作为覆盖终点,避免把后续版本的提交算进本版本
|
|
234
|
+
const tip = listed.reduce((a, b) =>
|
|
235
|
+
Number(git(["rev-list", "--count", a])) >= Number(git(["rev-list", "--count", b])) ? a : b,
|
|
236
|
+
);
|
|
237
|
+
const prevTag = git(["tag", "--merged", tip, "--sort=-v:refname"])
|
|
238
|
+
.split("\n")
|
|
239
|
+
.find((tag) => tag && tag !== `v${version}`);
|
|
240
|
+
assert(Boolean(prevTag), `找到上一版本 tag(${prevTag})`);
|
|
241
|
+
|
|
242
|
+
const range = git(["log", "--format=%h", `${prevTag}..${tip}`]).split("\n").filter(Boolean);
|
|
243
|
+
const missing = range.filter((h) => !listed.some((l) => h.startsWith(l) || l.startsWith(h)));
|
|
244
|
+
assert(
|
|
245
|
+
missing.length === 0,
|
|
246
|
+
missing.length === 0
|
|
247
|
+
? `${releaseDoc} 覆盖 ${prevTag}..${tip} 全部 ${range.length} 个 commit`
|
|
248
|
+
: `${releaseDoc} 缺少 ${missing.length} 个 commit: ${missing.join(", ")}`,
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
// ═══════════════════════════════════════════════════════════════
|
|
252
|
+
// Summary
|
|
253
|
+
// ═══════════════════════════════════════════════════════════════
|
|
254
|
+
|
|
255
|
+
console.log(`\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);
|
|
256
|
+
console.log(`结果: ${pass} 通过, ${fail} 失败, 共 ${pass + fail} 个测试`);
|
|
257
|
+
console.log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);
|
|
258
|
+
|
|
259
|
+
if (fail > 0) {
|
|
260
|
+
console.error("\n⚠️ 部分测试未通过");
|
|
261
|
+
process.exit(1);
|
|
262
|
+
} else {
|
|
263
|
+
console.log("\n✅ 所有测试通过");
|
|
264
|
+
}
|
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
# Agent Frontmatter 配置参考
|
|
2
|
-
|
|
3
|
-
所有子代理的行为通过其 `.md` 文件的 YAML frontmatter 配置。
|
|
4
|
-
每个字段对应 `spawnSubagent()` 构造的 pi CLI 参数。
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## 完整字段一览
|
|
9
|
-
|
|
10
|
-
```yaml
|
|
11
|
-
---
|
|
12
|
-
name: <string> # 必填 — agent 标识名
|
|
13
|
-
description: <string> # 必填 — agent 描述
|
|
14
|
-
tools: <csv> # 工具白名单(逗号分隔)
|
|
15
|
-
thinking: <string> # 推理等级
|
|
16
|
-
session: <boolean> # 是否保存 session
|
|
17
|
-
session-dir: <string> # session 存储目录(默认 .pi-dev-output/pi-subagent-sessions/)
|
|
18
|
-
no-context: <boolean> # 是否跳过 AGENTS.md/CLAUDE.md
|
|
19
|
-
no-extensions: <boolean> # 是否禁用扩展加载
|
|
20
|
-
mode: <string> # 输出模式
|
|
21
|
-
extra-args: <string> # 额外 CLI 参数(空格分隔)
|
|
22
|
-
---
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
---
|
|
26
|
-
|
|
27
|
-
## 字段详解
|
|
28
|
-
|
|
29
|
-
### `name` — Agent 标识名
|
|
30
|
-
|
|
31
|
-
- **必填** ✓
|
|
32
|
-
- **类型**: `string`
|
|
33
|
-
- **作用**: 作为 `subagent` tool 的 `agent` 参数值、日志标识、session 文件名前缀
|
|
34
|
-
- **示例**: `planner`, `git-agent`, `review-agent`
|
|
35
|
-
|
|
36
|
-
### `description` — Agent 描述
|
|
37
|
-
|
|
38
|
-
- **必填** ✓
|
|
39
|
-
- **类型**: `string`
|
|
40
|
-
- **作用**: 在工具描述中展示,帮助 LLM 理解该 agent 的用途
|
|
41
|
-
|
|
42
|
-
### `tools` — 工具白名单
|
|
43
|
-
|
|
44
|
-
- **类型**: 逗号分隔的字符串
|
|
45
|
-
- **作用**: 对应 `--tools` CLI 参数
|
|
46
|
-
- **参数范围**: pi 内置工具名(可用 `pi --help` 查看),如 `read`, `bash`, `write`, `find`, `ls`, `grep`, `edit` 等
|
|
47
|
-
- **默认值**: 不传 `--tools` 则所有内置工具可用
|
|
48
|
-
- **示例**: `tools: read, bash, write, find, ls, grep`
|
|
49
|
-
|
|
50
|
-
### `thinking` — 推理等级
|
|
51
|
-
|
|
52
|
-
- **类型**: 字符串
|
|
53
|
-
- **作用**: 对应 `--thinking` CLI 参数
|
|
54
|
-
- **参数范围**:
|
|
55
|
-
|
|
56
|
-
| 值 | 说明 | 延迟影响 | Token 影响 |
|
|
57
|
-
|----|------|---------|-----------|
|
|
58
|
-
| `off` | 关闭推理(纯执行) | 基准 | 基准 |
|
|
59
|
-
| `low` | 少量推理 | +20~40% | +30~50% |
|
|
60
|
-
| `medium` | 中等推理 | +50~100% | +50~80% |
|
|
61
|
-
| `high` | 深度推理 | +100~300% | +100~200% |
|
|
62
|
-
| `xhigh` | 极限推理 | +200~500% | +200~400% |
|
|
63
|
-
|
|
64
|
-
- **建议**:
|
|
65
|
-
- `off` — git 操作、按计划写代码、机械精简
|
|
66
|
-
- `low` — 计划制定、代码审查、设计评审、PRD 编写
|
|
67
|
-
- `medium` — 复杂架构分析、跨模块重构
|
|
68
|
-
- `high` — 安全审计、深层 Bug 追踪
|
|
69
|
-
- `xhigh` — 极其复杂的跨领域分析
|
|
70
|
-
|
|
71
|
-
### `session` — Session 持久化
|
|
72
|
-
|
|
73
|
-
- **类型**: 布尔值
|
|
74
|
-
- **作用**: 对应 `--no-session` / `--session` CLI 参数
|
|
75
|
-
- **参数范围**: `true` | `false`
|
|
76
|
-
- **`false`** (默认): 子代理运行结束后不保留交互记录,性能最优
|
|
77
|
-
- **`true`**: 保存完整交互记录,便于调试/查看子代理的思考过程
|
|
78
|
-
|
|
79
|
-
当 `session: true` 时:
|
|
80
|
-
- 自动生成 session 名: `{ISO时间戳}_{agent名称}`
|
|
81
|
-
- 默认存储路径: `.pi-dev-output/pi-subagent-sessions/`
|
|
82
|
-
- 可通过 `session-dir` 自定义路径
|
|
83
|
-
|
|
84
|
-
### `session-dir` — Session 存储目录
|
|
85
|
-
|
|
86
|
-
- **类型**: 字符串(路径)
|
|
87
|
-
- **作用**: 对应 `--session-dir` CLI 参数
|
|
88
|
-
- **仅在 `session: true` 时生效**
|
|
89
|
-
- **默认值**: `.pi-dev-output/pi-subagent-sessions/`
|
|
90
|
-
- **示例**: `session-dir: /tmp/my-sessions`
|
|
91
|
-
|
|
92
|
-
### `no-context` — 项目上下文文件
|
|
93
|
-
|
|
94
|
-
- **类型**: 布尔值
|
|
95
|
-
- **作用**: 对应 `-nc` CLI 参数
|
|
96
|
-
- **参数范围**: `true` | `false`
|
|
97
|
-
|
|
98
|
-
| 值 | 行为 | 适用场景 |
|
|
99
|
-
|----|------|---------|
|
|
100
|
-
| `true` (默认) | 跳过 AGENTS.md / CLAUDE.md | git 操作、纯执行场景 |
|
|
101
|
-
| `false` | 加载 AGENTS.md / CLAUDE.md | 需要项目上下文的 agent(架构分析、代码审查) |
|
|
102
|
-
|
|
103
|
-
### `no-extensions` — 扩展加载
|
|
104
|
-
|
|
105
|
-
- **类型**: 布尔值
|
|
106
|
-
- **作用**: 对应 `-ne` CLI 参数
|
|
107
|
-
- **参数范围**: `true` | `false`
|
|
108
|
-
|
|
109
|
-
| 值 | 行为 | 适用场景 |
|
|
110
|
-
|----|------|---------|
|
|
111
|
-
| `true` (默认) | 禁用所有扩展,启动更快 | git 操作(仅需 bash) |
|
|
112
|
-
| `false` | 加载扩展(MCP 工具、Skill 文件等) | 需要 MCP/Skill 的 agent(计划、审查、文档) |
|
|
113
|
-
|
|
114
|
-
### `mode` — 输出模式
|
|
115
|
-
|
|
116
|
-
- **类型**: 字符串
|
|
117
|
-
- **作用**: 对应 `--mode` CLI 参数
|
|
118
|
-
- **参数范围**: `json` | `text`
|
|
119
|
-
|
|
120
|
-
| 值 | 行为 | 适用场景 |
|
|
121
|
-
|----|------|---------|
|
|
122
|
-
| `json` (默认) | JSON 结构化输出,workflow-engine 可解析 | 工作流 agent(planner/worker/reviewer/trimmer/docWriter) |
|
|
123
|
-
| `text` | 自然文本输出 | LLM 直接调用的场景 |
|
|
124
|
-
|
|
125
|
-
**注意**: 工作流引擎依赖 `extractFinalOutput()` 解析 JSON 输出,工作流 agent 必须使用 `mode: json`。
|
|
126
|
-
|
|
127
|
-
### `extra-args` — 额外 CLI 参数
|
|
128
|
-
|
|
129
|
-
- **类型**: 字符串(空格分隔多个参数)
|
|
130
|
-
- **作用**: 在所有标准参数之后追加,优先级最高
|
|
131
|
-
- **用途**: 传递 pi CLI 的其他参数,如 `--verbose`, `--color always`, `--max-tokens 4096` 等
|
|
132
|
-
- **示例**: `extra-args: --verbose --max-tokens 4096`
|
|
133
|
-
|
|
134
|
-
---
|
|
135
|
-
|
|
136
|
-
## 原始 CLI 参数映射表
|
|
137
|
-
|
|
138
|
-
以下是对应关系:**原始硬编码参数 → 配置位置**
|
|
139
|
-
|
|
140
|
-
| 原始参数 | 含义 | 配置方式 |
|
|
141
|
-
|---------|------|---------|
|
|
142
|
-
| `-p` | 非交互模式 | **始终启用**,不可配置 |
|
|
143
|
-
| `--no-session` | 不保存会话 | frontmatter `session: false` 或 `argsOverride.session = false` |
|
|
144
|
-
| `-nc` | 禁用上下文文件 | frontmatter `no-context: true` 或 `argsOverride.noContext = true` |
|
|
145
|
-
| `-ne` | 禁用扩展发现 | frontmatter `no-extensions: true` 或 `argsOverride.noExtensions = true` |
|
|
146
|
-
| `--mode json` | JSON 结构化输出 | frontmatter `mode: json` 或 `argsOverride.mode = "json"` |
|
|
147
|
-
| `--thinking off` | 关闭深度思考 | frontmatter `thinking: off` 或 `argsOverride.thinkingLevel = "off"` |
|
|
148
|
-
| `--tools ...` | 工具白名单 | frontmatter `tools: read, bash, ...` 或 `argsOverride.tools = [...]` |
|
|
149
|
-
|
|
150
|
-
**优先级**: `argsOverride` (调用方) > frontmatter > 硬编码默认值
|
|
151
|
-
|
|
152
|
-
---
|
|
153
|
-
|
|
154
|
-
## Agent 配置速查表
|
|
155
|
-
|
|
156
|
-
| Agent | thinking | session | no-context | no-extensions | mode | 适用场景 |
|
|
157
|
-
|-------|----------|---------|------------|---------------|------|---------|
|
|
158
|
-
| **git-agent** | off | false | **true** ✅ | **true** ✅ | json | 纯 git 命令,最小开销 |
|
|
159
|
-
| **planner** | low | false | **false** 🔓 | **false** 🔓 | json | 需 MCP/Skill 分析代码结构 |
|
|
160
|
-
| **worker** | off | false | **false** 🔓 | **false** 🔓 | json | 按计划写代码,可调用 MCP |
|
|
161
|
-
| **reviewer** | low | false | **false** 🔓 | **false** 🔓 | json | 需 Skill 审查代码 |
|
|
162
|
-
| **trimmer** | off | false | **false** 🔓 | **false** 🔓 | json | 精简代码,可用 MCP |
|
|
163
|
-
| **docWriter** | off | false | **false** 🔓 | **false** 🔓 | json | 更新文档,可读代码库 |
|
|
164
|
-
| **review-agent** | low | false | **false** 🔓 | **false** 🔓 | json | HTML 审查报告 |
|
|
165
|
-
| **dev-*-grill-agent** | low | false | **false** 🔓 | **false** 🔓 | json | 设计评审追问 |
|
|
166
|
-
| **dev-prd-agent** | low | false | **false** 🔓 | **false** 🔓 | json | PRD 合成 |
|
|
167
|
-
|
|
168
|
-
> ✅ `true` = 禁用 / 🔓 `false` = 开启
|
|
169
|
-
|
|
170
|
-
---
|
|
171
|
-
|
|
172
|
-
## `argsOverride`(调用方覆写)参考
|
|
173
|
-
|
|
174
|
-
`spawnSubagent()` 第 7 个参数,TypeScript 接口:
|
|
175
|
-
|
|
176
|
-
```typescript
|
|
177
|
-
interface SubagentArgs {
|
|
178
|
-
thinkingLevel?: string; // "off" | "low" | "medium" | "high" | "xhigh"
|
|
179
|
-
session?: boolean; // true/false
|
|
180
|
-
sessionDir?: string; // 自定义 session 路径
|
|
181
|
-
noContext?: boolean; // true/false
|
|
182
|
-
noExtensions?: boolean; // true/false
|
|
183
|
-
mode?: string; // "json" | "text"
|
|
184
|
-
tools?: string[]; // 工具白名单数组
|
|
185
|
-
appendSystemPrompt?: string; // 额外 system prompt
|
|
186
|
-
extraArgs?: string[]; // 原始 CLI 参数
|
|
187
|
-
}
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
示例(workflow-engine 中覆写):
|
|
191
|
-
|
|
192
|
-
```typescript
|
|
193
|
-
const result = await spawnSubagent(agent, task, cwd, signal, timeout, onProgress, {
|
|
194
|
-
thinkingLevel: "medium", // 临时提升推理等级
|
|
195
|
-
session: true, // 调试时保存 session
|
|
196
|
-
noExtensions: false, // 临时开启 MCP
|
|
197
|
-
});
|
|
198
|
-
```
|