@godv61/dsh-task-engine 0.1.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/README.md +65 -0
- package/cordis.patch.yml +10 -0
- package/defaults/eng.json +18 -0
- package/lib/engine.d.ts +108 -0
- package/lib/engine.js +143 -0
- package/lib/engine.js.map +1 -0
- package/lib/index.d.ts +10 -0
- package/lib/index.js +204 -0
- package/lib/index.js.map +1 -0
- package/package.json +50 -0
- package/preset/persona.md +5 -0
- package/preset/preset.yml +2 -0
- package/skills/eng-delivery/SKILL.md +20 -0
package/README.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# dsh-task-engine
|
|
2
|
+
|
|
3
|
+
一个**可安装、项目无关、硬约束**的工程化交付引擎,把「需求评审 → 设计 → 开发 → 交付 → 代码审核」这套流程做成 DeepSeek Harness 的一个 bundle。同事 `dsh plugin add` 装一下,再选一个预设,就能在自己项目里用——**不需要**在每个项目手写 `.agents` / `.claude` / `.harness`。
|
|
4
|
+
|
|
5
|
+
核心是一个 `dev_task` 工具 + 内置技能。工具的硬约束在代码里执行,不是"提醒模型":
|
|
6
|
+
|
|
7
|
+
- **阶段流转**:只能沿 `.dsh/eng.json` 配的阶段图走;非法流转直接报错拒绝。
|
|
8
|
+
- **确认/验证门**:需求/方案未确认 → 进不了设计/开发;实施项没完 → 不能交付;高风险没验证证据 → 不能过评审。
|
|
9
|
+
- **提交门禁**:到检查点才能提交,消息必须匹配 `message_pattern`,`manual` 策略永不自动提交。
|
|
10
|
+
|
|
11
|
+
## 目录
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
cordis.patch.yml bundle 声明 + host 组合 patch(一行,注册本插件)
|
|
15
|
+
defaults/eng.json 内置默认工作流(可被项目 .dsh/eng.json 覆盖)
|
|
16
|
+
src/engine.ts 纯函数状态机(无 harness 依赖,可单测)
|
|
17
|
+
src/index.ts 插件:注册 dev_task 工具 + 内置技能
|
|
18
|
+
skills/eng-delivery/ 内置交付技能
|
|
19
|
+
preset/preset.yml 预设元数据
|
|
20
|
+
preset/persona.md 预设 persona 文案(复制粘贴用)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## 构建
|
|
24
|
+
|
|
25
|
+
> 依赖走**公共 npm**:`@deepseek-ai/*` 已发到 `0.1.2-rc.1`(tag `next`)/ `0.1.2-alpha.5`,`cordis` 是 `4.0.2`。本包依赖对齐到 `^0.1.2-rc.1` + `^4.0.2`,已实测 `npm install`(公网)+ `tsc` 构建/typecheck + 运行时冒烟全部通过。
|
|
26
|
+
|
|
27
|
+
```powershell
|
|
28
|
+
npm install # 从公共 npm 解析 @deepseek-ai/* 依赖
|
|
29
|
+
npm run typecheck # 严格模式零错误
|
|
30
|
+
npm run build # tsc 产出 lib/index.js + lib/index.d.ts
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 安装(别人集成)
|
|
34
|
+
|
|
35
|
+
```powershell
|
|
36
|
+
# 从公共 npm(发布后)
|
|
37
|
+
dsh plugin --profile <name> add @godv61/dsh-task-engine
|
|
38
|
+
# 从你的 git 仓库
|
|
39
|
+
dsh plugin --profile <name> add github:<你的org>/dsh-task-engine
|
|
40
|
+
# 或本地 checkout
|
|
41
|
+
dsh plugin --profile <name> add .
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## 启用(opt-in)
|
|
45
|
+
|
|
46
|
+
1. 用 roster `copy('standard', 'eng', '工程化开发引擎')` 复制一个预设(或手动建目录)。
|
|
47
|
+
2. 把该预设的 persona 替换成 `preset/persona.md` 内容。
|
|
48
|
+
3. 新会话选该预设即可。`dev_task` 工具与 `eng-delivery` 技能由 bundle 提供。
|
|
49
|
+
|
|
50
|
+
## 项目配置(让流程贴合你的项目)
|
|
51
|
+
|
|
52
|
+
在项目根放 `.dsh/eng.json`(复制 `defaults/eng.json` 改字段即可):
|
|
53
|
+
|
|
54
|
+
- `stages` / `start_stage` / `transitions`:阶段与流转图;每条边的 `requires` 用引擎原生 guard。
|
|
55
|
+
- `commit.policy`(`task|item|manual`)、`commit.message_pattern`/`message_hint`、`commit.checkpoints`。
|
|
56
|
+
- `high_risk_requires_verification`。
|
|
57
|
+
|
|
58
|
+
原生 guard:`requirement_confirmation`、`solution_confirmation`、`todos_done`、`verified`、`review_passed`。
|
|
59
|
+
|
|
60
|
+
## 已知待办(Phase 0 边界)
|
|
61
|
+
|
|
62
|
+
- 已用 monorepo TypeScript 工具链对真实 harness API 跑过 strict 编译(`exactOptionalPropertyTypes` + `noUncheckedIndexedAccess`)零错误,3 个此前标记的 API 校验点全部确认;并临时挂进 workspace 做了真实 `tsc` 构建 + 运行时冒烟——`dev_task` 工具与 `eng-delivery` 技能注册成功,非法流转/未过 guard/非法提交在运行时被硬拒绝。
|
|
63
|
+
- 已实测:`npm install`(公网 `0.1.2-rc.1`)+ `npm run typecheck`/`build` 全过,构建产物在运行时注册 `dev_task`/`eng-delivery` 并硬拒绝非法流转/未过 guard/非法提交。剩下没亲自跑的是 `dsh plugin add` 装进 profile + 真实模型会话(要 `DEEPSEEK_API_KEY`)。
|
|
64
|
+
- 提交仍是"工具校验 + 模型执行 git";要彻底防止绕过 `git commit`,需项目加 pre-commit hook(机械门禁,下一步)。
|
|
65
|
+
- 阶段产物(设计文档/评审字段)的硬 schema 校验属于你未选的"更重"档,Phase 0 不包含。
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# dsh-task-engine bundle: one host-plane row that registers the `dev_task` tool
|
|
2
|
+
# and the shipped engineering skills. The agent-plane opt-in (persona + routing)
|
|
3
|
+
# lives in `preset/` and is copied into a preset by whoever enables the engine.
|
|
4
|
+
#
|
|
5
|
+
# Host row + global tools/skills registries means: install the bundle once and the
|
|
6
|
+
# capability is dormant-available to every agent; the preset decides whether an
|
|
7
|
+
# agent actually routes its work through it.
|
|
8
|
+
- insert:
|
|
9
|
+
- id: task-engine
|
|
10
|
+
name: '@godv61/dsh-task-engine'
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"stages": ["requirement_review", "design", "implement", "deliver", "review", "done"],
|
|
3
|
+
"start_stage": "requirement_review",
|
|
4
|
+
"transitions": [
|
|
5
|
+
{ "from": "requirement_review", "to": "design", "requires": ["requirement_confirmation"] },
|
|
6
|
+
{ "from": "design", "to": "implement", "requires": ["solution_confirmation"] },
|
|
7
|
+
{ "from": "implement", "to": "deliver", "requires": ["todos_done"] },
|
|
8
|
+
{ "from": "deliver", "to": "review", "requires": ["verified"] },
|
|
9
|
+
{ "from": "review", "to": "done", "requires": ["review_passed"] }
|
|
10
|
+
],
|
|
11
|
+
"commit": {
|
|
12
|
+
"policy": "task",
|
|
13
|
+
"message_pattern": "^【(\\S+)】【(?:TASK|T\\d+)】.+",
|
|
14
|
+
"message_hint": "【<module>】【TASK/T1】说明 —— 写结果,不写空泛动作",
|
|
15
|
+
"checkpoints": ["deliver"]
|
|
16
|
+
},
|
|
17
|
+
"high_risk_requires_verification": true
|
|
18
|
+
}
|
package/lib/engine.d.ts
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config-driven engineering workflow engine — pure and harness-free.
|
|
3
|
+
*
|
|
4
|
+
* `loadWorkflow`, `legalTargets`, `assertAdvance`, `validateCommitMessage`, and
|
|
5
|
+
* `commitCheckpoint` are pure functions over a `WorkflowConfig` and a `TaskState`.
|
|
6
|
+
* They hold every hard gate the `dev_task` tool exposes, so the state machine is
|
|
7
|
+
* unit-testable without a harness and the same code enforces the process whatever
|
|
8
|
+
* config (stage graph, guards, commit policy) a project supplies.
|
|
9
|
+
*
|
|
10
|
+
* @module dsh-task-engine/engine
|
|
11
|
+
*/
|
|
12
|
+
export type WorkSize = 'tiny' | 'standard' | 'complex';
|
|
13
|
+
export type RiskLevel = 'standard' | 'high_risk';
|
|
14
|
+
export type ItemStatus = 'todo' | 'doing' | 'done';
|
|
15
|
+
/** Guard names the engine resolves natively. Opaque names are config errors. */
|
|
16
|
+
export type GuardName = 'requirement_confirmation' | 'solution_confirmation' | 'todos_done' | 'verified' | 'review_passed';
|
|
17
|
+
/** One allowed stage transition and the guards that must already hold. */
|
|
18
|
+
export interface Transition {
|
|
19
|
+
from: string;
|
|
20
|
+
to: string;
|
|
21
|
+
requires?: GuardName[];
|
|
22
|
+
}
|
|
23
|
+
/** Commit policy and message shape. Empty `message_pattern` disables format checking. */
|
|
24
|
+
export interface CommitRule {
|
|
25
|
+
policy: 'task' | 'item' | 'manual';
|
|
26
|
+
message_pattern: string;
|
|
27
|
+
message_hint: string;
|
|
28
|
+
/** Stages at which a commit checkpoint sits (a commit is due before leaving these). */
|
|
29
|
+
checkpoints: string[];
|
|
30
|
+
}
|
|
31
|
+
export interface WorkflowConfig {
|
|
32
|
+
stages: string[];
|
|
33
|
+
start_stage: string;
|
|
34
|
+
transitions: Transition[];
|
|
35
|
+
commit: CommitRule;
|
|
36
|
+
/** A high_risk task cannot cross an edge guarded by `verified` without passing evidence. */
|
|
37
|
+
high_risk_requires_verification: boolean;
|
|
38
|
+
}
|
|
39
|
+
export interface TaskItem {
|
|
40
|
+
id: string;
|
|
41
|
+
title: string;
|
|
42
|
+
status: ItemStatus;
|
|
43
|
+
}
|
|
44
|
+
export interface TaskState {
|
|
45
|
+
schema: 1;
|
|
46
|
+
id: string;
|
|
47
|
+
title: string;
|
|
48
|
+
branch: string;
|
|
49
|
+
work_size: WorkSize;
|
|
50
|
+
risk_level: RiskLevel;
|
|
51
|
+
stage: string;
|
|
52
|
+
requirement_confirmed: boolean;
|
|
53
|
+
solution_confirmed: boolean;
|
|
54
|
+
items: TaskItem[];
|
|
55
|
+
verification: {
|
|
56
|
+
passed: boolean;
|
|
57
|
+
evidence: string[];
|
|
58
|
+
};
|
|
59
|
+
review: {
|
|
60
|
+
outcome: 'pending' | 'pass' | 'blocked';
|
|
61
|
+
};
|
|
62
|
+
commits: {
|
|
63
|
+
label: string;
|
|
64
|
+
hash?: string;
|
|
65
|
+
}[];
|
|
66
|
+
}
|
|
67
|
+
export interface Result {
|
|
68
|
+
ok: boolean;
|
|
69
|
+
errors?: string[];
|
|
70
|
+
}
|
|
71
|
+
/** Stage-merge an override over a default; absent fields keep the default. */
|
|
72
|
+
export declare function loadWorkflow(defaults: WorkflowConfig, override?: Partial<WorkflowConfig>): WorkflowConfig;
|
|
73
|
+
/** Target stages reachable from `stage` via a configured transition. */
|
|
74
|
+
export declare function legalTargets(stage: string, config: WorkflowConfig): string[];
|
|
75
|
+
/** The edge from `from` to `to`, or undefined when not configured. */
|
|
76
|
+
export declare function findTransition(from: string, to: string, config: WorkflowConfig): Transition | undefined;
|
|
77
|
+
/**
|
|
78
|
+
* Validate an advance from `state.stage` to `targetStage`.
|
|
79
|
+
*
|
|
80
|
+
* Returns `{ ok: false, errors }` when the target is unknown, the edge is not
|
|
81
|
+
* configured, or any declared guard is unmet. This is the hard transition gate:
|
|
82
|
+
* the tool rejects rather than degrades.
|
|
83
|
+
*/
|
|
84
|
+
export declare function assertAdvance(state: TaskState, targetStage: string, config: WorkflowConfig): Result;
|
|
85
|
+
/** Validate a commit summary against the configured message pattern. */
|
|
86
|
+
export declare function validateCommitMessage(message: string, config: WorkflowConfig): Result;
|
|
87
|
+
export interface CommitCheckpoint {
|
|
88
|
+
allowed: boolean;
|
|
89
|
+
label?: string;
|
|
90
|
+
reason?: string;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Decide whether the current task state permits a commit and with what label.
|
|
94
|
+
*
|
|
95
|
+
* `manual` never auto-commits. `task` allows a single `TASK` at a checkpoint
|
|
96
|
+
* stage. `item` allows `T<n>` commits mid-flow and a closing `TASK` at a
|
|
97
|
+
* checkpoint. A stage only permits a commit once its outgoing guards already
|
|
98
|
+
* hold, so the engine cannot be asked to commit before its own state is valid.
|
|
99
|
+
*/
|
|
100
|
+
export declare function commitCheckpoint(state: TaskState, config: WorkflowConfig): CommitCheckpoint;
|
|
101
|
+
/** A fresh task pinned to the config's start stage. */
|
|
102
|
+
export declare function newTask(input: {
|
|
103
|
+
id: string;
|
|
104
|
+
title: string;
|
|
105
|
+
branch: string;
|
|
106
|
+
work_size: WorkSize;
|
|
107
|
+
risk_level: RiskLevel;
|
|
108
|
+
}, config: WorkflowConfig): TaskState;
|
package/lib/engine.js
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config-driven engineering workflow engine — pure and harness-free.
|
|
3
|
+
*
|
|
4
|
+
* `loadWorkflow`, `legalTargets`, `assertAdvance`, `validateCommitMessage`, and
|
|
5
|
+
* `commitCheckpoint` are pure functions over a `WorkflowConfig` and a `TaskState`.
|
|
6
|
+
* They hold every hard gate the `dev_task` tool exposes, so the state machine is
|
|
7
|
+
* unit-testable without a harness and the same code enforces the process whatever
|
|
8
|
+
* config (stage graph, guards, commit policy) a project supplies.
|
|
9
|
+
*
|
|
10
|
+
* @module dsh-task-engine/engine
|
|
11
|
+
*/
|
|
12
|
+
function requireKnownStage(stage, config) {
|
|
13
|
+
if (!config.stages.includes(stage)) {
|
|
14
|
+
return { ok: false, errors: [`unknown stage "${stage}"`] };
|
|
15
|
+
}
|
|
16
|
+
return { ok: true };
|
|
17
|
+
}
|
|
18
|
+
/** Stage-merge an override over a default; absent fields keep the default. */
|
|
19
|
+
export function loadWorkflow(defaults, override) {
|
|
20
|
+
if (!override)
|
|
21
|
+
return defaults;
|
|
22
|
+
return {
|
|
23
|
+
stages: override.stages ?? defaults.stages,
|
|
24
|
+
start_stage: override.start_stage ?? defaults.start_stage,
|
|
25
|
+
transitions: override.transitions ?? defaults.transitions,
|
|
26
|
+
commit: { ...defaults.commit, ...(override.commit ?? {}) },
|
|
27
|
+
high_risk_requires_verification: override.high_risk_requires_verification ?? defaults.high_risk_requires_verification,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/** Target stages reachable from `stage` via a configured transition. */
|
|
31
|
+
export function legalTargets(stage, config) {
|
|
32
|
+
return config.transitions
|
|
33
|
+
.filter(transition => transition.from === stage)
|
|
34
|
+
.map(transition => transition.to);
|
|
35
|
+
}
|
|
36
|
+
/** The edge from `from` to `to`, or undefined when not configured. */
|
|
37
|
+
export function findTransition(from, to, config) {
|
|
38
|
+
return config.transitions.find(transition => transition.from === from && transition.to === to);
|
|
39
|
+
}
|
|
40
|
+
function guardSatisfied(guard, state, config) {
|
|
41
|
+
switch (guard) {
|
|
42
|
+
case 'requirement_confirmation':
|
|
43
|
+
return state.requirement_confirmed;
|
|
44
|
+
case 'solution_confirmation':
|
|
45
|
+
return state.solution_confirmed;
|
|
46
|
+
case 'todos_done':
|
|
47
|
+
return state.items.length > 0 && state.items.every(item => item.status === 'done');
|
|
48
|
+
case 'verified':
|
|
49
|
+
if (!state.verification.passed)
|
|
50
|
+
return false;
|
|
51
|
+
return config.high_risk_requires_verification && state.risk_level === 'high_risk'
|
|
52
|
+
? state.verification.evidence.length > 0
|
|
53
|
+
: true;
|
|
54
|
+
case 'review_passed':
|
|
55
|
+
return state.review.outcome === 'pass';
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Validate an advance from `state.stage` to `targetStage`.
|
|
60
|
+
*
|
|
61
|
+
* Returns `{ ok: false, errors }` when the target is unknown, the edge is not
|
|
62
|
+
* configured, or any declared guard is unmet. This is the hard transition gate:
|
|
63
|
+
* the tool rejects rather than degrades.
|
|
64
|
+
*/
|
|
65
|
+
export function assertAdvance(state, targetStage, config) {
|
|
66
|
+
const known = requireKnownStage(targetStage, config);
|
|
67
|
+
if (!known.ok)
|
|
68
|
+
return known;
|
|
69
|
+
const transition = findTransition(state.stage, targetStage, config);
|
|
70
|
+
if (!transition) {
|
|
71
|
+
return {
|
|
72
|
+
ok: false,
|
|
73
|
+
errors: [`no transition from "${state.stage}" to "${targetStage}"` +
|
|
74
|
+
` (legal: ${legalTargets(state.stage, config).join(', ') || 'none'})`],
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
const unmet = (transition.requires ?? []).filter(guard => !guardSatisfied(guard, state, config));
|
|
78
|
+
if (unmet.length > 0) {
|
|
79
|
+
return { ok: false, errors: [`guards unmet: ${unmet.join(', ')}`] };
|
|
80
|
+
}
|
|
81
|
+
return { ok: true };
|
|
82
|
+
}
|
|
83
|
+
/** Validate a commit summary against the configured message pattern. */
|
|
84
|
+
export function validateCommitMessage(message, config) {
|
|
85
|
+
if (config.commit.message_pattern === '')
|
|
86
|
+
return { ok: true };
|
|
87
|
+
const re = new RegExp(config.commit.message_pattern);
|
|
88
|
+
if (re.test(message))
|
|
89
|
+
return { ok: true };
|
|
90
|
+
return {
|
|
91
|
+
ok: false,
|
|
92
|
+
errors: [`commit summary "${message}" does not match ${config.commit.message_hint}`],
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Decide whether the current task state permits a commit and with what label.
|
|
97
|
+
*
|
|
98
|
+
* `manual` never auto-commits. `task` allows a single `TASK` at a checkpoint
|
|
99
|
+
* stage. `item` allows `T<n>` commits mid-flow and a closing `TASK` at a
|
|
100
|
+
* checkpoint. A stage only permits a commit once its outgoing guards already
|
|
101
|
+
* hold, so the engine cannot be asked to commit before its own state is valid.
|
|
102
|
+
*/
|
|
103
|
+
export function commitCheckpoint(state, config) {
|
|
104
|
+
const { policy, checkpoints } = config.commit;
|
|
105
|
+
if (policy === 'manual') {
|
|
106
|
+
return { allowed: false, reason: 'commit policy is manual — await an explicit user instruction' };
|
|
107
|
+
}
|
|
108
|
+
if (checkpoints.includes(state.stage)) {
|
|
109
|
+
const ready = config.transitions
|
|
110
|
+
.filter(transition => transition.from === state.stage)
|
|
111
|
+
.every(transition => (transition.requires ?? []).every(g => guardSatisfied(g, state, config)));
|
|
112
|
+
if (!ready) {
|
|
113
|
+
return { allowed: false, reason: 'checkpoint stage reached but its outgoing guards are unmet' };
|
|
114
|
+
}
|
|
115
|
+
return { allowed: true, label: 'TASK' };
|
|
116
|
+
}
|
|
117
|
+
if (policy === 'item') {
|
|
118
|
+
const done = state.items.filter(item => item.status === 'done').length;
|
|
119
|
+
if (done > 0) {
|
|
120
|
+
return { allowed: true, label: `T${done}` };
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return { allowed: false, reason: 'no commit is due at this stage under the current policy' };
|
|
124
|
+
}
|
|
125
|
+
/** A fresh task pinned to the config's start stage. */
|
|
126
|
+
export function newTask(input, config) {
|
|
127
|
+
return {
|
|
128
|
+
schema: 1,
|
|
129
|
+
id: input.id,
|
|
130
|
+
title: input.title,
|
|
131
|
+
branch: input.branch,
|
|
132
|
+
work_size: input.work_size,
|
|
133
|
+
risk_level: input.risk_level,
|
|
134
|
+
stage: config.start_stage,
|
|
135
|
+
requirement_confirmed: false,
|
|
136
|
+
solution_confirmed: false,
|
|
137
|
+
items: [],
|
|
138
|
+
verification: { passed: false, evidence: [] },
|
|
139
|
+
review: { outcome: 'pending' },
|
|
140
|
+
commits: [],
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dsh-task-engine plugin: registers the model-facing `dev_task` tool (the hard
|
|
3
|
+
* gate) and ships the bundled engineering skills.
|
|
4
|
+
*
|
|
5
|
+
* @module dsh-task-engine
|
|
6
|
+
*/
|
|
7
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
8
|
+
export declare const name = "task-engine";
|
|
9
|
+
export declare const inject: string[];
|
|
10
|
+
export declare function apply(ctx: Context): void;
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dsh-task-engine plugin: registers the model-facing `dev_task` tool (the hard
|
|
3
|
+
* gate) and ships the bundled engineering skills.
|
|
4
|
+
*
|
|
5
|
+
* @module dsh-task-engine
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync, readdirSync } from 'node:fs';
|
|
8
|
+
import { fileURLToPath } from 'node:url';
|
|
9
|
+
import { defineTool } from '@deepseek-ai/dsh-tools';
|
|
10
|
+
import { assertAdvance, commitCheckpoint, legalTargets, loadWorkflow, newTask, validateCommitMessage, } from "./engine.js";
|
|
11
|
+
export const name = 'task-engine';
|
|
12
|
+
export const inject = ['tools', 'fs'];
|
|
13
|
+
const DEFAULTS = JSON.parse(readFileSync(fileURLToPath(new URL('../defaults/eng.json', import.meta.url)), 'utf8'));
|
|
14
|
+
async function readText(fs, relPath) {
|
|
15
|
+
try {
|
|
16
|
+
return await fs.readText(fs.resolve(relPath));
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async function writeText(fs, relPath, content) {
|
|
23
|
+
await fs.writeText(fs.resolve(relPath), content);
|
|
24
|
+
}
|
|
25
|
+
function sanitize(id) {
|
|
26
|
+
return id.replace(/[^0-9a-zA-Z_-]/g, '-');
|
|
27
|
+
}
|
|
28
|
+
const taskPath = (id) => `.dsh/task-${sanitize(id)}.json`;
|
|
29
|
+
/** Resolve the effective workflow: bundled default overlaid by `.dsh/eng.json`. */
|
|
30
|
+
async function resolveWorkflow(fs) {
|
|
31
|
+
const raw = await readText(fs, '.dsh/eng.json');
|
|
32
|
+
if (raw === undefined)
|
|
33
|
+
return DEFAULTS;
|
|
34
|
+
try {
|
|
35
|
+
return loadWorkflow(DEFAULTS, JSON.parse(raw));
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return DEFAULTS;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function loadTask(fs, id) {
|
|
42
|
+
const raw = await readText(fs, taskPath(id));
|
|
43
|
+
if (raw === undefined)
|
|
44
|
+
throw new Error(`no task "${id}" under ${taskPath(id)}`);
|
|
45
|
+
return JSON.parse(raw);
|
|
46
|
+
}
|
|
47
|
+
async function writeTask(fs, state) {
|
|
48
|
+
await writeText(fs, taskPath(state.id), JSON.stringify(state, null, 2));
|
|
49
|
+
}
|
|
50
|
+
const OPERATIONS = ['status', 'create', 'confirm', 'advance', 'verify', 'review', 'commit'];
|
|
51
|
+
const TOOL_DESCRIPTION = 'Own the engineering delivery workflow as hard state. Read or create the task record, record a ' +
|
|
52
|
+
'confirmation, advance one stage (rejected unless every configured guard already holds), record ' +
|
|
53
|
+
'verification or review, and gate a commit on stage/scope/message. The tool refuses illegal moves ' +
|
|
54
|
+
'instead of degrading — treat a rejection as a fact to fix, not a prompt to retry another way.';
|
|
55
|
+
export function apply(ctx) {
|
|
56
|
+
ctx.tools.register(defineTool({
|
|
57
|
+
name: 'dev_task',
|
|
58
|
+
description: TOOL_DESCRIPTION,
|
|
59
|
+
parameters: {
|
|
60
|
+
operation: { type: 'string', enum: [...OPERATIONS], required: true, description: 'Which task-record action to perform.' },
|
|
61
|
+
task_id: { type: 'string', description: 'Task id; required except for create.' },
|
|
62
|
+
branch: { type: 'string', description: 'Current git branch (recorded on create).' },
|
|
63
|
+
title: { type: 'string', description: 'Task title (create).' },
|
|
64
|
+
work_size: { type: 'string', enum: ['tiny', 'standard', 'complex'], description: 'Workload tier (create).' },
|
|
65
|
+
risk_level: { type: 'string', enum: ['standard', 'high_risk'], description: 'Risk tier (create).' },
|
|
66
|
+
items: {
|
|
67
|
+
type: 'array',
|
|
68
|
+
description: 'Implementation items (create/update).',
|
|
69
|
+
items: {
|
|
70
|
+
type: 'object',
|
|
71
|
+
additionalProperties: false,
|
|
72
|
+
properties: {
|
|
73
|
+
id: { type: 'string' },
|
|
74
|
+
title: { type: 'string' },
|
|
75
|
+
status: { type: 'string', enum: ['todo', 'doing', 'done'] },
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
field: { type: 'string', enum: ['requirement', 'solution'], description: 'Which confirmation (confirm).' },
|
|
80
|
+
target_stage: { type: 'string', description: 'Stage to advance to (advance).' },
|
|
81
|
+
passed: { type: 'boolean', description: 'Verification passed (verify).' },
|
|
82
|
+
evidence: { type: 'array', items: { type: 'string' }, description: 'Verification evidence (verify).' },
|
|
83
|
+
outcome: { type: 'string', enum: ['pass', 'blocked'], description: 'Review outcome (review).' },
|
|
84
|
+
message: { type: 'string', description: 'Commit summary to validate (commit).' },
|
|
85
|
+
hash: { type: 'string', description: 'Commit hash to record after the git commit (commit).' },
|
|
86
|
+
},
|
|
87
|
+
output: {
|
|
88
|
+
schema: { type: 'string' },
|
|
89
|
+
render(_args, value) {
|
|
90
|
+
return [{ type: 'text', text: value }];
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
async execute(args) {
|
|
94
|
+
const a = args;
|
|
95
|
+
const workflow = await resolveWorkflow(ctx.fs);
|
|
96
|
+
if (a.operation === 'create') {
|
|
97
|
+
if (!a.task_id || !a.title || !a.branch) {
|
|
98
|
+
throw new Error('create requires task_id, title, and branch');
|
|
99
|
+
}
|
|
100
|
+
const state = newTask({
|
|
101
|
+
id: a.task_id,
|
|
102
|
+
title: a.title,
|
|
103
|
+
branch: a.branch,
|
|
104
|
+
work_size: a.work_size ?? 'standard',
|
|
105
|
+
risk_level: a.risk_level ?? 'standard',
|
|
106
|
+
}, workflow);
|
|
107
|
+
state.items = a.items ?? [];
|
|
108
|
+
await writeTask(ctx.fs, state);
|
|
109
|
+
return `created ${state.id} at stage ${state.stage}; legal next: ${legalTargets(state.stage, workflow).join(', ') || 'none'}`;
|
|
110
|
+
}
|
|
111
|
+
if (!a.task_id)
|
|
112
|
+
throw new Error('task_id is required for this operation');
|
|
113
|
+
const state = await loadTask(ctx.fs, a.task_id);
|
|
114
|
+
if (a.operation === 'status') {
|
|
115
|
+
return JSON.stringify({
|
|
116
|
+
id: state.id,
|
|
117
|
+
stage: state.stage,
|
|
118
|
+
risk_level: state.risk_level,
|
|
119
|
+
work_size: state.work_size,
|
|
120
|
+
requirement_confirmed: state.requirement_confirmed,
|
|
121
|
+
solution_confirmed: state.solution_confirmed,
|
|
122
|
+
items_done: `${state.items.filter(i => i.status === 'done').length}/${state.items.length}`,
|
|
123
|
+
verification: state.verification,
|
|
124
|
+
review: state.review,
|
|
125
|
+
legal_next: legalTargets(state.stage, workflow),
|
|
126
|
+
commit: commitCheckpoint(state, workflow),
|
|
127
|
+
}, null, 2);
|
|
128
|
+
}
|
|
129
|
+
if (a.operation === 'commit') {
|
|
130
|
+
const checkpoint = commitCheckpoint(state, workflow);
|
|
131
|
+
if (!checkpoint.allowed)
|
|
132
|
+
throw new Error(checkpoint.reason ?? 'no commit is due');
|
|
133
|
+
const message = validateCommitMessage(a.message ?? '', workflow);
|
|
134
|
+
if (!message.ok)
|
|
135
|
+
throw new Error(message.errors.join('; '));
|
|
136
|
+
if (a.hash)
|
|
137
|
+
state.commits.push({ label: checkpoint.label, hash: a.hash });
|
|
138
|
+
await writeTask(ctx.fs, state);
|
|
139
|
+
return `commit approved (${checkpoint.label ?? ''}) — git add <task files>; git commit -m "${a.message ?? ''}"`;
|
|
140
|
+
}
|
|
141
|
+
switch (a.operation) {
|
|
142
|
+
case 'confirm':
|
|
143
|
+
if (a.field === 'requirement')
|
|
144
|
+
state.requirement_confirmed = true;
|
|
145
|
+
else if (a.field === 'solution')
|
|
146
|
+
state.solution_confirmed = true;
|
|
147
|
+
else
|
|
148
|
+
throw new Error('confirm requires field: requirement|solution');
|
|
149
|
+
break;
|
|
150
|
+
case 'advance': {
|
|
151
|
+
const result = assertAdvance(state, a.target_stage ?? '', workflow);
|
|
152
|
+
if (!result.ok)
|
|
153
|
+
throw new Error(result.errors.join('; '));
|
|
154
|
+
state.stage = a.target_stage;
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
case 'verify':
|
|
158
|
+
state.verification = { passed: a.passed === true, evidence: a.evidence ?? [] };
|
|
159
|
+
break;
|
|
160
|
+
case 'review':
|
|
161
|
+
if (a.outcome !== 'pass' && a.outcome !== 'blocked')
|
|
162
|
+
throw new Error('review requires outcome: pass|blocked');
|
|
163
|
+
state.review.outcome = a.outcome;
|
|
164
|
+
break;
|
|
165
|
+
default:
|
|
166
|
+
throw new Error(`unknown operation ${a.operation}`);
|
|
167
|
+
}
|
|
168
|
+
await writeTask(ctx.fs, state);
|
|
169
|
+
return `ok (stage ${state.stage})`;
|
|
170
|
+
},
|
|
171
|
+
}));
|
|
172
|
+
// Ship the bundled engineering skills into this bundle's layer of the host
|
|
173
|
+
// skill registry (optional surface: skip when the registry is absent).
|
|
174
|
+
const skills = ctx.get('skills');
|
|
175
|
+
if (skills !== undefined) {
|
|
176
|
+
const skillsRoot = fileURLToPath(new URL('../skills/', import.meta.url));
|
|
177
|
+
for (const entry of readdirSync(skillsRoot, { withFileTypes: true })) {
|
|
178
|
+
if (!entry.isDirectory())
|
|
179
|
+
continue;
|
|
180
|
+
const raw = readFileSync(fileURLToPath(new URL(`../skills/${entry.name}/SKILL.md`, import.meta.url)), 'utf8');
|
|
181
|
+
const m = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
182
|
+
if (!m)
|
|
183
|
+
continue;
|
|
184
|
+
const head = m[1];
|
|
185
|
+
const body = m[2];
|
|
186
|
+
const meta = {};
|
|
187
|
+
for (const line of head.split('\n')) {
|
|
188
|
+
const i = line.indexOf(':');
|
|
189
|
+
if (i > 0)
|
|
190
|
+
meta[line.slice(0, i).trim()] = line.slice(i + 1).trim();
|
|
191
|
+
}
|
|
192
|
+
if (!meta.name || !meta.description)
|
|
193
|
+
continue;
|
|
194
|
+
skills.register({
|
|
195
|
+
name: meta.name,
|
|
196
|
+
description: meta.description,
|
|
197
|
+
...(meta.whenToUse !== undefined ? { whenToUse: meta.whenToUse } : {}),
|
|
198
|
+
content: body,
|
|
199
|
+
source: 'custom',
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@godv61/dsh-task-engine",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Config-driven engineering delivery engine for DeepSeek Harness: a `dev_task` tool that hard-gates workflow stage transitions and commit scope/message, plus bundled skills and an opt-in preset.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "lib/index.js",
|
|
7
|
+
"types": "lib/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./lib/index.d.ts",
|
|
11
|
+
"default": "./lib/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./cordis.patch.yml": "./cordis.patch.yml",
|
|
14
|
+
"./defaults/eng.json": "./defaults/eng.json",
|
|
15
|
+
"./package.json": "./package.json"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"lib/**",
|
|
19
|
+
"cordis.patch.yml",
|
|
20
|
+
"defaults/eng.json",
|
|
21
|
+
"skills/**",
|
|
22
|
+
"preset/**",
|
|
23
|
+
"README.md"
|
|
24
|
+
],
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"dsh": {
|
|
30
|
+
"bundle": {
|
|
31
|
+
"patch": "./cordis.patch.yml"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "tsc -p tsconfig.json",
|
|
36
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
37
|
+
"prepare": "tsc -p tsconfig.json"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"@deepseek-ai/cordis": "^4.0.2",
|
|
41
|
+
"@deepseek-ai/dsh-tools": "^0.1.2-rc.1"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@deepseek-ai/cordis": "^4.0.2",
|
|
45
|
+
"@deepseek-ai/dsh-tools": "^0.1.2-rc.1",
|
|
46
|
+
"@deepseek-ai/dsh-fs": "^0.1.2-rc.1",
|
|
47
|
+
"@types/node": "^22.0.0",
|
|
48
|
+
"typescript": "^5.7.2"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
You are an engineering-delivery coding agent, powered by the {{model}} model, running on DeepSeek Harness. Your working directory is {{cwd}}.
|
|
2
|
+
|
|
3
|
+
本仓库采用工程化交付流程,由 `dev_task` 工具硬性持有任务状态机:需求评审 → 设计 → 开发 → 交付 → 代码审核。阶段、流转门槛、提交格式都来自项目根 `.dsh/eng.json`(没有该文件则用内置默认)。任何开发类请求开始前,先加载 `eng-delivery` 技能。
|
|
4
|
+
|
|
5
|
+
铁律:一切阶段流转、确认、验证、评审和提交都必须通过 `dev_task`——它拒绝时是硬事实,必须修正前置条件,禁止绕过。只做任务范围内的本地提交;绝不 push、合并、创建 PR、执行数据库、操作 Jenkins、部署或发布。
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: eng-delivery
|
|
3
|
+
description: 使用 dev_task 工具编排工程化交付流程;按当前分支任务、配置的状态机与提交门禁推进需求评审、设计、开发、交付、代码审核。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 工程化交付
|
|
7
|
+
|
|
8
|
+
`dev_task` 工具是流程的唯一事实来源与硬约束。阶段、流转门槛、提交格式来自项目根 `.dsh/eng.json`(没有该文件则用 bundle 内置默认,见 `defaults/eng.json`)。
|
|
9
|
+
|
|
10
|
+
## 入口
|
|
11
|
+
|
|
12
|
+
1. 先 `dev_task`(operation=status)读当前分支任务;没有任务则(operation=create)建立任务并停在起始阶段。
|
|
13
|
+
2. 每阶段:完成本阶段产物后,用 `dev_task`(operation=advance)流转到目标阶段;被拒绝说明 guard 未满足(确认没过 / 实施项没完 / 高风险没验证 / 评审没过),先补齐再重试,不得绕过。
|
|
14
|
+
3. 提交前用 `dev_task`(operation=commit)校验阶段、提交范围与消息格式;拿到 approved 消息后再执行 `git add <任务内文件>; git commit -m "<approved>"`,并把 commit hash 通过 `dev_task`(operation=commit, hash=...)回写。
|
|
15
|
+
|
|
16
|
+
## 硬规则
|
|
17
|
+
|
|
18
|
+
- 需求、Bug、继续开发、验证、评审、提交请求一律经 `dev_task` 状态机推进,不自行绕过。
|
|
19
|
+
- 只做任务范围内的本地提交;绝不 push、合并、创建 PR、执行数据库、操作 Jenkins、部署或发布。
|
|
20
|
+
- `dev_task` 的拒绝是硬事实:修正前置条件,而不是换一种方式绕过。
|