cowork-flow 2.3.0 → 2.4.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.
Files changed (60) hide show
  1. package/CHANGELOG.md +18 -1
  2. package/README.en.md +34 -18
  3. package/README.md +8 -5
  4. package/docs/architecture.en.md +95 -0
  5. package/docs/architecture.md +7 -3
  6. package/docs/direction.en.md +71 -0
  7. package/docs/direction.md +6 -1
  8. package/docs/hosts.en.md +299 -0
  9. package/docs/hosts.md +3 -1
  10. package/docs/index.en.md +30 -0
  11. package/docs/index.md +2 -0
  12. package/docs/release.en.md +108 -0
  13. package/docs/release.md +2 -0
  14. package/package.json +2 -2
  15. package/presets/claude-code/.claude-plugin/plugin.json +1 -1
  16. package/presets/claude-code/skills/cowork-flow-bootstrap/SKILL.md +4 -0
  17. package/presets/codex/.codex-plugin/plugin.json +1 -1
  18. package/presets/codex/skills/cowork-flow-bootstrap/SKILL.md +4 -0
  19. package/presets/kimi-code/.kimi-plugin/plugin.json +1 -1
  20. package/presets/kimi-code/skills/cowork-flow-bootstrap/SKILL.md +4 -0
  21. package/presets/opencode/cowork-flow/skills/cowork-flow-bootstrap/SKILL.md +4 -0
  22. package/presets/qoder/.qoder-plugin/plugin.json +1 -1
  23. package/presets/qoder/skills/cowork-flow-bootstrap/SKILL.md +4 -0
  24. package/presets/zcode/.zcode-plugin/plugin.json +1 -1
  25. package/presets/zcode/skills/cowork-flow-bootstrap/SKILL.md +4 -0
  26. package/src/commands/init.js +129 -2
  27. package/src/commands/registry.js +3 -1
  28. package/src/commands/source-refresh.js +5 -1
  29. package/src/commands/sync.js +3 -0
  30. package/src/lib/copy-template.js +23 -5
  31. package/src/lib/host-assets.js +117 -2
  32. package/src/lib/language.js +162 -0
  33. package/template/.cowork-flow/.version +1 -1
  34. package/template/.cowork-flow/config.yaml +8 -0
  35. package/template/.cowork-flow/scripts/adapters/cli/task_create_command.py +5 -3
  36. package/template/.cowork-flow/scripts/adapters/host/host_manifest.py +71 -2
  37. package/template/.cowork-flow/scripts/infra/config.py +85 -0
  38. package/template/.cowork-flow/scripts/services/decision_anchor_schema.py +104 -0
  39. package/template/.cowork-flow/scripts/services/fact_view.py +21 -15
  40. package/template/.cowork-flow/scripts/services/task_context.py +13 -7
  41. package/template/.cowork-flow/scripts/services/task_creation.py +72 -30
  42. package/template/.cowork-flow/scripts/services/task_gate_profiles.py +7 -24
  43. package/template/.cowork-flow/spec/contracts/context-injection.md +5 -4
  44. package/template/.cowork-flow/spec/contracts/decision-anchor.md +21 -14
  45. package/template/.cowork-flow/spec/contracts/plan-binding.md +2 -1
  46. package/template/.cowork-flow/spec/index.md +26 -26
  47. package/template/.cowork-flow/spec/references/definition-of-done.md +26 -26
  48. package/template/.cowork-flow/spec/references/index.md +16 -16
  49. package/template/.cowork-flow/spec/references/orchestration-patterns.md +71 -71
  50. package/template/.cowork-flow/spec/references/security-checklist.md +37 -37
  51. package/template/.cowork-flow/spec/references/testing-checklist.md +32 -32
  52. package/template/.cowork-flow/spec/runtime/host-assets.json +23 -4
  53. package/template/.cowork-flow/spec/runtime/index.md +10 -12
  54. package/template/.cowork-flow/spec/schemas/host-assets.schema.json +31 -0
  55. package/template/.cowork-flow/spec/schemas/index.md +5 -5
  56. package/template/.cowork-flow/templates/plan-template.md +91 -0
  57. package/template/locales/en-US/.cowork-flow/spec/contracts/decision-anchor.md +160 -0
  58. package/template/locales/en-US/.cowork-flow/templates/plan-template.md +91 -0
  59. package/template/skills/runtime-health/scripts/doctor.py +110 -0
  60. package/template/skills/task-planning/SKILL.md +19 -92
