@godv61/dsh-task-engine 0.25.0 → 0.26.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/.acceptance.mjs +150 -150
- package/.assessment-batch1.mjs +20 -20
- package/.enforce-test.mjs +138 -138
- package/.evidence-test.mjs +118 -119
- package/.filter-test.mjs +92 -92
- package/.hook-test.mjs +195 -195
- package/.p0-test.mjs +59 -59
- package/.preset-test.mjs +160 -160
- package/.revision-test.mjs +30 -16
- package/.roundtrip-test.mjs +178 -63
- package/.workflow-test.mjs +86 -0
- package/README.md +7 -7
- package/cordis.patch.yml +10 -10
- package/defaults/eng.json +70 -22
- package/docs/BRIEF-FOR-REVIEW.md +162 -162
- package/docs/CHANGELOG.md +12 -0
- package/docs/README.md +40 -40
- package/docs/configuration.md +12 -9
- package/docs/development.md +1 -1
- package/docs/faq.md +4 -4
- package/docs/listing/godv61__dsh-task-engine.yml +5 -5
- package/docs/listing/submission.md +83 -83
- package/docs/manual.html +31 -26
- package/docs/releases/0.23.2.md +21 -21
- package/docs/roadmap.md +34 -34
- package/docs/testing/0.23.2/R02/344/270/232/345/212/241/346/265/213/350/257/225/346/230/216/347/273/206.md +56 -56
- package/docs/testing/0.23.2/R03/344/270/232/345/212/241/346/265/213/350/257/225/346/230/216/347/273/206.md +38 -38
- package/docs/testing/0.23.2//346/265/213/350/257/225/346/212/245/345/221/212.md +65 -65
- package/hooks/commit-msg +70 -1
- package/lib/client.js +825 -570
- package/lib/client.js.map +3 -3
- package/lib/controller.d.ts +2 -1
- package/lib/controller.js +6 -3
- package/lib/controller.js.map +1 -1
- package/lib/dev-task.js +79 -11
- package/lib/dev-task.js.map +1 -1
- package/lib/engine.d.ts +15 -0
- package/lib/engine.js +29 -5
- package/lib/engine.js.map +1 -1
- package/lib/hook.js +3 -0
- package/lib/hook.js.map +1 -1
- package/lib/skill-audit.js +3 -3
- package/lib/skill-audit.js.map +1 -1
- package/lib/workflows.d.ts +4 -1
- package/lib/workflows.js +90 -2
- package/lib/workflows.js.map +1 -1
- package/package.json +1 -1
- package/preset/agent.cordis.yml +21 -21
- package/preset/enable.mjs +87 -87
- package/preset/persona.md +4 -4
- package/preset/preset.yml +1 -1
- package/rules/coding-conventions.md +6 -6
- package/rules/commit-conventions.md +6 -6
- package/rules/security-redlines.md +5 -5
- package/scripts/verify-dsh-compat.mjs +144 -144
- package/skills/code-verify/SKILL.md +3 -3
package/.workflow-test.mjs
CHANGED
|
@@ -75,6 +75,92 @@ function fixture(stage = '开发', extra = {}, services = {}) {
|
|
|
75
75
|
state: () => JSON.parse(records.get(join(cwd, '.dsh/task-LIVE-1.json'))) }
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
test('manual skill evidence is approved by the host without a shell command', async () => {
|
|
79
|
+
const config = resolveFlow('minimal', { flow: 'minimal', stage_bindings: {
|
|
80
|
+
'开发': { skills: [{ skill: { source: 'project', name: 'human-check' }, rules: [], evidence: 'manual' }] },
|
|
81
|
+
} }).config
|
|
82
|
+
const approvals = []
|
|
83
|
+
const f = fixture('开发', { flow: { flow: 'minimal', version: 3, config } }, {
|
|
84
|
+
approval: { request: async request => { approvals.push(request); return 'allowed-once' } },
|
|
85
|
+
})
|
|
86
|
+
f.load('human-check')
|
|
87
|
+
await f.call({ operation: 'skill_result', skill_name: 'human-check', evidence: ['checked by owner'] })
|
|
88
|
+
assert.equal(f.runs.length, 0)
|
|
89
|
+
assert.equal(approvals.length, 1)
|
|
90
|
+
assert.equal(f.state().skill_results['开发']['human-check'].approved, true)
|
|
91
|
+
assert.deepEqual(JSON.parse(await f.call({ operation: 'status' })).skill_blockers, [])
|
|
92
|
+
const denied = fixture('开发', { flow: { flow: 'minimal', version: 3, config } }, {
|
|
93
|
+
approval: { request: async () => 'rejected' },
|
|
94
|
+
})
|
|
95
|
+
denied.load('human-check')
|
|
96
|
+
await assert.rejects(denied.call({ operation: 'skill_result', skill_name: 'human-check', evidence: ['claimed approval'] }), /not approved/)
|
|
97
|
+
assert.equal(denied.state().skill_results?.['开发']?.['human-check'], undefined)
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
test('completion rejects unresolved terminal skills and rules', async () => {
|
|
101
|
+
const config = resolveFlow('minimal', { flow: 'minimal', stage_bindings: {
|
|
102
|
+
'交付': { skills: [{ skill: { source: 'project', name: 'must-run' }, rules: [{ source: 'project', name: 'missing' }], evidence: 'command' }] },
|
|
103
|
+
} }).config
|
|
104
|
+
const f = fixture('交付', {
|
|
105
|
+
flow: { flow: 'minimal', version: 3, config },
|
|
106
|
+
items: [{ id: 'A', title: 'small', status: 'done', review: { spec: { outcome: 'pass' }, quality: { outcome: 'pass' } } }],
|
|
107
|
+
commits: [{ label: 'TASK', hash: 'abcdef1' }],
|
|
108
|
+
})
|
|
109
|
+
const status = JSON.parse(await f.call({ operation: 'status' }))
|
|
110
|
+
assert.ok(status.skill_blockers.length > 0)
|
|
111
|
+
assert.ok(status.missing_rules.length > 0)
|
|
112
|
+
await assert.rejects(f.call({ operation: 'complete' }), /cannot complete.*must-run|cannot complete.*missing/)
|
|
113
|
+
assert.equal(f.state().completed, undefined)
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
test('same-named skill and rule freeze separately and disclose the rule body', async () => {
|
|
117
|
+
const f = fixture()
|
|
118
|
+
f.records.delete(join(f.cwd, '.dsh/task-LIVE-1.json'))
|
|
119
|
+
f.records.set(join(f.cwd, '.dsh/eng.json'), JSON.stringify({ flow: 'minimal', stage_bindings: {
|
|
120
|
+
'开发': { skills: [{ skill: { source: 'project', name: 'custom' }, rules: [{ source: 'project', name: 'custom' }], evidence: 'none' }] },
|
|
121
|
+
} }))
|
|
122
|
+
f.records.set(join(f.cwd, '.dsh/skills/custom/SKILL.md'), 'SKILL BODY')
|
|
123
|
+
f.records.set(join(f.cwd, '.dsh/rules/custom.md'), 'RULE BODY')
|
|
124
|
+
await f.call({ operation: 'create', title: 'collision', branch: 'main', files: ['app.js'] })
|
|
125
|
+
const resources = f.state().flow.resources.filter(resource => resource.ref.name === 'custom')
|
|
126
|
+
assert.deepEqual(resources.map(resource => resource.kind).sort(), ['rule', 'skill'])
|
|
127
|
+
assert.equal(JSON.parse(await f.call({ operation: 'status' })).bindings.rules[0].content, 'RULE BODY')
|
|
128
|
+
f.records.set(join(f.cwd, '.dsh/skills/custom/SKILL.md'), 'CHANGED SKILL')
|
|
129
|
+
assert.equal(JSON.parse(await f.call({ operation: 'status' })).bindings.skill_contents[0].content, 'SKILL BODY')
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
test('task creation applies skill_profiles rules even when legacy inline bindings are empty', async () => {
|
|
133
|
+
const f = fixture()
|
|
134
|
+
const skill = { source: 'project', name: 'custom' }
|
|
135
|
+
const rule = { source: 'project', name: 'my-rule' }
|
|
136
|
+
f.records.delete(join(f.cwd, '.dsh/task-LIVE-1.json'))
|
|
137
|
+
f.records.set(join(f.cwd, '.dsh/eng.json'), JSON.stringify({ flow: 'minimal',
|
|
138
|
+
stage_bindings: {
|
|
139
|
+
'开发': { skills: [{ skill, rules: [], evidence: 'none' }] },
|
|
140
|
+
'交付': { skills: [{ skill, rules: [], evidence: 'none' }] },
|
|
141
|
+
},
|
|
142
|
+
skill_profiles: { 'project:custom': { rules: [rule], evidence: 'none' } },
|
|
143
|
+
}))
|
|
144
|
+
f.records.set(join(f.cwd, '.dsh/skills/custom/SKILL.md'), 'SKILL BODY')
|
|
145
|
+
await assert.rejects(f.call({ operation: 'create', title: 'profile regression', branch: 'main', files: ['app.js'] }), /rule:project:my-rule/)
|
|
146
|
+
f.records.set(join(f.cwd, '.dsh/rules/my-rule.md'), 'RULE BODY')
|
|
147
|
+
await f.call({ operation: 'create', title: 'profile regression', branch: 'main', files: ['app.js'] })
|
|
148
|
+
assert.deepEqual(f.state().flow.config.stage_bindings['开发'].skills[0].rules, [rule])
|
|
149
|
+
assert.deepEqual(f.state().flow.config.stage_bindings['交付'].skills[0].rules, [rule])
|
|
150
|
+
assert.equal(f.state().flow.resources.find(resource => resource.kind === 'rule')?.content, 'RULE BODY')
|
|
151
|
+
assert.equal(JSON.parse(await f.call({ operation: 'status' })).bindings.rules[0].content, 'RULE BODY')
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
test('task creation rejects an unavailable skill or rule before writing a record', async () => {
|
|
155
|
+
const f = fixture()
|
|
156
|
+
f.records.delete(join(f.cwd, '.dsh/task-LIVE-1.json'))
|
|
157
|
+
f.records.set(join(f.cwd, '.dsh/eng.json'), JSON.stringify({ flow: 'minimal', stage_bindings: {
|
|
158
|
+
'开发': { skills: [{ skill: { source: 'project', name: 'missing-skill' }, rules: [] }] },
|
|
159
|
+
} }))
|
|
160
|
+
await assert.rejects(f.call({ operation: 'create', title: 'missing', branch: 'main' }), /unreadable bound resources/)
|
|
161
|
+
assert.equal(f.records.has(join(f.cwd, '.dsh/task-LIVE-1.json')), false)
|
|
162
|
+
})
|
|
163
|
+
|
|
78
164
|
test('审查通过后更新状态并激活下一项,保留已完成项的审计', async () => {
|
|
79
165
|
const f = fixture()
|
|
80
166
|
await f.call({ operation: 'items', items: [{ id: 'A', title: 'first', status: 'doing' }, { id: 'B', title: 'second' }] })
|
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
让 AI 修改代码时,你可以先明确需求,再检查方案、推进实施、验证结果,最后审核提交。DSH Task Engine 把这些步骤组织成可检查、可追踪的任务流程,适合在本机使用 DeepSeek Harness 开发个人项目。
|
|
28
28
|
|
|
29
29
|
- **知道下一步做什么**:按所选流程推进,当前阶段需要的条件和产物清楚可查。
|
|
30
|
-
-
|
|
30
|
+
- **复用自己的工作方法**:把技能和规则安装到项目或个人目录,将规则配置在技能下,再把技能挂到节点上;同一技能在任何节点都使用同一套约束。
|
|
31
31
|
- **找得到过程记录**:任务台账集中查看阶段、实施项、验证与审核状态。
|
|
32
32
|
|
|
33
33
|
## 快速开始
|
|
@@ -53,7 +53,7 @@ dsh plugin --profile web add @godv61/dsh-task-engine
|
|
|
53
53
|
| **项目初始化** | 查看或编辑 `AGENTS.md`,让 AI 生成项目说明,预览后保存。 |
|
|
54
54
|
| **流程配置** | 选择流程骨架,给节点挂技能,并在技能上配置它遵循的规则。需要现成起点时可「采用推荐配置」。 |
|
|
55
55
|
| **任务台账** | 查看实施、验证和审核记录,按关键词、阶段或风险筛选。 |
|
|
56
|
-
| **技能** |
|
|
56
|
+
| **技能** | 安装、编辑技能,并集中维护每个技能唯一的规则列表。 |
|
|
57
57
|
| **规则** | 选择 Markdown 文件安装规则,维护项目或个人开发约定。 |
|
|
58
58
|
|
|
59
59
|
内置技能和规则只读;项目与个人资源可编辑。安装、删除都会明确展示目标位置。
|
|
@@ -64,11 +64,11 @@ dsh plugin --profile web add @godv61/dsh-task-engine
|
|
|
64
64
|
|
|
65
65
|
| 预设 | 阶段顺序 | 适用场景 |
|
|
66
66
|
| :--- | :--- | :--- |
|
|
67
|
-
|
|
|
68
|
-
|
|
|
69
|
-
|
|
|
67
|
+
| **完整研发** `standard` | 需求评审 → 设计 → 开发 → 交付 → 代码审核 → 完成 | 需要需求、方案和交付检查的完整开发任务。 |
|
|
68
|
+
| **日常迭代** `agile` | 需求 → 开发 → 交付 → 审查 | 目标明确的日常开发任务。 |
|
|
69
|
+
| **快速修改** `minimal` | 开发 → 交付 | 已明确做法的小改动。 |
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
阶段顺序和检查条件由预设固定;技能与规则由用户配置。选择流程不会强制加入内置技能;需要现成起点时可显式采用推荐配置。**可视化自定义流程不在计划内**,详见[功能规划](docs/roadmap.md)。
|
|
72
72
|
|
|
73
73
|
## 把自己的技能和规则带进来
|
|
74
74
|
|
|
@@ -98,7 +98,7 @@ dsh plugin --profile web add @godv61/dsh-task-engine
|
|
|
98
98
|
|
|
99
99
|
## 能力说明
|
|
100
100
|
|
|
101
|
-
`dev_task`
|
|
101
|
+
`dev_task` 按配置检查阶段、产物和提交条件。新任务的验证要求真实命令回执;技能可按自身配置要求命令、产物、审核、人工批准或无需额外证据,执行义务可在任务状态中查看。任务保存创建时的流程与资源快照,之后修改项目配置不会直接改变进行中的任务。
|
|
102
102
|
|
|
103
103
|
审核结论、实施项完成情况和测试覆盖面仍需要你判断。本地提交钩子提供即时检查,不能替代人工审核或项目自己的 CI。详细说明见[常见问题](docs/faq.md)。
|
|
104
104
|
|
package/cordis.patch.yml
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# dsh-task-engine bundle: one host-plane row that mounts the `task-engine`
|
|
2
|
-
# Remote namespace (what the browser workbench reads/writes) plus, via
|
|
3
|
-
# `dsh.client`, the workbench UI. This host row registers NO model-facing tool
|
|
4
|
-
# and NO skill — `dev_task` and the shipped skills live on the AGENT plane,
|
|
5
|
-
# behind the `@godv61/dsh-task-engine/agent` entry. A preset's
|
|
6
|
-
# `agent.cordis.yml` names that agent row to activate the flow for its
|
|
7
|
-
# sessions; presets that never name it get neither the tool nor the skills
|
|
8
|
-
# (the workbench stays available so a human can still configure the flow).
|
|
9
|
-
- insert:
|
|
10
|
-
- id: task-engine
|
|
1
|
+
# dsh-task-engine bundle: one host-plane row that mounts the `task-engine`
|
|
2
|
+
# Remote namespace (what the browser workbench reads/writes) plus, via
|
|
3
|
+
# `dsh.client`, the workbench UI. This host row registers NO model-facing tool
|
|
4
|
+
# and NO skill — `dev_task` and the shipped skills live on the AGENT plane,
|
|
5
|
+
# behind the `@godv61/dsh-task-engine/agent` entry. A preset's
|
|
6
|
+
# `agent.cordis.yml` names that agent row to activate the flow for its
|
|
7
|
+
# sessions; presets that never name it get neither the tool nor the skills
|
|
8
|
+
# (the workbench stays available so a human can still configure the flow).
|
|
9
|
+
- insert:
|
|
10
|
+
- id: task-engine
|
|
11
11
|
name: '@godv61/dsh-task-engine'
|
package/defaults/eng.json
CHANGED
|
@@ -2,48 +2,96 @@
|
|
|
2
2
|
"flow": "standard",
|
|
3
3
|
"stage_bindings": {
|
|
4
4
|
"需求评审": {
|
|
5
|
-
"
|
|
5
|
+
"skill_refs": [
|
|
6
6
|
{
|
|
7
|
-
"
|
|
8
|
-
"
|
|
7
|
+
"source": "bundled",
|
|
8
|
+
"name": "requirement-analysis"
|
|
9
9
|
}
|
|
10
10
|
]
|
|
11
11
|
},
|
|
12
12
|
"设计": {
|
|
13
|
-
"
|
|
14
|
-
{
|
|
13
|
+
"skill_refs": [
|
|
14
|
+
{
|
|
15
|
+
"source": "bundled",
|
|
16
|
+
"name": "solution-design"
|
|
17
|
+
}
|
|
15
18
|
]
|
|
16
19
|
},
|
|
17
20
|
"开发": {
|
|
18
|
-
"
|
|
21
|
+
"skill_refs": [
|
|
19
22
|
{
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
{ "source": "bundled", "name": "coding-conventions" },
|
|
23
|
-
{ "source": "bundled", "name": "security-redlines" }
|
|
24
|
-
]
|
|
23
|
+
"source": "bundled",
|
|
24
|
+
"name": "code-implement"
|
|
25
25
|
}
|
|
26
26
|
]
|
|
27
27
|
},
|
|
28
28
|
"交付": {
|
|
29
|
-
"
|
|
30
|
-
{
|
|
29
|
+
"skill_refs": [
|
|
30
|
+
{
|
|
31
|
+
"source": "bundled",
|
|
32
|
+
"name": "code-verify"
|
|
33
|
+
}
|
|
31
34
|
]
|
|
32
35
|
},
|
|
33
36
|
"代码审核": {
|
|
34
|
-
"
|
|
37
|
+
"skill_refs": [
|
|
38
|
+
{
|
|
39
|
+
"source": "bundled",
|
|
40
|
+
"name": "code-review"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"source": "bundled",
|
|
44
|
+
"name": "code-commit"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"skill_profiles": {
|
|
50
|
+
"bundled:requirement-analysis": {
|
|
51
|
+
"rules": [
|
|
52
|
+
{
|
|
53
|
+
"source": "bundled",
|
|
54
|
+
"name": "security-redlines"
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
},
|
|
58
|
+
"bundled:solution-design": {
|
|
59
|
+
"rules": []
|
|
60
|
+
},
|
|
61
|
+
"bundled:code-implement": {
|
|
62
|
+
"rules": [
|
|
35
63
|
{
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
{ "source": "bundled", "name": "coding-conventions" },
|
|
39
|
-
{ "source": "bundled", "name": "security-redlines" }
|
|
40
|
-
]
|
|
64
|
+
"source": "bundled",
|
|
65
|
+
"name": "coding-conventions"
|
|
41
66
|
},
|
|
42
67
|
{
|
|
43
|
-
"
|
|
44
|
-
"
|
|
68
|
+
"source": "bundled",
|
|
69
|
+
"name": "security-redlines"
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
"bundled:code-verify": {
|
|
74
|
+
"rules": []
|
|
75
|
+
},
|
|
76
|
+
"bundled:code-review": {
|
|
77
|
+
"rules": [
|
|
78
|
+
{
|
|
79
|
+
"source": "bundled",
|
|
80
|
+
"name": "coding-conventions"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"source": "bundled",
|
|
84
|
+
"name": "security-redlines"
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
"bundled:code-commit": {
|
|
89
|
+
"rules": [
|
|
90
|
+
{
|
|
91
|
+
"source": "bundled",
|
|
92
|
+
"name": "commit-conventions"
|
|
45
93
|
}
|
|
46
94
|
]
|
|
47
95
|
}
|
|
48
96
|
}
|
|
49
|
-
}
|
|
97
|
+
}
|
package/docs/BRIEF-FOR-REVIEW.md
CHANGED
|
@@ -1,163 +1,163 @@
|
|
|
1
|
-
# DSH Task Engine —— 技术简报(供评估与优化讨论)
|
|
2
|
-
|
|
3
|
-
> 用途:把事实交给 GPT 讨论时使用。以下内容均经代码/实测核对,不是印象。
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 1. 它是什么
|
|
8
|
-
|
|
9
|
-
DeepSeek Harness(DSH)的插件:给 AI 编码会话加一套**可检查的工程交付流程**。
|
|
10
|
-
|
|
11
|
-
- npm: `@godv61/dsh-task-engine`(`latest` = 0.23.9,MIT)
|
|
12
|
-
- GitHub: https://github.com/godv61/dsh-task-engine(**已被 [awesome-dsh-plugin](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin) 收录**,PR #5681 一次通过)
|
|
13
|
-
- 规模:host 面 **4079 行** TS,client 面 **2173 行** TSX,测试 146 项 P0 断言 + 52 项 `node:test`
|
|
14
|
-
|
|
15
|
-
### 核心机制
|
|
16
|
-
|
|
17
|
-
**一个工具 `dev_task`**,7 个操作:`status` / `config` / `init` / `create` / `commit` / `install_hook` / `verify_hook`。
|
|
18
|
-
|
|
19
|
-
它持有任务状态机,**阶段流转是硬门禁**(模型无法绕过):
|
|
20
|
-
|
|
21
|
-
| 守卫 | 含义 |
|
|
22
|
-
| :--- | :--- |
|
|
23
|
-
| `requirement_confirmation` | 需求须经人确认 |
|
|
24
|
-
| `solution_confirmation` | 方案须经人确认 |
|
|
25
|
-
| `artifacts_present` | 阶段产物须齐备 |
|
|
26
|
-
| `todos_done` | 实施项须全部完成 |
|
|
27
|
-
| `verified` | 须有**真实命令回执**(退出码 0,未超时/中止/被沙箱拒) |
|
|
28
|
-
| `review_passed` | 须有审核结论 |
|
|
29
|
-
|
|
30
|
-
**三个内置流程**(阶段顺序与守卫由预设固化):
|
|
31
|
-
|
|
32
|
-
| 流程 | 阶段 |
|
|
33
|
-
| :--- | :--- |
|
|
34
|
-
| `standard` | 需求评审 → 设计 → 开发 → 交付 → 代码审核 → 完成 |
|
|
35
|
-
| `agile` | 需求 → 开发 → 交付 → 审查 |
|
|
36
|
-
| `minimal` | 开发 → 交付 |
|
|
37
|
-
|
|
38
|
-
**渐进式披露**:每个阶段挂「技能 + 规则」,进入该阶段才披露,避免一次性灌入上下文。
|
|
39
|
-
|
|
40
|
-
**工作台 5 个标签页**:项目初始化 / 流程配置 / 任务台账 / 技能 / 规则。
|
|
41
|
-
|
|
42
|
-
---
|
|
43
|
-
|
|
44
|
-
## 2. 已知的设计缺口(当前讨论起点)
|
|
45
|
-
|
|
46
|
-
### 2.1 技能与规则是平级的,但存在**隐式依赖**
|
|
47
|
-
|
|
48
|
-
**数据模型**(`src/engine.ts`):
|
|
49
|
-
|
|
50
|
-
```ts
|
|
51
|
-
interface StageBinding {
|
|
52
|
-
skills?: string[] // 独立数组
|
|
53
|
-
rules?: string[] // 独立数组
|
|
54
|
-
}
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
引擎分别解析:
|
|
58
|
-
|
|
59
|
-
```ts
|
|
60
|
-
const rules = await resolveRules(binding?.rules ?? [], fs, cwd) // 不经技能
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
**但技能文本里引用了具体规则**,例如 `code-implement/SKILL.md`:
|
|
64
|
-
|
|
65
|
-
> 代码质量:按内置规则 **coding-conventions** 查「做得好不好」
|
|
66
|
-
|
|
67
|
-
**问题**:这个依赖**只写在散文里,没有结构化**。因此:
|
|
68
|
-
|
|
69
|
-
- 用户在 UI 勾了 `code-implement` 但没勾 `coding-conventions` → 技能执行时引用一个不存在的规则
|
|
70
|
-
- **引擎不校验,UI 不提示**
|
|
71
|
-
- 默认配置碰巧配对,用户改绑定就可能拆散
|
|
72
|
-
|
|
73
|
-
**默认配置印证耦合确实存在**:规则 `coding-conventions` 同时挂在「开发」(`code-implement`)和「交付」(`code-verify`)两个阶段。
|
|
74
|
-
|
|
75
|
-
### 2.2 待决策的四个方案
|
|
76
|
-
|
|
77
|
-
| 方案 | 做法 | 代价 |
|
|
78
|
-
| :--- | :--- | :--- |
|
|
79
|
-
| **A. 声明式依赖** | `SKILL.md` frontmatter 加 `requires_rules: [...]` | 是 B/C/D 的前置条件;需改 7 个内置技能 |
|
|
80
|
-
| **B. 软提示** | 规则列表全量显示,标注「此技能建议配合 X」 | 保留自由组合;仅提示 |
|
|
81
|
-
| **C. 强联动** | 勾技能 → 规则列表过滤到相关项 | ⚠️ 破坏自由组合(同一规则复用于多技能) |
|
|
82
|
-
| **D. 仅保存时校验** | 不联动 UI,保存时警告「技能 X 引用了未挂载的规则 Y」 | 最轻量;问题暴露较晚 |
|
|
83
|
-
|
|
84
|
-
**当前倾向**:A + D(先让关系可表达,再做校验),或 A + B。**C 需要在 A 的数据之上才成立。**
|
|
85
|
-
|
|
86
|
-
---
|
|
87
|
-
|
|
88
|
-
## 3. 其他可能值得评估的方向
|
|
89
|
-
|
|
90
|
-
### 3.1 流程定制能力的边界
|
|
91
|
-
|
|
92
|
-
**现状**:阶段顺序与守卫由预设固化,**可视化自定义流程不在计划内**(曾评估,结论是不做——把流程设计负担转嫁给使用者)。
|
|
93
|
-
|
|
94
|
-
**可调部分**:项目根 `.dsh/eng.json` 只声明 `flow`(选哪套预设)+ `stage_bindings`(每阶段挂什么)。
|
|
95
|
-
|
|
96
|
-
**待评估**:这个边界是否过窄?例如是否该允许「加一个自定义阶段但保留守卫语义」?
|
|
97
|
-
|
|
98
|
-
### 3.2 验证与审核的可信度边界
|
|
99
|
-
|
|
100
|
-
**现状**(README 与 FAQ 都声明):
|
|
101
|
-
|
|
102
|
-
> 命令覆盖是否充分、审核是否准确仍需判断,**不能把一个成功退出码当作全部需求已验证**。
|
|
103
|
-
|
|
104
|
-
- 验证需真实回执,但**回执不等于需求被完整覆盖**
|
|
105
|
-
- 审核/实施项结论**由模型记录**,非独立验证
|
|
106
|
-
- 任务 JSON **无签名**,有文件写权限者可同时改内容与摘要
|
|
107
|
-
|
|
108
|
-
**待评估**:对「成熟开源产品」而言,这个边界是否需要更强机制(如独立验收、产物哈希链)?
|
|
109
|
-
|
|
110
|
-
### 3.3 提交门禁可被绕过
|
|
111
|
-
|
|
112
|
-
**现状**:`hooks/commit-msg` 检查任务、阶段、消息与文件范围。但:
|
|
113
|
-
|
|
114
|
-
> `--no-verify`、替换 `hooksPath` 或直接改本地数据**仍可能绕过**。
|
|
115
|
-
|
|
116
|
-
**待评估**:是否需要与 CI 结合的服务端校验?还是明确声明「个人本机工具,不提供防篡改」即可?
|
|
117
|
-
|
|
118
|
-
### 3.4 多环境一致性
|
|
119
|
-
|
|
120
|
-
**现状问题**:同一插件需在**桌面版 DSH**(`0.1.2-rc.1`)与**源码版 DSH**(`0.1.7-alpha.1`)上工作,两者契约不同:
|
|
121
|
-
|
|
122
|
-
- persona 字段:桌面版要 `text`,源码版要 `prefix`(已在 0.23.7 通过「跟着运行环境走」解决)
|
|
123
|
-
- 插件管理:桌面版用 generation 机制,源码版用 pnpm
|
|
124
|
-
|
|
125
|
-
**已采取的防护**:CI 加 `dsh-contract` job(跑 `scripts/verify-dsh-compat.mjs`),peer 范围用显式 `||` 分支覆盖各版本。
|
|
126
|
-
|
|
127
|
-
**待评估**:DSH 处于 alpha、**1–3 天一个 tag**,这个跟踪成本是否可持续?
|
|
128
|
-
|
|
129
|
-
### 3.5 其他
|
|
130
|
-
|
|
131
|
-
- **国际化**:目前中文为主,README 有中英双版。是否需要完整 i18n?
|
|
132
|
-
- **可访问性**:工作台介入了 `aria-label`,但未系统测试
|
|
133
|
-
- **性能**:任务台账在任务多时的表现未测
|
|
134
|
-
- **文档**:本次刚做过一次重组(发布说明归入 `docs/releases/`,索引分「当前/历史」)
|
|
135
|
-
|
|
136
|
-
---
|
|
137
|
-
|
|
138
|
-
## 4. 近期已完成的修复(供判断演进方向)
|
|
139
|
-
|
|
140
|
-
| 版本 | 内容 |
|
|
141
|
-
| :--- | :--- |
|
|
142
|
-
| 0.23.9 | 可搜索绑定选择器(独立搜索/仅看已选/计数/就地滚动/预设默认锁定);source map 停止内联源码(447→148 KB);修 10 处 UTF-8 字节损坏 |
|
|
143
|
-
| 0.23.8 | 文档修正(4 处与代码矛盾的陈述)+ 目录重组 |
|
|
144
|
-
| 0.23.7 | persona 字段兼容(新旧 DSH 都能用)——**读源预设用哪个字段就写哪个**,不再硬编码 |
|
|
145
|
-
| 0.23.6 | eng 预设每次启动从运行中 harness 重新派生(此前只在首次生成,DSH 升级后失效) |
|
|
146
|
-
|
|
147
|
-
---
|
|
148
|
-
|
|
149
|
-
## 5. 环境依赖(影响可测试性)
|
|
150
|
-
|
|
151
|
-
- **DSH 0.1.7-alpha.1** 曾有 bug 致**所有工具调用失败**(`ctx.tools[TOOL_RUNTIME_SCHEDULER]` 为 `undefined`),社区在 discussions #7035 / #7194 报告,**0.1.7 已修**
|
|
152
|
-
- 源码版用 `pnpm dsh web` 会触发模块双重加载;绕过方式:`node apps/cli/lib/bin.js <profile>`
|
|
153
|
-
- 桌面版插件由 `dshmarket` + generation 机制管理,**不能用 CLI 的 `dsh plugin` 直接操作**(会与它冲突)
|
|
154
|
-
|
|
155
|
-
---
|
|
156
|
-
|
|
157
|
-
## 6. 想请对方重点回答的问题
|
|
158
|
-
|
|
159
|
-
1. **技能↔规则依赖**:A/B/C/D 选哪个?还是有更好的模型(如规则直接属于技能、互不独立)?
|
|
160
|
-
2. **流程定制边界**:「不做自定义流程」对一个成熟产品是否合理?还是该提供受限的扩展点?
|
|
161
|
-
3. **可信度声明**:当前「不防篡改」的边界,是明确声明即可,还是需要机制补强?
|
|
162
|
-
4. **对 DSH alpha 的跟踪成本**:1–3 天一个 tag,插件该怎么定位(追最新?固定版本?)
|
|
1
|
+
# DSH Task Engine —— 技术简报(供评估与优化讨论)
|
|
2
|
+
|
|
3
|
+
> 用途:把事实交给 GPT 讨论时使用。以下内容均经代码/实测核对,不是印象。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. 它是什么
|
|
8
|
+
|
|
9
|
+
DeepSeek Harness(DSH)的插件:给 AI 编码会话加一套**可检查的工程交付流程**。
|
|
10
|
+
|
|
11
|
+
- npm: `@godv61/dsh-task-engine`(`latest` = 0.23.9,MIT)
|
|
12
|
+
- GitHub: https://github.com/godv61/dsh-task-engine(**已被 [awesome-dsh-plugin](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin) 收录**,PR #5681 一次通过)
|
|
13
|
+
- 规模:host 面 **4079 行** TS,client 面 **2173 行** TSX,测试 146 项 P0 断言 + 52 项 `node:test`
|
|
14
|
+
|
|
15
|
+
### 核心机制
|
|
16
|
+
|
|
17
|
+
**一个工具 `dev_task`**,7 个操作:`status` / `config` / `init` / `create` / `commit` / `install_hook` / `verify_hook`。
|
|
18
|
+
|
|
19
|
+
它持有任务状态机,**阶段流转是硬门禁**(模型无法绕过):
|
|
20
|
+
|
|
21
|
+
| 守卫 | 含义 |
|
|
22
|
+
| :--- | :--- |
|
|
23
|
+
| `requirement_confirmation` | 需求须经人确认 |
|
|
24
|
+
| `solution_confirmation` | 方案须经人确认 |
|
|
25
|
+
| `artifacts_present` | 阶段产物须齐备 |
|
|
26
|
+
| `todos_done` | 实施项须全部完成 |
|
|
27
|
+
| `verified` | 须有**真实命令回执**(退出码 0,未超时/中止/被沙箱拒) |
|
|
28
|
+
| `review_passed` | 须有审核结论 |
|
|
29
|
+
|
|
30
|
+
**三个内置流程**(阶段顺序与守卫由预设固化):
|
|
31
|
+
|
|
32
|
+
| 流程 | 阶段 |
|
|
33
|
+
| :--- | :--- |
|
|
34
|
+
| `standard` | 需求评审 → 设计 → 开发 → 交付 → 代码审核 → 完成 |
|
|
35
|
+
| `agile` | 需求 → 开发 → 交付 → 审查 |
|
|
36
|
+
| `minimal` | 开发 → 交付 |
|
|
37
|
+
|
|
38
|
+
**渐进式披露**:每个阶段挂「技能 + 规则」,进入该阶段才披露,避免一次性灌入上下文。
|
|
39
|
+
|
|
40
|
+
**工作台 5 个标签页**:项目初始化 / 流程配置 / 任务台账 / 技能 / 规则。
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 2. 已知的设计缺口(当前讨论起点)
|
|
45
|
+
|
|
46
|
+
### 2.1 技能与规则是平级的,但存在**隐式依赖**
|
|
47
|
+
|
|
48
|
+
**数据模型**(`src/engine.ts`):
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
interface StageBinding {
|
|
52
|
+
skills?: string[] // 独立数组
|
|
53
|
+
rules?: string[] // 独立数组
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
引擎分别解析:
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
const rules = await resolveRules(binding?.rules ?? [], fs, cwd) // 不经技能
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**但技能文本里引用了具体规则**,例如 `code-implement/SKILL.md`:
|
|
64
|
+
|
|
65
|
+
> 代码质量:按内置规则 **coding-conventions** 查「做得好不好」
|
|
66
|
+
|
|
67
|
+
**问题**:这个依赖**只写在散文里,没有结构化**。因此:
|
|
68
|
+
|
|
69
|
+
- 用户在 UI 勾了 `code-implement` 但没勾 `coding-conventions` → 技能执行时引用一个不存在的规则
|
|
70
|
+
- **引擎不校验,UI 不提示**
|
|
71
|
+
- 默认配置碰巧配对,用户改绑定就可能拆散
|
|
72
|
+
|
|
73
|
+
**默认配置印证耦合确实存在**:规则 `coding-conventions` 同时挂在「开发」(`code-implement`)和「交付」(`code-verify`)两个阶段。
|
|
74
|
+
|
|
75
|
+
### 2.2 待决策的四个方案
|
|
76
|
+
|
|
77
|
+
| 方案 | 做法 | 代价 |
|
|
78
|
+
| :--- | :--- | :--- |
|
|
79
|
+
| **A. 声明式依赖** | `SKILL.md` frontmatter 加 `requires_rules: [...]` | 是 B/C/D 的前置条件;需改 7 个内置技能 |
|
|
80
|
+
| **B. 软提示** | 规则列表全量显示,标注「此技能建议配合 X」 | 保留自由组合;仅提示 |
|
|
81
|
+
| **C. 强联动** | 勾技能 → 规则列表过滤到相关项 | ⚠️ 破坏自由组合(同一规则复用于多技能) |
|
|
82
|
+
| **D. 仅保存时校验** | 不联动 UI,保存时警告「技能 X 引用了未挂载的规则 Y」 | 最轻量;问题暴露较晚 |
|
|
83
|
+
|
|
84
|
+
**当前倾向**:A + D(先让关系可表达,再做校验),或 A + B。**C 需要在 A 的数据之上才成立。**
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## 3. 其他可能值得评估的方向
|
|
89
|
+
|
|
90
|
+
### 3.1 流程定制能力的边界
|
|
91
|
+
|
|
92
|
+
**现状**:阶段顺序与守卫由预设固化,**可视化自定义流程不在计划内**(曾评估,结论是不做——把流程设计负担转嫁给使用者)。
|
|
93
|
+
|
|
94
|
+
**可调部分**:项目根 `.dsh/eng.json` 只声明 `flow`(选哪套预设)+ `stage_bindings`(每阶段挂什么)。
|
|
95
|
+
|
|
96
|
+
**待评估**:这个边界是否过窄?例如是否该允许「加一个自定义阶段但保留守卫语义」?
|
|
97
|
+
|
|
98
|
+
### 3.2 验证与审核的可信度边界
|
|
99
|
+
|
|
100
|
+
**现状**(README 与 FAQ 都声明):
|
|
101
|
+
|
|
102
|
+
> 命令覆盖是否充分、审核是否准确仍需判断,**不能把一个成功退出码当作全部需求已验证**。
|
|
103
|
+
|
|
104
|
+
- 验证需真实回执,但**回执不等于需求被完整覆盖**
|
|
105
|
+
- 审核/实施项结论**由模型记录**,非独立验证
|
|
106
|
+
- 任务 JSON **无签名**,有文件写权限者可同时改内容与摘要
|
|
107
|
+
|
|
108
|
+
**待评估**:对「成熟开源产品」而言,这个边界是否需要更强机制(如独立验收、产物哈希链)?
|
|
109
|
+
|
|
110
|
+
### 3.3 提交门禁可被绕过
|
|
111
|
+
|
|
112
|
+
**现状**:`hooks/commit-msg` 检查任务、阶段、消息与文件范围。但:
|
|
113
|
+
|
|
114
|
+
> `--no-verify`、替换 `hooksPath` 或直接改本地数据**仍可能绕过**。
|
|
115
|
+
|
|
116
|
+
**待评估**:是否需要与 CI 结合的服务端校验?还是明确声明「个人本机工具,不提供防篡改」即可?
|
|
117
|
+
|
|
118
|
+
### 3.4 多环境一致性
|
|
119
|
+
|
|
120
|
+
**现状问题**:同一插件需在**桌面版 DSH**(`0.1.2-rc.1`)与**源码版 DSH**(`0.1.7-alpha.1`)上工作,两者契约不同:
|
|
121
|
+
|
|
122
|
+
- persona 字段:桌面版要 `text`,源码版要 `prefix`(已在 0.23.7 通过「跟着运行环境走」解决)
|
|
123
|
+
- 插件管理:桌面版用 generation 机制,源码版用 pnpm
|
|
124
|
+
|
|
125
|
+
**已采取的防护**:CI 加 `dsh-contract` job(跑 `scripts/verify-dsh-compat.mjs`),peer 范围用显式 `||` 分支覆盖各版本。
|
|
126
|
+
|
|
127
|
+
**待评估**:DSH 处于 alpha、**1–3 天一个 tag**,这个跟踪成本是否可持续?
|
|
128
|
+
|
|
129
|
+
### 3.5 其他
|
|
130
|
+
|
|
131
|
+
- **国际化**:目前中文为主,README 有中英双版。是否需要完整 i18n?
|
|
132
|
+
- **可访问性**:工作台介入了 `aria-label`,但未系统测试
|
|
133
|
+
- **性能**:任务台账在任务多时的表现未测
|
|
134
|
+
- **文档**:本次刚做过一次重组(发布说明归入 `docs/releases/`,索引分「当前/历史」)
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## 4. 近期已完成的修复(供判断演进方向)
|
|
139
|
+
|
|
140
|
+
| 版本 | 内容 |
|
|
141
|
+
| :--- | :--- |
|
|
142
|
+
| 0.23.9 | 可搜索绑定选择器(独立搜索/仅看已选/计数/就地滚动/预设默认锁定);source map 停止内联源码(447→148 KB);修 10 处 UTF-8 字节损坏 |
|
|
143
|
+
| 0.23.8 | 文档修正(4 处与代码矛盾的陈述)+ 目录重组 |
|
|
144
|
+
| 0.23.7 | persona 字段兼容(新旧 DSH 都能用)——**读源预设用哪个字段就写哪个**,不再硬编码 |
|
|
145
|
+
| 0.23.6 | eng 预设每次启动从运行中 harness 重新派生(此前只在首次生成,DSH 升级后失效) |
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## 5. 环境依赖(影响可测试性)
|
|
150
|
+
|
|
151
|
+
- **DSH 0.1.7-alpha.1** 曾有 bug 致**所有工具调用失败**(`ctx.tools[TOOL_RUNTIME_SCHEDULER]` 为 `undefined`),社区在 discussions #7035 / #7194 报告,**0.1.7 已修**
|
|
152
|
+
- 源码版用 `pnpm dsh web` 会触发模块双重加载;绕过方式:`node apps/cli/lib/bin.js <profile>`
|
|
153
|
+
- 桌面版插件由 `dshmarket` + generation 机制管理,**不能用 CLI 的 `dsh plugin` 直接操作**(会与它冲突)
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## 6. 想请对方重点回答的问题
|
|
158
|
+
|
|
159
|
+
1. **技能↔规则依赖**:A/B/C/D 选哪个?还是有更好的模型(如规则直接属于技能、互不独立)?
|
|
160
|
+
2. **流程定制边界**:「不做自定义流程」对一个成熟产品是否合理?还是该提供受限的扩展点?
|
|
161
|
+
3. **可信度声明**:当前「不防篡改」的边界,是明确声明即可,还是需要机制补强?
|
|
162
|
+
4. **对 DSH alpha 的跟踪成本**:1–3 天一个 tag,插件该怎么定位(追最新?固定版本?)
|
|
163
163
|
5. **还缺什么才能称得上「成熟开源产品」**:贡献指南、issue 模板、语义化版本、变更日志规范、安全策略、行为准则?
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,18 @@
|
|
|
4
4
|
|
|
5
5
|
按版本查阅功能变化。当前使用方式以[项目首页](../README.md)和使用指南为准;历史条目中的实现方式、限制与测试数量可能已被后续版本替代。
|
|
6
6
|
|
|
7
|
+
## 0.26.0
|
|
8
|
+
|
|
9
|
+
- 修复旧内联阶段绑定与新 `skill_profiles` 同时存在时,技能档案规则未展开、同一技能跨节点误报冲突的问题;明确的技能档案现在覆盖旧内联副本,并在任务创建时冻结实际生效的规则。
|
|
10
|
+
- 技能规则改为项目级 `skill_profiles`,节点在 `.dsh/eng.json` 中只保存 `skill_refs`。旧内联绑定继续读取;没有明确技能档案时,同一技能在不同节点的规则或证据冲突会明确报错,保存时转换为单一配置。
|
|
11
|
+
- “技能”页可集中编辑技能规则和完成凭证。流程页只选择技能,并可查看当前节点的有效规则;修改同一技能的配置会同步其所有节点引用。
|
|
12
|
+
- 任务快照以资源类型、来源、名称定位技能和规则,避免同名资源正文串用;任务创建时拒绝缺失的绑定资源,并在运行时披露冻结的技能与规则正文。
|
|
13
|
+
- `complete` 检查终态技能、证据与缺失规则,完成后禁止继续修改任务(可通过 `revise` 返工)。`status` 增加完成状态和完成阻塞原因。
|
|
14
|
+
- `manual` 技能证据通过宿主人工审批记录,不再强制执行 shell;`artifact` 证据要求该阶段有产物定义且必填字段完整。
|
|
15
|
+
- `commit_required: false` 同时取消离开提交检查点的强制提交要求。返工会使受影响阶段的技能结果失效。
|
|
16
|
+
- 增加配置保存读回、同名资源、人工审批、终态阻塞及返工证据回归测试。
|
|
17
|
+
- 工作台改用更宽的自适应布局;流程页用双栏穿梭框绑定技能,技能卡片和已绑定技能都可打开右侧规则配置抽屉,窄屏自动改为纵向布局。
|
|
18
|
+
|
|
7
19
|
## 0.25.0
|
|
8
20
|
|
|
9
21
|
针对 2026-09-24 复评的改造。**这是一个破坏性版本**:预设不再自带任何技能、产物或提交格式,`SkillBinding` 新增 `evidence` 字段,敏捷流程的门禁语义与版本号都变了。核心是落实产品原则:**流程只控制状态,业务方法由用户配置,Rule 真正归属 Skill。**
|