@michaelxwb/code-flow 0.6.5 → 0.8.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/README.md +47 -3
- package/docs/USAGE.md +1529 -0
- package/docs/acceptance-contract.md +217 -0
- package/docs/ci/acceptance-evidence.md +77 -0
- package/docs/migrations/runtime-0.7.0.md +41 -0
- package/docs/migrations/runtime-0.8.0.md +154 -0
- package/docs/migrations/runtime-0.9.0.md +40 -0
- package/docs/spec-injection-hardening.md +54 -0
- package/docs/spec-injection-performance.json +73 -0
- package/docs/spec-optimization.md +12 -0
- package/package.json +18 -3
- package/src/adapters/claude/CLAUDE.md +1 -1
- package/src/adapters/claude/commands/cf-init.md +1 -3
- package/src/adapters/claude/commands/cf-spec.md +23 -3
- package/src/adapters/claude/commands/cf-stats.md +11 -1
- package/src/adapters/claude/commands/cf-sync.md +20 -6
- package/src/adapters/claude/commands/cf-task/align.md +25 -3
- package/src/adapters/claude/commands/cf-task/archive.md +36 -42
- package/src/adapters/claude/commands/cf-task/block.md +15 -2
- package/src/adapters/claude/commands/cf-task/graph.md +13 -1
- package/src/adapters/claude/commands/cf-task/note.md +13 -1
- package/src/adapters/claude/commands/cf-task/plan.md +137 -23
- package/src/adapters/claude/commands/cf-task/prd.md +13 -2
- package/src/adapters/claude/commands/cf-task/start.md +52 -39
- package/src/adapters/claude/commands/cf-task/status.md +12 -0
- package/src/adapters/claude/commands/cf-task/verify-e2e.md +68 -35
- package/src/adapters/claude/commands/cf-validate.md +30 -5
- package/src/adapters/codex/AGENTS.md +1 -1
- package/src/adapters/codex/hooks.json +14 -10
- package/src/adapters/codex/skills/cf-init/SKILL.md +4 -4
- package/src/adapters/codex/skills/cf-spec/SKILL.md +34 -6
- package/src/adapters/codex/skills/cf-stats/SKILL.md +11 -1
- package/src/adapters/codex/skills/cf-sync/SKILL.md +21 -6
- package/src/adapters/codex/skills/cf-task-align/SKILL.md +30 -8
- package/src/adapters/codex/skills/cf-task-archive/SKILL.md +36 -42
- package/src/adapters/codex/skills/cf-task-block/SKILL.md +15 -2
- package/src/adapters/codex/skills/cf-task-graph/SKILL.md +13 -1
- package/src/adapters/codex/skills/cf-task-note/SKILL.md +13 -1
- package/src/adapters/codex/skills/cf-task-plan/SKILL.md +175 -21
- package/src/adapters/codex/skills/cf-task-prd/SKILL.md +13 -2
- package/src/adapters/codex/skills/cf-task-start/SKILL.md +52 -39
- package/src/adapters/codex/skills/cf-task-status/SKILL.md +12 -0
- package/src/adapters/codex/skills/cf-task-verify-e2e/SKILL.md +69 -35
- package/src/adapters/codex/skills/cf-validate/SKILL.md +31 -5
- package/src/adapters/commands.json +115 -0
- package/src/adapters/costrict/CLAUDE.md +1 -1
- package/src/adapters/costrict/commands/cf-init.md +1 -3
- package/src/adapters/costrict/commands/cf-spec.md +23 -3
- package/src/adapters/costrict/commands/cf-stats.md +11 -1
- package/src/adapters/costrict/commands/cf-sync.md +20 -6
- package/src/adapters/costrict/commands/cf-task/align.md +25 -3
- package/src/adapters/costrict/commands/cf-task/archive.md +36 -42
- package/src/adapters/costrict/commands/cf-task/block.md +15 -2
- package/src/adapters/costrict/commands/cf-task/graph.md +13 -1
- package/src/adapters/costrict/commands/cf-task/note.md +13 -1
- package/src/adapters/costrict/commands/cf-task/plan.md +137 -23
- package/src/adapters/costrict/commands/cf-task/prd.md +13 -2
- package/src/adapters/costrict/commands/cf-task/start.md +52 -39
- package/src/adapters/costrict/commands/cf-task/status.md +12 -0
- package/src/adapters/costrict/commands/cf-task/verify-e2e.md +68 -35
- package/src/adapters/costrict/commands/cf-validate.md +30 -5
- package/src/adapters/install-plan.json +100 -0
- package/src/adapters/opencode/AGENTS.md +1 -1
- package/src/adapters/opencode/commands/cf-init.md +7 -7
- package/src/adapters/opencode/commands/cf-learn.md +6 -6
- package/src/adapters/opencode/commands/cf-spec.md +34 -2
- package/src/adapters/opencode/commands/cf-stats.md +17 -7
- package/src/adapters/opencode/commands/cf-sync.md +21 -6
- package/src/adapters/opencode/commands/cf-task/align.md +25 -8
- package/src/adapters/opencode/commands/cf-task/archive.md +36 -42
- package/src/adapters/opencode/commands/cf-task/block.md +16 -2
- package/src/adapters/opencode/commands/cf-task/graph.md +14 -1
- package/src/adapters/opencode/commands/cf-task/note.md +14 -1
- package/src/adapters/opencode/commands/cf-task/plan.md +137 -23
- package/src/adapters/opencode/commands/cf-task/prd.md +13 -2
- package/src/adapters/opencode/commands/cf-task/start.md +53 -45
- package/src/adapters/opencode/commands/cf-task/status.md +13 -0
- package/src/adapters/opencode/commands/cf-task/verify-e2e.md +68 -35
- package/src/adapters/opencode/commands/cf-validate.md +35 -9
- package/src/adapters/opencode/plugins/code-flow/index.js +128 -179
- package/src/adapters/platform-bindings.json +370 -0
- package/src/cli.js +369 -316
- package/src/core/code-flow/config.yml +4 -1
- package/src/core/code-flow/runtime-commands.json +259 -0
- package/src/core/code-flow/scripts/cf_acceptance_manifest.py +5 -289
- package/src/core/code-flow/scripts/cf_acceptance_runner.py +5 -187
- package/src/core/code-flow/scripts/cf_audit.py +10 -0
- package/src/core/code-flow/scripts/cf_codex_hook.py +10 -0
- package/src/core/code-flow/scripts/cf_design_lint.py +10 -0
- package/src/core/code-flow/scripts/cf_evidence_import.py +10 -0
- package/src/core/code-flow/scripts/cf_feedback.py +5 -51
- package/src/core/code-flow/scripts/cf_opencode_event.py +10 -0
- package/src/core/code-flow/scripts/cf_post_hook.py +6 -191
- package/src/core/code-flow/scripts/cf_pre_tool_hook.py +6 -99
- package/src/core/code-flow/scripts/cf_scenarios.py +10 -0
- package/src/core/code-flow/scripts/cf_spec_context.py +5 -1741
- package/src/core/code-flow/scripts/cf_spec_gate.py +5 -259
- package/src/core/code-flow/scripts/cf_spec_session.py +5 -114
- package/src/core/code-flow/scripts/cf_stats.py +5 -501
- package/src/core/code-flow/scripts/cf_stop_hook.py +6 -376
- package/src/core/code-flow/scripts/cf_sync.py +5 -135
- package/src/core/code-flow/scripts/cf_task_index.py +5 -143
- package/src/core/code-flow/scripts/cf_task_parallel.py +5 -389
- package/src/core/code-flow/scripts/cf_task_workflow.py +6 -201
- package/src/core/code-flow/scripts/cf_user_prompt_hook.py +6 -173
- package/src/core/code-flow/scripts/cf_validation.py +6 -77
- package/src/core/code-flow/scripts/codeflow/__init__.py +0 -0
- package/src/core/code-flow/scripts/codeflow/acceptance/__init__.py +0 -0
- package/src/core/code-flow/scripts/codeflow/acceptance/cf_acceptance_evidence.py +347 -0
- package/src/core/code-flow/scripts/codeflow/acceptance/cf_acceptance_manifest_core.py +660 -0
- package/src/core/code-flow/scripts/codeflow/acceptance/cf_acceptance_plan.py +202 -0
- package/src/core/code-flow/scripts/codeflow/acceptance/cf_acceptance_registration.py +60 -0
- package/src/core/code-flow/scripts/codeflow/acceptance/cf_acceptance_risk.py +73 -0
- package/src/core/code-flow/scripts/codeflow/acceptance/cf_acceptance_schema.py +282 -0
- package/src/core/code-flow/scripts/codeflow/acceptance/cf_acceptance_selection.py +266 -0
- package/src/core/code-flow/scripts/codeflow/acceptance/cf_check_inputs.py +172 -0
- package/src/core/code-flow/scripts/codeflow/acceptance/cf_check_registration.py +326 -0
- package/src/core/code-flow/scripts/{cf_checks.py → codeflow/acceptance/cf_checks.py} +8 -11
- package/src/core/code-flow/scripts/codeflow/acceptance/cf_plan_quality.py +197 -0
- package/src/core/code-flow/scripts/codeflow/acceptance/cf_scenario_quality.py +174 -0
- package/src/core/code-flow/scripts/codeflow/acceptance/cf_scenario_source.py +300 -0
- package/src/core/code-flow/scripts/codeflow/acceptance/cf_traceability.py +502 -0
- package/src/core/code-flow/scripts/codeflow/cli/__init__.py +0 -0
- package/src/core/code-flow/scripts/codeflow/cli/cf_acceptance_manifest.py +347 -0
- package/src/core/code-flow/scripts/codeflow/cli/cf_acceptance_runner.py +1490 -0
- package/src/core/code-flow/scripts/codeflow/cli/cf_audit.py +533 -0
- package/src/core/code-flow/scripts/codeflow/cli/cf_design_lint.py +172 -0
- package/src/core/code-flow/scripts/codeflow/cli/cf_evidence_import.py +607 -0
- package/src/core/code-flow/scripts/codeflow/cli/cf_feedback.py +53 -0
- package/src/core/code-flow/scripts/codeflow/cli/cf_scenarios.py +58 -0
- package/src/core/code-flow/scripts/codeflow/cli/cf_spec_context.py +1175 -0
- package/src/core/code-flow/scripts/codeflow/cli/cf_spec_gate.py +60 -0
- package/src/core/code-flow/scripts/codeflow/cli/cf_spec_session.py +46 -0
- package/src/core/code-flow/scripts/codeflow/cli/cf_stats.py +540 -0
- package/src/core/code-flow/scripts/codeflow/cli/cf_sync.py +144 -0
- package/src/core/code-flow/scripts/codeflow/cli/cf_task_index.py +177 -0
- package/src/core/code-flow/scripts/codeflow/cli/cf_task_parallel.py +1142 -0
- package/src/core/code-flow/scripts/codeflow/cli/cf_task_workflow.py +742 -0
- package/src/core/code-flow/scripts/codeflow/cli/cf_validation.py +31 -0
- package/src/core/code-flow/scripts/codeflow/core/__init__.py +0 -0
- package/src/core/code-flow/scripts/codeflow/core/cf_context_cache.py +67 -0
- package/src/core/code-flow/scripts/{cf_core.py → codeflow/core/cf_core.py} +119 -297
- package/src/core/code-flow/scripts/codeflow/core/cf_exec_base.py +325 -0
- package/src/core/code-flow/scripts/codeflow/core/cf_fs.py +57 -0
- package/src/core/code-flow/scripts/codeflow/core/cf_git.py +92 -0
- package/src/core/code-flow/scripts/{cf_log.py → codeflow/core/cf_log.py} +13 -7
- package/src/core/code-flow/scripts/codeflow/core/cf_markdown.py +77 -0
- package/src/core/code-flow/scripts/codeflow/core/cf_native_paths.py +26 -0
- package/src/core/code-flow/scripts/codeflow/core/cf_patch.py +33 -0
- package/src/core/code-flow/scripts/codeflow/core/cf_runtime_install.py +32 -0
- package/src/core/code-flow/scripts/codeflow/core/cf_stop_guard.py +53 -0
- package/src/core/code-flow/scripts/codeflow/core/cf_task_state.py +9 -0
- package/src/core/code-flow/scripts/codeflow/core/cf_validators.py +408 -0
- package/src/core/code-flow/scripts/codeflow/core/cf_worktree_env.py +253 -0
- package/src/core/code-flow/scripts/codeflow/evidence/__init__.py +0 -0
- package/src/core/code-flow/scripts/codeflow/evidence/cf_evidence_store.py +527 -0
- package/src/core/code-flow/scripts/codeflow/hooks/__init__.py +0 -0
- package/src/core/code-flow/scripts/codeflow/hooks/cf_codex_hook.py +95 -0
- package/src/core/code-flow/scripts/codeflow/hooks/cf_opencode_event.py +98 -0
- package/src/core/code-flow/scripts/codeflow/hooks/cf_post_hook.py +30 -0
- package/src/core/code-flow/scripts/codeflow/hooks/cf_pre_tool_hook.py +41 -0
- package/src/core/code-flow/scripts/codeflow/hooks/cf_stop_hook.py +292 -0
- package/src/core/code-flow/scripts/codeflow/hooks/cf_user_prompt_hook.py +161 -0
- package/src/core/code-flow/scripts/codeflow/spec/__init__.py +0 -0
- package/src/core/code-flow/scripts/codeflow/spec/cf_active_task.py +412 -0
- package/src/core/code-flow/scripts/codeflow/spec/cf_context_refresh.py +301 -0
- package/src/core/code-flow/scripts/codeflow/spec/cf_edit_service.py +149 -0
- package/src/core/code-flow/scripts/codeflow/spec/cf_injection.py +111 -0
- package/src/core/code-flow/scripts/codeflow/spec/cf_rule_readiness.py +114 -0
- package/src/core/code-flow/scripts/{cf_scan.py → codeflow/spec/cf_scan.py} +93 -21
- package/src/core/code-flow/scripts/codeflow/spec/cf_spec_budget.py +55 -0
- package/src/core/code-flow/scripts/codeflow/spec/cf_spec_context_model.py +477 -0
- package/src/core/code-flow/scripts/codeflow/spec/cf_spec_impact.py +119 -0
- package/src/core/code-flow/scripts/{cf_spec_metadata.py → codeflow/spec/cf_spec_metadata.py} +5 -2
- package/src/core/code-flow/scripts/{cf_spec_migrate.py → codeflow/spec/cf_spec_migrate.py} +27 -10
- package/src/core/code-flow/scripts/codeflow/spec/cf_spec_optimize.py +193 -0
- package/src/core/code-flow/scripts/codeflow/spec/cf_spec_optimize_apply.py +187 -0
- package/src/core/code-flow/scripts/{cf_spec_resolver.py → codeflow/spec/cf_spec_resolver.py} +39 -17
- package/src/core/code-flow/scripts/{cf_spec_router.py → codeflow/spec/cf_spec_router.py} +96 -36
- package/src/core/code-flow/scripts/{cf_spec_verify.py → codeflow/spec/cf_spec_verify.py} +163 -35
- package/src/core/code-flow/scripts/codeflow/spec/cf_stage_gate.py +330 -0
- package/src/core/code-flow/scripts/codeflow/spec/cf_task_projection.py +83 -0
- package/src/core/code-flow/scripts/codeflow/spec/cf_workflow_service.py +755 -0
- package/src/core/code-flow/scripts/{cf_workflow_transaction.py → codeflow/spec/cf_workflow_transaction.py} +29 -15
- package/src/core/code-flow/scripts/codeflow/task/__init__.py +0 -0
- package/src/core/code-flow/scripts/codeflow/task/cf_requirement_verification.py +867 -0
- package/src/core/code-flow/scripts/codeflow/task/cf_task_doc.py +178 -0
- package/src/core/code-flow/scripts/codeflow/task/cf_task_merge.py +635 -0
- package/src/core/code-flow/scripts/codeflow/task/cf_task_plan.py +251 -0
- package/src/core/code-flow/scripts/codeflow/task/cf_task_runtime.py +570 -0
- package/src/core/code-flow/scripts/codeflow/task/cf_validation_service.py +73 -0
- package/src/core/code-flow/scripts/runtime-resources.json +29 -0
- package/src/core/code-flow/specs/shared/design/design-frontend.md +18 -15
- package/src/core/code-flow/specs/shared/design/design-full.md +33 -23
- package/src/core/code-flow/specs/shared/design/design-lite.md +23 -13
- package/src/core/code-flow/specs/shared/scenarios-template.md +55 -0
- package/src/core/code-flow/validation.yml +9 -3
- package/src/migrate/runtime.js +213 -0
- package/src/migrate/spec-workflow.js +16 -1
- package/src/runtime.js +219 -0
- package/src/core/code-flow/scripts/cf_acceptance_evidence.py +0 -100
- package/src/core/code-flow/scripts/cf_acceptance_schema.py +0 -83
- package/src/core/code-flow/scripts/cf_exec_base.py +0 -112
- package/src/core/code-flow/scripts/cf_task_runtime.py +0 -304
- package/src/core/code-flow/scripts/cf_task_state.py +0 -3
- package/src/core/code-flow/scripts/cf_workflow_service.py +0 -366
- /package/src/core/code-flow/scripts/{cf_session_state.py → codeflow/core/cf_session_state.py} +0 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# 可执行验收契约
|
|
2
|
+
|
|
3
|
+
`scenarios parse --quality` 校验场景语义,`design lint` 校验设计引用,`acceptance manifest --verify-plan` 聚合完整计划门禁。旧文件继续可读;重新规划时必须修复门禁报告的缺口,不能把旧状态当成已验证。
|
|
4
|
+
|
|
5
|
+
本页描述仓库 0.8.0 实现。安装与事务升级见 [README](../README.md#升级)和[迁移指南](migrations/runtime-0.8.0.md);常规流程见[使用手册](USAGE.md)。
|
|
6
|
+
|
|
7
|
+
## 场景与边界
|
|
8
|
+
|
|
9
|
+
浏览器关键旅程使用 `e2e`;API/CLI/后台服务完整链路使用 `system`,局部模块组合使用 `integration`。容量测试可使用 `capacity` 层级或 `tags: [capacity]`,并登记真实 capacity 用例。
|
|
10
|
+
|
|
11
|
+
```yaml
|
|
12
|
+
schema: 1
|
|
13
|
+
requirement: 订单创建
|
|
14
|
+
scenarios:
|
|
15
|
+
- id: S-01
|
|
16
|
+
title: 浏览器创建订单
|
|
17
|
+
priority: P0
|
|
18
|
+
level: e2e
|
|
19
|
+
exec: deferred
|
|
20
|
+
env: browser
|
|
21
|
+
components: [browser, frontend, api, db]
|
|
22
|
+
boundary: browser -> api -> db
|
|
23
|
+
why_e2e: 真实浏览器登录态与后端订单提交必须联合验证
|
|
24
|
+
preconditions: [用户已经登录]
|
|
25
|
+
steps: [提交订单]
|
|
26
|
+
expected: [订单出现在列表中且状态为 created]
|
|
27
|
+
expected_refs: [{expected: 1, steps: [1]}]
|
|
28
|
+
features: [FEAT-01]
|
|
29
|
+
design_refs: [API-01]
|
|
30
|
+
trigger_paths: [src/frontend/*, src/orders/*]
|
|
31
|
+
smoke: true
|
|
32
|
+
defer_reason: 在需求级终验执行真实浏览器链路
|
|
33
|
+
owner: TASK-001
|
|
34
|
+
target_phase: review
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
expected_refs 的 expected/steps 均从 1 开始。也可用 assertions 引用场景中已声明的稳定断言 ID;引用必须存在。条件式结果允许,但必须声明可构造的前置条件和确定的可观察结果。
|
|
38
|
+
|
|
39
|
+
环境枚举为 none/local/local-api/browser/external/staging/capacity/ci/production。components 使用稳定标识符,可使用项目模块 ID;浏览器 E2E 的组件声明必须与 boundary 相符。延后阶段为 plan/code/review/ci/release。
|
|
40
|
+
|
|
41
|
+
| 字段 | 约束 |
|
|
42
|
+
|------|------|
|
|
43
|
+
| `level` | unit / component / contract / integration / system / capacity / e2e / manual;输入 E2E 会归一为 e2e |
|
|
44
|
+
| `env` / `components` | 浏览器 E2E 要求 env=browser,或组件包含 frontend/browser;boundary 同时描述浏览器边界。数据库用组件 db/pg 表达,env 不接受 db |
|
|
45
|
+
| `expected` / `expected_refs` | 每个结果都引用存在的步骤或断言;拒绝“不回归”“提升可观”等模糊结果。性能结果给出负载、测量窗口与阈值 |
|
|
46
|
+
| `exec: deferred` | 必须有 defer_reason、owner、target_phase;延期仍须满足场景质量与计划登记检查 |
|
|
47
|
+
| `features` / `design_refs` | 分别引用功能 ID 与设计位置/ID,ID 必须在本需求设计中定义 |
|
|
48
|
+
| `checks` | plan 生成实际 check ID 后绑定;一个场景可绑定多个 checks,全部成员都需要各自的有效证据 |
|
|
49
|
+
|
|
50
|
+
条件式预期可以使用,但应先定义可构造的前置条件,再写确定结果,例如“库存为零时提交订单,显示错误码 OUT_OF_STOCK”。`assertions` 引用示例为 `assertions: [ASSERT-order-created]` 配合 `expected_refs: [{expected: 1, assertions: [ASSERT-order-created]}]`;断言 ID 的存在性检查不能替代断言实际执行。
|
|
51
|
+
|
|
52
|
+
### 对应的最小设计
|
|
53
|
+
|
|
54
|
+
将上述 YAML 保存为 `order.scenarios.md`(也可放入文件 frontmatter),下例保存为 `order.design.md`。design 只引用场景 ID,不复制完整验收表。
|
|
55
|
+
|
|
56
|
+
```markdown
|
|
57
|
+
---
|
|
58
|
+
design_template: lite
|
|
59
|
+
---
|
|
60
|
+
# 订单创建设计
|
|
61
|
+
|
|
62
|
+
## 需求概述
|
|
63
|
+
登录用户通过浏览器提交订单。
|
|
64
|
+
|
|
65
|
+
## 功能方案
|
|
66
|
+
| 功能ID | 名称 |
|
|
67
|
+
|--------|------|
|
|
68
|
+
| FEAT-01 | 创建订单 |
|
|
69
|
+
|
|
70
|
+
| 接口ID | 定义 |
|
|
71
|
+
|--------|------|
|
|
72
|
+
| API-01 | POST /orders,成功返回 201 和订单 ID |
|
|
73
|
+
|
|
74
|
+
## 范围与边界
|
|
75
|
+
包含浏览器登录态、订单 API 与数据库持久化,支付功能延期。
|
|
76
|
+
|
|
77
|
+
## 验收条件
|
|
78
|
+
| 场景ID | 功能ID | 接口ID |
|
|
79
|
+
|--------|--------|--------|
|
|
80
|
+
| S-01 | FEAT-01 | API-01 |
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
code-flow scenarios parse --file order.scenarios.md --quality --json
|
|
85
|
+
code-flow design lint --file order.design.md --scenarios-file order.scenarios.md --json
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
这些命令检查语义和引用;计划通过还需要真实任务、冻结的 Context、manifest 和测试登记。
|
|
89
|
+
|
|
90
|
+
## 规则引用与计划负责人
|
|
91
|
+
|
|
92
|
+
每个 TASK 的 `Spec-Refs` 列出实际适用的规则,供该任务的 Session 投影使用。承担计划验证的 TASK 还在 `Rule-Owner-Refs` 中列出对应规则;其他任务可引用同一规则,并用 `Rule-Owner-Refs: N/A` 表示不承担该规则的计划责任。每条 required 规则必须有且仅有一个负责人,且负责人本身必须引用该规则并提供 verifier 和验收契约。
|
|
93
|
+
|
|
94
|
+
当整个任务文件都没有 `Rule-Owner-Refs` 时,旧计划仍按单个引用者作为负责人的规则校验;一旦任一 TASK 声明该字段,所有 required 规则都需要显式负责人。缺失、重复、未引用或格式无效的负责人会阻断计划。
|
|
95
|
+
|
|
96
|
+
## 测试登记与收集
|
|
97
|
+
|
|
98
|
+
锁定时加 `--register-checks`,工具从 pytest / Playwright 的真实收集结果登记套件、具体用例、markers 和 collect。默认收集超时 10 秒,登记总预算 60 秒;只收集,不执行测试体。登记失败会保留原锁文件并输出具体 check、命令和错误。重新锁定会保留登记设置,更改设置使旧输入指纹失效。
|
|
99
|
+
|
|
100
|
+
pytest 示例:项目应注册并实际使用 browser/smoke/capacity markers。
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
{
|
|
104
|
+
"command": ["python3", "-m", "pytest", "-q", "tests/test_orders.py::test_create_order"],
|
|
105
|
+
"suite": "browser",
|
|
106
|
+
"test_ids": ["tests/test_orders.py::test_create_order"],
|
|
107
|
+
"markers": ["browser", "smoke"],
|
|
108
|
+
"collect": {
|
|
109
|
+
"argv": ["python3", "-m", "pytest", "--collect-only", "-q", "-m", "browser and smoke"],
|
|
110
|
+
"format": "pytest",
|
|
111
|
+
"timeout": 20
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
原生 pytest 收集仅接受明确的 marker 或 and 组合,拒绝无法证明每个已选用例都具有相应标记的 or/not 表达式。
|
|
117
|
+
|
|
118
|
+
Playwright 示例:使用明确的 chromium/firefox/webkit/browser 项目名称,或在项目 metadata 中声明 `capabilities: ["browser"]`;用例 tags 声明 @smoke/@capacity。test_ids 使用相对项目根目录的 `file:line@projectName`。适配器按[官方 JSON Reporter](https://github.com/microsoft/playwright/blob/main/packages/playwright/src/reporters/json.ts)的 rootDir、项目 metadata 和用例 tags 解析。
|
|
119
|
+
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"command": ["npx", "playwright", "test", "tests/orders.spec.ts:8", "--project=chromium"],
|
|
123
|
+
"suite": "browser",
|
|
124
|
+
"test_ids": ["tests/orders.spec.ts:8@chromium"],
|
|
125
|
+
"markers": ["smoke"],
|
|
126
|
+
"collect": {
|
|
127
|
+
"argv": ["npx", "playwright", "test", "--list", "--reporter=json"],
|
|
128
|
+
"format": "playwright",
|
|
129
|
+
"timeout": 30
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
自定义收集器可使用 format=json,输出 `{"tests":[{"id":"具体用例ID","capabilities":["browser"],"markers":["smoke"]}]}`。适配器必须从真实测试框架收集结果生成此报告;静态编造报告不能证明测试边界。登记/收集只证明套件与用例可选,实际执行仍须经过契约声明的真实边界、关键断言与有效证据。
|
|
135
|
+
|
|
136
|
+
check 的 command 必须实际选择已登记的测试 ID、文件或匹配的 marker。不可证明选择范围的 -k/grep 过滤应改用具体用例 ID。npm/pnpm/yarn 脚本会解析到 package.json 中的直接命令;串联多个 shell 命令时请拆成 preflight 与测试 check,避免登记正确却执行了别的命令。
|
|
137
|
+
|
|
138
|
+
上面的 JSON 是对应 check 的字段片段。使用项目自定义收集器时,先生成 manifest 获取真实 check ID,将登记字段放入独立文件,再通过正式命令写入:
|
|
139
|
+
|
|
140
|
+
```json
|
|
141
|
+
{"checks":{"CHK-实际ID":{"suite":"browser","test_ids":["tests/orders.spec.ts:8@chromium"],"markers":["smoke"],"collect":{"argv":["node","scripts/collect-tests.js"],"format":"json","timeout":20}}}}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
code-flow acceptance manifest --task-file "<任务文件>" --output "<需求目录>/.acceptance-manifest.json" --registration-file registration.json
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
`--registration-file` 同样执行真实收集和执行选择校验;只允许修改登记字段,未知 check ID 会报错。capacity check 与收集到的用例都需要 capacity marker,smoke 同理。
|
|
149
|
+
|
|
150
|
+
## 计划到终验
|
|
151
|
+
|
|
152
|
+
在已完成 plan 的真实需求上使用以下入口;将尖括号路径替换为本项目路径:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
# 生成或重新锁定 manifest;沿用项目实际命名的场景源
|
|
156
|
+
code-flow acceptance manifest --task-file "<任务文件>" --output "<需求目录>/.acceptance-manifest.json" --scenarios-file "<需求>.scenarios.md" --register-checks
|
|
157
|
+
# 同步已修改工件的引用哈希,再执行完整计划门禁
|
|
158
|
+
code-flow spec refresh --task-dir "<需求目录>" --root "$PWD" --json
|
|
159
|
+
code-flow acceptance manifest --verify-plan --require-scenarios --task-dir "<需求目录>" --task-file "<任务文件>"
|
|
160
|
+
# 开发期间只跑 validators,允许任务进行中,不推进状态
|
|
161
|
+
code-flow task verify --task-dir "<需求目录>" --checks --profile full --root "$PWD" --json
|
|
162
|
+
# 全层终验:按当前输入执行或复用有效证据
|
|
163
|
+
code-flow task verify --task-dir "<需求目录>" --layers validators,review,e2e --profile full --root "$PWD" --json
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
`--require-scenarios` 用于明确要求场景源;即使不传,`--verify-plan` 也始终检查 manifest 基线、场景语义、实际登记/收集、设计闭环和 plan Spec Gate。已有场景源会被自动发现。新锁文件声明 `quality_schema: 2`,start 复核当前质量和登记;旧锁文件缺少该版本时,start 保留原 E2E 门禁并输出 `legacy_quality_schema` 警告,提示补字段并重锁,不宣称新质量检查通过。
|
|
167
|
+
|
|
168
|
+
显式 `exec: deferred` 的 E2E 保留在 owned/smoke 提示中,编码阶段不进入 scheduled,也不执行登记收集;完整 verify-plan 仍检查其质量和登记,需求终验再执行。Done 的 integration/system/capacity 延后场景也可保留 e2e_deferred;verified 必须闭环。批次验证包含相关且已就绪的共享 smoke,即使其 owner 属于旧批次;需求终验继续覆盖整个需求。
|
|
169
|
+
|
|
170
|
+
场景可用 `expected_checks: [{expected: 1, checks: ["CHK-contract", "CHK-component"]}]` 将每个 1-based 预期绑定到必要 check;所有成员均须通过。混合层级逐 check 声明 `level`,缺失映射或未知 check 阻断锁定;旧计划未声明字段时保留原有语义。重锁改变契约会保留历史并使旧证据失效。
|
|
171
|
+
|
|
172
|
+
CAS 冲突可组合 contract、component 和真实存储 integration;聚合补零和关系绑定也优先用低层验证。Cookie 身份隔离、SSE 恢复可保留关键浏览器链路。E2E 数量、比例和耗时只作诊断,不设配额;设计评审判断独特故障、低层覆盖与剩余风险。相关已完成批次可用 `code-flow task verify --tasks TASK-001,TASK-002 --layers validators,e2e --profile smoke`;部分通过不等于需求终验。
|
|
173
|
+
|
|
174
|
+
重锁按场景保存 status、revision、evidence、runs 和 stale_checks。场景契约或 check 配置变化时,保留历史并标为 stale;未变场景保留有效状态。CLI 的 relock 字段报告 preserved/stale/removed,旧锁文件损坏会给出 warnings。
|
|
175
|
+
|
|
176
|
+
验收指纹包含尚未跟踪的新文件;同一份内容在 add/commit 前后保持一致,删除后提交也一致。测试报告、计数文件等产物应加入 .gitignore;默认工作树指纹排除 .code-flow 和标准 .acceptance-manifest.json,显式 inputs 单独计算。
|
|
177
|
+
|
|
178
|
+
变更 command、inputs 或登记配置会使旧输入证明失效。多 check 场景逐个保存结果,A 通过不能覆盖 B 失败;CI 按 check 回传,格式见 [CI 证据指南](ci/acceptance-evidence.md)。手工将 TASK 或场景状态改成 verified 不会产生执行证据。
|
|
179
|
+
|
|
180
|
+
## ID、模板和规则证据
|
|
181
|
+
|
|
182
|
+
设计 frontmatter 设置 `design_template: lite|full|frontend` 中的实际模板值,再运行 `code-flow design lint --file <design> --scenarios-file <scenarios> --json`。多份设计重复 --file。检查未定义 FEAT/API/NFR、冲突 NFR、无场景功能、场景与功能错配及对应模板的必填章节。
|
|
183
|
+
|
|
184
|
+
doctor 会分别报告健康检查与各阶段 readiness。applied artifact 必须引用正确章节中的已完成条目;仅出现 Rule ID 或含有“待确认/TBD”的占位说明不构成证明。code/review 必须有执行证据。Conventions 中的关键约束应提升为 Rules;其余通过 convention_review_required 明确提示审查。
|
|
185
|
+
|
|
186
|
+
`spec apply/bind` 的工件相对当前需求目录解析,gate/doctor 使用同一基准;不搜索其他需求的同名文件。section_id 支持标题、标准 slug 和 TASK 编号;旧 task-008、rule-api-002 别名按大小写无关的完整 ID 解析。写入应用引用时立即验证目标章节和条目,仍拒绝未解决占位。`rule_artifact_stale` 保留阻断并在 next 给出显式 refresh 命令。
|
|
187
|
+
|
|
188
|
+
规则无需改代码也可以通过有效自动验证证明符合,因此 `decision=null` 本身不是错误。确实不适用时使用 `not_applicable` 和用户 decision;不得将未处理的“需同步 spec 文本”标为 applied。doctor 顶层 decision 表示诊断健康,`readiness.plan/code/review` 分别表示阶段准备情况,二者应一起查看。
|
|
189
|
+
|
|
190
|
+
## 报告与常见修复
|
|
191
|
+
|
|
192
|
+
| 报告字段 | 含义 |
|
|
193
|
+
|----------|------|
|
|
194
|
+
| `e2e_count` / `e2e_browser_count` | 声明的 E2E 数量 / 其中声明浏览器边界的数量,仍须查看 quality.errors |
|
|
195
|
+
| `system_count` / `capacity_count` | system 场景数 / capacity 层级或标签的场景数 |
|
|
196
|
+
| `runnable_smoke_count` / `runnable_browser_count` | 通过登记、真实收集和执行选择校验的场景数,不是测试用例数或已执行通过数 |
|
|
197
|
+
| `registration_status` | parse 时为 not_checked,verify-plan 收集后为 passed/failed;未检查的 runnable 值为 null,parse 不提供 runnable_browser_count |
|
|
198
|
+
| `verified_browser_count` | 当前语义报告中为 null,不以静态声明或收集结果推断浏览器执行成功 |
|
|
199
|
+
|
|
200
|
+
| 错误/提示 | 修复方式 |
|
|
201
|
+
|-----------|----------|
|
|
202
|
+
| `e2e_browser_boundary_missing` / `scenario_boundary_components_mismatch` | 确认真实浏览器边界并对齐 env/components/boundary;API/后台全链路改用 system/integration |
|
|
203
|
+
| `scenario_expected_nondeterministic` / `scenario_expected_reference_missing` | 写出可观察结果、明确条件与有效的步骤/断言引用 |
|
|
204
|
+
| `scenario_defer_metadata_missing` | 补齐延期原因、责任人和目标阶段 |
|
|
205
|
+
| `traceability_undefined_id` / `nfr_id_mismatch` / `scenario_feature_mismatch` | 在所有设计和场景源中统一 ID 定义、NFR 含义与功能对应关系 |
|
|
206
|
+
| `feature_without_scenario` / `template_section_missing` | 补验收场景或明确移出本期范围;补齐声明模板的必填章节 |
|
|
207
|
+
| `e2e_check_not_browser` / `capacity_check_not_marked` / `smoke_check_not_registered` | 修复实际套件/marker 及收集配置;不能只修改统计字段 |
|
|
208
|
+
| `check_test_not_collected` / `check_execution_selection_mismatch` | 核对具体 ID、文件/项目选择和真正执行的 command |
|
|
209
|
+
| `rule_applied_unresolved` / `rule_execution_evidence_missing` | 完成引用条目并重做有效验证;需要不适用决策时记录用户确认 |
|
|
210
|
+
| `legacy_quality_schema` | 旧计划继续使用原门禁;补齐新字段并重锁,再执行完整 verify-plan |
|
|
211
|
+
| `check_collection_inference_unsupported` | 用 --registration-file 声明项目收集器,再执行真实登记校验 |
|
|
212
|
+
| `stop_already_running` | 提示包含锁持有者 PID;等待该进程退出后重试,进程结束或被终止后 OS 自动释放锁 |
|
|
213
|
+
|
|
214
|
+
本轮问题回归入口为 `tests/test_workflow_issue_regressions.py`,覆盖同名工件隔离、旧引用、延期范围、批次 owner、真实收集、重锁历史、提交前后指纹、refresh 提示及 Stop 并发/进程超时。
|
|
215
|
+
| `convention_review_required` | 审查未纳入 Rules 的重要约定;需机器强制的约定提升为稳定 Rule 与 verifier |
|
|
216
|
+
|
|
217
|
+
修改 canonical 场景或任务后重新锁定 manifest,再运行 verify-plan;Context 漂移按 `code-flow spec refresh` 的诊断处理。不要删除 marker、手改 input_hash 或绕过失败的门禁。
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# CI 验收与证据回传
|
|
2
|
+
|
|
3
|
+
本地默认 `changed`,全量 E2E 放到 CI/nightly。CI 执行后把报告导入 central evidence,下一次本地 verify 可以复用;`source=ci` 的运行仍会校验 `commit`、`run_url`、`exit_code`。
|
|
4
|
+
|
|
5
|
+
可选择由 code-flow 直接执行验收,或导入外部测试框架报告。前者已经写入执行证据,无需再将同一次运行的报告重复导入。场景与测试登记先通过[完整计划门禁](../acceptance-contract.md#计划到终验),收集证明与执行证明分别保存。
|
|
6
|
+
|
|
7
|
+
## GitHub Actions 示例
|
|
8
|
+
|
|
9
|
+
以下示例假定 runner 已安装与项目 runtime 匹配的 code-flow CLI,并按项目准备测试依赖、浏览器与数据库;需求内任务已完成、可以进行终验。将示例需求路径替换为实际路径,CLI 安装方式见[迁移指南](../migrations/runtime-0.8.0.md)。
|
|
10
|
+
|
|
11
|
+
```yaml
|
|
12
|
+
name: acceptance
|
|
13
|
+
|
|
14
|
+
on:
|
|
15
|
+
pull_request:
|
|
16
|
+
schedule:
|
|
17
|
+
- cron: "0 18 * * *" # nightly
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
verify:
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v4
|
|
24
|
+
- uses: actions/setup-python@v5
|
|
25
|
+
with:
|
|
26
|
+
python-version: "3.12"
|
|
27
|
+
- name: Install
|
|
28
|
+
run: pip install -r requirements.txt
|
|
29
|
+
- name: Full acceptance
|
|
30
|
+
run: |
|
|
31
|
+
code-flow task verify \
|
|
32
|
+
--task-dir .code-flow/tasks/2026-10-22/demo \
|
|
33
|
+
--root "$PWD" \
|
|
34
|
+
--layers validators,review,e2e \
|
|
35
|
+
--profile full \
|
|
36
|
+
--json > "$RUNNER_TEMP/acceptance.json"
|
|
37
|
+
- uses: actions/upload-artifact@v4
|
|
38
|
+
if: always()
|
|
39
|
+
with:
|
|
40
|
+
name: acceptance
|
|
41
|
+
path: ${{ runner.temp }}/acceptance.json
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
JSON 输出放在仓库之外,避免生成报告本身改变 repo scope 输入指纹。直接执行产生的 central evidence 位于 Git common dir;上传 JSON 摘要不等于将证据恢复到另一个 checkout。
|
|
45
|
+
|
|
46
|
+
## 外部报告回传
|
|
47
|
+
|
|
48
|
+
外部流水线必须真实运行测试并生成 JUnit/Playwright 报告,再在相同 commit 的干净 checkout 导入。报告放在仓库之外或已忽略路径,CLI 不会代为执行外部报告中的测试:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
code-flow evidence import --format junit --file "/tmp/junit.xml" \
|
|
52
|
+
--task-dir "<需求目录>" --root "$PWD" \
|
|
53
|
+
--commit "$(git rev-parse HEAD)" --run-url "<真实 CI 运行 URL>" --json
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
用例必须能唯一映射到实际 manifest check。多 check 场景的报告应分别覆盖全部成员,例如以下用例名中的 CHK-A/CHK-B 需替换为真实 check ID:
|
|
57
|
+
|
|
58
|
+
```xml
|
|
59
|
+
<testsuite name="acceptance">
|
|
60
|
+
<testcase name="test_browser_order[CHK-A]" />
|
|
61
|
+
<testcase name="test_order_storage[CHK-B]" />
|
|
62
|
+
</testsuite>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
单 check 报告可以使用 `--check "<check ID>"` 明确归属;不能用它将单个报告扩散为多个 check 的成功。A 通过、B 失败时按 check 保留结果,缺少 B 的证据不能用场景汇总 pass 代替。详细映射、skipped 与退出码约束见[使用手册](../USAGE.md#code-flow-evidence-import--ci-证据导入)。
|
|
66
|
+
|
|
67
|
+
## 约束
|
|
68
|
+
|
|
69
|
+
- `--profile full` 必须显式指定;本地 `changed` 不应升级成全量 E2E。
|
|
70
|
+
- 夜间任务可以只跑 `--layers e2e --profile full`,functional/validators 由 PR 流水线负责。
|
|
71
|
+
- 导入失败(commit/run_url 缺失、用例无法映射)必须让 job 失败,不得吞掉。
|
|
72
|
+
- CI 证据写入 git common dir;worktree 不提交 evidence 目录。
|
|
73
|
+
- 不同 checkout 需通过合法导入形成自己的证据;同一仓库 worktree 才共享 common dir。验收仍会检查当前输入指纹,更改 command/inputs/登记配置后旧证据失效。
|
|
74
|
+
- browser/smoke/capacity 的测试登记和收集仍由 verify-plan 检查,测试必须在声明的真实环境执行;不要通过改 marker 或汇总数字伪造结果。
|
|
75
|
+
# 环境身份与时效
|
|
76
|
+
|
|
77
|
+
外部环境 check 可登记 `environment_revision` 和正数 `evidence_ttl_seconds`。缺少可证明环境身份时不跨运行复用;有效期到期、环境或输入变化、较新失败和 skipped/超时都会使旧通过结果失效。环境值只进入摘要,不写入证据明文。
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# 0.7.0 原生平台运行时迁移
|
|
2
|
+
|
|
3
|
+
0.7.0 将 Agent 的公开调用统一到 `code-flow`,Codex 使用原生 `apply_patch` 事件入口。没有旧命令别名、无效参数容错或双写路径。
|
|
4
|
+
|
|
5
|
+
新项目执行 `code-flow init --platform=codex`。已安装 schema-v1 的项目在使用新版 CLI 后执行:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
code-flow migrate --runtime --dry-run
|
|
9
|
+
code-flow migrate --runtime --apply
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
dry-run 在 `.code-flow/migrations/runtime-*/` 构建并验证产物后,清理备份和暂存目录,仅保留预览日志,项目目标文件保持原样。apply 重新构建并验证待安装产物,保留事务备份,更新全部已安装平台,保留用户配置、规范和任务,替换受管理的 Codex Hook 定义;`.version` 最后写入。安装版本高于 CLI 时拒绝迁移,必须先更新 CLI。
|
|
13
|
+
|
|
14
|
+
返回 `committed` 后在 Codex `/hooks` 中信任变更定义。迁移文件仍保留,可按输出的 `migration_id` 回滚:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
code-flow migrate --runtime --rollback runtime-<timestamp>-<pid>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
失败时自动恢复已写入文件。进程中断后必须先按错误提示回滚对应事务;不能启动第二次 apply 越过未完成事务。回滚不会覆盖迁移完成后又发生的文件修改,遇到此类修改会阻断并指出路径。
|
|
21
|
+
|
|
22
|
+
公开命令示例:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
code-flow spec validate --task-dir ".code-flow/tasks/<日期>/<需求>" --json
|
|
26
|
+
code-flow task start --help
|
|
27
|
+
code-flow task finish --help
|
|
28
|
+
code-flow task verify-e2e --help
|
|
29
|
+
code-flow acceptance run --help
|
|
30
|
+
code-flow validate --help
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`.code-flow/runtime-commands.json` 定义公开命令与业务模块的唯一映射,参数由实际解析器验证;错误入口或未知参数会明确报错。开发时执行 `node src/render-runtime-contract.js`,从同一契约生成四个平台技能中的命令示例。`.runtime-install.json` 记录版本和受管理文件哈希,命令执行及 Codex Hook 会检查完整性。安装损坏时通过上述事务迁移修复。
|
|
34
|
+
|
|
35
|
+
编辑 Hook 覆盖补丁操作;通过 shell 或其他工具修改的文件仍由 Finish 的任务基线 diff 校验。Hook 不替代阶段门禁。
|
|
36
|
+
|
|
37
|
+
Codex Hook 模板通过官方 `commandWindows` 字段提供 Windows 原生入口,使用 Python Launcher `py -3`;macOS/Linux 使用 `python3`。两者从当前目录向上定位入口,并将原始事件传给同一个 Codex 处理器。
|
|
38
|
+
|
|
39
|
+
安装损坏时 Stop 返回 `decision: block`,其余事件输出诊断;无法确认 `apply_patch` 成功时不产生 edit Evidence,并写入 degrade 日志。成功判定不接受猜测的 `status: completed` 包装。
|
|
40
|
+
|
|
41
|
+
OpenCode v2 同样使用专用原生入口 `cf_opencode_event.py`。插件传入原生 event、sessionID 和会话 location.directory,直接调用共享 prompt/edit/stop 服务,不构造 Claude 工具事件或读取其他平台的 Hook 输出。`edit/write` 使用 input.path,`patch` 使用 input.patchText;只有原生 status=completed 产生 edit Evidence。已在 v2.0.15 验证插件加载和 prompt 事件。idle 无阻断接口,收尾失败反馈进入下轮 context,Finish/verify-e2e 保持硬门禁。
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# 0.8.0 运行时与命令面迁移
|
|
2
|
+
|
|
3
|
+
0.8.0 把用户命令面从 16 条收敛到 11 条,并把执行、证据与状态机升级为 manifest v3 + evidence sidecar。旧命令文件不删除,保留一个 minor 的兼容别名(0.9.0 移除)。
|
|
4
|
+
|
|
5
|
+
本文包括仓库 0.8.0 的验收契约硬化;npm 发布状态独立,先核对实际安装版本。完整字段、可复制示例与错误处理见[可执行验收契约](../acceptance-contract.md)。
|
|
6
|
+
|
|
7
|
+
## 1. 升级前置
|
|
8
|
+
|
|
9
|
+
- CLI 与项目内运行时版本必须可比较:安装版本高于 CLI 时迁移会拒绝降级,先更新全局包。
|
|
10
|
+
- 迁移前确认工作区干净(至少 `.code-flow/` 之外无未提交改动);迁移会备份 `.code-flow/`。
|
|
11
|
+
- 需要 Python 3.9+ 与 pyyaml;0.8 没有新增 npm 运行时依赖,`package.json` 仍只有 `@ccusage/codex`。
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
code-flow --version
|
|
15
|
+
npm view @michaelxwb/code-flow dist-tags --json
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
确认注册表已有所需版本后再安装。需要尚未发布的仓库修复时,按 [README](../../README.md#升级)构建并安装本地 tarball;不要用较旧的 latest 覆盖本地版本。CLI 更新后进入目标项目:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
cd your-project
|
|
22
|
+
code-flow migrate --runtime --dry-run
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`--dry-run` 在 `.code-flow/migrations/runtime-<id>/` 构建并校验产物,只写预览 journal,不改目标文件。确认 `status=previewed` 与 `files` 清单后再执行:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
code-flow migrate --runtime --apply
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
apply 使用同一事务:备份 → staging → 校验 → journal → 写目标 → `.version` 最后写。返回 `committed` 后再在 Codex `/hooks` 中信任变更定义。
|
|
32
|
+
|
|
33
|
+
## 2. 命令面变化(16 → 11)
|
|
34
|
+
|
|
35
|
+
| 0.7 命令 | 0.8 状态 | 0.8 用法 |
|
|
36
|
+
|----------|----------|----------|
|
|
37
|
+
| `cf-init` | 用户命令 | `/cf-init` |
|
|
38
|
+
| `cf-learn` | 用户命令 | `/cf-learn` |
|
|
39
|
+
| `cf-spec` | 用户命令 | 新增 `code-flow spec doctor` 运行时入口 |
|
|
40
|
+
| `cf-stats` | 用户命令 | `/cf-stats --audit` |
|
|
41
|
+
| `cf-task:prd` | 用户命令 | `/cf-task:prd` |
|
|
42
|
+
| `cf-task:align` | 用户命令 | `/cf-task:align` |
|
|
43
|
+
| `cf-task:plan` | 用户命令 | 默认能力级拆解与预算门禁 |
|
|
44
|
+
| `cf-task:start` | 用户命令 | `/cf-task:start` |
|
|
45
|
+
| `cf-task:status` | 用户命令 | 吸收 `--notes` / `--block` / `--graph` 子动作 |
|
|
46
|
+
| `cf-task:archive` | 用户命令 | `/cf-task:archive` |
|
|
47
|
+
| `cf-task:verify-e2e` | 用户命令 | `code-flow task verify` 的兼容别名 |
|
|
48
|
+
| `cf-task:note` | 别名 | `/cf-task:status --notes` |
|
|
49
|
+
| `cf-task:block` | 别名 | `/cf-task:status --block` |
|
|
50
|
+
| `cf-task:graph` | 别名 | `/cf-task:status --graph` |
|
|
51
|
+
| `cf-validate` | 别名 | `code-flow task verify --checks`(等价 `--layers validators`) |
|
|
52
|
+
| `cf-sync` | internal | 开发/发布维护专用,不属于用户安装面 |
|
|
53
|
+
|
|
54
|
+
命令清单的唯一权威源是 `src/adapters/commands.json`:每个条目声明 `kind=user|alias|internal`、平台文件路径与别名参数。四平台(Claude Code / Codex / Costrict / OpenCode)的命令文件集必须与该目录一致;内容 canonical 源仍是 Claude 命令,其余平台只允许绑定 token 差异。`tests/test_adapter_parity.py` 与 `tests/test_command_surface.py` 守住这条约束。
|
|
55
|
+
|
|
56
|
+
兼容窗口:0.8.x 期间旧别名文件保留且行为不变;0.9.0 删除别名文件,调用方需提前迁移到新入口。
|
|
57
|
+
|
|
58
|
+
## 3. 状态机(0.7 → 0.8)
|
|
59
|
+
|
|
60
|
+
0.8 的 TASK 状态由证据推导,不再接受手写 terminal 状态:
|
|
61
|
+
|
|
62
|
+
| 状态 | 含义 |
|
|
63
|
+
|------|------|
|
|
64
|
+
| `done` | 本任务 required code check 全部 verified |
|
|
65
|
+
| `provisional` | 任一 required code check 为 deferred / env_blocked / incomplete;真实 failed 必须 block |
|
|
66
|
+
| `verified` | 需求级 Gate 通过,且证据 input_hash 与当前工作区匹配 |
|
|
67
|
+
| `deferred` | 仅允许 review-stage / heavy 检查延后;预算导致的延后不是合法 deferral |
|
|
68
|
+
|
|
69
|
+
规则:
|
|
70
|
+
|
|
71
|
+
- required code check 未全部 verified 时,手写 `done`/`verified` 会被拒绝并报告冲突。
|
|
72
|
+
- `env_blocked` 是环境失败,不是产品失败:不写 verified,也不计产品 failed。
|
|
73
|
+
- 只有 `--profile full` 且全部层通过才把需求提升为 `verified`;`smoke`/`changed` 不会伪造终态。
|
|
74
|
+
- `task finish --batch TASK-001,TASK-002` 与 `task finish --capability <名称>` 在一次执行内复用共享 check,失败任务不会污染已通过任务。
|
|
75
|
+
|
|
76
|
+
## 4. Manifest v3
|
|
77
|
+
|
|
78
|
+
`.acceptance-manifest.json` 从 schema 2 迁移到 schema 3:
|
|
79
|
+
|
|
80
|
+
- `checks[]`:可执行命令、cwd、timeout、env/env_scope/preflight/parallel_safe、inputs,以及 suite/test_ids/markers/collect 登记;按 `CHK-*` 去重。
|
|
81
|
+
- `scenarios[]`:保留 ID / owner / assertions 和场景语义,通过 `checks` 绑定全部成员;兼容旧 `check`,同一 check 可被多个 scenario 引用。
|
|
82
|
+
- schema 2 输入按 `command + cwd + timeout` 自动归并为 checks,读取时返回 `schema2_compat`;旧证据仍可读。
|
|
83
|
+
- check 或 scenario 映射冲突 fail closed,列出冲突字段,不静默覆盖。
|
|
84
|
+
|
|
85
|
+
运行时迁移更新受管理脚本和平台入口,不代写需求场景与测试登记。已有需求按下方步骤检查并重新锁定 manifest;一个场景的全部 checks 都必须绑定并各自保留证据。
|
|
86
|
+
|
|
87
|
+
## 5. Evidence sidecar
|
|
88
|
+
|
|
89
|
+
- 证据集中到 git common dir:`.git/code-flow/evidence/`(非 git 项目回落到 `.code-flow/evidence/`)。
|
|
90
|
+
- 文件按 `run_id` 唯一,原子写(临时文件 + `os.replace`),同一 run_id 幂等去重。
|
|
91
|
+
- `spec-context.yml` 只保留每个 rule 的最新状态;历史压缩进 sidecar(上限 200 条),不再把全部 evidence 塞进 Context。
|
|
92
|
+
- 重锁 plan 不清证据;旧 verified 在 input_hash 变化后降为 stale,而不是删除。
|
|
93
|
+
- CI 证据通过 `code-flow evidence import --format junit|playwright` 导入,校验 commit / run_url / exit_code / source=ci;无法映射的用例拒绝导入。
|
|
94
|
+
- 并行 worktree 共享 central evidence,worker 分支不提交证据文件;collect 只接受 done/verified,拒绝 provisional/blocked。
|
|
95
|
+
|
|
96
|
+
## 6. 验证与诊断
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
code-flow spec doctor --task-dir ".code-flow/tasks/<日期>/<需求>" --root "$PWD" --json
|
|
100
|
+
code-flow audit --task-dir ".code-flow/tasks/<日期>/<需求>" --json
|
|
101
|
+
code-flow task verify --task-dir ".code-flow/tasks/<日期>/<需求>" --checks --profile full --root "$PWD" --json
|
|
102
|
+
code-flow task verify --task-dir ".code-flow/tasks/<日期>/<需求>" --layers validators,review,e2e --profile full --root "$PWD" --json
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
`spec doctor` 只读诊断 config schema、active marker、Context hash、迁移 journal/lock、运行时 manifest 与 legacy residue,并检查未解决的 applied 引用、提示 Conventions 审查。顶层 decision 表示诊断健康,`readiness.plan/code/review` 分别表示阶段准备情况;应同时查看。阻断项按 `next` 修复,不能把健康通过当作阶段通过。
|
|
106
|
+
|
|
107
|
+
code/review 的 applied 引用不能替代执行证据。自动 verifier 能证明符合时无需另造用户 decision;规则确实不适用才用 not_applicable 与用户确认。`audit` 按每个 check 对账,A 的成功不能覆盖 B 的失败;缺部分 central evidence 时不借用场景汇总 pass。
|
|
108
|
+
|
|
109
|
+
### 重新锁定现有需求
|
|
110
|
+
|
|
111
|
+
1. 找到 canonical 场景源;没有时按 [Scenario-First 迁移说明](runtime-0.9.0.md)从完整旧定义生成草稿。只有引用的旧 design 不能回退为完整场景。
|
|
112
|
+
2. API/CLI/后台全链路改为 system/integration,同时移除 why_e2e;保留为 e2e 的场景必须有浏览器 env/组件和匹配 boundary。
|
|
113
|
+
3. 补齐具体 expected 与逐条 expected_refs;有条件预期声明前置条件。deferred 补 defer_reason、owner、target_phase。
|
|
114
|
+
4. 使用合法 env;数据库放在 components。设计声明实际 design_template,统一 FEAT/API/NFR 定义及功能到场景关系。
|
|
115
|
+
5. 生成 manifest 时加 --register-checks,由真实 pytest / Playwright 收集登记;自定义收集器使用 --registration-file。执行 command 必须选中登记用例。延期执行不免除完整计划登记。
|
|
116
|
+
6. 执行以下门禁。更改登记配置或命令会使旧输入证明失效,按实际需要重跑受影响检查。
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
code-flow scenarios parse --file "<需求>.scenarios.md" --quality --json
|
|
120
|
+
code-flow design lint --file "<需求>.design.md" --scenarios-file "<需求>.scenarios.md" --json
|
|
121
|
+
code-flow acceptance manifest --task-file "<任务文件>" --output "<需求目录>/.acceptance-manifest.json" --scenarios-file "<需求>.scenarios.md" --register-checks
|
|
122
|
+
code-flow spec refresh --task-dir "<需求目录>" --root "$PWD" --json
|
|
123
|
+
# 登记与引用同步后再运行
|
|
124
|
+
code-flow acceptance manifest --verify-plan --require-scenarios --task-dir "<需求目录>" --task-file "<任务文件>"
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
`--verify-plan` 始终执行完整检查,不能通过不传 `--require-scenarios` 绕过。旧文档可读与旧 evidence 可追溯不代表新计划自动通过。`--checks` 只跑开发期 validators、不推进终态;需求级 full 终验才证明完整范围。浏览器可运行数量来自实际收集,已执行结果仍来自有效运行证据。
|
|
128
|
+
|
|
129
|
+
旧锁文件缺少 quality_schema: 2 时,start 保留原 E2E 门禁并提示 legacy_quality_schema,给在途任务留下显式补字段与重锁的窗口;不会自动生成 expected_refs、延期负责人或用户确认。重锁启用当前门禁。已有场景历史按 ID 保留,契约变化标为 stale,CLI relock 字段列出影响;登记失败保留旧锁文件。
|
|
130
|
+
|
|
131
|
+
## 7. 回滚
|
|
132
|
+
|
|
133
|
+
迁移 journal 保留在 `.code-flow/migrations/runtime-<id>/`,apply 返回的 `migration_id` 可直接回滚:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
code-flow migrate --runtime --rollback runtime-<timestamp>-<pid>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
- 回滚只恢复该事务写过的文件;迁移完成后再手工修改的文件会被检测并阻断,不会覆盖后续工作。
|
|
140
|
+
- `--dry-run` 产生的 `previewed` journal 也可回滚,用于清理预览目录。
|
|
141
|
+
- 进程中断后不要直接再次 apply:先按错误提示回滚未完成事务(`staging`/`applying`),`spec doctor` 会列出待恢复的 journal。
|
|
142
|
+
- 回滚后 `.version` 回到迁移前版本;如 CLI 已是 0.8.0,再次 `--apply` 即可重新升级。
|
|
143
|
+
|
|
144
|
+
## 8. 发布验收
|
|
145
|
+
|
|
146
|
+
0.8.0 发布前必须全绿:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
python3 -m pytest -q tests/test_adapter_parity.py
|
|
150
|
+
python3 -m pytest -q tests/test_command_surface.py
|
|
151
|
+
node tests/test_cli_merge_helpers.js
|
|
152
|
+
node tests/test_spec_workflow_migrate.js
|
|
153
|
+
node src/cli.js sync check --root .
|
|
154
|
+
```
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Scenario-First Acceptance 迁移
|
|
2
|
+
|
|
3
|
+
文件名沿用最初的 0.9 规划;Scenario-First 已包含在当前仓库 0.8.0 中。本页不表示 0.9 已发布,也不要求把 package 版本改为 0.9。
|
|
4
|
+
|
|
5
|
+
## 变化
|
|
6
|
+
|
|
7
|
+
- `<需求>.scenarios.md` 是验收场景唯一源,design 只引用 S-/E-/B- ID 并说明设计影响。
|
|
8
|
+
- plan 将场景投影到任务 Acceptance Coverage 与 manifest,audit 对账三者及逐 check 证据。
|
|
9
|
+
- 场景语义、设计 ID 和测试登记按[验收契约](../acceptance-contract.md)检查;仅能解析文件不等于计划通过。
|
|
10
|
+
|
|
11
|
+
## 迁移步骤
|
|
12
|
+
|
|
13
|
+
先安装匹配的 CLI 并完成[运行时迁移](runtime-0.8.0.md)。保留旧设计和任务定义,再从完整任务文件提取场景草稿:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
code-flow scenarios migrate --task-file "<任务文件>" --output "<需求>.scenarios.md" --json
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
1. 检查草稿是否覆盖旧需求全部场景,补真实步骤、具体 expected 和逐条 expected_refs。
|
|
20
|
+
2. 明确 e2e/system/integration/capacity;e2e 声明浏览器边界,非 e2e 移除 why_e2e。
|
|
21
|
+
3. 补环境、组件、design_refs/features、触发路径与延期责任。API/CLI 全链路不再占用浏览器 E2E 数量。
|
|
22
|
+
4. 场景源完整后将 design 中的重复场景表改为引用,保留 FEAT/API/NFR 定义和对应关系;声明实际 design_template。
|
|
23
|
+
5. 重新锁定 manifest,在实际 check 上补齐套件、marker 与真实测试收集配置,再运行完整门禁。
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
code-flow scenarios parse --file "<需求>.scenarios.md" --quality --json
|
|
27
|
+
code-flow design lint --file "<需求>.design.md" --scenarios-file "<需求>.scenarios.md" --json
|
|
28
|
+
code-flow acceptance manifest --task-file "<任务文件>" --output "<需求目录>/.acceptance-manifest.json" --scenarios-file "<需求>.scenarios.md"
|
|
29
|
+
# 补齐对应 check 的登记配置后运行
|
|
30
|
+
code-flow acceptance manifest --verify-plan --require-scenarios --task-dir "<需求目录>" --task-file "<任务文件>"
|
|
31
|
+
code-flow audit --task-dir "<需求目录>" --root "$PWD" --json
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
迁移命令生成的草稿需要人工完善,尤其不能从旧命令名推断真实浏览器边界。登记与收集通过后仍需实际执行才能产生验收证据。
|
|
35
|
+
|
|
36
|
+
## 旧需求兼容
|
|
37
|
+
|
|
38
|
+
没有场景源且 design 保留完整旧场景定义的需求可走兼容审计,并标记 deprecated;只有引用的 design 缺少场景源时明确报 scenario_source_missing,不能推断或编造场景。
|
|
39
|
+
|
|
40
|
+
回退需恢复成套的旧设计、任务与 manifest,再执行审计。不要只删除场景源来绕过门禁;重锁计划仍需满足当前规则。
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Specs 自动注入校验
|
|
2
|
+
|
|
3
|
+
Prompt 和编辑入口共用 Context-first 路由。存在 active TASK 时,绑定事实来自持久化 Context;无 active TASK 的明确本地路径使用 path_mapping,没有本地路径时展示 Catalog。
|
|
4
|
+
|
|
5
|
+
**源文件与投影版本**
|
|
6
|
+
|
|
7
|
+
每次事件读取 Context 后校验 marker 的身份哈希,并对已绑定 Spec 的原始字节计算 SHA256。文件变化或缺失返回 `bound_spec_drift` / `bound_spec_missing`,需要显式 refresh;不会重选规范或继续发送旧规则。源哈希校验在输出去重之前执行,mtime 不变也不能隐藏内容变化。
|
|
8
|
+
|
|
9
|
+
投影缓存同时检查 Context 文件版本和 TASK 内容哈希。会话去重按实际输出内容生成指纹,因此 Spec-Refs、合同、Context 身份或投影中的 artifact 引用变化都能触发重注入。缓存不保存新的绑定事实。
|
|
10
|
+
|
|
11
|
+
`.code-flow/.context-state.json` 缓存经过 schema 校验的解析结果与原有身份哈希,键包含 Context 原始字节哈希、文件路径及解析器版本,缓存体另有完整性校验。每次先读取真实源文件;源文件变化、解析器变化或缓存损坏都重新解析源 YAML。缓存缺失不能让损坏源文件通过,也不会自动刷新绑定。
|
|
12
|
+
|
|
13
|
+
**批量编辑**
|
|
14
|
+
|
|
15
|
+
Codex apply_patch、OpenCode patch 把全部路径交给 `prepare_edits`;单文件编辑使用同一批量服务。服务按路径所属的项目分组,每组加载一次 Context、校验一次绑定源、解析一次相关的未绑定 Spec headers。删除与移动源路径仍参与检查。
|
|
16
|
+
|
|
17
|
+
路径查询先按 mapping 过滤无关域,再解析匹配及全局规范。全量 resolver 和 `code-flow spec catalog` 继续保留完整候选与全库元数据检查能力。
|
|
18
|
+
|
|
19
|
+
**错误和拒绝**
|
|
20
|
+
|
|
21
|
+
配置损坏、Context 无效、源文件漂移、缺失 Spec-Refs / Acceptance Contract,以及超预算都产生结构化 `SPEC_WORKFLOW_BLOCKED`。Claude/Costrict/Codex 编辑入口使用 `hookSpecificOutput.permissionDecision: deny`;OpenCode 返回原生 `blocked: true`。
|
|
22
|
+
|
|
23
|
+
Codex 字段依据 [官方 Hooks 文档](https://learn.chatgpt.com/docs/hooks#pretooluse)。入口 JSON 测试与真实宿主拒绝写入测试是不同验证层次,报告测试结果时须区分。
|
|
24
|
+
|
|
25
|
+
历史 enforcement=warn/inject 仍兼容部分旧验证降级,doctor 返回 `legacy_enforcement_mode` 提示审查后显式改回 required。它们不能隐藏上述路由完整性错误。新增路径引入未绑定 required Spec 仍按现有规范给出 refresh 提示,允许本次编辑。
|
|
26
|
+
|
|
27
|
+
**输出与预算**
|
|
28
|
+
|
|
29
|
+
TASK/path 注入状态按 session_id 的 SHA256 分文件隔离,位于 `.code-flow/sessions/injection/`;此目录属于可重建运行状态。只有成功序列化、写出并 flush 输出后,入口才提交待更新的去重状态。输出异常或超时不会提前标记已发送。状态不可用时允许重新注入,并记录诊断。
|
|
30
|
+
|
|
31
|
+
Prompt 每 25 轮保留周期重注入。Prompt 和编辑前共享同一模式的投影指纹,因此重复的路径或 TASK 不重复发送相同全文。
|
|
32
|
+
|
|
33
|
+
path 模式使用 `min(budget.total, budget.l1_max)`,缺省分别为 2500/1700。token 使用当前项目的 `len(text) // 4` 估算。required 内容放不下时返回 `spec_budget_exceeded`,不发送残缺规则;应创建聚焦 TASK Context 或拆分编辑范围。
|
|
34
|
+
|
|
35
|
+
Catalog 排除 `_session/` 和 tags=[] 命令模板。Tier 0 文件仅作为导航展示。目录省略时,预算内保留已展示/总数和完整查询命令:
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
code-flow spec catalog --root . --stage code --json
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**回归验证**
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
python3 -m pytest -q tests/test_cf_injection_hardening.py tests/test_cf_user_prompt_hook.py tests/test_cf_pre_tool_hook.py tests/test_cf_injection_version.py tests/test_codex_native_hook.py tests/test_opencode_native.py
|
|
45
|
+
CODE_FLOW_HOST_TESTS=1 python3 -m pytest -q tests/test_codex_host_injection.py
|
|
46
|
+
code-flow sync check
|
|
47
|
+
code-flow validate --root . --json
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
规模回归构造真实 Context:200 个绑定 Spec、TASK 引用一条规则、一次编辑 20 个文件。断言 Context 与身份哈希各计算一次,已绑定 Spec 不重复解析 header,并对实际 Codex 入口施加配置中的 5 秒超时。时间测量与解析调用次数共同用于判断回归,避免把单个小 Context 的进程内缓存结果当成实际 Hook 性能。
|
|
51
|
+
|
|
52
|
+
真实宿主测试需要本机 Codex CLI 和已有模型元数据缓存,默认跳过。显式运行时使用隔离项目、已审查的测试 Hook、本地确定性 Responses 服务和独立 provider,不调用付费模型;正例实际写入临时文件,反例由宿主拒绝并确认文件不存在。
|
|
53
|
+
|
|
54
|
+
本机 Apple M5 Pro / Python 3.9.6 的[测量记录](spec-injection-performance.json):500 个 Spec、仅命中一个的路径 Prompt 中位数从 229.33 ms 降至 56.02 ms;200 个绑定、输出被去重的 Prompt 从 285.23 ms 降至 56.48 ms。20 文件编辑服务在解析缓存可用时从 9631.24 ms 降至 8.03 ms;完整安装的 Codex Hook 新进程首次解析为 333.36 ms,缓存可用时中位数 67.45 ms。服务调用与完整 Hook 进程分别列出,缓存状态与样本数见记录,数值不作为跨机器 SLA。
|