@@ -0,0 +1,160 @@
1
+ # Decision Anchor Contract
2
+
3
+ **Every task must have a `decision-anchor.md`: the single authoritative decision
4
+ source that prevents drift during execution.**
5
+
6
+ It merges and replaces the former `prd.md`, carrying both "what to do" and "why not
7
+ the alternatives", which compresses the number of task artifacts.
8
+
9
+ ## Schema
10
+
11
+ These section names are machine-readable. The runtime parser accepts both the
12
+ Chinese and English heading sets, and new anchors use the language configured in
13
+ `.cowork-flow/config.yaml` (`zh-CN` is the default).
14
+
15
+ ```markdown
16
+ # Decision Anchor
17
+
18
+ ## Goal
19
+ <one sentence>
20
+
21
+ ## Acceptance Criteria
22
+ - [ ] AC-001: <verifiable>
23
+ - [ ] AC-002: <verifiable>
24
+
25
+ ## Rejected Options
26
+ - **Option B**: <summary> — rejected because: <why>
27
+
28
+ ## Key Assumptions
29
+ - <assumption 1>
30
+
31
+ ## Scope Boundary
32
+ - In scope: <list>
33
+ - Out of scope: <list>
34
+
35
+ ## Verification Commands
36
+ - `<command>` → <expected>
37
+ - Spec check: clause-by-clause check against applicable `.cowork-flow/spec/<dev_type>/` rules → pass / not_applicable (with reason)
38
+ ```
39
+
40
+ ## Section requirements
41
+
42
+ Both heading columns below are accepted; the right column is the `en-US` output
43
+ and the left column the `zh-CN` output.
44
+
45
+ | Section | Required | Why |
46
+ |------|------|------|
47
+ | `## Goal` / `## 目标` | required | no goal, no acceptance baseline |
48
+ | `## Acceptance Criteria` / `## 验收标准` | required | `task_start` is blocked without acceptance criteria |
49
+ | `## Rejected Options` / `## 被拒方案` | optional | required for brainstorming tasks, so a rejected option is not reconsidered during execution |
50
+ | `## Key Assumptions` / `## 关键假设` | optional | filled in for complex tasks to surface implicit constraints; not read by the runtime parser |
51
+ | `## Scope Boundary` / `## 范围边界` | optional | prevents scope creep |
52
+ | `## Verification Commands` / `## 验证命令` | optional | filled in for complex tasks, as the basis for automated verification; when the changed files are covered by `.cowork-flow/spec/backend/` or `frontend/` rules, it must also carry the spec/gate check for the task's `dev_type` (deciding command, or clause-by-clause `pass` / `not_applicable` with reason) |
53
+
54
+ ### Machine-readable line formats (for injection)
55
+
56
+ `## Verification Commands` and `## Scope Boundary` are parsed by stage-contract
57
+ injection and by the MCP fact view (`services/fact_view.parse_decision_anchor`).
58
+ Line-format conventions:
59
+
60
+ - `## Verification Commands`: one command per line (an optional `- ` prefix),
61
+ truncated to 120 characters, at most 10 lines; the implementing agent runs them
62
+ itself (self-declared, self-checked) and the reviewer verifies the execution
63
+ evidence. When the changed files are covered by `.cowork-flow/spec/<dev_type>/`
64
+ rules, the section must also carry the spec/gate check for the task's
65
+ `dev_type`: a deciding command, or a `Spec check:` line reviewed clause by
66
+ clause (`pass` / `not_applicable` + reason). This is a strong review reminder,
67
+ not a `spec-check` hard gate.
68
+ - `## Scope Boundary`: only the first non-empty line is taken, truncated to 160
69
+ characters.
70
+
71
+ ## Scenarios
72
+
73
+ | Scenario | Source | What gets filled in |
74
+ |------|------|---------|
75
+ | Has brainstorming | extracted from the discussion outcome | every section |
76
+ | No brainstorming (requirements already clear) | extracted from the requirement description and the plan | the minimum: goal + acceptance criteria |
77
+
78
+ ## Artifact compression
79
+
80
+ Before merging (6 files): `prd.md` + `implement.jsonl` + `check.jsonl` +
81
+ `debug.jsonl` + `task.json`
82
+
83
+ After merging (5 files): `decision-anchor.md` + `implement.jsonl` + `check.jsonl` +
84
+ `debug.jsonl` + `task.json`
85
+
86
+ **A net reduction of one file type. Related-file tracking is now owned entirely by
87
+ `implement.jsonl`.**
88
+
89
+ ## Lifecycle check coupling
90
+
91
+ - The preflight for `task next <dir> --run` checks that `decision-anchor.md` is
92
+ non-empty and requires the `## Goal` / `## 目标` and `## Acceptance Criteria` /
93
+ `## 验收标准` sections to be present.
94
+ - **Gate profile `meta.gateProfile`**: a newly created task is written as
95
+ `"strict"`; an unmarked task is treated as `"legacy"` — existing tasks are not
96
+ retro-fitted with the stricter gate, and the profile is queryable through the
97
+ fact view. On top of the section check, a strict task additionally requires: at
98
+ least one parseable `- [ ] AC-xxx: ...` row in `## Acceptance Criteria` /
99
+ `## 验收标准`, no duplicate AC ids, no non-AC list rows in that section, and a
100
+ declared `dev_type` (otherwise `task specs` dev-type dispatch silently comes
101
+ back shorter).
102
+ - An acceptance row's checkbox state (`- [ ]` / `- [x]`) and the evidence records
103
+ (the task directory's `evidence.jsonl`) are the fact source of the completion
104
+ gate: completion is blocked when an unchecked AC exists (`LIFECYCLE-AC-001`), a
105
+ declared AC has no evidence (`LIFECYCLE-AC-002`), a strict task cannot read any
106
+ AC row (`LIFECYCLE-AC-003`), or the AC-evidence module is unavailable
107
+ (`LIFECYCLE-AC-004`). Schema and exemptions are in `evidence-completion.md`.
108
+ - **Review receipt change fingerprint** (a strict task requires its latest receipt
109
+ to match the current state at completion, `LIFECYCLE-REVIEW-003`). Input = the
110
+ git-visible change set (paths + content digests) + this anchor's goal and AC text
111
+ + the content digest of the bound plan + `dev_type` + the **content digest** of
112
+ every referenced spec + the content digest of `implement.jsonl`. Both `spec/**`
113
+ and `tasks/**` are gitignored, which is why the last two must enter the
114
+ fingerprint explicitly — otherwise rewriting a referenced spec's prose, or
115
+ widening the declared scope, would leave a stale receipt valid.
116
+ - Fingerprint **exclusions** (mechanism): the change set excludes the whole
117
+ `.cowork-flow/tasks/**` tree, `.cowork-flow/.runtime/**`, and
118
+ `.cowork-flow/logs/**` — task-directory artifacts (`task.json`,
119
+ `evidence.jsonl`, `review.jsonl`, `check.jsonl`, `debug.jsonl`, and the anchor's
120
+ **path entry**) and runtime metadata are not counted, or a receipt would
121
+ invalidate itself the moment it was recorded. `implement.jsonl`'s path entry is
122
+ excluded the same way; its **content** is counted instead through the `scope`
123
+ component.
124
+ A **consequence** (expected cost, not a defect): **any byte change in
125
+ `implement.jsonl`** (appending or removing a scope entry, rewording a `reason`,
126
+ a domain-guide entry) **or a rewrite of a
127
+ referenced spec's prose invalidates an existing receipt**, requiring one more
128
+ review run against the final state. Appending evidence, ticking ACs, and runtime
129
+ metadata are not in that set.
130
+ - **Light profile `meta.taskType: "tiny"`**: applies to `strict` tasks only
131
+ (`legacy` + `tiny` stays a compatibility path). A light task **is still strict**
132
+ — what it waives are three things: the review receipt, AC evidence, and
133
+ `dev_type`. It does **not** waive the file-scope gate or "AC rows
134
+ are non-empty" (`LIFECYCLE-AC-003`/`004` still apply). Plan-file binding is not
135
+ among the three, but the pre-existing field-level exemption for tiny applies, so
136
+ a light task does not require `planFile` either. `tiny` **can only be declared at
137
+ creation time** (`task next --run --task-type tiny`) with no later edit path; the
138
+ light profile is visible in `task next --list` (a `[light]` text marker and
139
+ `lightProfile` in `--json`) and in doctor's task-hygiene output. The single
140
+ decision source is `task_gate_profiles.is_light_task` (`strict` + the field is
141
+ `tiny`); the start-preflight plan-file exemption still uses the field-level
142
+ `declares_light_profile` so existing pre-strict tiny tasks keep behaving as
143
+ before. The light profile **must not** be used for a task touching runtime /
144
+ gates / specs — that rule rests on visibility and review, not on a machine gate.
145
+ - Read by `cowork-implement`: see .cowork-flow/spec/contracts/subagent-dispatch.md
146
+ - Read by `cowork-check`: same as above
147
+ - `debug.jsonl` reference: optional; on deviation diagnosis it records the anchor
148
+ delta
149
+
150
+ ## Formal-release behavior
151
+
152
+ The formal release does not auto-migrate a legacy `prd.md`. When a task is
153
+ started, only `decision-anchor.md` is recognized as the authoritative decision
154
+ source; if a task directory has only `prd.md` and no `decision-anchor.md`,
155
+ `task next <dir> --run` must fail-closed and report
156
+ `decision-anchor.md is missing or empty`.
157
+
158
+ An existing legacy task needs a human to convert the `prd.md` content into
159
+ `decision-anchor.md`, fill in `## Goal` / `## 目标` and
160
+ `## Acceptance Criteria` / `## 验收标准`, and only then start.
@@ -0,0 +1,91 @@
1
+ # <Feature> Implementation Plan
2
+
3
+ > Execution rule: this plan exists to prevent implementation drift. The implementer must work through tasks in order.
4
+ > If the plan conflicts with current code facts, a plan-external file becomes necessary, or a test fails for an unplanned reason, stop and report back instead of expanding scope.
5
+ >
6
+ > For formal fixed-agent work: create a runtime context with `.cowork-flow/run subagent init`, pass `cowork_runtime_context_id: <runtime_context_id>` through the active Host Adapter, then dispatch `cowork-implement` or `cowork-check`. Close the runtime context after verification.
7
+
8
+ | Field | Content |
9
+ |----|------|
10
+ | **Task Type** | Tiny / Normal / High-risk: <reason> |
11
+ | **Strategy** | Serial / Parallel: <why> |
12
+ | **Success Criteria** | AC-001 / AC-002 / AC-003 |
13
+ | **Final Verification** | `<command>` -> exit 0; clause-by-clause check against applicable `.cowork-flow/spec/<dev_type>/` rules and project gates -> `pass` / `not_applicable` per clause |
14
+ | **Primary Risk** | Low / Medium / High: <one sentence> |
15
+
16
+ **Goal:** <One sentence describing the observable behavior change>
17
+
18
+ ## Goal
19
+
20
+ <1-3 sentences describing the expected observable behavior.>
21
+
22
+ ## Acceptance Criteria
23
+
24
+ - AC-001: <observable behavior>
25
+ - AC-002: <observable behavior>
26
+
27
+ ## Global Constraints
28
+
29
+ - <Architecture boundary, compatibility requirement, command, or output field that must be preserved>
30
+ - <Explicitly prohibited scope expansion>
31
+
32
+ ## File Boundaries
33
+
34
+ - `path/a.py`: <responsibility; only change this function or region>
35
+ - `tests/test_a.py`: <responsibility; only add or modify these tests>
36
+
37
+ ## Tasks
38
+
39
+ Tiny plans may keep a shorter brief, but must still name exact file boundaries, completion conditions, and one verification command.
40
+
41
+ ### Task N: <small goal>
42
+
43
+ **Purpose**
44
+ - <Observable behavior after this task is complete>
45
+
46
+ **Code Fact Sources**
47
+ - Read: `path/a.py::function_name`
48
+ - Read: `tests/test_a.py::test_existing_behavior`
49
+
50
+ **File Boundaries**
51
+ - Create / Modify / Test: `path/a.py` (only change <function/region>)
52
+ - Test: `tests/test_a.py` (only change <test/region>)
53
+
54
+ **Key Symbols**
55
+ - Change: `function_name()`, `ClassName.method()`, `<config-key>`
56
+ - Preserve: `existing_helper()`, output field `<field>`
57
+
58
+ **Implementation Notes**
59
+ ```python
60
+ # Core control-flow sketch; adjust names to match existing code.
61
+ # Do not copy a complete implementation into the plan.
62
+ ...
63
+ ```
64
+
65
+ **Test Proof**
66
+ - `tests/test_a.py::test_x`: proves <specific behavior>
67
+ - Core assertion: <one sentence describing the assertion, not only the test name>
68
+
69
+ **Verification Command**
70
+ ```bash
71
+ <command>
72
+ ```
73
+
74
+ When changed files are covered by `.cowork-flow/spec/<dev_type>/` rules, add the deciding command or a spec/gate check line (`pass` / `not_applicable` with reason) here; it is a strong review reminder, not a hard gate.
75
+
76
+ **Completion Conditions**
77
+ - <2-4 checkable conditions>
78
+
79
+ **Prohibited Drift**
80
+ - <2-5 explicit prohibited changes>
81
+
82
+ **Deviation Conditions**
83
+ - If <plan-external file/layer> becomes necessary, must stop and report back because the file boundary is wrong.
84
+
85
+ ## Final Verification
86
+
87
+ ```bash
88
+ <command>
89
+ ```
90
+
91
+ Spec check: clause-by-clause check against applicable `.cowork-flow/spec/<dev_type>/` rules -> <pass / not_applicable + reason>.
@@ -6,6 +6,7 @@ from __future__ import annotations
6
6
  import argparse
7
7
  import json
8
8
  import os
9
+ import re
9
10
  import sys
10
11
  from datetime import datetime, timezone
11
12
  from pathlib import Path
@@ -31,6 +32,7 @@ from adapters.host.host_manifest import (
31
32
  validate_host_assets,
32
33
  )
33
34
  from infra.paths import DIR_WORKFLOW, get_repo_root
35
+ from infra.config import UnsupportedLanguageError, get_language
34
36
  from infra.skill_manifest import SkillManifestError, action_owners, load_skill_manifests
35
37
  from infra.storage.operation_log import OperationLog
36
38
  from infra.storage.state_store import DEFAULT_STALE_LOCK_SECONDS, StateStore
@@ -205,6 +207,101 @@ def check_distribution(repo_root: Path) -> list[str]:
205
207
  return errors
206
208
 
207
209
 
210
+ _ANCHOR_LANGUAGE_CHECKS = {
211
+ "zh-CN": ("## 目标", "## 验收标准", "## 被拒方案", "## 验证命令"),
212
+ "en-US": ("## Goal", "## Acceptance Criteria", "## Rejected Options", "## Verification Commands"),
213
+ }
214
+ _PLAN_LANGUAGE_CHECKS = {
215
+ "zh-CN": re.compile(r"(?m)^\*\*目标(?::\*\*|\*\*:)"),
216
+ "en-US": re.compile(r"(?m)^\*\*Goal(?::\*\*|\*\*:)"),
217
+ }
218
+
219
+
220
+ def _contract_block(text: str) -> str:
221
+ """The schema example is the machine-readable heading source."""
222
+ match = re.search(r"```markdown\n(.*?)```", text, re.DOTALL)
223
+ return match.group(1) if match else text
224
+
225
+
226
+ def _asset_language(path: Path, kind: str) -> str | None:
227
+ """Detected output language, `mixed`, or None when the asset is absent."""
228
+ try:
229
+ text = path.read_text(encoding="utf-8")
230
+ except (OSError, UnicodeDecodeError):
231
+ return None
232
+ if kind == "anchor":
233
+ block = _contract_block(text)
234
+ present = {
235
+ language
236
+ for language, markers in _ANCHOR_LANGUAGE_CHECKS.items()
237
+ if all(marker in block for marker in markers)
238
+ }
239
+ else:
240
+ present = {
241
+ language
242
+ for language, pattern in _PLAN_LANGUAGE_CHECKS.items()
243
+ if pattern.search(text)
244
+ }
245
+ if len(present) > 1:
246
+ return "mixed"
247
+ return next(iter(present), None)
248
+
249
+
250
+ def check_language(repo_root: Path) -> list[dict[str, str]]:
251
+ """Report an invalid `language` value and localized-asset drift.
252
+
253
+ A missing config key or a missing asset means the project predates the
254
+ language option: it is not drift, so it stays silent until the first sync.
255
+ """
256
+ config_file = repo_root / DIR_WORKFLOW / "config.yaml"
257
+ try:
258
+ config_text = config_file.read_text(encoding="utf-8")
259
+ except (OSError, UnicodeDecodeError):
260
+ return []
261
+ if not re.search(r"(?m)^language\s*:", config_text):
262
+ return []
263
+
264
+ try:
265
+ language = get_language(repo_root, strict=True)
266
+ except UnsupportedLanguageError as error:
267
+ return [
268
+ _issue(
269
+ code="CONFIG-LANGUAGE-001",
270
+ severity="error",
271
+ path=config_file.relative_to(repo_root).as_posix(),
272
+ message=str(error),
273
+ command_hint="Edit .cowork-flow/config.yaml, then run cwf project sync",
274
+ contract="runtime-health:language",
275
+ )
276
+ ]
277
+
278
+ issues: list[dict[str, str]] = []
279
+ assets = (
280
+ (".cowork-flow/spec/contracts/decision-anchor.md", "anchor"),
281
+ (".cowork-flow/templates/plan-template.md", "plan"),
282
+ )
283
+ for relative, kind in assets:
284
+ path = repo_root / relative
285
+ detected = _asset_language(path, kind)
286
+ if detected is None:
287
+ continue
288
+ if detected != language:
289
+ issues.append(
290
+ _issue(
291
+ code="LANGUAGE-DRIFT-001",
292
+ severity="warning",
293
+ path=relative,
294
+ message=(
295
+ f"installed asset language is {detected}, but "
296
+ f".cowork-flow/config.yaml selects {language}"
297
+ ),
298
+ command_hint="cwf project sync",
299
+ contract="runtime-health:language",
300
+ )
301
+ )
302
+ return issues
303
+
304
+
208
305
  def _task_path(repo_root: Path, task_dir: Path) -> str:
209
306
  try:
210
307
  return task_dir.resolve().relative_to(repo_root.resolve()).as_posix()
@@ -1673,6 +1770,7 @@ def _all_check_result(repo_root: Path) -> dict[str, object]:
1673
1770
  host_issues = _host_issues(repo_root)
1674
1771
  runtime_errors = check_runtime(repo_root)
1675
1772
  distribution_errors = check_distribution(repo_root)
1773
+ language_issues = check_language(repo_root)
1676
1774
  task_hygiene_issues = check_task_hygiene(repo_root)
1677
1775
  state_recovery_issues = check_state_recovery(repo_root)
1678
1776
  session_hygiene_issues = check_session_hygiene(repo_root)
@@ -1697,11 +1795,17 @@ def _all_check_result(repo_root: Path) -> dict[str, object]:
1697
1795
  {"kind": "distribution", "message": error}
1698
1796
  for error in distribution_errors
1699
1797
  )
