agent-project-sdlc 0.1.9 → 0.1.11
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 +17 -1
- package/assets/agents/AGENTS_CORE.md +20 -16
- package/assets/docs/README.md +20 -5
- package/assets/make/sdlc-harness.mk +6 -1
- package/assets/policies/allowed_paths.yaml +3 -0
- package/assets/policies/gates.yaml +12 -0
- package/assets/policies/phase_contracts.yaml +12 -0
- package/assets/skills/pjsdlc_architect_design/SKILL.md +32 -3
- package/assets/skills/pjsdlc_dev_sprint/SKILL.md +6 -6
- package/assets/skills/pjsdlc_manager/SKILL.md +9 -7
- package/assets/skills/pjsdlc_pm_prd/SKILL.md +26 -2
- package/assets/skills/pjsdlc_release_manager/SKILL.md +18 -0
- package/assets/skills/pjsdlc_reviewer/SKILL.md +18 -0
- package/assets/skills/pjsdlc_rfc_recalibrate/SKILL.md +17 -0
- package/assets/skills/pjsdlc_tester/SKILL.md +18 -0
- package/assets/templates/PLAN_TEMPLATE.yaml +16 -13
- package/assets/templates/TECH_DESIGN_TEMPLATE.md +1 -1
- package/dist/commands/index.js +6 -0
- package/dist/lib/init.js +2 -2
- package/dist/lib/migrations.js +30 -11
- package/dist/lib/validators.js +368 -25
- package/package.json +1 -1
|
@@ -17,8 +17,11 @@ description: Use during RELEASING to prepare release notes, smoke evidence, depl
|
|
|
17
17
|
|
|
18
18
|
Release note 面向人类读者,必须说明变更价值、影响范围和注意事项;rollback plan 面向执行者,必须具体到触发条件、操作入口、验证方式和负责人。
|
|
19
19
|
|
|
20
|
+
发布准备本身也是 workflow task。开始 release 工作前,先在 `<harnessRoot>/state/plan.yaml` 创建或选择一个足够小的 `TASK-*` open task,并设置 `phase: "RELEASING"`;当前轮只产出一个 release slice、一次 smoke evidence 补充、一个部署检查或一个 rollback plan 单元。发布动作本身仍需用户明确授权。
|
|
21
|
+
|
|
20
22
|
## 输入
|
|
21
23
|
|
|
24
|
+
- `<harnessRoot>/state/plan.yaml`
|
|
22
25
|
- `.docs/07_test/`
|
|
23
26
|
- build artifacts
|
|
24
27
|
- changelog 或 task list
|
|
@@ -27,6 +30,7 @@ Release note 面向人类读者,必须说明变更价值、影响范围和注
|
|
|
27
30
|
## 输出
|
|
28
31
|
|
|
29
32
|
- `.docs/08_release/` 下的 release note
|
|
33
|
+
- 更新后的 `<harnessRoot>/state/plan.yaml`
|
|
30
34
|
- smoke test result
|
|
31
35
|
- deployment checklist
|
|
32
36
|
- rollback plan
|
|
@@ -40,6 +44,17 @@ Release note 面向人类读者,必须说明变更价值、影响范围和注
|
|
|
40
44
|
- 如果只是补充同一版本的 smoke evidence 或 rollback step,应更新原 release slice。
|
|
41
45
|
- 发布 slice 完成后更新 `.docs/INDEX.md`;不再维护 Harness archive。
|
|
42
46
|
|
|
47
|
+
## Plan Protocol
|
|
48
|
+
|
|
49
|
+
发布阶段受 `plan.yaml` 管控:
|
|
50
|
+
|
|
51
|
+
1. 没有 open task 时,先创建一个最小 `TASK-*` task,设置 `phase: "RELEASING"` 和 `current_task_id`。
|
|
52
|
+
2. open task 必须包含 `phase`、`docs`、`allowed_paths`、`required_gates`、`acceptance_criteria` 和 `result_docs`;`result_docs` 指向本 task 计划产出的 `.docs/08_release/**` 文件。
|
|
53
|
+
3. 单个 task 的目标应足够小:一个版本 release note、一个 smoke evidence 补充、一个 deployment checklist 或一个 rollback plan。
|
|
54
|
+
4. 执行当前 task 时只编辑 `allowed_paths` 中的 release 产物、`.docs/INDEX.md`、overview 和 `plan.yaml`。
|
|
55
|
+
5. 完成后运行 `make validate-plan` 和 task required gates;阶段出口前运行 `make validate-release`。
|
|
56
|
+
6. task 完成后从 `plan.yaml.tasks` 移除;如果还有 pending release task,下一轮 `/release` 或 `/next` 再继续。
|
|
57
|
+
|
|
43
58
|
## 规则
|
|
44
59
|
|
|
45
60
|
1. 除非用户明确要求,不自动部署。
|
|
@@ -47,10 +62,13 @@ Release note 面向人类读者,必须说明变更价值、影响范围和注
|
|
|
47
62
|
3. Rollback plan 必须可执行。
|
|
48
63
|
4. Smoke test evidence 必须链接或摘要记录。
|
|
49
64
|
5. Human confirmation items 必须明确。
|
|
65
|
+
6. 发布阶段一次只执行一个 `TASK-*` task。
|
|
50
66
|
|
|
51
67
|
## 完成检查
|
|
52
68
|
|
|
53
69
|
- [ ] Release note 已生成。
|
|
70
|
+
- [ ] 当前发布工作已绑定 `plan.yaml` 中一个最小 `TASK-*` task,并设置 `phase: "RELEASING"`。
|
|
71
|
+
- [ ] 当前 task 已从 `plan.yaml` 移除,或因中断/blocker 保留为可恢复 open task。
|
|
54
72
|
- [ ] Build artifacts 已记录。
|
|
55
73
|
- [ ] Smoke test result 已记录。
|
|
56
74
|
- [ ] 已判断 release slice 的版本或发布批次边界。
|
|
@@ -17,8 +17,11 @@ Review 时先建立证据链:PRD 说什么、技术方案承诺什么、implem
|
|
|
17
17
|
|
|
18
18
|
不要把个人偏好包装成 blocker。区分 blocking issue、follow-up improvement 和 open question。如果没有发现问题,要明确说明,同时列出剩余测试缺口或残余风险。
|
|
19
19
|
|
|
20
|
+
Review 产出本身也是 workflow task。开始 review 前,先在 `<harnessRoot>/state/plan.yaml` 创建或选择一个足够小的 `TASK-*` open task,并设置 `phase: "REVIEWING"`;当前轮只产出一个 review batch、一个风险主题 slice 或一次 PR review 结论。不要在一个任务里覆盖多个互不相关的 review 主题。
|
|
21
|
+
|
|
20
22
|
## 输入
|
|
21
23
|
|
|
24
|
+
- `<harnessRoot>/state/plan.yaml`
|
|
22
25
|
- `.docs/01_product/`
|
|
23
26
|
- `.docs/03_tech_plan/`
|
|
24
27
|
- `.docs/04_implementation/`
|
|
@@ -29,6 +32,7 @@ Review 时先建立证据链:PRD 说什么、技术方案承诺什么、implem
|
|
|
29
32
|
## 输出
|
|
30
33
|
|
|
31
34
|
- `.docs/06_review/REVIEW_REPORT.md`
|
|
35
|
+
- 更新后的 `<harnessRoot>/state/plan.yaml`
|
|
32
36
|
- 风险清单
|
|
33
37
|
- 重构建议
|
|
34
38
|
- 是否允许进入 `TESTING` 的结论
|
|
@@ -41,6 +45,17 @@ Review 时先建立证据链:PRD 说什么、技术方案承诺什么、implem
|
|
|
41
45
|
- Review 不重切上游 PRD / tech plan;如果发现上游边界错误,记录 blocker 或建议 RFC。
|
|
42
46
|
- 每次新增或拆分 review slice 后,都要更新 `.docs/INDEX.md`。
|
|
43
47
|
|
|
48
|
+
## Plan Protocol
|
|
49
|
+
|
|
50
|
+
Review 阶段受 `plan.yaml` 管控:
|
|
51
|
+
|
|
52
|
+
1. 没有 open task 时,先创建一个最小 `TASK-*` task,设置 `phase: "REVIEWING"` 和 `current_task_id`。
|
|
53
|
+
2. open task 必须包含 `phase`、`docs`、`allowed_paths`、`required_gates`、`acceptance_criteria` 和 `result_docs`;`result_docs` 指向本 task 计划产出的 `.docs/06_review/**` 文件。
|
|
54
|
+
3. 单个 task 的目标应足够小:一次 review batch、一个 PR、一个模块或一个风险主题。
|
|
55
|
+
4. 执行当前 task 时只写 review 产物、`.docs/INDEX.md`、`overview.md` 和 `plan.yaml`,不修改源码。
|
|
56
|
+
5. 完成后运行 `make validate-plan` 和 `make docs-overview`;阶段出口前运行 `make validate-review`。
|
|
57
|
+
6. task 完成后从 `plan.yaml.tasks` 移除;如果还有 pending review task,下一轮 `/review` 或 `/next` 再继续。
|
|
58
|
+
|
|
44
59
|
## 规则
|
|
45
60
|
|
|
46
61
|
1. 本 Skill 不修改源码。
|
|
@@ -48,10 +63,13 @@ Review 时先建立证据链:PRD 说什么、技术方案承诺什么、implem
|
|
|
48
63
|
3. 每条 finding 尽量引用文件、需求、任务或文档路径。
|
|
49
64
|
4. 区分 blocking issues 和 follow-up improvements。
|
|
50
65
|
5. 如果未发现问题,明确说明,并列出剩余测试缺口或残余风险。
|
|
66
|
+
6. Review 阶段一次只执行一个 `TASK-*` task。
|
|
51
67
|
|
|
52
68
|
## 完成检查
|
|
53
69
|
|
|
54
70
|
- [ ] Review report 已生成。
|
|
71
|
+
- [ ] 当前 review 工作已绑定 `plan.yaml` 中一个最小 `TASK-*` task,并设置 `phase: "REVIEWING"`。
|
|
72
|
+
- [ ] 当前 task 已从 `plan.yaml` 移除,或因中断/blocker 保留为可恢复 open task。
|
|
55
73
|
- [ ] 已评估需求一致性。
|
|
56
74
|
- [ ] 已评估架构和可维护性风险。
|
|
57
75
|
- [ ] 已判断 review slice 的范围和风险主题边界。
|
|
@@ -19,6 +19,8 @@ description: Use during RFC_RECALIBRATION to process requirement changes with im
|
|
|
19
19
|
|
|
20
20
|
影响面分析必须先于补丁。至少检查 docs/state/skills/policies/templates/tools/package assets/tests/migrations/generated artifacts 是否受影响;如果某一类不受影响,也要显式说明不受影响或不需要修改。对于 Harness package 相关变更,还要检查 `sync`、`upgrade`、source mappings、package assets 和用户项目迁移行为。
|
|
21
21
|
|
|
22
|
+
RFC recalibration 本身也是 workflow task。开始处理变更前,先在 `<harnessRoot>/state/plan.yaml` 创建或选择一个足够小的 `TASK-*` open task,并设置 `phase: "RFC_RECALIBRATION"`;当前轮只处理一个 RFC 文件、一个 impact analysis 单元或一个局部补丁单元。
|
|
23
|
+
|
|
22
24
|
## 输入
|
|
23
25
|
|
|
24
26
|
- `.docs/rfc/RFC_*.md`
|
|
@@ -33,6 +35,7 @@ description: Use during RFC_RECALIBRATION to process requirement changes with im
|
|
|
33
35
|
- 局部更新后的 PRD 和技术方案
|
|
34
36
|
- 被标记为 `pending_revision` 的受影响任务,或新增增量任务
|
|
35
37
|
- Regression requirements
|
|
38
|
+
- 更新后的 `<harnessRoot>/state/plan.yaml`
|
|
36
39
|
- 更新后的 `.docs/INDEX.md`
|
|
37
40
|
|
|
38
41
|
## 语义切片
|
|
@@ -43,6 +46,17 @@ description: Use during RFC_RECALIBRATION to process requirement changes with im
|
|
|
43
46
|
- 对受影响产物做局部补丁,不重写无关稳定 slice。
|
|
44
47
|
- 每次 RFC 影响了文档边界,都要更新 `.docs/INDEX.md` 并记录受影响任务状态。
|
|
45
48
|
|
|
49
|
+
## Plan Protocol
|
|
50
|
+
|
|
51
|
+
RFC 阶段受 `plan.yaml` 管控:
|
|
52
|
+
|
|
53
|
+
1. 没有 open task 时,先创建一个最小 `TASK-*` task,设置 `phase: "RFC_RECALIBRATION"` 和 `current_task_id`。
|
|
54
|
+
2. open task 必须包含 `phase`、`docs`、`allowed_paths`、`required_gates`、`acceptance_criteria` 和 `result_docs`;`result_docs` 指向本 task 计划产出的 RFC、受影响 PRD/tech plan/test docs 或 plan update。
|
|
55
|
+
3. 单个 task 的目标应足够小:一份 RFC 的 impact analysis、一个受影响 slice 的局部补丁、一组任务状态调整,或一个回归要求更新。
|
|
56
|
+
4. 执行当前 task 时只编辑 `allowed_paths` 中的 RFC、受影响 facts、`.docs/INDEX.md`、overview 和 `plan.yaml`。
|
|
57
|
+
5. 完成后运行 `make validate-plan` 和 task required gates;阶段出口前运行 `make validate-rfc`。
|
|
58
|
+
6. task 完成后从 `plan.yaml.tasks` 移除;如果还有 pending RFC task,下一轮 `/rfc` 或 `/next` 再继续。
|
|
59
|
+
|
|
46
60
|
## 规则
|
|
47
61
|
|
|
48
62
|
1. 影响已接受产物的需求变化,必须先进入本 Skill。
|
|
@@ -51,10 +65,13 @@ description: Use during RFC_RECALIBRATION to process requirement changes with im
|
|
|
51
65
|
4. 受影响的 `pending` 或 `in_progress` 任务追加 revision notes。
|
|
52
66
|
5. 不重写无关的稳定文档。
|
|
53
67
|
6. 只有 `make validate-rfc` 通过后,才能恢复原阶段或进入 `SPRINTING`。
|
|
68
|
+
7. RFC 阶段一次只执行一个 `TASK-*` task。
|
|
54
69
|
|
|
55
70
|
## 完成检查
|
|
56
71
|
|
|
57
72
|
- [ ] RFC 包含有效 status 和 acceptance criteria。
|
|
73
|
+
- [ ] 当前 RFC 工作已绑定 `plan.yaml` 中一个最小 `TASK-*` task,并设置 `phase: "RFC_RECALIBRATION"`。
|
|
74
|
+
- [ ] 当前 task 已从 `plan.yaml` 移除,或因中断/blocker 保留为可恢复 open task。
|
|
58
75
|
- [ ] Product impact 和 technical impact 已记录。
|
|
59
76
|
- [ ] 已判断 RFC 是否需要拆分,以及是否影响其它阶段 slice。
|
|
60
77
|
- [ ] 已列出 docs/state/skills/policies/templates/tools/package assets/tests/migrations/generated artifacts 的影响面。
|
|
@@ -17,10 +17,13 @@ description: Use during TESTING to produce a test matrix, run regression, and do
|
|
|
17
17
|
|
|
18
18
|
执行回归时,优先选择能证明阶段出口的 gate。测试无法运行、环境缺失或数据不可得时,不要宣布通过,应记录 blocker、已完成检查和恢复条件。
|
|
19
19
|
|
|
20
|
+
测试计划和回归证据产出本身也是 workflow task。开始测试前,先在 `<harnessRoot>/state/plan.yaml` 创建或选择一个足够小的 `TASK-*` open task,并设置 `phase: "TESTING"`;当前轮只产出一个测试矩阵 slice、一个回归批次、一个风险验证片区或一组 scoped test changes。
|
|
21
|
+
|
|
20
22
|
如果用户明确要求并行、多 agent 或多 worktree,测试阶段可以启用 `parallel_execution`,让 worker 分别执行互不依赖的回归片区、smoke、兼容性或风险验证。worker 只提交证据和必要的 scoped test changes;最终 `.docs/07_test/**`、coverage gaps、PASS/BLOCKED 决策和阶段 gate 由主 Agent 汇总。没有用户显式要求时,测试 workflow 保持串行。
|
|
21
23
|
|
|
22
24
|
## 输入
|
|
23
25
|
|
|
26
|
+
- `<harnessRoot>/state/plan.yaml`
|
|
24
27
|
- `.docs/01_product/`
|
|
25
28
|
- `.docs/03_tech_plan/`
|
|
26
29
|
- `.docs/04_implementation/`
|
|
@@ -32,6 +35,7 @@ description: Use during TESTING to produce a test matrix, run regression, and do
|
|
|
32
35
|
|
|
33
36
|
- `.docs/07_test/TEST_PLAN.md`
|
|
34
37
|
- 必要时在 `tests/` 下补充测试
|
|
38
|
+
- 更新后的 `<harnessRoot>/state/plan.yaml`
|
|
35
39
|
- 回归测试记录
|
|
36
40
|
- 覆盖缺口清单
|
|
37
41
|
|
|
@@ -43,6 +47,17 @@ description: Use during TESTING to produce a test matrix, run regression, and do
|
|
|
43
47
|
- 如果新增测试只是覆盖同一验收标准,应更新原 test slice,不要创建重复测试计划。
|
|
44
48
|
- 每次新增、拆分或合并 test slice 后,都要更新 `.docs/INDEX.md`。
|
|
45
49
|
|
|
50
|
+
## Plan Protocol
|
|
51
|
+
|
|
52
|
+
测试阶段受 `plan.yaml` 管控:
|
|
53
|
+
|
|
54
|
+
1. 没有 open task 时,先创建一个最小 `TASK-*` task,设置 `phase: "TESTING"` 和 `current_task_id`。
|
|
55
|
+
2. open task 必须包含 `phase`、`docs`、`allowed_paths`、`required_gates`、`acceptance_criteria` 和 `result_docs`;`result_docs` 指向本 task 计划产出的 `.docs/07_test/**` 文件,必要时也列出 scoped test files。
|
|
56
|
+
3. 单个 task 的目标应足够小:一个测试矩阵 slice、一个回归批次、一个风险验证片区,或一组紧密相关的测试变更。
|
|
57
|
+
4. 执行当前 task 时只编辑 `allowed_paths` 中的测试、测试文档、`.docs/INDEX.md`、overview 和 `plan.yaml`。
|
|
58
|
+
5. 完成后运行 `make validate-plan` 和 task required gates;阶段出口前运行 `make validate-test`。
|
|
59
|
+
6. task 完成后从 `plan.yaml.tasks` 移除;如果还有 pending testing task,下一轮 `/test` 或 `/next` 再继续。
|
|
60
|
+
|
|
46
61
|
## 规则
|
|
47
62
|
|
|
48
63
|
1. 测试用例必须追溯到 PRD acceptance criteria 或 Review findings。
|
|
@@ -50,10 +65,13 @@ description: Use during TESTING to produce a test matrix, run regression, and do
|
|
|
50
65
|
3. 如果有意延后覆盖,必须记录风险和 follow-up。
|
|
51
66
|
4. 并行测试必须使用 `parallel_execution.trigger: "user_requested"`;`runtime_managed` 只在当前 runtime 支持 subagent 时使用,否则输出 `user_orchestrated` worker prompt。
|
|
52
67
|
5. 宣布阶段完成前运行 `make test-all`。
|
|
68
|
+
6. 测试阶段一次只执行一个 `TASK-*` task。
|
|
53
69
|
|
|
54
70
|
## 完成检查
|
|
55
71
|
|
|
56
72
|
- [ ] Test matrix 已把需求映射到测试。
|
|
73
|
+
- [ ] 当前测试工作已绑定 `plan.yaml` 中一个最小 `TASK-*` task,并设置 `phase: "TESTING"`。
|
|
74
|
+
- [ ] 当前 task 已从 `plan.yaml` 移除,或因中断/blocker 保留为可恢复 open task。
|
|
57
75
|
- [ ] Regression checklist 已完成。
|
|
58
76
|
- [ ] 已判断 test plan / test matrix 的语义切片边界。
|
|
59
77
|
- [ ] Coverage gaps 已明确。
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
current_task_id: "DEV-001"
|
|
1
|
+
current_task_id: "TASK-001"
|
|
3
2
|
next_task_sequence: 2
|
|
4
3
|
# Optional. Omit this block for normal serial workflow. Only add it when the
|
|
5
4
|
# user explicitly asks for parallel / multi-agent / multi-worktree execution.
|
|
@@ -7,9 +6,7 @@ next_task_sequence: 2
|
|
|
7
6
|
# enabled: true
|
|
8
7
|
# trigger: "user_requested"
|
|
9
8
|
# mode: "user_orchestrated" # or "runtime_managed" when the current agent runtime can spawn subagents
|
|
10
|
-
# phase: "SPRINTING"
|
|
11
9
|
# coordinator: "main_agent"
|
|
12
|
-
# linked_task_id: "DEV-001"
|
|
13
10
|
# workers:
|
|
14
11
|
# - id: "worker-feature"
|
|
15
12
|
# writes_repo: true
|
|
@@ -33,24 +30,30 @@ next_task_sequence: 2
|
|
|
33
30
|
# fact_source_updates:
|
|
34
31
|
# - ".docs/04_implementation/"
|
|
35
32
|
tasks:
|
|
36
|
-
- id: "
|
|
37
|
-
|
|
33
|
+
- id: "TASK-001"
|
|
34
|
+
phase: "REQUIREMENT_GATHERING"
|
|
35
|
+
title: "生成示例 PRD slice"
|
|
38
36
|
status: "pending"
|
|
39
37
|
summary: "一句话描述任务目标和交付边界。"
|
|
40
38
|
docs:
|
|
39
|
+
raw:
|
|
40
|
+
- ".docs/00_raw/example.md"
|
|
41
41
|
product:
|
|
42
42
|
- ".docs/01_product/example.md"
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
architecture: []
|
|
44
|
+
tech_plan: []
|
|
45
45
|
rfc: []
|
|
46
46
|
allowed_paths:
|
|
47
|
-
- "
|
|
48
|
-
- "
|
|
47
|
+
- ".docs/00_raw/**"
|
|
48
|
+
- ".docs/01_product/**"
|
|
49
|
+
- ".docs/INDEX.md"
|
|
50
|
+
- "<harnessRoot>/state/plan.yaml"
|
|
49
51
|
required_gates:
|
|
50
|
-
- "make
|
|
51
|
-
- "make
|
|
52
|
+
- "make validate-plan"
|
|
53
|
+
- "make docs-overview"
|
|
52
54
|
acceptance_criteria:
|
|
53
55
|
- "验收标准写在 open task 内,完成后从当前 plan 删除。"
|
|
54
56
|
working_notes:
|
|
55
57
|
- "执行现场备注只在 open task 保留。"
|
|
56
|
-
|
|
58
|
+
result_docs:
|
|
59
|
+
- ".docs/01_product/example.md"
|
|
@@ -41,7 +41,7 @@ Input
|
|
|
41
41
|
|
|
42
42
|
| Task ID | 标题(Title) | Allowed Paths | Required Gates | Implementation Doc |
|
|
43
43
|
|---|---|---|---|---|
|
|
44
|
-
|
|
|
44
|
+
| TASK-001 | | `src/**`, `tests/**` | `make lint`, `make test-current-domain` | `.docs/04_implementation/...` |
|
|
45
45
|
|
|
46
46
|
`Implementation Doc` 应指向模块、子系统或核心数据流级文档;多个 task 可以更新同一份文档,task id 和 commit 记录在该文档的 provenance / Change Log 中。
|
|
47
47
|
|
package/dist/commands/index.js
CHANGED
|
@@ -13,9 +13,14 @@ export const commands = {
|
|
|
13
13
|
validate,
|
|
14
14
|
"validate-harness": (args) => validate(["validate-harness", ...args]),
|
|
15
15
|
"validate-current": (args) => validate(["validate-current", ...args]),
|
|
16
|
+
"validate-plan": (args) => validate(["validate-plan", ...args]),
|
|
16
17
|
"validate-pm": (args) => validate(["validate-pm", ...args]),
|
|
17
18
|
"validate-design": (args) => validate(["validate-design", ...args]),
|
|
18
19
|
"validate-dev": (args) => validate(["validate-dev", ...args]),
|
|
20
|
+
"validate-review": (args) => validate(["validate-review", ...args]),
|
|
21
|
+
"validate-test": (args) => validate(["validate-test", ...args]),
|
|
22
|
+
"validate-release": (args) => validate(["validate-release", ...args]),
|
|
23
|
+
"validate-rfc": (args) => validate(["validate-rfc", ...args]),
|
|
19
24
|
package: packageSource
|
|
20
25
|
};
|
|
21
26
|
export function help() {
|
|
@@ -26,5 +31,6 @@ export function help() {
|
|
|
26
31
|
upgrade Run migrations and then sync
|
|
27
32
|
doctor Diagnose project configuration and drift
|
|
28
33
|
validate <gate> Run a Harness validation gate
|
|
34
|
+
validate-* Run a named gate directly, including validate-plan/review/test/release/rfc
|
|
29
35
|
package <subcommand> Maintain package canonical source`);
|
|
30
36
|
}
|
package/dist/lib/init.js
CHANGED
|
@@ -53,8 +53,8 @@ async function createProjectState(projectRoot, root, report) {
|
|
|
53
53
|
harnessPath(root, "state", "lifecycle.yaml"),
|
|
54
54
|
`project_name: "Project"\nversion: "v0.1"\ncurrent_phase: "SPRINTING"\nactive_role: "developer"\nactive_skill: "pjsdlc_dev_sprint"\ncurrent_milestone: "MVP"\nblocked_reason: ""\nsuspended_phase: ""\nallowed_next_phases:\n - "REVIEWING"\n`
|
|
55
55
|
],
|
|
56
|
-
[harnessPath(root, "state", "plan.yaml"), `
|
|
57
|
-
[harnessPath(root, "state", "plan.draft.yaml"), `
|
|
56
|
+
[harnessPath(root, "state", "plan.yaml"), `current_task_id: ""\nnext_task_sequence: 1\ntasks: []\n`],
|
|
57
|
+
[harnessPath(root, "state", "plan.draft.yaml"), `next_task_sequence: 1\ntasks: []\n`],
|
|
58
58
|
[harnessPath(root, "state", "memory.md"), "# Project Memory\n\n短期执行计划写入 plan.yaml;长期稳定知识简短记录在这里,并链接到 `.docs/` 正式出处。\n"]
|
|
59
59
|
];
|
|
60
60
|
for (const [relative, content] of files) {
|
package/dist/lib/migrations.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { readdir, rename, rm } from "node:fs/promises";
|
|
3
|
-
import { readConfig } from "./config.js";
|
|
3
|
+
import { defaultConfig, readConfig } from "./config.js";
|
|
4
4
|
import { ensureDir, listFiles, pathExists, readText, writeTextIfChanged } from "./fs.js";
|
|
5
5
|
import { harnessConfigPath, harnessPath, harnessRoot } from "./harness-root.js";
|
|
6
6
|
import { parseYaml, stringifyYaml } from "./yaml.js";
|
|
@@ -23,8 +23,8 @@ export async function runMigrations(projectRoot) {
|
|
|
23
23
|
await migrateConfig(projectRoot, root, report);
|
|
24
24
|
await migrateLegacyManagedPaths(projectRoot, root, report);
|
|
25
25
|
await migrateLifecycle(projectRoot, root, report);
|
|
26
|
-
await migratePlan(projectRoot, root, report, "plan.yaml", "tasks.yaml");
|
|
27
|
-
await migratePlan(projectRoot, root, report, "plan.draft.yaml", "tasks.draft.yaml");
|
|
26
|
+
await migratePlan(projectRoot, root, report, "plan.yaml", "tasks.yaml", { activePlan: true });
|
|
27
|
+
await migratePlan(projectRoot, root, report, "plan.draft.yaml", "tasks.draft.yaml", { activePlan: false });
|
|
28
28
|
await removeLegacyGateResults(projectRoot, root, report);
|
|
29
29
|
await removeLegacyCheckpoints(projectRoot, root, report);
|
|
30
30
|
await ensureMemory(projectRoot, root, report);
|
|
@@ -38,6 +38,9 @@ async function migrateConfig(projectRoot, root, report) {
|
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
40
|
const config = await readConfig(projectRoot);
|
|
41
|
+
const currentCore = defaultConfig(root).core;
|
|
42
|
+
config.core.package = currentCore.package;
|
|
43
|
+
config.core.version = currentCore.version;
|
|
41
44
|
config.core.schema_version = CURRENT_SCHEMA_VERSION;
|
|
42
45
|
config.managed_files = migrateManagedFiles(config.managed_files, root);
|
|
43
46
|
config.local_overrides = config.local_overrides.map((item) => migrateLocalOverride(item, root));
|
|
@@ -197,7 +200,7 @@ async function migrateLifecycle(projectRoot, root, report) {
|
|
|
197
200
|
report.skipped.push(relativeLifecyclePath);
|
|
198
201
|
}
|
|
199
202
|
}
|
|
200
|
-
async function migratePlan(projectRoot, root, report, planFileName, legacyFileName) {
|
|
203
|
+
async function migratePlan(projectRoot, root, report, planFileName, legacyFileName, options) {
|
|
201
204
|
const relativePlanPath = harnessPath(root, "state", planFileName);
|
|
202
205
|
const planPath = path.join(projectRoot, relativePlanPath);
|
|
203
206
|
const legacyTasksPath = path.join(projectRoot, harnessPath(root, "state", legacyFileName));
|
|
@@ -208,18 +211,32 @@ async function migratePlan(projectRoot, root, report, planFileName, legacyFileNa
|
|
|
208
211
|
}
|
|
209
212
|
const data = (parseYaml(await readText(sourcePath)) ?? {});
|
|
210
213
|
let changed = false;
|
|
211
|
-
if (
|
|
212
|
-
data.current_phase
|
|
214
|
+
if ("current_phase" in data) {
|
|
215
|
+
delete data.current_phase;
|
|
213
216
|
changed = true;
|
|
214
217
|
}
|
|
215
|
-
if (!("current_task_id" in data)) {
|
|
218
|
+
if (options.activePlan && !("current_task_id" in data)) {
|
|
216
219
|
data.current_task_id = "";
|
|
217
220
|
changed = true;
|
|
218
221
|
}
|
|
222
|
+
if (!options.activePlan && "current_task_id" in data) {
|
|
223
|
+
delete data.current_task_id;
|
|
224
|
+
changed = true;
|
|
225
|
+
}
|
|
219
226
|
if (!Array.isArray(data.tasks)) {
|
|
220
227
|
data.tasks = [];
|
|
221
228
|
changed = true;
|
|
222
229
|
}
|
|
230
|
+
if (isRecord(data.parallel_execution)) {
|
|
231
|
+
if ("phase" in data.parallel_execution) {
|
|
232
|
+
delete data.parallel_execution.phase;
|
|
233
|
+
changed = true;
|
|
234
|
+
}
|
|
235
|
+
if ("linked_task_id" in data.parallel_execution) {
|
|
236
|
+
delete data.parallel_execution.linked_task_id;
|
|
237
|
+
changed = true;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
223
240
|
if (Array.isArray(data.tasks)) {
|
|
224
241
|
const retainedTasks = [];
|
|
225
242
|
let maxTaskSequence = 0;
|
|
@@ -266,10 +283,12 @@ async function migratePlan(projectRoot, root, report, planFileName, legacyFileNa
|
|
|
266
283
|
changed = true;
|
|
267
284
|
}
|
|
268
285
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
data
|
|
272
|
-
|
|
286
|
+
if (options.activePlan) {
|
|
287
|
+
const currentTaskId = String(data.current_task_id ?? "");
|
|
288
|
+
if (currentTaskId && !taskById(data, currentTaskId)) {
|
|
289
|
+
data.current_task_id = "";
|
|
290
|
+
changed = true;
|
|
291
|
+
}
|
|
273
292
|
}
|
|
274
293
|
if (changed || sourcePath !== planPath) {
|
|
275
294
|
if (await writeTextIfChanged(planPath, stringifyYaml(data))) {
|