@godv61/dsh-task-engine 0.27.1 → 0.29.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 +11 -11
- package/.adaptive-test.mjs +189 -0
- package/.assessment-batch1.mjs +14 -14
- package/.codex-project-test.mjs +80 -80
- package/.enforce-test.mjs +12 -12
- package/.evidence-test.mjs +8 -8
- package/.filter-test.mjs +6 -6
- package/.freeze-test.mjs +44 -44
- package/.hook-test.mjs +19 -2
- package/.p0-test.mjs +21 -21
- package/.preset-test.mjs +11 -1
- package/.revision-test.mjs +16 -16
- package/.roundtrip-test.mjs +247 -247
- package/.workflow-test.mjs +122 -120
- package/README.md +33 -27
- package/cordis.patch.yml +158 -9
- package/docs/CHANGELOG.md +44 -30
- package/docs/README.md +6 -5
- package/docs/adaptive-workflows.md +72 -0
- package/docs/configuration.md +25 -25
- package/docs/development.md +1 -1
- package/docs/faq.md +14 -6
- package/docs/getting-started.md +8 -5
- package/docs/manual-legacy.html +380 -0
- package/docs/manual.html +124 -378
- package/docs/resource-install.md +5 -5
- package/docs/roadmap.md +8 -9
- package/hooks/commit-msg +39 -22
- package/lib/adaptive.d.ts +15 -0
- package/lib/adaptive.js +54 -0
- package/lib/adaptive.js.map +1 -0
- package/lib/client.js +719 -433
- package/lib/client.js.map +3 -3
- package/lib/controller.d.ts +50 -0
- package/lib/controller.js +132 -0
- package/lib/controller.js.map +1 -1
- package/lib/dev-task.js +413 -18
- package/lib/dev-task.js.map +1 -1
- package/lib/engine.d.ts +20 -0
- package/lib/engine.js +4 -1
- package/lib/engine.js.map +1 -1
- package/lib/hook.js +50 -29
- package/lib/hook.js.map +1 -1
- package/lib/project-init.d.ts +23 -0
- package/lib/project-init.js +94 -0
- package/lib/project-init.js.map +1 -0
- package/lib/skill-audit.js +8 -7
- package/lib/skill-audit.js.map +1 -1
- package/lib/sonar.d.ts +33 -0
- package/lib/sonar.js +80 -0
- package/lib/sonar.js.map +1 -0
- package/package.json +15 -16
- package/preset/agent.cordis.yml +3 -3
- package/preset/enable.mjs +2 -2
- package/preset/persona.md +4 -2
- package/scripts/verify-package.mjs +9 -5
- package/skills/architecture-design/SKILL.md +11 -0
- package/skills/code-development/SKILL.md +11 -0
- package/skills/code-review/SKILL.md +11 -0
- package/skills/eng-delivery/SKILL.md +19 -15
- package/skills/requirements-analysis/SKILL.md +11 -0
- package/skills/task-orchestration/SKILL.md +11 -0
- package/skills/test-validation/SKILL.md +11 -0
package/docs/roadmap.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[← 文档导航](README.md)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
本页记录已发布能力与后续方向;任务级流程见[自适应工程任务](adaptive-workflows.md)。
|
|
6
6
|
已发布的能力与版本变化见[更新日志](CHANGELOG.md)。
|
|
7
7
|
|
|
8
8
|
## 当前能力边界
|
|
@@ -10,16 +10,16 @@
|
|
|
10
10
|
| 能力 | 状态 |
|
|
11
11
|
| :--- | :--- |
|
|
12
12
|
| 三个内置流程(`standard`、`agile`、`minimal`) | ✅ 已发布,开箱即用 |
|
|
13
|
-
| 阶段选择技能、规则归属技能 | ✅ 已发布 |
|
|
13
|
+
| 阶段选择技能、规则归属技能 | ✅ 已发布 |
|
|
14
14
|
| 任务台账、验证与审核回执、提交门禁 | ✅ 已发布 |
|
|
15
|
-
| 项目级与个人级资源安装、来源保留 | ✅ 已发布 |
|
|
16
|
-
|
|
|
15
|
+
| 项目级与个人级资源安装、来源保留 | ✅ 已发布 |
|
|
16
|
+
| 四档任务级流程、元技能、项目扫描 init、可选审核期 SonarQube CI 接入 | ✅ 0.29.0 |
|
|
17
|
+
| **自由编辑流程阶段与条件** | ❌ **不在计划内** |
|
|
17
18
|
|
|
18
19
|
**关于自定义流程**:让使用者自行设计阶段、条件与提交流程曾被评估,结论是**不列入计划**——
|
|
19
|
-
|
|
20
|
-
实现;相关尝试保留在非发布分支,不在 `main` 上。
|
|
20
|
+
任务级四档流程覆盖常见开发复杂度,用户可挂载项目技能;自由编辑状态机仍不在当前范围。
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
旧任务继续读取 `.dsh/eng.json`;新任务用 `.dsh/meta.json` 管理元技能挂载,复杂度在任务创建时确定。
|
|
23
23
|
|
|
24
24
|
## 后续体验方向
|
|
25
25
|
|
|
@@ -30,5 +30,4 @@
|
|
|
30
30
|
|
|
31
31
|
## 产品范围
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
解决工作区目标清晰、文件误操作、任务连续性和操作反馈。
|
|
33
|
+
本项目服务本机与团队分支开发中的个人会话。多用户服务器的会话权限架构不列为当前版本的必修项。日常改进优先解决工作区目标清晰、文件误操作、任务连续性和操作反馈。
|
package/hooks/commit-msg
CHANGED
|
@@ -148,7 +148,7 @@ function commitCheckpoint(state2, config2) {
|
|
|
148
148
|
return { allowed: false, reason: "no commit is due at this stage under the current policy" };
|
|
149
149
|
}
|
|
150
150
|
function isEngineMeta(file) {
|
|
151
|
-
return /^\.dsh\/(task-[^/]+\.json|eng\.json)$/.test(file);
|
|
151
|
+
return /^\.dsh\/(task-[^/]+\.json|eng\.json|meta\.json)$/.test(file);
|
|
152
152
|
}
|
|
153
153
|
function checkFileScope(state2, committing, config2) {
|
|
154
154
|
if (!config2.commit.file_scope) return { ok: true, outside: [], noScope: false };
|
|
@@ -419,6 +419,9 @@ function normalizeTask(task) {
|
|
|
419
419
|
branch: String(task.branch ?? ""),
|
|
420
420
|
work_size: task.work_size ?? "standard",
|
|
421
421
|
risk_level: task.risk_level ?? "standard",
|
|
422
|
+
...task.complexity !== void 0 ? { complexity: task.complexity } : {},
|
|
423
|
+
...task.sonar_policy !== void 0 ? { sonar_policy: task.sonar_policy } : {},
|
|
424
|
+
...task.sonar_audit !== void 0 ? { sonar_audit: task.sonar_audit } : {},
|
|
422
425
|
stage: String(task.stage ?? ""),
|
|
423
426
|
requirement_confirmed: task.requirement_confirmed === true,
|
|
424
427
|
solution_confirmed: task.solution_confirmed === true,
|
|
@@ -501,7 +504,21 @@ function extractTaskId(message2) {
|
|
|
501
504
|
return match ? match[1] : void 0;
|
|
502
505
|
}
|
|
503
506
|
function isEngineMeta2(file) {
|
|
504
|
-
return /^\.dsh\/(task-[^/]+\.json|eng\.json)$/.test(file);
|
|
507
|
+
return /^\.dsh\/(task-[^/]+\.json|eng\.json|meta\.json)$/.test(file);
|
|
508
|
+
}
|
|
509
|
+
function scopeHash(state2, root) {
|
|
510
|
+
const entries2 = [...new Set(state2.files)].filter((file) => !isEngineMeta2(file)).sort().map((file) => {
|
|
511
|
+
const target = import_node_path.default.resolve(root, file);
|
|
512
|
+
const inside = import_node_path.default.relative(root, target);
|
|
513
|
+
if (inside.startsWith("..") || import_node_path.default.isAbsolute(inside)) refuse(`\u4EFB\u52A1\u8303\u56F4\u8DEF\u5F84\u8D8A\u754C: ${file}`);
|
|
514
|
+
try {
|
|
515
|
+
return [file, hashText(import_node_fs.default.readFileSync(target, "utf8"))];
|
|
516
|
+
} catch (error) {
|
|
517
|
+
if (error.code === "ENOENT") return [file, null];
|
|
518
|
+
refuse(`\u65E0\u6CD5\u8BFB\u53D6\u4EFB\u52A1\u6587\u4EF6 ${file}: ${error instanceof Error ? error.message : String(error)}`);
|
|
519
|
+
}
|
|
520
|
+
});
|
|
521
|
+
return hashText(JSON.stringify(entries2));
|
|
505
522
|
}
|
|
506
523
|
function riskyPaths(entries2) {
|
|
507
524
|
return entries2.filter((entry) => !isEngineMeta2(entry.path)).filter((entry) => DEFAULT_RISK_POLICY.sensitive_paths.some((prefix) => entry.path === prefix || entry.path.startsWith(`${prefix}/`))).map((entry) => entry.path);
|
|
@@ -536,30 +553,11 @@ function loadWorkflow(parsed) {
|
|
|
536
553
|
}
|
|
537
554
|
return resolved.config;
|
|
538
555
|
}
|
|
539
|
-
var cwd = process.cwd();
|
|
540
|
-
var configPath = import_node_path.default.join(cwd, ".dsh", "eng.json");
|
|
541
|
-
var config;
|
|
542
|
-
if (import_node_fs.default.existsSync(configPath)) {
|
|
543
|
-
let raw = "";
|
|
544
|
-
try {
|
|
545
|
-
raw = import_node_fs.default.readFileSync(configPath, "utf8");
|
|
546
|
-
} catch {
|
|
547
|
-
raw = "";
|
|
548
|
-
}
|
|
549
|
-
let parsed;
|
|
550
|
-
try {
|
|
551
|
-
parsed = JSON.parse(raw);
|
|
552
|
-
} catch (error) {
|
|
553
|
-
refuse("invalid JSON in .dsh/eng.json: " + (error instanceof Error ? error.message : String(error)));
|
|
554
|
-
}
|
|
555
|
-
config = loadWorkflow(parsed);
|
|
556
|
-
} else {
|
|
557
|
-
config = loadWorkflow(void 0);
|
|
558
|
-
}
|
|
559
556
|
if (!messageFile) {
|
|
560
557
|
process.exit(0);
|
|
561
558
|
}
|
|
562
559
|
var message = readCommitMessage(messageFile);
|
|
560
|
+
var cwd = process.cwd();
|
|
563
561
|
var tasks = loadTasks();
|
|
564
562
|
var taskId = extractTaskId(message);
|
|
565
563
|
var state;
|
|
@@ -578,8 +576,20 @@ if (!state) {
|
|
|
578
576
|
if (state.flow?.hash !== void 0 && hashConfig(state.flow.config) !== state.flow.hash) {
|
|
579
577
|
refuse(`\u4EFB\u52A1 ${state.id} \u7684\u6D41\u7A0B\u5FEB\u7167 hash \u4E0D\u5339\u914D\u2014\u2014task \u8BB0\u5F55\u5728\u521B\u5EFA\u540E\u88AB\u6539\u52A8\u8FC7\uFF0C\u4FEE\u590D\u6216\u91CD\u5EFA\u4EFB\u52A1\u540E\u518D\u63D0\u4EA4`);
|
|
580
578
|
}
|
|
579
|
+
var config;
|
|
581
580
|
if (state.flow !== void 0 && state.flow.config !== void 0) {
|
|
582
581
|
config = state.flow.config;
|
|
582
|
+
} else {
|
|
583
|
+
const configPath = import_node_path.default.join(cwd, ".dsh", "eng.json");
|
|
584
|
+
if (import_node_fs.default.existsSync(configPath)) {
|
|
585
|
+
let parsed;
|
|
586
|
+
try {
|
|
587
|
+
parsed = JSON.parse(import_node_fs.default.readFileSync(configPath, "utf8"));
|
|
588
|
+
} catch (error) {
|
|
589
|
+
refuse("invalid JSON in .dsh/eng.json: " + (error instanceof Error ? error.message : String(error)));
|
|
590
|
+
}
|
|
591
|
+
config = loadWorkflow(parsed);
|
|
592
|
+
} else config = loadWorkflow(void 0);
|
|
583
593
|
}
|
|
584
594
|
var verdict = validateCommitMessage(message, config);
|
|
585
595
|
if (!verdict.ok) {
|
|
@@ -589,6 +599,13 @@ var checkpoint = commitCheckpoint(state, config);
|
|
|
589
599
|
if (!checkpoint.allowed) {
|
|
590
600
|
refuse((checkpoint.reason ?? "commit checkpoint rejected") + "\uFF08\u5F53\u524D\u9636\u6BB5: " + state.stage + "\uFF09");
|
|
591
601
|
}
|
|
602
|
+
if (state.sonar_policy?.enabled && ["\u4EE3\u7801\u5BA1\u6838", "\u5B8C\u6210"].includes(state.stage)) {
|
|
603
|
+
const audit = state.sonar_audit;
|
|
604
|
+
const lastCommit = state.commits.findLast((entry) => entry.hash !== void 0)?.hash;
|
|
605
|
+
if (!audit || audit.gate !== "OK" || audit.blocking.length > 0 || audit.scope_hash !== scopeHash(state, cwd) || !lastCommit || audit.commit_hash !== lastCommit) {
|
|
606
|
+
refuse("SonarQube \u5BA1\u6838\u672A\u901A\u8FC7\u6216\u5DF2\u8FC7\u671F\u2014\u2014\u5728\u4EE3\u7801\u5BA1\u6838\u9636\u6BB5\u5B8C\u6210\u65B0\u4E00\u6B21 CI \u626B\u63CF\u5E76\u8C03\u7528 dev_task operation=sonar_check");
|
|
607
|
+
}
|
|
608
|
+
}
|
|
592
609
|
var entries = stagedEntries();
|
|
593
610
|
var scope = checkFileScope(state, entries.map((entry) => entry.path), config);
|
|
594
611
|
if (!scope.ok) {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Task-scoped engineering flows. The grade selects gates; risk remains separate. */
|
|
2
|
+
import type { WorkflowConfig } from './engine.ts';
|
|
3
|
+
export type Complexity = 'low' | 'medium' | 'high' | 'ultra';
|
|
4
|
+
export type MetaSkill = 'requirements-analysis' | 'architecture-design' | 'task-orchestration' | 'code-development' | 'test-validation' | 'code-review';
|
|
5
|
+
export declare const COMPLEXITY_OPTIONS: readonly {
|
|
6
|
+
id: Complexity;
|
|
7
|
+
label: string;
|
|
8
|
+
guidance: string;
|
|
9
|
+
}[];
|
|
10
|
+
export declare const META_STAGES: Readonly<Record<MetaSkill, string>>;
|
|
11
|
+
export declare const ADAPTIVE_VERSION = 1;
|
|
12
|
+
/** A grade is a per-task snapshot, never a project-wide forced flow. */
|
|
13
|
+
export declare function adaptiveWorkflow(grade: Complexity): WorkflowConfig;
|
|
14
|
+
export declare function isComplexity(value: unknown): value is Complexity;
|
|
15
|
+
export declare function metaForStage(stage: string): MetaSkill | undefined;
|
package/lib/adaptive.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export const COMPLEXITY_OPTIONS = [
|
|
2
|
+
{ id: 'low', label: '低', guidance: '边界明确的局部修改;一个实施项即可说明改动。' },
|
|
3
|
+
{ id: 'medium', label: '中', guidance: '常规功能或缺陷修复;先写清需求与验收条件。' },
|
|
4
|
+
{ id: 'high', label: '高', guidance: '跨模块或有先后依赖的需求;按实现顺序编排任务与交接产物。' },
|
|
5
|
+
{ id: 'ultra', label: '超高', guidance: '完整新模块或大范围重构;先明确架构边界,再按依赖顺序实施。' },
|
|
6
|
+
];
|
|
7
|
+
export const META_STAGES = {
|
|
8
|
+
'requirements-analysis': '需求分析',
|
|
9
|
+
'architecture-design': '架构设计',
|
|
10
|
+
'task-orchestration': '任务编排',
|
|
11
|
+
'code-development': '代码开发',
|
|
12
|
+
'test-validation': '测试',
|
|
13
|
+
'code-review': '代码审核',
|
|
14
|
+
};
|
|
15
|
+
export const ADAPTIVE_VERSION = 1;
|
|
16
|
+
const COMMON_ARTIFACTS = [
|
|
17
|
+
{ stage: '需求分析', id: 'requirement', name: '需求与验收条件', fields: ['goal', 'scope', 'acceptance'] },
|
|
18
|
+
{ stage: '架构设计', id: 'architecture', name: '架构边界', fields: ['approach', 'impact', 'tradeoffs'] },
|
|
19
|
+
{ stage: '任务编排', id: 'task-plan', name: '按实现顺序排列的任务', fields: ['steps', 'dependencies', 'handoffs'] },
|
|
20
|
+
];
|
|
21
|
+
/** A grade is a per-task snapshot, never a project-wide forced flow. */
|
|
22
|
+
export function adaptiveWorkflow(grade) {
|
|
23
|
+
const prefix = grade === 'low' ? []
|
|
24
|
+
: grade === 'medium' ? ['需求分析']
|
|
25
|
+
: grade === 'high' ? ['需求分析', '任务编排']
|
|
26
|
+
: ['需求分析', '架构设计', '任务编排'];
|
|
27
|
+
const stages = [...prefix, '代码开发', '测试', '代码审核', '完成'];
|
|
28
|
+
const transitions = stages.slice(0, -1).map((from, index) => {
|
|
29
|
+
const to = stages[index + 1];
|
|
30
|
+
const requires = from === '需求分析' || from === '架构设计' || from === '任务编排'
|
|
31
|
+
? ['artifacts_present']
|
|
32
|
+
: from === '代码开发' ? ['todos_done']
|
|
33
|
+
: from === '测试' ? ['verified']
|
|
34
|
+
: from === '代码审核' ? ['review_passed'] : [];
|
|
35
|
+
return { from, to, requires };
|
|
36
|
+
});
|
|
37
|
+
return {
|
|
38
|
+
stages,
|
|
39
|
+
start_stage: stages[0],
|
|
40
|
+
transitions,
|
|
41
|
+
artifacts: COMMON_ARTIFACTS.filter(artifact => stages.includes(artifact.stage)),
|
|
42
|
+
// The branch must be committed/pushed before its CI Sonar scan can run.
|
|
43
|
+
commit: { policy: 'task', message_pattern: '', message_hint: '无格式要求', checkpoints: ['测试'], file_scope: true },
|
|
44
|
+
high_risk_requires_verification: true,
|
|
45
|
+
review_depth: grade === 'low' ? 'single' : 'two-stage',
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export function isComplexity(value) {
|
|
49
|
+
return value === 'low' || value === 'medium' || value === 'high' || value === 'ultra';
|
|
50
|
+
}
|
|
51
|
+
export function metaForStage(stage) {
|
|
52
|
+
return Object.entries(META_STAGES).find(([, label]) => label === stage)?.[0];
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=adaptive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adaptive.js","sourceRoot":"","sources":["../src/adaptive.ts"],"names":[],"mappings":"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"}
|