1798
+ errors.extend(
1799
+ {"kind": "language", **issue}
1800
+ for issue in language_issues
1801
+ if issue["severity"] == "error"
1802
+ )
1700
1803
  return {
1701
1804
  "ok": not errors,
1702
1805
  "errors": errors,
1703
1806
  "issues": {
1704
1807
  "hostAdapters": host_issues,
1808
+ "language": language_issues,
1705
1809
  "taskHygiene": task_hygiene_issues,
1706
1810
  "stateRecovery": state_recovery_issues,
1707
1811
  "sessionHygiene": session_hygiene_issues,
@@ -1725,6 +1829,12 @@ def _run_checks(repo_root: Path, *, structured: bool = False) -> int:
1725
1829
  if structured:
1726
1830
  print(json.dumps(result, ensure_ascii=False))
1727
1831
  return 1 if errors else 0
1832
+ for issue in result["issues"]["language"]:
1833
+ if issue["severity"] == "error":
1834
+ continue
1835
+ print(f"Language ({issue['code']}): {issue['message']}")
1836
+ if issue.get("commandHint"):
1837
+ print(f" fix: {issue['commandHint']}")
1728
1838
  _print_task_hygiene_issues(result["issues"]["taskHygiene"])
1729
1839
  _print_state_recovery_issues(result["issues"]["stateRecovery"])
1730
1840
  _print_session_hygiene_issues(result["issues"]["sessionHygiene"])
@@ -14,6 +14,7 @@ Before writing a plan, confirm the request has an executable scope, acceptance c
14
14
  Read:
15
15
 
16
16
  - Active task `decision-anchor.md`.
17
+ - The installed `.cowork-flow/templates/plan-template.md`.
17
18
  - Relevant decision-anchor, design, guide, or spec files.
18
19
  - Relevant `.cowork-flow/spec/` indexes and target specs.
19
20
  - `.cowork-flow/spec/guides/index.md` for non-trivial, ambiguous, cross-layer, or reusable-work planning.
@@ -23,111 +24,29 @@ Read:
23
24
 
24
25
  Save plans to `.cowork-flow/plans/YYYY-MM-DD-<slug>.md` unless the user asks for another path.
25
26
 
26
- ### Plan Style: Task Briefs, Not Design Docs
27
-
28
- Plans exist to prevent implementation drift. They must guide implementation by pinning task order, file boundaries, key symbols, the core patch shape, test proof, completion conditions, and prohibited drift. They are not architecture essays and must not explain every possible option.
29
-
30
- Do not write option-comparison tables unless the user explicitly asks. Do not copy complete implementations into the plan. The plan should expose the core patch shape: where to change, what behavior changes, what key branch or pseudocode should guide the edit, how tests prove it, and which boundaries must not be crossed.
31
-
32
- Start with a concise brief:
33
-
34
- ```markdown
35
- # <Feature> Implementation Plan
36
-
37
- > Execution rule: this plan exists to prevent implementation drift. The implementer must work through tasks in order.
38
- > If the plan conflicts with current code facts, a plan-external file becomes necessary, or a test fails for an unplanned reason, stop and report back instead of expanding scope.
39
- >
40
- > For formal fixed-agent work: create a runtime context with `.cowork-flow/run subagent init`, pass `cowork_runtime_context_id: <runtime_context_id>` through the active Host Adapter, then dispatch `cowork-implement` or `cowork-check`. Close the runtime context after verification.
27
+ Use the installed `.cowork-flow/templates/plan-template.md` as the plan skeleton. It carries the execution rule, header table, goal and acceptance sections, global constraints, file boundaries, the per-task brief fields, and the final verification section, so this Skill does not restate them.
41
28
 
42
- | Field | Content |
43
- |----|------|
44
- | **Goal** | <One sentence describing the observable behavior change> |
45
- | **Task Type** | Tiny / Normal / High-risk: <reason> |
46
- | **Strategy** | Serial / Parallel: <why> |
47
- | **Success Criteria** | AC-001 / AC-002 / AC-003 |
48
- | **Final Verification** | `<command>` -> exit 0; clause-by-clause check against applicable `.cowork-flow/spec/<dev_type>/` rules and project gates -> `pass` / `not_applicable` per clause |
49
- | **Primary Risk** | Low / Medium / High: <one sentence> |
29
+ If the installed template is missing, stop and report it (run `cwf project sync .` to install it); do not invent a replacement shape.
50
30
 
51
- ## Goal
31
+ The template is distributed at install time for the project language configured in `.cowork-flow/config.yaml` (`zh-CN` by default, or `en-US`). Write the plan in that language. Keep the template's machine-readable goal line and `AC-NNN` identifiers unchanged so task creation and workflow gates can parse them. Do not translate paths, commands, code identifiers, or spec file names.
52
32
 
53
- <1-3 sentences describing the expected observable behavior.>
54
-
55
- ## Acceptance Criteria
56
-
57
- - AC-001: <observable behavior>
58
- - AC-002: <observable behavior>
59
-
60
- ## Global Constraints
61
-
62
- - <Architecture boundary, compatibility requirement, command, or output field that must be preserved>
63
- - <Explicitly prohibited scope expansion>
64
-
65
- ## File Boundaries
33
+ ### Plan Style: Task Briefs, Not Design Docs
66
34
 
67
- - `path/a.py`: <responsibility; only change this function or region>
68
- - `tests/test_a.py`: <responsibility; only add or modify these tests>
35
+ Plans exist to prevent implementation drift. They must guide implementation by pinning task order, file boundaries, key symbols, the core patch shape, test proof, completion conditions, and prohibited drift. They are not architecture essays and must not explain every possible option.
69
36
 
70
- ## Tasks
71
- ```
37
+ Do not write option-comparison tables unless the user explicitly asks. Do not copy complete implementations into the plan. The plan should expose the core patch shape: where to change, what behavior changes, what key branch or pseudocode should guide the edit, how tests prove it, and which boundaries must not be crossed.
72
38
 
73
- Then list task briefs, followed by integrated verification and completion checks.
39
+ Fill the template in order: header table and goal first, then acceptance criteria, global constraints, file boundaries, one task brief per executable step, and a final verification section. Do not add a second plan shape or rename the template sections.
74
40
 
75
41
  ## Task Rules
76
42
 
77
43
  - Classify the plan before writing tasks:
78
44
  - **Tiny**: pure docs, names, comments, or no-behavior cleanup. Use file boundaries, completion conditions, and one verification command.
79
- - **Normal**: ordinary behavior, test, or workflow guidance changes. Use the full task brief below.
45
+ - **Normal**: ordinary behavior, test, or workflow guidance changes. Use the full task brief.
80
46
  - **High-risk**: workflow, runtime, template, spec, hook, state-machine, migration, or security-sensitive changes. Use the full task brief plus code-fact sources and explicit drift boundaries.
81
47
  - Each task names exact files to create, modify, or test.
82
48
  - Each task is small enough to execute and verify independently.
83
- - Every Normal or High-risk task must use this brief format:
84
-
85
- ```markdown
86
- ### Task N: <small goal>
87
-
88
- **Purpose**
89
- - <Observable behavior after this task is complete>
90
-
91
- **Code Fact Sources**
92
- - Read: `path/a.py::function_name`
93
- - Read: `tests/test_a.py::test_existing_behavior`
94
-
95
- **File Boundaries**
96
- - Create / Modify / Test: `path/a.py` (only change <function/region>)
97
- - Test: `tests/test_a.py` (only change <test/region>)
98
-
99
- **Key Symbols**
100
- - Change: `function_name()`, `ClassName.method()`, `<config-key>`
101
- - Preserve: `existing_helper()`, output field `<field>`
102
-
103
- **Implementation Notes**
104
- ```python
105
- # Core control-flow sketch; adjust names to match existing code.
106
- # Do not copy a complete implementation into the plan.
107
- ...
108
- ```
109
-
110
- **Test Proof**
111
- - `tests/test_a.py::test_x`: proves <specific behavior>
112
- - Core assertion: <one sentence describing the assertion, not only the test name>
113
-
114
- **Verification Command**
115
- ```bash
116
- <command>
117
- ```
118
-
119
- When changed files are covered by `.cowork-flow/spec/<dev_type>/` rules, add the deciding command or a spec/gate check line (`pass` / `not_applicable` with reason; format example in `decision-anchor.md`) here; it is a strong review reminder, not a hard gate.
120
-
121
- **Completion Conditions**
122
- - <2-4 checkable conditions>
123
-
124
- **Prohibited Drift**
125
- - <2-5 explicit prohibited changes>
126
-
127
- **Deviation Conditions**
128
- - If <plan-external file/layer> becomes necessary, must stop and report back because the file boundary is wrong.
129
- ```
130
-
49
+ - Every Normal or High-risk task fills every required field in the template's task brief: Purpose, Code Fact Sources, File Boundaries, Key Symbols, Implementation Notes, Test Proof, Verification Command, Completion Conditions, Prohibited Drift, and Deviation Conditions.
131
50
  - For Tiny tasks, keep the brief short but still name exact file boundaries, completion conditions, and verification commands.
132
51
  - For behavior changes, include a failing test before implementation when behavior can be tested.
133
52
  - For implementation tasks whose changed files are covered by `.cowork-flow/spec/` requirements, name the covered spec files in the plan and add the clause check to the task's `Verification Command` and the plan's `Final Verification`: run the deciding command when one exists, otherwise check clause by clause and record `pass` / `not_applicable` with reason. This is a strong review reminder, not a separate hard gate.
@@ -149,6 +68,12 @@ Then list task briefs, followed by integrated verification and completion checks
149
68
  | "This task does not need a verification command." | No verification means no completion signal. Every task needs an executable verification command. | Add at least one automated check, such as typecheck, test, lint, or build. |
150
69
  | "The plan should explore every alternative." | Heavy option analysis slows routine implementation and hides the path to execute. | State the chosen path and drift boundaries. Add option analysis only when the user asks or the decision is genuinely architectural. |
151
70
 
71
+ ## Fixed-Agent Dispatch
72
+
73
+ > For formal fixed-agent work: create a runtime context with `.cowork-flow/run subagent init`, pass `cowork_runtime_context_id: <runtime_context_id>` through the active Host Adapter, then dispatch `cowork-implement` or `cowork-check`. Close the runtime context after verification.
74
+
75
+ Use this path when a task is dispatched to a fixed agent. The plan owns the task boundaries; the runtime context binds the dispatched agent to the current task.
76
+
152
77
  ## Plan Approval Gate
153
78
 
154
79
  A plan can be marked approved only when all conditions hold:
@@ -156,6 +81,7 @@ A plan can be marked approved only when all conditions hold:
156
81
  - Every task in the plan has clear acceptance criteria.
157
82
  - Every task has implementation steps and verification commands.
158
83
  - Task dependencies are explicit, including whether work is serial or parallelizable.
84
+ - The plan uses the installed `.cowork-flow/templates/plan-template.md` shape and the configured output language.
159
85
 
160
86
  `implement.jsonl` is the current task's context index — the files in scope and
161
87
  the spec pointers it needs — not the task list. The plan owns the task list.
@@ -189,7 +115,8 @@ Before handoff:
189
115
 
190
116
  1. Confirm every `decision-anchor.md` acceptance criterion maps to a task.
191
117
  2. Search the plan for placeholders.
192
- 3. Confirm every Normal or High-risk task has file boundaries, key symbols, implementation notes, test proof, completion conditions, and prohibited drift.
118
+ 3. Confirm every Normal or High-risk task fills every required brief field in the template.
193
119
  4. Check names, paths, command syntax, and expected outputs.
194
120
  5. Confirm the plan says to stop and report back when code facts conflict with the plan, a plan-external file becomes necessary, or a test fails for an unplanned reason.
195
121
  6. Confirm Final Verification carries the applicable `.cowork-flow/spec/<dev_type>/` clause check, or states why no spec file applies.
122
+ 7. Confirm the plan is written in the configured language and keeps the machine-readable goal line and `AC-NNN` identifiers unchanged.