cowork-flow 2.3.0 → 2.4.1
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/CHANGELOG.md +31 -1
- package/README.en.md +34 -18
- package/README.md +8 -5
- package/docs/architecture.en.md +95 -0
- package/docs/architecture.md +7 -3
- package/docs/direction.en.md +71 -0
- package/docs/direction.md +6 -1
- package/docs/hosts.en.md +299 -0
- package/docs/hosts.md +3 -1
- package/docs/index.en.md +30 -0
- package/docs/index.md +2 -0
- package/docs/release.en.md +108 -0
- package/docs/release.md +2 -0
- package/package.json +2 -2
- package/presets/claude-code/.claude-plugin/plugin.json +1 -1
- package/presets/claude-code/skills/cowork-flow-bootstrap/SKILL.md +4 -0
- package/presets/codex/.codex-plugin/plugin.json +1 -1
- package/presets/codex/skills/cowork-flow-bootstrap/SKILL.md +4 -0
- package/presets/kimi-code/.kimi-plugin/plugin.json +1 -1
- package/presets/kimi-code/skills/cowork-flow-bootstrap/SKILL.md +4 -0
- package/presets/opencode/cowork-flow/skills/cowork-flow-bootstrap/SKILL.md +4 -0
- package/presets/qoder/.qoder-plugin/plugin.json +1 -1
- package/presets/qoder/skills/cowork-flow-bootstrap/SKILL.md +4 -0
- package/presets/zcode/.zcode-plugin/plugin.json +1 -1
- package/presets/zcode/skills/cowork-flow-bootstrap/SKILL.md +4 -0
- package/src/commands/init.js +129 -2
- package/src/commands/registry.js +3 -1
- package/src/commands/source-refresh.js +5 -1
- package/src/commands/sync.js +3 -0
- package/src/lib/copy-template.js +23 -5
- package/src/lib/host-assets.js +117 -2
- package/src/lib/language.js +162 -0
- package/template/.cowork-flow/.version +1 -1
- package/template/.cowork-flow/config.yaml +8 -0
- package/template/.cowork-flow/scripts/adapters/cli/task_create_command.py +5 -3
- package/template/.cowork-flow/scripts/adapters/host/host_manifest.py +71 -2
- package/template/.cowork-flow/scripts/infra/config.py +85 -0
- package/template/.cowork-flow/scripts/services/decision_anchor_schema.py +228 -0
- package/template/.cowork-flow/scripts/services/fact_view.py +27 -15
- package/template/.cowork-flow/scripts/services/plan_binding.py +34 -0
- package/template/.cowork-flow/scripts/services/plan_schema.py +182 -0
- package/template/.cowork-flow/scripts/services/task_context.py +84 -12
- package/template/.cowork-flow/scripts/services/task_creation.py +89 -30
- package/template/.cowork-flow/scripts/services/task_gate_profiles.py +7 -24
- package/template/.cowork-flow/spec/contracts/context-injection.md +5 -4
- package/template/.cowork-flow/spec/contracts/decision-anchor.md +35 -19
- package/template/.cowork-flow/spec/contracts/plan-binding.md +27 -4
- package/template/.cowork-flow/spec/index.md +26 -26
- package/template/.cowork-flow/spec/references/definition-of-done.md +26 -26
- package/template/.cowork-flow/spec/references/index.md +16 -16
- package/template/.cowork-flow/spec/references/orchestration-patterns.md +71 -71
- package/template/.cowork-flow/spec/references/security-checklist.md +37 -37
- package/template/.cowork-flow/spec/references/testing-checklist.md +32 -32
- package/template/.cowork-flow/spec/runtime/contract-registry.json +1 -0
- package/template/.cowork-flow/spec/runtime/host-assets.json +23 -4
- package/template/.cowork-flow/spec/runtime/index.md +10 -12
- package/template/.cowork-flow/spec/schemas/host-assets.schema.json +31 -0
- package/template/.cowork-flow/spec/schemas/index.md +5 -5
- package/template/.cowork-flow/templates/plan-template.md +91 -0
- package/template/locales/en-US/.cowork-flow/spec/contracts/decision-anchor.md +169 -0
- package/template/locales/en-US/.cowork-flow/templates/plan-template.md +91 -0
- package/template/skills/runtime-health/scripts/doctor.py +110 -0
- package/template/skills/task-planning/SKILL.md +21 -94
|
@@ -1,51 +1,51 @@
|
|
|
1
1
|
# Security Quick Reference
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Security quick reference. Load on demand when handling user input, authentication, data storage, or external integrations.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Contract: ERROR_OUTPUT_AS_DATA_V1 (see .cowork-flow/spec/contracts/error-output-as-data.md)
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Input validation
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
9
|
+
- Validate all external input at the boundary (API entry points, file uploads, CLI arguments)
|
|
10
|
+
- Error messages must not leak internal implementation details (stack traces, paths, library versions)
|
|
11
|
+
- Use parameterized queries; never concatenate SQL strings
|
|
12
|
+
- Prefer length/type/range allowlists over blocklists
|
|
13
13
|
|
|
14
|
-
##
|
|
14
|
+
## Authentication and authorization
|
|
15
15
|
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
16
|
+
- Authentication state is not stored on the client (httpOnly secure cookie only)
|
|
17
|
+
- Perform permission checks on every protected operation (do not rely on the frontend to hide controls)
|
|
18
|
+
- Authentication failures do not distinguish wrong username from wrong password (use a uniform "authentication failed" message)
|
|
19
|
+
- Sessions have an expiry time and rotate on privilege change
|
|
20
20
|
|
|
21
|
-
##
|
|
21
|
+
## Dependencies and supply chain
|
|
22
22
|
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
23
|
+
- Third-party dependencies come from trusted sources
|
|
24
|
+
- No known CVEs (`pip audit` / `npm audit`)
|
|
25
|
+
- Lockfiles are committed to version control
|
|
26
26
|
|
|
27
|
-
##
|
|
27
|
+
## Data and privacy
|
|
28
28
|
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
29
|
+
- Logs contain no sensitive data (passwords, tokens, PII)
|
|
30
|
+
- Encrypt in transit (TLS) and at rest (bcrypt/argon2)
|
|
31
|
+
- Treat error output as untrusted data (see ERROR_OUTPUT_AS_DATA_V1)
|
|
32
32
|
|
|
33
|
-
## OWASP Top 10
|
|
33
|
+
## OWASP Top 10 quick mapping
|
|
34
34
|
|
|
35
|
-
|
|
|
35
|
+
| ID | Category | Check | Risk if missing |
|
|
36
36
|
|---|---|---|---|
|
|
37
|
-
| A01 |
|
|
38
|
-
| A02 |
|
|
39
|
-
| A03 |
|
|
40
|
-
| A04 | XXE |
|
|
41
|
-
| A05 |
|
|
42
|
-
| A06 |
|
|
43
|
-
| A07 | XSS |
|
|
44
|
-
| A08 |
|
|
45
|
-
| A09 |
|
|
46
|
-
| A10 |
|
|
47
|
-
|
|
48
|
-
##
|
|
49
|
-
|
|
50
|
-
- `spec/contracts/error-output-as-data.md` —
|
|
51
|
-
- `skills/test-first/SKILL.md` —
|
|
37
|
+
| A01 | Injection | Parameterized queries | Data disclosure or loss |
|
|
38
|
+
| A02 | Broken authentication | bcrypt + session rotation | Account takeover |
|
|
39
|
+
| A03 | Sensitive data exposure | Encryption in transit + at rest + no leakage | Data disclosure |
|
|
40
|
+
| A04 | XXE | Disable external entity parsing | XML injection |
|
|
41
|
+
| A05 | Broken access control | Re-authorize on every request | Unauthorized operations |
|
|
42
|
+
| A06 | Security misconfiguration | Secure defaults + no debug headers | Information disclosure |
|
|
43
|
+
| A07 | XSS | Input/output encoding + CSP | Browser-side code execution |
|
|
44
|
+
| A08 | Insecure deserialization | Do not deserialize untrusted data | RCE |
|
|
45
|
+
| A09 | Vulnerable components | Regular audits | Known exploits |
|
|
46
|
+
| A10 | Unauthorized replay | Nonce + rate limit | Automated abuse |
|
|
47
|
+
|
|
48
|
+
## See also
|
|
49
|
+
|
|
50
|
+
- `spec/contracts/error-output-as-data.md` — defending against prompt injection
|
|
51
|
+
- `skills/test-first/SKILL.md` — security regression test evidence
|
|
@@ -1,45 +1,45 @@
|
|
|
1
1
|
# Testing Checklist
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Quick reference for test quality. Load on demand when reviewing test files, writing test cases, or checking behavior coverage.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Test structure
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
- AAA
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
7
|
+
- Test names describe behavior: `test_<unit>_<scenario>_<expected>`
|
|
8
|
+
- AAA layout (visual separation between Arrange/Act/Assert)
|
|
9
|
+
- One test verifies one behavior
|
|
10
|
+
- Assert behavior contracts, not implementation details
|
|
11
|
+
- Mocks verify behavior calls, not call counts
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## Depth
|
|
14
14
|
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
15
|
+
- Not a test that passes via `assert True`
|
|
16
|
+
- Not a test that only checks whether a function exists
|
|
17
|
+
- Not a test that uses `unittest.mock` call counts instead of behavior verification
|
|
18
|
+
- Not a test that snapshots an empty structure (`assert result == {}`)
|
|
19
|
+
- Does not depend on test execution order
|
|
20
|
+
- Does not skip necessary setup/teardown
|
|
21
|
+
- Asserts exact values or behavior contracts, not truthy/falsy
|
|
22
|
+
- Has at least one test for the error path
|
|
23
23
|
|
|
24
|
-
##
|
|
24
|
+
## Anti-patterns
|
|
25
25
|
|
|
26
|
-
|
|
|
26
|
+
| Anti-pattern | Problem | Alternative |
|
|
27
27
|
|---|---|---|
|
|
28
|
-
|
|
|
29
|
-
|
|
|
30
|
-
|
|
|
31
|
-
|
|
|
32
|
-
|
|
|
33
|
-
|
|
|
28
|
+
| Hard-coding expected values to implementation output | Test couples to implementation; it fails when implementation changes but behavior does not | Verify the behavior contract: input -> expected output |
|
|
29
|
+
| Mocking internal calls of the function under test | Tests implementation instead of behavior | Keep mocks at boundaries (API/filesystem/time) |
|
|
30
|
+
| Packing unrelated behaviors into one test | A failure does not reveal what broke | One test per behavior, with a descriptive name |
|
|
31
|
+
| Asserting `assert True` | Always passes | Use semantic assertions (assertEqual/assertGreater, etc.) |
|
|
32
|
+
| Only checking that a function exists (`assert module.func`) | Does not verify behavior | Call the function and verify output or exceptions |
|
|
33
|
+
| Not cleaning up global state / fixtures | Cross-test pollution causes order dependence | Clean up in setup/teardown |
|
|
34
34
|
|
|
35
|
-
##
|
|
35
|
+
## Scope
|
|
36
36
|
|
|
37
|
-
-
|
|
38
|
-
-
|
|
39
|
-
-
|
|
37
|
+
- The changed function/module has a direct unit test
|
|
38
|
+
- Downstream dependencies have integration tests
|
|
39
|
+
- Boundary conditions (empty/extreme values/concurrency) have at least one test
|
|
40
40
|
|
|
41
|
-
##
|
|
41
|
+
## See also
|
|
42
42
|
|
|
43
|
-
- `spec/backend/quality-guidelines.md` —
|
|
44
|
-
- `skills/test-first/SKILL.md` —
|
|
45
|
-
- `references/security-checklist.md` —
|
|
43
|
+
- `spec/backend/quality-guidelines.md` — backend testing rules
|
|
44
|
+
- `skills/test-first/SKILL.md` — full TDD workflow
|
|
45
|
+
- `references/security-checklist.md` — security boundary checks in tests
|
|
@@ -108,6 +108,7 @@
|
|
|
108
108
|
"digest": [
|
|
109
109
|
"Plan binding records repo-relative task.json.meta.planFile.",
|
|
110
110
|
"Task start blocks clear missing plan facts for non-Tiny tasks.",
|
|
111
|
+
"Strict non-Tiny start requires the configured-language plan template shape and a filled spec-check line.",
|
|
111
112
|
"V1 does not parse plan steps, AC text, or verification evidence."
|
|
112
113
|
],
|
|
113
114
|
"readWhen": [
|
|
@@ -442,16 +442,36 @@
|
|
|
442
442
|
],
|
|
443
443
|
"excludedPrefixes": [
|
|
444
444
|
"skills/",
|
|
445
|
+
"locales/",
|
|
445
446
|
".zcode/",
|
|
446
447
|
".qoder/"
|
|
447
448
|
],
|
|
449
|
+
"localization": {
|
|
450
|
+
"default": "zh-CN",
|
|
451
|
+
"supported": [
|
|
452
|
+
"zh-CN",
|
|
453
|
+
"en-US"
|
|
454
|
+
],
|
|
455
|
+
"assets": {
|
|
456
|
+
"en-US": [
|
|
457
|
+
".cowork-flow/spec/contracts/decision-anchor.md",
|
|
458
|
+
".cowork-flow/templates/plan-template.md"
|
|
459
|
+
]
|
|
460
|
+
}
|
|
461
|
+
},
|
|
448
462
|
"syncPolicy": {
|
|
449
463
|
"protectedFiles": [
|
|
450
464
|
".cowork-flow/config.yaml",
|
|
451
465
|
".cowork-flow/.developer"
|
|
452
466
|
],
|
|
467
|
+
"forceProtectedFiles": [
|
|
468
|
+
".cowork-flow/config.yaml"
|
|
469
|
+
],
|
|
453
470
|
"protectedPrefixes": [
|
|
454
|
-
".cowork-flow/spec/",
|
|
471
|
+
".cowork-flow/spec/backend/",
|
|
472
|
+
".cowork-flow/spec/frontend/",
|
|
473
|
+
".cowork-flow/spec/guides/",
|
|
474
|
+
".cowork-flow/spec/references/",
|
|
455
475
|
".cowork-flow/tasks/",
|
|
456
476
|
".cowork-flow/plans/"
|
|
457
477
|
],
|
|
@@ -459,9 +479,7 @@
|
|
|
459
479
|
".cowork-flow/.gitignore",
|
|
460
480
|
".cowork-flow/.version",
|
|
461
481
|
".cowork-flow/run",
|
|
462
|
-
".cowork-flow/run.cmd"
|
|
463
|
-
".cowork-flow/spec/contracts/workflow-state-templates.md",
|
|
464
|
-
".cowork-flow/spec/runtime/scope-rules.json"
|
|
482
|
+
".cowork-flow/run.cmd"
|
|
465
483
|
],
|
|
466
484
|
"safePrefixes": [
|
|
467
485
|
".cowork-flow/"
|
|
@@ -511,6 +529,7 @@
|
|
|
511
529
|
".claude/skills/update-spec",
|
|
512
530
|
".claude/skills/using-cowork-flow",
|
|
513
531
|
".claude/skills/writing-plans",
|
|
532
|
+
".cowork-flow/plan-template.md",
|
|
514
533
|
".cowork-flow/project-context.md",
|
|
515
534
|
".cowork-flow/scripts/application",
|
|
516
535
|
".cowork-flow/scripts/services/batch_execution.py",
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
# Runtime Specs
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This directory holds machine configuration read directly by the workflow runtime.
|
|
4
4
|
|
|
5
|
-
- `contract-registry.json`:
|
|
6
|
-
- `host-assets.json`:
|
|
5
|
+
- `contract-registry.json`: registry of the contract digests injected by hooks/plugins.
|
|
6
|
+
- `host-assets.json`: single source for host platforms, asset ownership, skill read roots and host discovery channels (`skillReadRoot` / `skillDiscovery[]`, entries are repo-relative paths plus `gates` / `evidence`; machine-level payloads do not participate as skill sources), machine-level plugin payload declarations (`payload`: the package-relative payload directory and plugin manifest name; `null` for hosts without a plugin payload; machine install locations are not declared here), the sync protection policy, and the obsolete-asset migration list. The structure is constrained by `../schemas/host-assets.schema.json`. `capabilityMatrix.hosts` must cover every id declared in `platforms` — the required host set is derived from platform data; the runtime does not maintain a host-name constant.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
避免崩溃,但必须在 digest 中暴露 warning;doctor/tests 负责发现缺失。
|
|
8
|
+
Missing or corrupted runtime files must not silently grant critical workflow capabilities. Host plugins may use a minimal fallback to avoid crashing, but must expose a warning in the digest; doctor/tests are responsible for detecting absence.
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
`spec/backend/`、`spec/frontend/`、`spec/guides/` 并输出审查结论。
|
|
10
|
+
User natural-language specs are not registered in this directory; the `task-review` skill reads `spec/backend/`, `spec/frontend/`, and `spec/guides/` directly and reports review findings.
|
|
13
11
|
|
|
14
|
-
|
|
12
|
+
Runtime write boundaries:
|
|
15
13
|
|
|
16
|
-
- CLI
|
|
17
|
-
- JSON
|
|
18
|
-
- init/sync
|
|
19
|
-
-
|
|
14
|
+
- CLI/host/Git adaptation lives in `scripts/adapters/`; use-case services live in `scripts/services/`.
|
|
15
|
+
- JSON state is read and written through `scripts/infra/storage/` with explicit UTF-8.
|
|
16
|
+
- init/sync commit assets through Asset Plan, staging, backup, and rollback; the version file is updated last.
|
|
17
|
+
- Old state is only allowed at read boundaries with migration tests; new writes must use the current schema and authoritative paths.
|
|
@@ -56,6 +56,9 @@
|
|
|
56
56
|
"excludedPrefixes": {
|
|
57
57
|
"$ref": "#/$defs/stringList"
|
|
58
58
|
},
|
|
59
|
+
"localization": {
|
|
60
|
+
"$ref": "#/$defs/localization"
|
|
61
|
+
},
|
|
59
62
|
"syncPolicy": {
|
|
60
63
|
"$ref": "#/$defs/syncPolicy"
|
|
61
64
|
}
|
|
@@ -68,6 +71,31 @@
|
|
|
68
71
|
"minLength": 1
|
|
69
72
|
}
|
|
70
73
|
},
|
|
74
|
+
"localization": {
|
|
75
|
+
"description": "Per-language asset overrides. Paths are canonical project-relative paths; the base template is the default language.",
|
|
76
|
+
"type": "object",
|
|
77
|
+
"additionalProperties": false,
|
|
78
|
+
"required": [
|
|
79
|
+
"default",
|
|
80
|
+
"supported",
|
|
81
|
+
"assets"
|
|
82
|
+
],
|
|
83
|
+
"properties": {
|
|
84
|
+
"default": {
|
|
85
|
+
"type": "string",
|
|
86
|
+
"minLength": 1
|
|
87
|
+
},
|
|
88
|
+
"supported": {
|
|
89
|
+
"$ref": "#/$defs/stringList"
|
|
90
|
+
},
|
|
91
|
+
"assets": {
|
|
92
|
+
"type": "object",
|
|
93
|
+
"additionalProperties": {
|
|
94
|
+
"$ref": "#/$defs/stringList"
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
},
|
|
71
99
|
"capabilities": {
|
|
72
100
|
"type": "object",
|
|
73
101
|
"minProperties": 1,
|
|
@@ -342,6 +370,9 @@
|
|
|
342
370
|
"protectedFiles": {
|
|
343
371
|
"$ref": "#/$defs/stringList"
|
|
344
372
|
},
|
|
373
|
+
"forceProtectedFiles": {
|
|
374
|
+
"$ref": "#/$defs/stringList"
|
|
375
|
+
},
|
|
345
376
|
"protectedPrefixes": {
|
|
346
377
|
"$ref": "#/$defs/stringList"
|
|
347
378
|
},
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# Schema Specs
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This directory holds JSON Schemas.
|
|
4
4
|
|
|
5
|
-
- `adapter.schema.json`:
|
|
6
|
-
- `host-assets.schema.json`: Host Asset Manifest schema
|
|
7
|
-
- `party-mode-v2-actions.schema.json`: Party Mode V2 action schema
|
|
5
|
+
- `adapter.schema.json`: host adapter declaration schema.
|
|
6
|
+
- `host-assets.schema.json`: Host Asset Manifest schema (structural constraints for `runtime/host-assets.json`).
|
|
7
|
+
- `party-mode-v2-actions.schema.json`: Party Mode V2 action schema.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Schemas describe data contracts only, not workflow guidance; workflow and behavior boundaries belong in `contracts/`, Skill command manifests, or `AGENTS.md`.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# <功能> 实施计划
|
|
2
|
+
|
|
3
|
+
> 执行规则:本计划用于防止实现漂移,实现者必须按任务顺序推进。
|
|
4
|
+
> 如果计划与当前代码事实冲突、需要计划外文件,或测试因未计划的原因失败,停止并报告,不要扩大范围。
|
|
5
|
+
>
|
|
6
|
+
> 正式固定代理工作:使用 `.cowork-flow/run subagent init` 创建 runtime context,通过当前 Host Adapter 传入 `cowork_runtime_context_id: <runtime_context_id>`,再派发 `cowork-implement` 或 `cowork-check`;验证完成后关闭 runtime context。
|
|
7
|
+
|
|
8
|
+
| 字段 | 内容 |
|
|
9
|
+
|----|------|
|
|
10
|
+
| **任务类型** | Tiny / Normal / High-risk:<理由> |
|
|
11
|
+
| **执行策略** | Serial / Parallel:<理由> |
|
|
12
|
+
| **成功标准** | AC-001 / AC-002 / AC-003 |
|
|
13
|
+
| **最终验证** | `<command>` → exit 0;逐条核对适用的 `.cowork-flow/spec/<dev_type>/` 规范与项目门禁 → 每条 `pass` / `not_applicable` |
|
|
14
|
+
| **主要风险** | Low / Medium / High:<一句话> |
|
|
15
|
+
|
|
16
|
+
**目标:** <一句话描述可观察的行为变化>
|
|
17
|
+
|
|
18
|
+
## 目标
|
|
19
|
+
|
|
20
|
+
<1-3 句话描述预期可观察行为。>
|
|
21
|
+
|
|
22
|
+
## 验收标准
|
|
23
|
+
|
|
24
|
+
- AC-001: <可验证行为>
|
|
25
|
+
- AC-002: <可验证行为>
|
|
26
|
+
|
|
27
|
+
## 全局约束
|
|
28
|
+
|
|
29
|
+
- <必须保留的架构边界、兼容要求、命令或输出字段>
|
|
30
|
+
- <明确禁止的范围扩张>
|
|
31
|
+
|
|
32
|
+
## 文件边界
|
|
33
|
+
|
|
34
|
+
- `path/a.py`:<职责;只改这个函数或区域>
|
|
35
|
+
- `tests/test_a.py`:<职责;只新增或修改这些测试>
|
|
36
|
+
|
|
37
|
+
## 任务
|
|
38
|
+
|
|
39
|
+
Tiny 任务可保留简化 brief,但仍须写明精确文件边界、完成条件和一条验证命令。
|
|
40
|
+
|
|
41
|
+
### 任务 N:<小目标>
|
|
42
|
+
|
|
43
|
+
**目的**
|
|
44
|
+
- <本任务完成后的可观察行为>
|
|
45
|
+
|
|
46
|
+
**代码事实来源**
|
|
47
|
+
- Read: `path/a.py::function_name`
|
|
48
|
+
- Read: `tests/test_a.py::test_existing_behavior`
|
|
49
|
+
|
|
50
|
+
**文件边界**
|
|
51
|
+
- Create / Modify / Test: `path/a.py`(只改 <函数/区域>)
|
|
52
|
+
- Test: `tests/test_a.py`(只改 <测试/区域>)
|
|
53
|
+
|
|
54
|
+
**关键符号**
|
|
55
|
+
- Change: `function_name()`、`ClassName.method()`、`<config-key>`
|
|
56
|
+
- Preserve: `existing_helper()`、输出字段 `<field>`
|
|
57
|
+
|
|
58
|
+
**实现说明**
|
|
59
|
+
```python
|
|
60
|
+
# 核心控制流草图;按现有代码调整名称。
|
|
61
|
+
# 不要把完整实现复制进计划。
|
|
62
|
+
...
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**测试证明**
|
|
66
|
+
- `tests/test_a.py::test_x`:证明 <具体行为>
|
|
67
|
+
- 核心断言:<一句话描述断言,不只有测试名>
|
|
68
|
+
|
|
69
|
+
**验证命令**
|
|
70
|
+
```bash
|
|
71
|
+
<command>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
当改动文件受 `.cowork-flow/spec/<dev_type>/` 规则覆盖时,在这里加入决定命令或规范门禁核对行(`pass` / `not_applicable` 并附理由)。strict 非 Tiny 任务启动前必须把 `<pass / not_applicable + 理由>` 替换为实际核对结果;保留模板占位符会被 start 门禁阻断。
|
|
75
|
+
|
|
76
|
+
**完成条件**
|
|
77
|
+
- <2-4 条可检查条件>
|
|
78
|
+
|
|
79
|
+
**禁止漂移**
|
|
80
|
+
- <2-5 条明确禁止的改动>
|
|
81
|
+
|
|
82
|
+
**偏差条件**
|
|
83
|
+
- 如果 <计划外文件/层> 变得必要,必须停止并报告,因为文件边界有误。
|
|
84
|
+
|
|
85
|
+
## 最终验证
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
<command>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
规范核对:逐条核对 `.cowork-flow/spec/<dev_type>/` 适用规范 → <pass / not_applicable + 理由>。
|
|
@@ -0,0 +1,169 @@
|
|
|
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` / `## 验证命令` | required for strict non-Tiny; optional for legacy/Tiny | filled in for complex tasks, as the basis for automated verification; a strict non-Tiny task also needs the configured-language section and a filled 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. A strict non-Tiny task must also carry a `Spec check:` line in the
|
|
64
|
+
configured language's section, with the actual `pass` / `not_applicable` result
|
|
65
|
+
and a reason. The template placeholder (`<pass / not_applicable + reason>`) does
|
|
66
|
+
not satisfy the start gate. This line is a hard start gate for strict non-Tiny
|
|
67
|
+
tasks, while its content remains self-declared and is reviewed by the check
|
|
68
|
+
agent. The fact view recognizes the line and does not return it as a shell
|
|
69
|
+
command.
|
|
70
|
+
- `## Scope Boundary`: only the first non-empty line is taken, truncated to 160
|
|
71
|
+
characters.
|
|
72
|
+
|
|
73
|
+
## Scenarios
|
|
74
|
+
|
|
75
|
+
| Scenario | Source | What gets filled in |
|
|
76
|
+
|------|------|---------|
|
|
77
|
+
| Has brainstorming | extracted from the discussion outcome | every section |
|
|
78
|
+
| No brainstorming (requirements already clear) | extracted from the requirement description and the plan | the minimum: goal + acceptance criteria |
|
|
79
|
+
|
|
80
|
+
## Artifact compression
|
|
81
|
+
|
|
82
|
+
Before merging (6 files): `prd.md` + `implement.jsonl` + `check.jsonl` +
|
|
83
|
+
`debug.jsonl` + `task.json`
|
|
84
|
+
|
|
85
|
+
After merging (5 files): `decision-anchor.md` + `implement.jsonl` + `check.jsonl` +
|
|
86
|
+
`debug.jsonl` + `task.json`
|
|
87
|
+
|
|
88
|
+
**A net reduction of one file type. Related-file tracking is now owned entirely by
|
|
89
|
+
`implement.jsonl`.**
|
|
90
|
+
|
|
91
|
+
## Lifecycle check coupling
|
|
92
|
+
|
|
93
|
+
- The preflight for `task next <dir> --run` checks that `decision-anchor.md` is
|
|
94
|
+
non-empty and requires the `## Goal` / `## 目标` and `## Acceptance Criteria` /
|
|
95
|
+
`## 验收标准` sections to be present.
|
|
96
|
+
- **Gate profile `meta.gateProfile`**: a newly created task is written as
|
|
97
|
+
`"strict"`; an unmarked task is treated as `"legacy"` — existing tasks are not
|
|
98
|
+
retro-fitted with the stricter gate, and the profile is queryable through the
|
|
99
|
+
fact view. On top of the section check, a strict task additionally requires: at
|
|
100
|
+
least one parseable `- [ ] AC-xxx: ...` row in `## Acceptance Criteria` /
|
|
101
|
+
`## 验收标准`, no duplicate AC ids, no non-AC list rows in that section, and a
|
|
102
|
+
declared `dev_type` (otherwise `task specs` dev-type dispatch silently comes
|
|
103
|
+
back shorter).
|
|
104
|
+
- A strict non-Tiny task also requires the configured-language
|
|
105
|
+
`## Verification Commands` / `## 验证命令` section with a filled
|
|
106
|
+
`Spec check:` / `规范核对:` line. A missing section, the other-language
|
|
107
|
+
heading, or the template placeholder blocks start. Tiny tasks and legacy tasks
|
|
108
|
+
are exempt. The bound plan's `## Final Verification` / `## 最终验证` section
|
|
109
|
+
carries the same filled check; plan structure and language are covered by
|
|
110
|
+
`plan-binding.md`.
|
|
111
|
+
- An acceptance row's checkbox state (`- [ ]` / `- [x]`) and the evidence records
|
|
112
|
+
(the task directory's `evidence.jsonl`) are the fact source of the completion
|
|
113
|
+
gate: completion is blocked when an unchecked AC exists (`LIFECYCLE-AC-001`), a
|
|
114
|
+
declared AC has no evidence (`LIFECYCLE-AC-002`), a strict task cannot read any
|
|
115
|
+
AC row (`LIFECYCLE-AC-003`), or the AC-evidence module is unavailable
|
|
116
|
+
(`LIFECYCLE-AC-004`). Schema and exemptions are in `evidence-completion.md`.
|
|
117
|
+
- **Review receipt change fingerprint** (a strict task requires its latest receipt
|
|
118
|
+
to match the current state at completion, `LIFECYCLE-REVIEW-003`). Input = the
|
|
119
|
+
git-visible change set (paths + content digests) + this anchor's goal and AC text
|
|
120
|
+
+ the content digest of the bound plan + `dev_type` + the **content digest** of
|
|
121
|
+
every referenced spec + the content digest of `implement.jsonl`. Both `spec/**`
|
|
122
|
+
and `tasks/**` are gitignored, which is why the last two must enter the
|
|
123
|
+
fingerprint explicitly — otherwise rewriting a referenced spec's prose, or
|
|
124
|
+
widening the declared scope, would leave a stale receipt valid.
|
|
125
|
+
- Fingerprint **exclusions** (mechanism): the change set excludes the whole
|
|
126
|
+
`.cowork-flow/tasks/**` tree, `.cowork-flow/.runtime/**`, and
|
|
127
|
+
`.cowork-flow/logs/**` — task-directory artifacts (`task.json`,
|
|
128
|
+
`evidence.jsonl`, `review.jsonl`, `check.jsonl`, `debug.jsonl`, and the anchor's
|
|
129
|
+
**path entry**) and runtime metadata are not counted, or a receipt would
|
|
130
|
+
invalidate itself the moment it was recorded. `implement.jsonl`'s path entry is
|
|
131
|
+
excluded the same way; its **content** is counted instead through the `scope`
|
|
132
|
+
component.
|
|
133
|
+
A **consequence** (expected cost, not a defect): **any byte change in
|
|
134
|
+
`implement.jsonl`** (appending or removing a scope entry, rewording a `reason`,
|
|
135
|
+
a domain-guide entry) **or a rewrite of a
|
|
136
|
+
referenced spec's prose invalidates an existing receipt**, requiring one more
|
|
137
|
+
review run against the final state. Appending evidence, ticking ACs, and runtime
|
|
138
|
+
metadata are not in that set.
|
|
139
|
+
- **Light profile `meta.taskType: "tiny"`**: applies to `strict` tasks only
|
|
140
|
+
(`legacy` + `tiny` stays a compatibility path). A light task **is still strict**
|
|
141
|
+
— what it waives are three things: the review receipt, AC evidence, and
|
|
142
|
+
`dev_type`. It does **not** waive the file-scope gate or "AC rows
|
|
143
|
+
are non-empty" (`LIFECYCLE-AC-003`/`004` still apply). Plan-file binding is not
|
|
144
|
+
among the three, but the pre-existing field-level exemption for tiny applies, so
|
|
145
|
+
a light task does not require `planFile` either. `tiny` **can only be declared at
|
|
146
|
+
creation time** (`task next --run --task-type tiny`) with no later edit path; the
|
|
147
|
+
light profile is visible in `task next --list` (a `[light]` text marker and
|
|
148
|
+
`lightProfile` in `--json`) and in doctor's task-hygiene output. The single
|
|
149
|
+
decision source is `task_gate_profiles.is_light_task` (`strict` + the field is
|
|
150
|
+
`tiny`); the start-preflight plan-file exemption still uses the field-level
|
|
151
|
+
`declares_light_profile` so existing pre-strict tiny tasks keep behaving as
|
|
152
|
+
before. The light profile **must not** be used for a task touching runtime /
|
|
153
|
+
gates / specs — that rule rests on visibility and review, not on a machine gate.
|
|
154
|
+
- Read by `cowork-implement`: see .cowork-flow/spec/contracts/subagent-dispatch.md
|
|
155
|
+
- Read by `cowork-check`: same as above
|
|
156
|
+
- `debug.jsonl` reference: optional; on deviation diagnosis it records the anchor
|
|
157
|
+
delta
|
|
158
|
+
|
|
159
|
+
## Formal-release behavior
|
|
160
|
+
|
|
161
|
+
The formal release does not auto-migrate a legacy `prd.md`. When a task is
|
|
162
|
+
started, only `decision-anchor.md` is recognized as the authoritative decision
|
|
163
|
+
source; if a task directory has only `prd.md` and no `decision-anchor.md`,
|
|
164
|
+
`task next <dir> --run` must fail-closed and report
|
|
165
|
+
`decision-anchor.md is missing or empty`.
|
|
166
|
+
|
|
167
|
+
An existing legacy task needs a human to convert the `prd.md` content into
|
|
168
|
+
`decision-anchor.md`, fill in `## Goal` / `## 目标` and
|
|
169
|
+
`## Acceptance Criteria` / `## 验收标准`, and only then start.
|