@hupan56/wlkj 3.1.32 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +117 -0
- package/package.json +1 -1
- package/templates/qoder/agents/insight-planning.md +67 -67
- package/templates/qoder/agents/prd-reference.md +47 -47
- package/templates/qoder/commands/optional/wl-insight.md +4 -4
- package/templates/qoder/commands/optional/wl-report.md +1 -1
- package/templates/qoder/commands/optional/wl-spec.md +23 -3
- package/templates/qoder/commands/optional/wl-status.md +12 -1
- package/templates/qoder/commands/wl-code.md +138 -7
- package/templates/qoder/commands/wl-commit.md +12 -1
- package/templates/qoder/commands/wl-design.md +70 -6
- package/templates/qoder/commands/wl-init.md +27 -0
- package/templates/qoder/commands/wl-prd.md +230 -15
- package/templates/qoder/commands/wl-req.md +10 -3
- package/templates/qoder/commands/wl-search.md +74 -20
- package/templates/qoder/commands/wl-task.md +3 -3
- package/templates/qoder/commands/wl-test.md +17 -2
- package/templates/qoder/contracts/CHANGELOG.md +418 -0
- package/templates/qoder/contracts/README.md +180 -0
- package/templates/qoder/contracts/code.md +82 -0
- package/templates/qoder/contracts/commit.md +86 -0
- package/templates/qoder/contracts/contract-header.md +76 -0
- package/templates/qoder/contracts/design.md +106 -0
- package/templates/qoder/contracts/fallback.md +126 -0
- package/templates/qoder/contracts/isolation.md +119 -0
- package/templates/qoder/contracts/prd.md +118 -0
- package/templates/qoder/contracts/schemas/design-spec.schema.json +46 -0
- package/templates/qoder/contracts/schemas/prd.schema.json +36 -0
- package/templates/qoder/contracts/schemas/test-cases.schema.json +40 -0
- package/templates/qoder/contracts/spec.md +116 -0
- package/templates/qoder/contracts/task.md +125 -0
- package/templates/qoder/contracts/test.md +112 -0
- package/templates/qoder/hooks/post-tool-use.py +61 -0
- package/templates/qoder/hooks/session-start.py +34 -66
- package/templates/qoder/hooks/stop-eval.py +47 -0
- package/templates/qoder/rules/wl-pipeline.md +37 -0
- package/templates/qoder/scripts/capability/__pycache__/__init__.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/__pycache__/registry.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/__pycache__/registry_mcp.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/adapters/__init__.py +1 -1
- package/templates/qoder/scripts/capability/adapters/__pycache__/__init__.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/adapters/__pycache__/cli.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/adapters/__pycache__/mcp.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/adapters/__pycache__/qw.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/adapters/mcp.py +76 -100
- package/templates/qoder/scripts/capability/adapters/qw.py +295 -295
- package/templates/qoder/scripts/capability/caps/__init__.py +1 -1
- package/templates/qoder/scripts/capability/caps/__pycache__/__init__.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/caps/__pycache__/context.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/caps/__pycache__/cron.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/caps/__pycache__/identity.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/caps/__pycache__/memory.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/caps/__pycache__/notify.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/caps/__pycache__/present.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/caps/__pycache__/repo.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/caps/__pycache__/sandbox.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/capability/caps/memory.py +1 -1
- package/templates/qoder/scripts/capability/registry.py +21 -23
- package/templates/qoder/scripts/capability/registry_mcp.py +69 -5
- package/templates/qoder/scripts/capability/smoke_test_report.json +34 -20
- package/templates/qoder/scripts/deployment/setup/carriers.py +3 -1
- package/templates/qoder/scripts/deployment/setup/init_doctor.py +10 -3
- package/templates/qoder/scripts/deployment/setup/install_qoderwork.py +11 -0
- package/templates/qoder/scripts/deployment/setup/wlkj_shim.py +104 -0
- package/templates/qoder/scripts/domain/__pycache__/__init__.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/domain/deployment/deploy_to_test.py +298 -0
- package/templates/qoder/scripts/domain/integration/__init__.py +0 -0
- package/templates/qoder/scripts/domain/integration/__pycache__/__init__.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/domain/integration/__pycache__/return_to_platform.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/domain/integration/return_to_platform.py +392 -0
- package/templates/qoder/scripts/domain/integration/spec_upload.py +209 -0
- package/templates/qoder/scripts/domain/kg/build/kg_build.py +268 -25
- package/templates/qoder/scripts/domain/kg/build/kg_incremental.py +108 -3
- package/templates/qoder/scripts/domain/kg/build/kg_signatures.py +169 -0
- package/templates/qoder/scripts/domain/kg/extract/asset/__init__.py +10 -0
- package/templates/qoder/scripts/domain/kg/extract/asset/asset_tree.py +57 -0
- package/templates/qoder/scripts/domain/kg/extract/asset/discussion_importer.py +62 -0
- package/templates/qoder/scripts/domain/kg/extract/asset/prd_importer.py +146 -0
- package/templates/qoder/scripts/domain/kg/extract/asset/prototype_importer.py +64 -0
- package/templates/qoder/scripts/domain/kg/extract/asset/returns_importer.py +52 -0
- package/templates/qoder/scripts/domain/kg/extract/build_goal3.py +104 -0
- package/templates/qoder/scripts/domain/kg/extract/build_goal4.py +55 -0
- package/templates/qoder/scripts/domain/kg/extract/build_goal5.py +95 -0
- package/templates/qoder/scripts/domain/kg/extract/db/__init__.py +8 -0
- package/templates/qoder/scripts/domain/kg/extract/db/data_profile.py +22 -0
- package/templates/qoder/scripts/domain/kg/extract/db/fk_extractor.py +55 -0
- package/templates/qoder/scripts/domain/kg/extract/db/schema_extractor.py +90 -0
- package/templates/qoder/scripts/domain/kg/extract/extract.py +84 -0
- package/templates/qoder/scripts/domain/kg/extract/extract.py.bak +430 -0
- package/templates/qoder/scripts/domain/kg/extract/inference/__init__.py +9 -0
- package/templates/qoder/scripts/domain/kg/extract/inference/community_summarizer.py +206 -0
- package/templates/qoder/scripts/domain/kg/extract/inference/embed_builder.py +132 -0
- package/templates/qoder/scripts/domain/kg/extract/inference/naming_matcher.py +80 -0
- package/templates/qoder/scripts/domain/kg/extract/inference/promote.py +59 -0
- package/templates/qoder/scripts/domain/kg/extract/inference/recompute.py +93 -0
- package/templates/qoder/scripts/domain/kg/extract/inference/weak_link.py +421 -0
- package/templates/qoder/scripts/domain/kg/extract/java/__init__.py +15 -0
- package/templates/qoder/scripts/domain/kg/extract/java/_parser.py +271 -0
- package/templates/qoder/scripts/domain/kg/extract/java/all.py +145 -0
- package/templates/qoder/scripts/domain/kg/extract/java/build_java_to_pg.py +102 -0
- package/templates/qoder/scripts/domain/kg/extract/java/call_chain.py +49 -0
- package/templates/qoder/scripts/domain/kg/extract/java/class_extractor.py +141 -0
- package/templates/qoder/scripts/domain/kg/extract/java/domain_extractor.py +148 -0
- package/templates/qoder/scripts/domain/kg/extract/java/dubbo_extractor.py +33 -0
- package/templates/qoder/scripts/domain/kg/extract/java/endpoint_extractor.py +36 -0
- package/templates/qoder/scripts/domain/kg/extract/java/javadoc_extractor.py +110 -0
- package/templates/qoder/scripts/domain/kg/extract/java/llm_cn_filler.py +150 -0
- package/templates/qoder/scripts/domain/kg/extract/java/member_extractor.py +157 -0
- package/templates/qoder/scripts/domain/kg/extract/java/mybatisplus_extractor.py +34 -0
- package/templates/qoder/scripts/domain/kg/extract/java/pg_upsert.py +165 -0
- package/templates/qoder/scripts/domain/kg/extract/java/satoken_extractor.py +30 -0
- package/templates/qoder/scripts/domain/kg/extract/java/spring_extractor.py +39 -0
- package/templates/qoder/scripts/domain/kg/extract/java/validation_extractor.py +33 -0
- package/templates/qoder/scripts/domain/kg/extract/mybatis/__init__.py +9 -0
- package/templates/qoder/scripts/domain/kg/extract/mybatis/all.py +79 -0
- package/templates/qoder/scripts/domain/kg/extract/mybatis/mapper_parser.py +99 -0
- package/templates/qoder/scripts/domain/kg/extract/mybatis/relation_builder.py +69 -0
- package/templates/qoder/scripts/domain/kg/extract/mybatis/sql_extractor.py +78 -0
- package/templates/qoder/scripts/domain/kg/extract/prd/__init__.py +8 -0
- package/templates/qoder/scripts/domain/kg/extract/prd/prd_chunk_embed.py +105 -0
- package/templates/qoder/scripts/domain/kg/extract/prd/prd_llm_extract.py +153 -0
- package/templates/qoder/scripts/domain/kg/extract/prd/req_anchor.py +120 -0
- package/templates/qoder/scripts/domain/kg/extract/ts_extract.py +111 -0
- package/templates/qoder/scripts/domain/kg/graph/kg_semantic.py +4 -2
- package/templates/qoder/scripts/domain/kg/kg.py +42 -5
- package/templates/qoder/scripts/domain/kg/search/_remote.py +187 -0
- package/templates/qoder/scripts/domain/kg/search/context_pack.py +32 -2
- package/templates/qoder/scripts/domain/kg/search/search_index.py +74 -20
- package/templates/qoder/scripts/domain/kg/storage/kg_duckdb.py +43 -0
- package/templates/qoder/scripts/domain/kg/switch_project.py +159 -0
- package/templates/qoder/scripts/domain/kg/sync_repowiki.py +109 -0
- package/templates/qoder/scripts/domain/requirement/req.py +134 -28
- package/templates/qoder/scripts/domain/task/__pycache__/wlkj_panel.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/domain/task/wlkj_panel.py +1348 -0
- package/templates/qoder/scripts/engine/poller.py +219 -0
- package/templates/qoder/scripts/foundation/__pycache__/__init__.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/foundation/core/__pycache__/__init__.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/foundation/core/__pycache__/paths.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/foundation/core/paths.py +102 -0
- package/templates/qoder/scripts/foundation/integrations/active_task.py +2 -1
- package/templates/qoder/scripts/orchestration/wlkj.py +4 -0
- package/templates/qoder/scripts/protocol/__pycache__/__init__.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/protocol/mcp/zentao_mcp_server.py +24 -11
- package/templates/qoder/scripts/protocol/transports/__pycache__/__init__.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/protocol/transports/__pycache__/base.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/protocol/transports/__pycache__/cli.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/protocol/transports/__pycache__/http.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/protocol/transports/__pycache__/stdio.cpython-39.pyc +0 -0
- package/templates/qoder/scripts/protocol/transports/http.py +7 -1
- package/templates/qoder/scripts/validation/eval/qwork_harness.py +1 -1
- package/templates/qoder/scripts/validation/eval/report-commands.md +2 -2
- package/templates/qoder/settings.json +27 -9
- package/templates/qoder/skills/design-import/SKILL.md +3 -3
- package/templates/qoder/skills/design-review/SKILL.md +1 -1
- package/templates/qoder/skills/prd-generator/SKILL.md +4 -4
- package/templates/qoder/skills/prd-review/SKILL.md +1 -1
- package/templates/qoder/skills/prototype-generator/SKILL.md +3 -3
- package/templates/qoder/skills/spec-coder/SKILL.md +1 -1
- package/templates/qoder/skills/spec-generator/SKILL.md +80 -23
- package/templates/qoder/skills/test-generator/SKILL.md +1 -1
- package/templates/qoder/skills/wl-code/SKILL.md +13 -1
- package/templates/qoder/skills/wl-commit/SKILL.md +1 -1
- package/templates/qoder/skills/wl-design/SKILL.md +6 -6
- package/templates/qoder/skills/wl-init/SKILL.md +2 -2
- package/templates/qoder/skills/wl-insight/SKILL.md +5 -5
- package/templates/qoder/skills/wl-prd/SKILL.md +60 -0
- package/templates/qoder/skills/wl-report/SKILL.md +2 -2
- package/templates/qoder/skills/wl-search/SKILL.md +1 -1
- package/templates/qoder/skills/wl-spec/SKILL.md +2 -2
- package/templates/qoder/skills/wl-status/SKILL.md +2 -2
- package/templates/qoder/skills/wl-task/SKILL.md +3 -3
- package/templates/qoder/skills/wl-test/SKILL.md +2 -2
- package/templates/qoder/templates/spec-template.md +124 -0
- package/templates/root/AGENTS.md +41 -14
- package/templates/qoder/scripts/domain/task/zentao_panel.py +0 -451
- package/templates/qoder/skills/wl-prd-full/SKILL.md +0 -121
- package/templates/qoder/skills/wl-prd-quick/SKILL.md +0 -50
- package/templates/qoder/skills/wl-prd-review/SKILL.md +0 -47
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# 模块契约:prd(需求)
|
|
2
|
+
|
|
3
|
+
> 产品模块。从「一句话」到「可发布的 PRD + 原型」。
|
|
4
|
+
> 这是**最上游的契约源**,下游 design/spec/task/test 都靠它。
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Input(吃什么)
|
|
9
|
+
|
|
10
|
+
| 优先级 | 输入 | 怎么用 |
|
|
11
|
+
|--------|------|--------|
|
|
12
|
+
| **完整** | 业务需求描述 + 平台 | `context_pack.py <词> --platform <web\|app>` 取上下文 |
|
|
13
|
+
| 降级 1 | 只有业务描述,没指定平台 | **必须先问平台**(见铁律),不许跳过 |
|
|
14
|
+
| 降级 2 ★ | 用户一句话口语需求 | 跑 context_pack + search_index --prd 自补上下文 |
|
|
15
|
+
| 参考 | 现有页面 / 字段 / API | 来自 context_pack 的 7 段输出,不强依赖 |
|
|
16
|
+
|
|
17
|
+
**平台是硬约束**:Web=fywl-ui / APP=Carmg-H5 / both。没定平台不许开干。
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Output(吐什么)
|
|
22
|
+
|
|
23
|
+
### 主产物:PRD 草稿
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
路径:workspace/members/{developer}/drafts/REQ-{YYYY}-{NNN}-{标题}.md
|
|
27
|
+
命名:REQ-ID 由 common/reqid.py 的 allocate_req_id() 原子分配
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**第一行必须是契约头**(软契约,缺了只警告):
|
|
31
|
+
|
|
32
|
+
```markdown
|
|
33
|
+
<!-- @contract prd v1
|
|
34
|
+
platform: web|app|both
|
|
35
|
+
req-id: REQ-2025-0042
|
|
36
|
+
title: 保单批改功能
|
|
37
|
+
mode: full|quick|reference|brainstorm|planning
|
|
38
|
+
# brainstorm/planning 已随探索能力迁至 /wl-insight,PRD 不再主动产出这两个模式。
|
|
39
|
+
# 保留枚举是为了向后兼容旧 PRD(eval_prd 仍能识别)。新 PRD 只用 quick/reference。
|
|
40
|
+
acceptance: [验收点1, 验收点2]
|
|
41
|
+
source: context_pack:保单批改,web
|
|
42
|
+
-->
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 副产物:原型
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
单端:workspace/members/{developer}/drafts/prototype-{feature}.html
|
|
49
|
+
两端:...prototype-{feature}-web.html + ...prototype-{feature}-app.html
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 归档(自动)
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
归档副本:workspace/members/{dev}/archive/{YYYY-MM-DD}/REQ-*.md(只复制不移动)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 发布
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
发布后:git_sync.py 的 collect_prds() 把草稿拷到 data/docs/prd/REQ-*.md(立刻可搜)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 必含字段骨架
|
|
67
|
+
|
|
68
|
+
### full 模式(完整需求)— 13 章
|
|
69
|
+
|
|
70
|
+
版本信息 / 变更日志 / 名词解释 / 需求背景 / 需求来源 / 产品现状 /
|
|
71
|
+
需求范围 / 功能清单 / 字段规格 / 操作与校验 / 非功能性需求 / 埋点 / 版本计划
|
|
72
|
+
|
|
73
|
+
> **"版本计划"章节边界**:只写**本期排期**(本需求何时上线)。
|
|
74
|
+
> 长期 roadmap / 多版本路线图已归 `/wl-insight plan`,不在 PRD 内展开。
|
|
75
|
+
> PRD 聚焦"本次做什么",不背"未来规划"的职责。
|
|
76
|
+
|
|
77
|
+
### quick 模式(零星需求)— 6 章
|
|
78
|
+
|
|
79
|
+
功能入口 / 需求背景 / 需求说明 / 影响范围 / 验收标准 / 不在本次范围
|
|
80
|
+
|
|
81
|
+
> quick 模式整体跳过 EVA 门禁(用于快速出稿,不背完整质量责任)。
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## 校验(唯一硬门禁)
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
python .qoder/scripts/orchestration/wlkj.py eval <prd.md> [原型.html]
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
| 维度 | 权重 | 检查内容 |
|
|
92
|
+
|------|------|----------|
|
|
93
|
+
| A1 现实锚定 | 40 分 | PRD 表格内 camelCase 字段、API 路径在索引命中比例 |
|
|
94
|
+
| A2 风格保真 | 30 分 | 原型颜色来自真源(无原型则跳过,满分降为 70) |
|
|
95
|
+
| A3 模板完整 | 30 分 | 章节齐全比例 |
|
|
96
|
+
|
|
97
|
+
**阈值:≥ 80% 才 PASS**(`PASS_THRESHOLD = 80.0`)。结果追加到 `data/learning/eval-history.jsonl`。
|
|
98
|
+
|
|
99
|
+
> full 模式无原型时满分 70,实际过线需 `A1+A3 ≥ 56`。
|
|
100
|
+
> **这是整个工作流唯一的硬门禁**——因为 prd 是契约源头,源头不靠谱全链路歪。
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 与下游的接口
|
|
105
|
+
|
|
106
|
+
| 下游模块 | 消费 prd 的什么 |
|
|
107
|
+
|----------|----------------|
|
|
108
|
+
| design | 验收标准里的界面相关点 + 平台 |
|
|
109
|
+
| task | 功能清单 → 拆任务 |
|
|
110
|
+
| spec | 全文,尤其是字段规格 + 操作校验 |
|
|
111
|
+
| test | `acceptance` 列表 → 测试用例 |
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## 现状提醒
|
|
116
|
+
|
|
117
|
+
- ✅ eval_prd.py 已存在,校验可跑。
|
|
118
|
+
- ⚠️ quick 模式跳过 EVA,可能产出质量较低的契约。下游拿到 quick PRD 时应留意。
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "qoder://contract/design-spec",
|
|
4
|
+
"title": "Design Spec 契约 (设计师规格)",
|
|
5
|
+
"description": "设计师从 Figma/Axure 录入的规格。优先级 > 代码风格 > PDF 规范。最适合 schema 化的契约 (纯 JSON 产物)。",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["_contract", "design_tokens", "layout", "components"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"_contract": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"required": ["type", "version", "platform", "requirement"],
|
|
12
|
+
"properties": {
|
|
13
|
+
"type": { "const": "design-spec" },
|
|
14
|
+
"version": { "type": "integer", "minimum": 1 },
|
|
15
|
+
"platform": { "type": "string", "enum": ["web", "app", "both"] },
|
|
16
|
+
"requirement": { "type": "string", "description": "关联的需求名/REQ-ID" },
|
|
17
|
+
"source": { "type": "string", "description": "figma:截图 / lanhu:链接" }
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"design_tokens": {
|
|
21
|
+
"type": "object",
|
|
22
|
+
"description": "配色/尺寸/字体/圆角等设计令牌",
|
|
23
|
+
"properties": {
|
|
24
|
+
"colors": { "type": "object" },
|
|
25
|
+
"spacing": { "type": "object" },
|
|
26
|
+
"fonts": { "type": "object" },
|
|
27
|
+
"radius": { "type": "object" }
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"layout": {
|
|
31
|
+
"type": "object",
|
|
32
|
+
"description": "页面布局结构 (栅格/区块/导航)"
|
|
33
|
+
},
|
|
34
|
+
"components": {
|
|
35
|
+
"type": "array",
|
|
36
|
+
"description": "组件清单 (类型/props/状态)",
|
|
37
|
+
"items": { "type": "object" }
|
|
38
|
+
},
|
|
39
|
+
"icons": {
|
|
40
|
+
"type": "array",
|
|
41
|
+
"description": "图标清单 (禁止 emoji, web=AntDesign SVG / app=Vant)",
|
|
42
|
+
"items": { "type": "string" }
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"additionalProperties": true
|
|
46
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "qoder://contract/prd",
|
|
4
|
+
"title": "PRD 契约 (产品需求文档)",
|
|
5
|
+
"description": "PRD 是最上游的契约源。下游 design/spec/task/test 都靠它。机器可校验版。",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["type", "version", "req-id", "platform", "title", "acceptance"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"type": { "const": "prd", "description": "契约类型标识" },
|
|
10
|
+
"version": { "type": "integer", "minimum": 1, "description": "契约版本, 未来演进用 (当前 v1)" },
|
|
11
|
+
"req-id": {
|
|
12
|
+
"type": "string",
|
|
13
|
+
"pattern": "^REQ-\\d{4}-\\d{3,}$",
|
|
14
|
+
"description": "需求编号, 贯穿全链路唯一 key, 由 reqid.py 原子分配"
|
|
15
|
+
},
|
|
16
|
+
"platform": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"enum": ["web", "app", "both"],
|
|
19
|
+
"description": "目标平台: web=fywl-ui / app=Carmg-H5 / both=两端"
|
|
20
|
+
},
|
|
21
|
+
"title": { "type": "string", "minLength": 2, "description": "需求标题" },
|
|
22
|
+
"acceptance": {
|
|
23
|
+
"type": "array",
|
|
24
|
+
"items": { "type": "string" },
|
|
25
|
+
"minItems": 1,
|
|
26
|
+
"description": "验收标准列表, 下游 test 据此生成用例"
|
|
27
|
+
},
|
|
28
|
+
"mode": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"enum": ["quick", "reference", "brainstorm", "planning"],
|
|
31
|
+
"description": "生成模式 (quick 零星需求, reference 完整档)"
|
|
32
|
+
},
|
|
33
|
+
"source": { "type": "string", "description": "来源: context_pack:词,平台 / manual" }
|
|
34
|
+
},
|
|
35
|
+
"additionalProperties": true
|
|
36
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "qoder://contract/test-cases",
|
|
4
|
+
"title": "Test Cases 契约 (测试用例集)",
|
|
5
|
+
"description": "从 PRD acceptance 或手动生成的测试用例。autotest 强依赖其结构。",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["_contract", "cases"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"_contract": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"required": ["type", "version"],
|
|
12
|
+
"properties": {
|
|
13
|
+
"type": { "const": "test-cases" },
|
|
14
|
+
"version": { "type": "integer", "minimum": 1 },
|
|
15
|
+
"platform": { "type": "string", "enum": ["web", "app", "both"] },
|
|
16
|
+
"req-id": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"pattern": "^REQ-\\d{4}-\\d{3,}$",
|
|
19
|
+
"description": "关联需求 (可空, 测试用例可能跨需求)"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"cases": {
|
|
24
|
+
"type": "array",
|
|
25
|
+
"minItems": 1,
|
|
26
|
+
"items": {
|
|
27
|
+
"type": "object",
|
|
28
|
+
"required": ["name", "intent"],
|
|
29
|
+
"properties": {
|
|
30
|
+
"name": { "type": "string", "description": "用例名" },
|
|
31
|
+
"intent": { "type": "string", "description": "测试意图/验收点" },
|
|
32
|
+
"anchor": { "type": "string", "description": "页面锚点 (定位用)" },
|
|
33
|
+
"steps": { "type": "array", "items": { "type": "string" } },
|
|
34
|
+
"expected": { "type": "string" }
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"additionalProperties": true
|
|
40
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# 模块契约:spec(技术规格)
|
|
2
|
+
|
|
3
|
+
> 规格模块。把 PRD 翻译成开发能照着写的**技术契约**。
|
|
4
|
+
> 是 code 模块的最佳输入。
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Input(吃什么)
|
|
9
|
+
|
|
10
|
+
| 优先级 | 输入 | 怎么用 |
|
|
11
|
+
|--------|------|--------|
|
|
12
|
+
| **禅道(推荐)** | 禅道 task 关联的 story(`get_task → get_story_detail` 读 `spec` 字段) | task 来的需求经此读 PRD,**解决"别人提的 PRD 本地没有"**。1 task ↔ 1 spec |
|
|
13
|
+
| 完整 | 本地已确认 PRD(`data/docs/prd/REQ-*.md`) | 字段规格 + 操作校验 → 接口/数据结构(禅道不可达时兜底) |
|
|
14
|
+
| 降级 | PRD 草稿(REQ-ID 容器里) | 也能写 spec,标 `source: draft` |
|
|
15
|
+
| 参考 | 历史 Spec | 同容器或历史 REQ-ID 容器看同类写法 |
|
|
16
|
+
| 参考 | 字段命名 | `search_index.py --field <字段名>` |
|
|
17
|
+
| 参考 | 数据字典 | `.qoder/context/data-dictionary.md`(不存在则跳过) |
|
|
18
|
+
|
|
19
|
+
**团队技术约定(写进 spec 的默认约束)**:
|
|
20
|
+
- 后端 Java:MyBatis Plus + RESTful + `BigDecimal` 金额 + JSR-303 校验 + `Result<T>`
|
|
21
|
+
- 表名 `t_{module}_{entity}`,全栈 Entity→Mapper→Service→Controller
|
|
22
|
+
- 不写 PRD 未定义的功能
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Output(吐什么)
|
|
27
|
+
|
|
28
|
+
### 主产物:Spec 文件
|
|
29
|
+
|
|
30
|
+
**路径(按来源)**:
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
① 禅道 task 来的(1 task ↔ 1 spec):workspace/tasks/{task_id}/spec.md
|
|
34
|
+
└ task_id 即禅道 task id;复用现有 task 目录约定
|
|
35
|
+
② 本地 PRD 来的:跟着 PRD 同容器(项目理念:一个需求的所有产出聚合在 REQ-ID 容器)
|
|
36
|
+
workspace/members/{dev}/{drafts|outputs}/{YYYY}/{MM}/{Ww}/{REQ-ID}/REQ-{ID}-{module}.spec.md
|
|
37
|
+
└ 复用 paths.get_req_dir() / find_req_dirs(),跨时间桶可查,不另开 specs 桶
|
|
38
|
+
③ 兜底(老 PRD 不在时间桶):workspace/specs/REQ-{ID}-{module}.spec.md
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**生成方式**:spec-generator **读 `templates/spec-template.md` 固定 6 章骨架逐节填空**(不自由发挥结构)。
|
|
42
|
+
|
|
43
|
+
**契约头**(含 `status` 状态字段 + 禅道关联 `zentao`):
|
|
44
|
+
|
|
45
|
+
```markdown
|
|
46
|
+
<!-- @contract spec v1
|
|
47
|
+
source-req: REQ-2025-0042
|
|
48
|
+
platform: web
|
|
49
|
+
module: policy
|
|
50
|
+
endpoints: [POST /api/policy/amend, GET /api/policy/amend/{id}]
|
|
51
|
+
status: draft
|
|
52
|
+
zentao: task=1453 story=761
|
|
53
|
+
zentao_id: 761
|
|
54
|
+
platform_spec_id:
|
|
55
|
+
-->
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**字段说明**:
|
|
59
|
+
- `status`:状态机见下表,/wl-code spec gate 的判据。
|
|
60
|
+
- `zentao`:禅道 task 来的必须填(task+story);本地来的留空,待回填时补。回填 task 后 spec 摘要写入该 task 的 `desc`。
|
|
61
|
+
- `zentao_id`:禅道 story 号(关联键,= zentao 的 story)。spec_upload 据此让平台反查 Requirement 挂载;缺失则上传暂存待产品推禅道后回填。
|
|
62
|
+
- `platform_spec_id`:平台 spec id(幂等锚)。spec_upload 首次 create 后自动回写,**勿手填**;有值则下次上传走 update_spec(新增版本不重复建)。
|
|
63
|
+
|
|
64
|
+
**`status` 状态机**(/wl-code spec gate 的判据):
|
|
65
|
+
|
|
66
|
+
| status | 含义 | 谁能改 |
|
|
67
|
+
|--------|------|--------|
|
|
68
|
+
| `draft` | 刚生成,待用户确认 | spec-generator 生成时写入 |
|
|
69
|
+
| `confirmed` | 用户已确认,可写码 | 仅 `/wl-code` 在用户明确确认后升级 |
|
|
70
|
+
|
|
71
|
+
### 骨架(固定模板,见 `templates/spec-template.md`)
|
|
72
|
+
|
|
73
|
+
6 章,必须照模板逐节填,结构每次一致、可复现:
|
|
74
|
+
|
|
75
|
+
0. 概述(来源/一句话/涉及端/AC条数/改动范围)
|
|
76
|
+
1. 接口定义(路径/方法/入参/出参/错误码,RESTful + JSR-303 + Result<T>)
|
|
77
|
+
2. 数据结构(表 `t_{module}_{entity}` / 字段 / 类型 / 约束,金额 BigDecimal)
|
|
78
|
+
3. **异常处理矩阵 ★强制**(每操作 × 全部失败场景 × 错误码 × HTTP × 处理策略)
|
|
79
|
+
4. **AI 能力边界 ★强制**(✅可自动 / ⚠️必须人工确认 / 🚫禁止AI做)
|
|
80
|
+
5. **测试用例 ★强制**(每条 PRD 验收标准 → 输入/预期/断言,详细可复现)
|
|
81
|
+
6. PRD 验收标准映射表(每条 acceptance → 接口/数据/异常/用例,可追溯不漏)
|
|
82
|
+
|
|
83
|
+
★强制章节不适用写"无"并附原因。
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 校验
|
|
88
|
+
|
|
89
|
+
- ❌ **无独立校验脚本**(待建 `eval_spec.py`)。本期靠固定模板 + 强制章节保证一致性。
|
|
90
|
+
- **spec gate(/wl-code 内,非侵入式)**:`/wl-code` Step 1 读 `status` 字段——
|
|
91
|
+
无 spec 或 `status≠confirmed` → 生成/展示 → 等用户确认 → 升级 `confirmed` → 才写码。
|
|
92
|
+
不调 `/wl-code` 时完全无感。
|
|
93
|
+
- 软契约:缺 `source-req` 只警告。
|
|
94
|
+
- review 模式(带 `review` 参数)只给改进建议,不重生成。
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## 与上下游的接口
|
|
99
|
+
|
|
100
|
+
| 方向 | 接口 |
|
|
101
|
+
|------|------|
|
|
102
|
+
| 上游 prd | 读 PRD 验收标准 + 字段规格 |
|
|
103
|
+
| 下游 code | spec 是 code 的最佳输入 |
|
|
104
|
+
| 下游 test | spec 的测试用例映射 → 单元测试 |
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## ⚠️ 现状提醒(KNOWN GAP)
|
|
109
|
+
|
|
110
|
+
- ✅ **固定模板已补**:`templates/spec-template.md`(6 章 + 异常矩阵/AI边界/测试用例 3 强制章节 + `status` 字段)。
|
|
111
|
+
- ✅ **spec gate 已落地**:`/wl-code` Step 1 读 `status`,非侵入式。
|
|
112
|
+
- ✅ **禅道对接已落地**:PRD 源优先读禅道 task→story(`get_task`/`get_story_detail`);1 task ↔ 1 spec;confirmed 后回填 task `desc`(`update_task` 加了 desc 参数)。
|
|
113
|
+
- ✅ **命名已统一**:`REQ-{ID}-{module}.spec.md`(spec-generator 与 wl-spec 一致,便于贯穿检索)。
|
|
114
|
+
- ✅ **存储对齐时间桶**:本地来源的 spec 跟 PRD 同 REQ-ID 容器,复用 `paths.get_req_dir / find_req_dirs`;禅道来源的放 `workspace/tasks/{task_id}/spec.md`。
|
|
115
|
+
- ⬜ 待修正 `wl-spec/SKILL.md` 的输出路径声明(仍写老平铺路径)。
|
|
116
|
+
- ⬜ 待建 `eval_spec.py` 独立校验脚本(本期靠固定模板保证一致性)。
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# 模块契约:task(任务)
|
|
2
|
+
|
|
3
|
+
> 任务模块。把 PRD 拆成可执行任务 + RICE 排优先级。
|
|
4
|
+
> task.json 是本模块的**唯一事实源**。
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Input(吃什么)
|
|
9
|
+
|
|
10
|
+
| 优先级 | 输入 | 怎么用 |
|
|
11
|
+
|--------|------|--------|
|
|
12
|
+
| **完整** | 一份 PRD(`REQ-*.md`) | 功能清单 → 拆任务 |
|
|
13
|
+
| 降级 1 | PRD 草稿(drafts 里的) | 也能拆,只是还没发布 |
|
|
14
|
+
| 降级 2 | 一句话任务描述 | 直接 `task.py create "XXX"` |
|
|
15
|
+
| 参考 | 已有任务 | `task.py list` 看排期,避免重复 |
|
|
16
|
+
|
|
17
|
+
不强依赖 prd 模块执行——可以直接手动建任务。
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Output(吐什么)
|
|
22
|
+
|
|
23
|
+
### 任务目录
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
路径:workspace/tasks/{MM-DD-slug}/
|
|
27
|
+
内含:
|
|
28
|
+
task.json ← 任务元数据 + 状态 + RICE
|
|
29
|
+
prd.md ← 任务级需求(可空)
|
|
30
|
+
implement.jsonl ← 实现记录
|
|
31
|
+
check.jsonl ← 检查记录
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### task.json 骨架(对齐 task.py 真实输出)
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"title": "...",
|
|
39
|
+
"slug": "baodan-piGai",
|
|
40
|
+
"status": "planning", // planning → in_progress → completed(归档时再补 archived_at)
|
|
41
|
+
"priority": "P0|P1|P2|P3",
|
|
42
|
+
"assignee": "{developer}", // ← 注意是 assignee 不是 owner
|
|
43
|
+
"creator": "{developer}",
|
|
44
|
+
"created_at": "...", "updated_at": "...",
|
|
45
|
+
"branch": null, "base_branch": null,
|
|
46
|
+
"scope": null,
|
|
47
|
+
"parent": null, "children": [], // 父子任务
|
|
48
|
+
"tags": ["REQ-2026-0042"], // ← PRD 的 REQ-ID 记这里(双向追溯)
|
|
49
|
+
"rice": 24, // ← RICE 排序时 AI 算好后写入(数值,不是对象)
|
|
50
|
+
// 能力增强字段(可选,旧 task.json 不含时取默认值)
|
|
51
|
+
"due_date": "2026-07-01", // YYYY-MM-DD(set-due 写)
|
|
52
|
+
"start_date": null,
|
|
53
|
+
"estimate_hours": null,
|
|
54
|
+
"blocked_by": [], // 被哪些任务阻塞(block 写,自动维护反向 blocks)
|
|
55
|
+
"blocks": [], // 被哪些任务依赖(自动维护)
|
|
56
|
+
"stage_ts": { "created": "...", "started": null, "completed": null },
|
|
57
|
+
"zentao_id": null // 对应禅道任务 ID(zentao_sync 写)。幂等主键: 已有则跳过 create。
|
|
58
|
+
// 隔离契约见 contracts/isolation.md「禅道同步」。
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
> ⚠️ 字段名以 **task.py 实际输出**为准(`assignee`/`planning`/`completed`/`rice` 为数值)。
|
|
63
|
+
> 上面是权威骨架,与 task.py 的 `cmd_create` 逐字段对齐。
|
|
64
|
+
|
|
65
|
+
### 状态流转
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
create(planning) → start → in_progress → finish → completed → archive
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**关键动作都会自动 stage workspace/tasks/ 到 team_sync**(push 后团队可见)。
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## 操作命令
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# 基础生命周期
|
|
79
|
+
python .qoder/scripts/orchestration/wlkj.py task create "XXX" [--slug ...] [--assignee ...] [--priority P0|P1|P2|P3]
|
|
80
|
+
python .qoder/scripts/orchestration/wlkj.py task list [--mine] [--status in_progress] [--ready] [--blocked]
|
|
81
|
+
python .qoder/scripts/orchestration/wlkj.py task show <task-dir>
|
|
82
|
+
python .qoder/scripts/orchestration/wlkj.py task start <task-dir> # planning → in_progress,设为活跃任务
|
|
83
|
+
python .qoder/scripts/orchestration/wlkj.py task current [--source] # 看当前活跃任务
|
|
84
|
+
python .qoder/scripts/orchestration/wlkj.py task finish # 活跃任务 → completed,清活跃指针
|
|
85
|
+
python .qoder/scripts/orchestration/wlkj.py task archive <task-dir> # 移到 .qoder/archive/{YYYY-MM}/,自动清孤儿依赖
|
|
86
|
+
|
|
87
|
+
# 子任务
|
|
88
|
+
python .qoder/scripts/orchestration/wlkj.py task add-subtask <parent> <child>
|
|
89
|
+
python .qoder/scripts/orchestration/wlkj.py task remove-subtask <parent> <child>
|
|
90
|
+
|
|
91
|
+
# 排期与依赖(B2 能力)
|
|
92
|
+
python .qoder/scripts/orchestration/wlkj.py task set-due <task> <YYYY-MM-DD>
|
|
93
|
+
python .qoder/scripts/orchestration/wlkj.py task block <task> <blocker> # 循环依赖自动检测,反向 blocks 自动维护
|
|
94
|
+
python .qoder/scripts/orchestration/wlkj.py task unblock <task> <blocker>
|
|
95
|
+
python .qoder/scripts/orchestration/wlkj.py task gantt [--weeks 4] # 只排有日期的任务,自动标逾期
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**退出码**:`0`=成功 / `1`=任务不存在/JSON 缺失/循环依赖 / `4`=权限不足(零信任 ACL,仅 creator/assignee/admin 可改)。
|
|
99
|
+
|
|
100
|
+
**RICE** = Reach × Impact × Confidence ÷ Effort(AI 层评估,算好后写入 task.json 的 `rice` 数值字段)
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 校验
|
|
105
|
+
|
|
106
|
+
- ❌ **无独立校验脚本**。当前靠 task.py 自身的状态机约束。
|
|
107
|
+
- 软契约:task.json 缺 `_contract` / `acceptance` 只警告不拦。
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## 与上下游的接口
|
|
112
|
+
|
|
113
|
+
| 方向 | 接口 |
|
|
114
|
+
|------|------|
|
|
115
|
+
| 上游 prd | 读 PRD 的功能清单 → 拆任务 |
|
|
116
|
+
| 下游 spec/code | 任务目录可放 `spec.md`(spec 模块写到任务目录时) |
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 现状提醒
|
|
121
|
+
|
|
122
|
+
- ✅ task.py 功能完整:CRUD + 依赖图(block/unblock + 循环检测)+ 排期(set-due/gantt)+ 子任务 + 零信任 ACL + 归档孤儿依赖清理。
|
|
123
|
+
- ✅ PRD→task 衔接:create 时把 REQ-ID 记进 `tags`,PRD 验收点贴进 task 的 `prd.md`(命令层引导)。
|
|
124
|
+
- ✅ RICE 排序在 AI 层(task.py 只存数值,不替 AI 算分)。
|
|
125
|
+
- 🧩 QoderWork 增强(可选):待办双向同步。无连接器则回退,task.json 仍为准。
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# 模块契约:test(测试)
|
|
2
|
+
|
|
3
|
+
> 测试模块。三条线:quick(默认)/ browser / unit。
|
|
4
|
+
> 测试用例锚定到 PRD 的验收标准编号。
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Input(吃什么)
|
|
9
|
+
|
|
10
|
+
三条线,输入不同:
|
|
11
|
+
|
|
12
|
+
| 线 | 输入 | 怎么用 |
|
|
13
|
+
|----|------|--------|
|
|
14
|
+
| **quick**(默认) | 零输入,用户直接给用例 | `autotest.py quick --cases '<JSON>' --desc "..." --platform <web\|app>` |
|
|
15
|
+
| **browser** | 任务名 | 读任务 PRD 的验收标准,**不搜源码**;`autotest.py generate <task>` / `run <task>` |
|
|
16
|
+
| **unit** | 代码关键词 | 搜代码读源码,test-generator skill + `search_index.py` |
|
|
17
|
+
| **assertion-gen** | PRD 验收章节 / GWT 文本 | `autotest.py assertion-gen --task <任务> --page <业务词>`(详见下方) |
|
|
18
|
+
|
|
19
|
+
### 降级链路
|
|
20
|
+
|
|
21
|
+
| 优先级 | 输入 |
|
|
22
|
+
|--------|------|
|
|
23
|
+
| **完整** | spec 文件(接口清晰) |
|
|
24
|
+
| 降级 1 | PRD(读 `acceptance` 列表) |
|
|
25
|
+
| 降级 2 | 任务 PRD(browser 线) |
|
|
26
|
+
| 降级 3 ★ | 一句话 + 全索引(搜相关页面/字段,凑出验收点) |
|
|
27
|
+
|
|
28
|
+
**环境**:域名/环境来自 `.qoder/config.yaml` 的 `autotest:` 段;`--url` 可临时覆盖。
|
|
29
|
+
**测试数据**:个人数据在 `workspace/members/{名字}/autotest-data.yaml`(gitignored);
|
|
30
|
+
真实数据用 `{{ask:描述}}` 占位,**绝不编造**。
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Output(吐什么)
|
|
35
|
+
|
|
36
|
+
### quick / browser
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
用例 JSON + 执行计划
|
|
40
|
+
回传:autotest.py ... --record '{"Q-1":"pass"}'
|
|
41
|
+
browser 骨架写到任务的 autotest-cases.jsonl
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### unit
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
路径:tests/{package-path}/{ClassName}Test.java
|
|
48
|
+
风格:Given-When-Then,@DisplayName 中文,AssertJ,全 Mock
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### assertion-gen(业务规则断言)
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
输出:workspace/tasks/<task>/assertions.json
|
|
55
|
+
结构:{ _contract:{type:assertions}, assertions:[{intent:"assert", expect:{...}, source, desc}] }
|
|
56
|
+
每条断言带 source 置信度标记:
|
|
57
|
+
- 规则·句中含接口 / 图谱·按钮画像 / 图谱·字段表命中 = 可信
|
|
58
|
+
- 需确认·字段未命中 / 需确认·接口未指明 = 待补 {{ask:}} 占位
|
|
59
|
+
expect 字段对齐 autotest_webaccess.py _check_expect 契约:
|
|
60
|
+
fetch 断言:{fetch, jsonpath, equals} 必填 + {method?, body?} 可选 (默认 POST/{})
|
|
61
|
+
dom 断言: {dom, jsonpath, equals} 三字段齐全
|
|
62
|
+
注: assertion_gen 只产必填 3 字段, method/body 走 _check_expect 默认值。
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**红线:断言不编造。** PRD 无结构化验收(空/纯描述)→ 输出"无可抽取的结构化断言"并退出码 2,
|
|
66
|
+
**绝不**让 LLM 瞜编 `expect.equals`。图谱/字段表只补字段不编语义。
|
|
67
|
+
|
|
68
|
+
### 用例契约头(JSON)
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"_contract": { "type": "test-cases", "version": 1, "source": "REQ-2025-0042" },
|
|
73
|
+
"cases": [
|
|
74
|
+
{ "id": "Q-1", "anchor": "REQ-2025-0042#验收点1", "step": "...", "expect": "..." }
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**每个用例的 `anchor` 字段锚定到 PRD 验收标准编号**——这是测试可追溯的关键。
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## 校验
|
|
84
|
+
|
|
85
|
+
- ❌ **无独立校验脚本**。靠自检清单:
|
|
86
|
+
- [ ] 正常路径 + 错误路径 100% 覆盖
|
|
87
|
+
- [ ] 核心边界覆盖
|
|
88
|
+
- [ ] 无外部依赖(全 Mock)
|
|
89
|
+
- [ ] 测试方法间无依赖
|
|
90
|
+
- [ ] 每个用例有 anchor 指向验收标准
|
|
91
|
+
|
|
92
|
+
**铁律**:`autotest.py` 绝不 import playwright/selenium。
|
|
93
|
+
浏览器执行由 QoderWork 连接器承担,无连接器 → 降级为人工核对清单(不报错)。
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## 与上下游的接口
|
|
98
|
+
|
|
99
|
+
| 方向 | 接口 |
|
|
100
|
+
|------|------|
|
|
101
|
+
| 上游 prd | 读 acceptance 列表 |
|
|
102
|
+
| 上游 spec | 读接口定义 |
|
|
103
|
+
| 上游 code | unit 线读源码 |
|
|
104
|
+
| 下游 commit | 测试通过是 commit 门禁之一 |
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## 现状提醒
|
|
109
|
+
|
|
110
|
+
- ✅ 三线分工清晰。
|
|
111
|
+
- 🧩 QoderWork 增强(可选):browser 线的浏览器执行。无连接器 → 降级人工核对。
|
|
112
|
+
- ⚠️ 测试数据绝不能编造——这条是红线。
|