@hupan56/wlkj 3.1.31 → 3.2.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/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 +276 -276
- package/templates/qoder/commands/optional/wl-spec.md +10 -2
- package/templates/qoder/commands/wl-code.md +63 -4
- package/templates/qoder/commands/wl-design.md +1 -1
- package/templates/qoder/commands/wl-prd.md +87 -13
- package/templates/qoder/commands/wl-req.md +10 -3
- package/templates/qoder/commands/wl-task.md +613 -613
- package/templates/qoder/commands/wl-test.md +2 -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 +112 -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 +20 -0
- package/templates/qoder/hooks/stop-eval.py +47 -0
- package/templates/qoder/rules/wl-pipeline.md +37 -0
- package/templates/qoder/scripts/deployment/setup/install_qoderwork.py +11 -0
- package/templates/qoder/scripts/deployment/setup/setup.py +70 -0
- package/templates/qoder/scripts/deployment/setup/wlkj_shim.py +104 -0
- package/templates/qoder/scripts/domain/deployment/deploy_to_test.py +298 -0
- package/templates/qoder/scripts/domain/kg/build/kg_build.py +241 -22
- 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/ts_extract.py +111 -0
- package/templates/qoder/scripts/domain/kg/storage/kg_duckdb.py +43 -0
- package/templates/qoder/scripts/domain/requirement/req.py +134 -28
- package/templates/qoder/scripts/domain/task/zentao_panel.py +688 -53
- package/templates/qoder/scripts/foundation/core/paths.py +102 -0
- package/templates/qoder/scripts/protocol/mcp/zentao_mcp_server.py +23 -10
- 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 +32 -4
- 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,82 @@
|
|
|
1
|
+
# 模块契约:code(编码)
|
|
2
|
+
|
|
3
|
+
> 编码模块。按 spec 写源码,直接落到 `data/code/`。
|
|
4
|
+
> **DANGEROUS**:执行前必须用户确认。
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Input(吃什么)
|
|
9
|
+
|
|
10
|
+
| 优先级 | 输入 | 怎么用 |
|
|
11
|
+
|--------|------|--------|
|
|
12
|
+
| **完整** | 一份 `status: confirmed` 的 spec(PRD 同容器 `workspace/.../{REQ-ID}/REQ-{ID}-*.spec.md`) | 照接口/数据结构实现 |
|
|
13
|
+
| 完整 2 | 任务目录的 spec(`workspace/tasks/{task-id}/spec.md`) | 同上 |
|
|
14
|
+
| ⚠️ 仅 PRD(无 spec) | **不再降级硬写**——`/wl-code` 会先调 spec-generator 生成 draft → 用户确认升 confirmed 后才进编码 | 走 spec gate |
|
|
15
|
+
| 参考 | 现有代码风格 | `search_index.py <模块关键词>` 找 top 2-3 相似文件 |
|
|
16
|
+
| 参考 | 架构 / 数据字典 | `.qoder/context/architecture.md`、`data-dictionary.md`(不存在则跳过) |
|
|
17
|
+
|
|
18
|
+
**目标代码库**:`data/code/`
|
|
19
|
+
- fywl-ics(后端 Java)
|
|
20
|
+
- fywl-ui(前端 Vue)
|
|
21
|
+
- Carmg-H5(移动端)
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Output(吐什么)
|
|
26
|
+
|
|
27
|
+
**直接写入源码**,无中间产物文件。
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
data/code/{项目}/{模块}/... ← Java / Vue 源码
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 实现结构约定(后端)
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
Entity → Mapper → Service → Controller
|
|
37
|
+
接口:RESTful + JSR-303 校验 + Result<T>
|
|
38
|
+
金额:一律 BigDecimal
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### 契约头(写进源码注释)
|
|
42
|
+
|
|
43
|
+
实现的关键文件顶部应标注它对接的 spec:
|
|
44
|
+
|
|
45
|
+
```java
|
|
46
|
+
/**
|
|
47
|
+
* @contract code
|
|
48
|
+
* @source-spec REQ-2025-0042-policy.spec.md
|
|
49
|
+
* @source-req REQ-2025-0042
|
|
50
|
+
*/
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 校验
|
|
56
|
+
|
|
57
|
+
- ❌ **无独立校验脚本**。靠自检清单:
|
|
58
|
+
- [ ] Spec 所有接口已实现
|
|
59
|
+
- [ ] 数据库字段与 Spec 一致
|
|
60
|
+
- [ ] 命名跟周围代码一致(不发明新风格)
|
|
61
|
+
- [ ] 无 TODO/FIXME 残留
|
|
62
|
+
- [ ] 金额用 BigDecimal
|
|
63
|
+
- 软契约:缺 `@source-spec` 只警告。
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 与上下游的接口
|
|
68
|
+
|
|
69
|
+
| 方向 | 接口 |
|
|
70
|
+
|------|------|
|
|
71
|
+
| 上游 spec | 读接口/数据结构(必须 `status: confirmed`,否则被 `/wl-code` gate 拦下) |
|
|
72
|
+
| 上游 prd | 不直接吃;无 spec 时 `/wl-code` 先调 spec-generator 走确认环节 |
|
|
73
|
+
| 下游 test | 改动的接口 → test 模块生成用例 |
|
|
74
|
+
| 下游 commit | 改动文件 → commit 模块提交 |
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 现状提醒
|
|
79
|
+
|
|
80
|
+
- ✅ 实现约定清晰(Java 全栈 + RESTful)。
|
|
81
|
+
- ✅ spec gate 已落地:`/wl-code` Step 1 要求 `status: confirmed` 才放行(非侵入式,不调命令时无感)。
|
|
82
|
+
- ✅ 不再"降级吃 PRD"硬写——无 spec 时先走 spec 生成+确认环节。
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# 模块契约:commit(提交)
|
|
2
|
+
|
|
3
|
+
> 提交模块。把改动推到远端。
|
|
4
|
+
> **DANGEROUS**:推远端代码前必须用户确认提交信息。
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Input(吃什么)
|
|
9
|
+
|
|
10
|
+
| 来源 | 内容 |
|
|
11
|
+
|------|------|
|
|
12
|
+
| `.qoder/.developer` | 当前开发者身份 |
|
|
13
|
+
| `.qoder/.current-task` | 关联的任务 ID(若有) |
|
|
14
|
+
| `git status` / `git diff --stat` | 当前改动 |
|
|
15
|
+
| 用户确认 | 提交信息文案(必须用户点头) |
|
|
16
|
+
|
|
17
|
+
**两类改动走不同路**:
|
|
18
|
+
|
|
19
|
+
| 改动类型 | 走哪个 |
|
|
20
|
+
|----------|--------|
|
|
21
|
+
| **源码**(data/code/ 下的 Java/Vue) | 本模块 `/wl-commit` |
|
|
22
|
+
| **产出**(PRD / 任务 / 索引 / 原型 / spec) | `team_sync.py push`(不是 commit) |
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Output(吐什么)
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
git 提交(远端可见)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 提交信息格式
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
[ai-generated] <type>: <简述>
|
|
36
|
+
|
|
37
|
+
<body 可选>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`type` ∈ feat / fix / refactor / docs / test / chore
|
|
41
|
+
|
|
42
|
+
### 流程
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
git add <精确文件> ← 不用 git add .,精确到文件
|
|
46
|
+
git commit
|
|
47
|
+
git pull --rebase
|
|
48
|
+
git push
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
记录到 `data/learning/`(供 /wl-report、/wl-status 统计)。
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 校验(提交前质量门禁)
|
|
56
|
+
|
|
57
|
+
**无脚本,逐项 AI/人工自检**:
|
|
58
|
+
|
|
59
|
+
- [ ] 无 TODO/FIXME 残留
|
|
60
|
+
- [ ] 金额用 BigDecimal
|
|
61
|
+
- [ ] 命名风格一致
|
|
62
|
+
- [ ] Spec 接口/字段已覆盖
|
|
63
|
+
- [ ] 测试通过
|
|
64
|
+
- [ ] 提交信息用户已确认
|
|
65
|
+
|
|
66
|
+
**失败处理**:
|
|
67
|
+
- 门禁不过 → 默认修复后提交(不硬拦,但要提示)
|
|
68
|
+
- push 被拒 → `git pull --rebase` 后重试
|
|
69
|
+
- 冲突 → 列出文件问用户(不让用户碰 git 命令,但要让用户拍板冲突解法)
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## 与上下游的接口
|
|
74
|
+
|
|
75
|
+
| 方向 | 接口 |
|
|
76
|
+
|------|------|
|
|
77
|
+
| 上游 code | 改动的源码文件 |
|
|
78
|
+
| 上游 所有模块 | 产出文件(走 team_sync,不走本模块) |
|
|
79
|
+
| 下游 report | commit 记录 → 日报周报 |
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## 现状提醒
|
|
84
|
+
|
|
85
|
+
- ✅ 提交流程清晰,身份 + 任务关联齐全。
|
|
86
|
+
- ⚠️ 「门禁不过默认修复后提交」是软策略——质量责任在人,不在脚本。
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# 契约头规范(@contract)
|
|
2
|
+
|
|
3
|
+
> 每个契约文件**应该**在最顶部带一个 `@contract` 注释块,用于自描述。
|
|
4
|
+
> **软契约**:缺了只警告,不拦截。
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 格式
|
|
9
|
+
|
|
10
|
+
### Markdown 文件(PRD / spec / 任务说明等)
|
|
11
|
+
|
|
12
|
+
文件**第一行**放 HTML 注释(不渲染、不污染正文):
|
|
13
|
+
|
|
14
|
+
```markdown
|
|
15
|
+
<!-- @contract prd v1
|
|
16
|
+
platform: web
|
|
17
|
+
req-id: REQ-2025-0042
|
|
18
|
+
title: 保单批改功能
|
|
19
|
+
acceptance: [批改后实时生效, 批改需审批, 批改记录可查]
|
|
20
|
+
source: context_pack:保单批改,web
|
|
21
|
+
-->
|
|
22
|
+
|
|
23
|
+
# 保单批改功能 PRD
|
|
24
|
+
...正文...
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### JSON 文件(design-spec / test-cases 等)
|
|
28
|
+
|
|
29
|
+
顶层加一个 `_contract` 字段:
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"_contract": {
|
|
34
|
+
"type": "design-spec",
|
|
35
|
+
"version": 1,
|
|
36
|
+
"platform": "app",
|
|
37
|
+
"requirement": "保单批改",
|
|
38
|
+
"source": "figma:截图1+截图2"
|
|
39
|
+
},
|
|
40
|
+
"design_tokens": { ... }
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 字段说明
|
|
47
|
+
|
|
48
|
+
| 字段 | 类型 | 作用 | 必填? |
|
|
49
|
+
|------|------|------|--------|
|
|
50
|
+
| `type` / 第一行模块名 | string | 声明这是哪类契约:`prd`/`design`/`spec`/`task`/`test` | ✅ |
|
|
51
|
+
| `version` / `v1` | int | 契约版本,将来格式演进用 | ✅ |
|
|
52
|
+
| `platform` | `web`/`app`/`both` | 决定下游用哪套模板/风格真源 | ✅(prd/design 必填) |
|
|
53
|
+
| `req-id` | string | 需求编号,贯穿全链路的唯一 key | ✅(prd/spec/code 必填) |
|
|
54
|
+
| `title` | string | 人类可读标题 | 推荐 |
|
|
55
|
+
| `acceptance` | string[] | 验收标准列表 | ✅(prd 必填) |
|
|
56
|
+
| `source` | string | 这份文件怎么来的:`context_pack:词,平台` / `figma:截图` / `manual` | 推荐 |
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 软契约的判读规则
|
|
61
|
+
|
|
62
|
+
下游模块读到一份文件时:
|
|
63
|
+
|
|
64
|
+
1. **有 `@contract` 头** → 直接读取 `platform` / `req-id` / `acceptance`,不依赖外部记忆。
|
|
65
|
+
2. **没有 `@contract` 头** → 不报错,**降级**:从头文件名 / 正文推断(比如文件名 `REQ-2025-0042-xxx.md` 推出 req-id),并打印一条 `⚠️ <文件> 缺少 @contract 头,已从文件名推断`。
|
|
66
|
+
3. **推断也推不出来** → 走「语言描述兜底」:把文件内容当自然语言,跑 context_pack 自检索补全。
|
|
67
|
+
|
|
68
|
+
**核心:永远不因为格式问题让模块停摆。** 停摆比降级产出更糟。
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## 为什么用 HTML 注释而不是 frontmatter?
|
|
73
|
+
|
|
74
|
+
- frontmatter(`---`)会跟 PRD 模板正文的 `---`(分割线)打架。
|
|
75
|
+
- HTML 注释 `<!-- -->` 在 Markdown 里不渲染、对人透明、对机器可解析。
|
|
76
|
+
- JSON 文件用 `_contract` 字段(下划线前缀表「元数据」)。
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# 模块契约:design(设计)
|
|
2
|
+
|
|
3
|
+
> 设计模块。确立**视觉单一真源**,让 AI 原型不再跟 Figma 打架。
|
|
4
|
+
> 由 design-import + prototype-generator + design-review 三个 skill 承担。
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Input(吃什么)
|
|
9
|
+
|
|
10
|
+
| 优先级 | 输入 | 怎么用 |
|
|
11
|
+
|--------|------|--------|
|
|
12
|
+
| **完整** | 设计师 spec.json(已录入的) | 优先级最高:`data/style/{需求}-design-spec.json` |
|
|
13
|
+
| 完整 2 | PRD + 设计师 Figma/Axure 截图 | design-import 把截图转成 spec.json |
|
|
14
|
+
| 降级 1 | 只有 PRD,无设计稿 | 用代码真源 / 系统风格做原型 |
|
|
15
|
+
| 降级 2 | 只有截图 + 一句话 | design-import 直接从截图提取 |
|
|
16
|
+
| 降级 2 ★ | 一句话描述 | fill_prototype.py + 风格真源硬干 |
|
|
17
|
+
|
|
18
|
+
**风格真源优先级**(高 → 低):
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
设计师 spec.json (data/style/*-design-spec.json)
|
|
22
|
+
> data/code/ 实际 Vue 源码
|
|
23
|
+
> data/index/ref-vben-style.json (Web) / Vant 变量 (APP)
|
|
24
|
+
> data/index/ref-chart-style.json (看板/大屏)
|
|
25
|
+
> data/style/*.pdf (规范文档,最后兜底)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**平台是硬约束**。
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Output(吐什么)
|
|
33
|
+
|
|
34
|
+
### 主产物 1:设计规范(design-import 产出)
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
路径:data/style/{需求名}-design-spec.json
|
|
38
|
+
格式:对齐 ref-vben-style.json 的结构
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"_contract": {
|
|
44
|
+
"type": "design-spec", "version": 1,
|
|
45
|
+
"platform": "web|app",
|
|
46
|
+
"requirement": "{需求名}",
|
|
47
|
+
"source": "figma:截图1+截图2"
|
|
48
|
+
},
|
|
49
|
+
"source": "...",
|
|
50
|
+
"imported_at": "2026-06-16T...",
|
|
51
|
+
"platform": "web",
|
|
52
|
+
"requirement": "...",
|
|
53
|
+
"design_tokens": { "color": {}, "spacing": {}, "typography": {} },
|
|
54
|
+
"layout": {},
|
|
55
|
+
"components": {},
|
|
56
|
+
"notes": {}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**契约头 `_contract`** 让下游原型/代码一眼识别这是设计师真源。
|
|
61
|
+
|
|
62
|
+
### 主产物 2:原型(prototype-generator 产出)
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
单端:workspace/members/{developer}/drafts/prototype-{feature}.html
|
|
66
|
+
两端:...-web.html + ...-app.html
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
起点必须是模板 `.qoder/templates/prototype-{web|app}.html`,
|
|
70
|
+
预填充走 `python .qoder/scripts/orchestration/wlkj.py fill-prototype <关键词> --platform <web|app> [--type table-page|form-page]`。
|
|
71
|
+
|
|
72
|
+
**铁律**:data/style/ 里有同需求的 spec.json → 原型必须锚定它,不许另起炉灶。
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 校验
|
|
77
|
+
|
|
78
|
+
design-review skill 用 checklist(**无独立脚本**):
|
|
79
|
+
|
|
80
|
+
- [ ] 组件规格完整
|
|
81
|
+
- [ ] 交互流程闭环
|
|
82
|
+
- [ ] 图标来自真源(`data/index/ref-icon.json`,**禁 emoji**)
|
|
83
|
+
- [ ] 颜色来自真源
|
|
84
|
+
- [ ] 匹配设计师 spec(若存在)
|
|
85
|
+
- [ ] 匹配 PRD 验收点
|
|
86
|
+
|
|
87
|
+
> 原型的颜色真源校验实际由 `eval_prd.py` 的 A2 分(30 分)承担——
|
|
88
|
+
> 也就是说设计质量目前挂在 prd 门禁上。无独立 design 校验脚本(待建)。
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 与下游的接口
|
|
93
|
+
|
|
94
|
+
| 下游模块 | 消费 design 的什么 |
|
|
95
|
+
|----------|-------------------|
|
|
96
|
+
| code | 原型的组件结构 / 交互 |
|
|
97
|
+
| prototype 重生成 | design-spec.json 的 token / layout / components |
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## 现状提醒(KNOWN GAP)
|
|
102
|
+
|
|
103
|
+
- ⚠️ **`data/style/` 当前只有 2 个 PDF,没有任何 spec.json**。
|
|
104
|
+
design-import 声明会产出 spec.json,但目前是「预期」而非「已落地」。
|
|
105
|
+
首次有设计师录入前,原型只能走「代码真源」级降级。
|
|
106
|
+
- ✅ 图标禁 emoji 这条已有 eval_prd A2 兜底。
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# 语言描述兜底(最终降级策略)
|
|
2
|
+
|
|
3
|
+
> 这是降级链路的**终点**:当模块连一份契约文件都没有、连截图都没有时,
|
|
4
|
+
> 用户只用一句话描述,AI 靠**全索引 + PRD 历史**自己检索上下文,硬把活干出来。
|
|
5
|
+
>
|
|
6
|
+
> 哲学:**永远不因为缺输入让模块停摆。停摆比降级产出更糟。**
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 降级链路总览
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
完整输入(契约文件 + 截图) 产出最稳 ★★★★★
|
|
14
|
+
↓ 降级 1
|
|
15
|
+
部分契约(PRD 或 单截图) 产出较稳 ★★★★
|
|
16
|
+
↓ 降级 2
|
|
17
|
+
一句话描述(口语需求) 产出可用 ★★★
|
|
18
|
+
↓ 降级 3 ★ 最终兜底
|
|
19
|
+
自然语言 + 全索引自检索 产出需人工复核 ★★
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**降级 3 的本质**:AI 把用户的一句话当成「检索 query」,用现有索引把上下文凑齐,
|
|
23
|
+
再带着这些上下文进模块开干。用户感觉只是说了句话,AI 背后自己找齐了弹药。
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 兜底执行流程(任何模块通用)
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
用户一句话("保单批改那块加个审批")
|
|
31
|
+
│
|
|
32
|
+
▼
|
|
33
|
+
┌───────────────────────────┐
|
|
34
|
+
│ Step 1: 提取业务关键词 │ common/terms.py 的 expand_chinese_query
|
|
35
|
+
│ "保单批改" → 精确/分词 │ 三级分词:精确 → 贪心 → 兜底
|
|
36
|
+
└───────────────────────────┘
|
|
37
|
+
│
|
|
38
|
+
▼
|
|
39
|
+
┌───────────────────────────┐
|
|
40
|
+
│ Step 2: 一次取全上下文 ★ │ python .qoder/scripts/orchestration/wlkj.py context
|
|
41
|
+
│ context_pack.py <词> │ <业务词> --platform <web|app>
|
|
42
|
+
│ --platform <web|app> │ 返回 7 段(代码/页面/字段/PRD/API/token/Wiki)
|
|
43
|
+
└───────────────────────────┘
|
|
44
|
+
│
|
|
45
|
+
▼
|
|
46
|
+
┌───────────────────────────┐
|
|
47
|
+
│ Step 3: 补查历史 PRD │ python .qoder/scripts/orchestration/wlkj.py search
|
|
48
|
+
│ search_index.py --prd <词>│ 看有没有同类需求做过,复用验收标准
|
|
49
|
+
└───────────────────────────┘
|
|
50
|
+
│
|
|
51
|
+
▼
|
|
52
|
+
┌───────────────────────────┐
|
|
53
|
+
│ Step 4: 补查字段/API │ 按 Step2 结果决定要不要 drill-down
|
|
54
|
+
│ search_index.py --field │ --field / --api 精确取
|
|
55
|
+
└───────────────────────────┘
|
|
56
|
+
│
|
|
57
|
+
▼
|
|
58
|
+
┌───────────────────────────┐
|
|
59
|
+
│ Step 5: 进模块开干 │ 带着凑齐的上下文,正常走模块逻辑
|
|
60
|
+
│ 产出标 source: fallback │ 产物的契约头标 source: fallback:index
|
|
61
|
+
└───────────────────────────┘
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 关键设计点
|
|
67
|
+
|
|
68
|
+
### 1. context_pack 是兜底的核心引擎
|
|
69
|
+
|
|
70
|
+
一条命令拿 7 段,**不需要等图谱更新完**:
|
|
71
|
+
- context_pack 只读 `data/index/`(只读消费,不抢写资源)
|
|
72
|
+
- 图谱在另一个窗口更新,这边用最新 mtime 的索引,互不干扰
|
|
73
|
+
- 有 24h 缓存(`.qoder/.runtime/ctx-cache-*.md`),重复问同一个词秒回
|
|
74
|
+
|
|
75
|
+
### 2. 平台缺失时怎么办
|
|
76
|
+
|
|
77
|
+
兜底场景下用户往往没说平台。**规则**:
|
|
78
|
+
- context_pack 的 `--platform` 如果缺,默认跑 `both`(两端都查)
|
|
79
|
+
- 但**进 prd / design 模块前必须补问平台**(这两块的硬约束不变)
|
|
80
|
+
- 其它模块(code/test)能从代码库自动判断平台,不用问
|
|
81
|
+
|
|
82
|
+
### 3. 产出必须标记 fallback
|
|
83
|
+
|
|
84
|
+
走兜底产出的契约文件,`source` 字段标 `fallback:index`:
|
|
85
|
+
|
|
86
|
+
```markdown
|
|
87
|
+
<!-- @contract prd v1
|
|
88
|
+
platform: web
|
|
89
|
+
source: fallback:index
|
|
90
|
+
acceptance: [...] ← 这些验收点是 AI 从历史 PRD 推断的,需人工复核
|
|
91
|
+
-->
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**目的**:下游看到 `source: fallback` 就知道这是「AI 凑出来的」,**质量责任在人**,
|
|
95
|
+
该人工复核就复核,别盲信。
|
|
96
|
+
|
|
97
|
+
### 4. 兜底不是万能的
|
|
98
|
+
|
|
99
|
+
兜底能补**上下文**(代码在哪、字段叫啥、历史怎么做),补不了**决策**:
|
|
100
|
+
- ❌ 兜底不能决定「这个功能该不该做」
|
|
101
|
+
- ❌ 兜底不能编造「用户没说但需要的验收点」(只能从历史 PRD 推断相似项)
|
|
102
|
+
- ✅ 兜底能补「相关代码、字段命名、同类需求的写法」
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 各模块的兜底差异
|
|
107
|
+
|
|
108
|
+
| 模块 | 兜底能凑出什么 | 凑不出什么(需人工) |
|
|
109
|
+
|------|--------------|---------------------|
|
|
110
|
+
| prd | 相关代码/字段/历史PRD/页面示例 | 业务决策、真实验收点 |
|
|
111
|
+
| design | 系统风格token/同类页面/图标 | 设计师的视觉决策 |
|
|
112
|
+
| task | 同类历史任务/估时参考 | 优先级决策 |
|
|
113
|
+
| spec | 接口惯例/数据结构惯例 | PRD 没定义的功能 |
|
|
114
|
+
| code | 周围代码风格/相似实现 | —— (兜底效果最好) |
|
|
115
|
+
| test | 同类页面的验收点 | PRD 没写的边界 |
|
|
116
|
+
|
|
117
|
+
**code 模块兜底效果最好**——因为代码风格、相似实现都在索引里,能直接照着写。
|
|
118
|
+
**prd 模块兜底效果最差**——因为需求决策终究是人定的,索引只能给参考。
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## 一句话
|
|
123
|
+
|
|
124
|
+
> **用户说一句话,AI 用 context_pack 把全索引跑一遍、用 search_index 把历史 PRD 捞一遍,
|
|
125
|
+
> 凑齐上下文后照常进模块开干。产出标 `source: fallback`,提示需人工复核。
|
|
126
|
+
> 不卡、不报错、不等图谱。**
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# 隔离与并发安全契约(ISOLATION)
|
|
2
|
+
|
|
3
|
+
> 回答团队最关心的三个问题:**我能不能改到别人的任务?同步会不会覆盖别人的工作?禅道同步会不会拉错/推错?**
|
|
4
|
+
> 本文件是这些保证的**单一事实源**。实现见 `task_utils.py` / `team_sync.py` / `syncgate.py`。
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## TL;DR(给 PM 的 3 句话)
|
|
9
|
+
|
|
10
|
+
1. **本地任务**:你只能改自己创建/被指派的任务,别人的任务 ACL 直接拒绝(返回 4)——改不到。
|
|
11
|
+
2. **team_sync 同步**:push 只暂存白名单路径(workspace/data/docs/data/index)+ 安全扩展名,pull 用 autostash 保护你的本地改动——正常不丢不覆盖。
|
|
12
|
+
3. **禅道同步**:禅道是**团队共享账号**,server 层不区分谁在操作 → **必须靠 assignedTo 归属过滤**,否则会拉到/覆盖队友任务。见下文「禅道同步」红线。
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 一、本地任务隔离(已实现,强保证)
|
|
17
|
+
|
|
18
|
+
### 1.1 任务存储:团队共享 + 字段隔离
|
|
19
|
+
|
|
20
|
+
- 任务文件 `workspace/tasks/{MM-DD-slug}/task.json` 是**团队共享目录**,push 后全队可见。
|
|
21
|
+
- 隔离**不靠物理分目录**,靠 task.json 里的 `creator` / `assignee` 字段 + ACL 校验。
|
|
22
|
+
- 真正「个人隔离」的只有:个人草稿产出(`workspace/members/{dev}/`)、活跃任务指针(`.runtime/current-task.{dev}` 按开发者命名)、私有凭证(`.private/`)。
|
|
23
|
+
|
|
24
|
+
### 1.2 ACL:谁能改一个任务
|
|
25
|
+
|
|
26
|
+
| 操作 | 谁能做 |
|
|
27
|
+
|------|--------|
|
|
28
|
+
| create(新建) | 任何人(新任务归属创建者,assignee 默认=创建者) |
|
|
29
|
+
| start / finish / archive / reassign / set-due / block / 子任务 | **仅** `creator ∪ assignee ∪ admin` |
|
|
30
|
+
| list / 查看所有人任务 | 任何人(产品要看全局排期);`--mine` 才过滤只看自己 |
|
|
31
|
+
|
|
32
|
+
- 实现:`task_utils.py` `assert_can_modify_task`。非归属人操作一律返回退出码 **4(权限拒绝)**。
|
|
33
|
+
- 所有变更命令都过此校验:`task_lifecycle.py`(create 除外)/ `task_relations.py` 全部写操作。
|
|
34
|
+
|
|
35
|
+
### 1.3 并发读改写:每任务一把锁
|
|
36
|
+
|
|
37
|
+
- `modify_task_json` 在文件锁 `task_dir/.task.lock` 内完成 load→改→write,**原子**。
|
|
38
|
+
- 锁竞争超时**不降级为无锁写**——宁可失败也不丢更新。
|
|
39
|
+
- 写入是原子操作(temp 文件 + `os.replace`),最坏情况是「半写」,不会产生损坏的 JSON。
|
|
40
|
+
- **结论**:两个 PM 同时改同一个任务的不同字段(一个改 status、一个改 due)→ 不丢更新。
|
|
41
|
+
|
|
42
|
+
### 1.4 已知边界(低风险,记录在案)
|
|
43
|
+
|
|
44
|
+
- `archive`(整目录移动)与并发写同一任务:ACL 先挡非归属人;归属人之间的极端时序靠 OS 文件系统兜底,最坏是「改完的内容随目录进了 archive」,不损坏但可能「以为没生效」。
|
|
45
|
+
- `list`(无 `--mine`)能看到所有人的任务——这是**有意设计**(产品看全局),不是隔离漏洞。
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 二、team_sync 同步(已实现,强保证)
|
|
50
|
+
|
|
51
|
+
### 2.1 push:只推白名单 + 安全扩展名 + 串行锁
|
|
52
|
+
|
|
53
|
+
- **路径白名单**(`SYNC_SCOPES`):只 `workspace` / `data/docs` / `data/index` 三个 scope。
|
|
54
|
+
- **扩展名白名单**(`SAFE_EXTENSIONS`):仅 `.md .html .json .jsonl .yaml .yml .toml .txt .csv .svg`。`.env .zip .docx` 等一律拒绝并打印跳过警告。
|
|
55
|
+
- **绝不** `git add -A`;改为逐 scope + 扩展名过滤的批量 add(每批 400 个)。
|
|
56
|
+
- **全局串行锁** `team-sync.lock`(push 与 pull 共用),同一时刻只有一个同步在跑。
|
|
57
|
+
- **零信任门禁**(commit 前):身份强制 + git 作者与注册身份一致 + 秘密扫描 + REQ-ID 撞号校验 + 平台标注 + EVA 质量门禁(≥80%)。任一失败 `git reset HEAD` 撤销暂存。
|
|
58
|
+
|
|
59
|
+
> 各人产出在 `members/{自己}/` 物理隔离:A push 会把 `members/B/` 也推上去,但路径不冲突,不会覆盖 B 的内容。
|
|
60
|
+
|
|
61
|
+
### 2.2 pull:autostash 保护本地改动 + 冲突安全回退
|
|
62
|
+
|
|
63
|
+
- `git pull --rebase --autostash`:本地未提交改动先 stash,rebase 完再 pop——**正常不丢**。
|
|
64
|
+
- 冲突时(`SYNC_CONFLICT` 标记 + 退出码 3):自动 `git rebase --abort` + 尝试恢复 stash + 输出 6 步 AI 指南。**绝不要求用户自己跑 git**(CRITICAL RULE #3)。
|
|
65
|
+
- `kg.duckdb` 二进制冲突有专门自动解决(取 `built_at` 更新的版本)。
|
|
66
|
+
|
|
67
|
+
### 2.3 已知边界
|
|
68
|
+
|
|
69
|
+
- `--autostash` 的 stash pop 本身也可能冲突(典型:两个 PM 同日改同一份共享索引)。此情况**数据不丢**(还在 stash 里),但需 AI/人工介入 `git stash pop`。
|
|
70
|
+
- 没有「本地有未提交改动就先警告再 pull」的预检——直接 autostash,靠 git 兜底。
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 三、禅道同步(共享账号 — 红线区,需重点遵守)
|
|
75
|
+
|
|
76
|
+
> ⚠️ 禅道 MCP 是**团队共享账号**(`.qoder/config.yaml` 的 `zentao.user`),server 层无法区分「这次操作是哪个本地开发者发起的」。
|
|
77
|
+
> 这是拉错/推错风险的**唯一来源**。
|
|
78
|
+
|
|
79
|
+
### 3.1 红线(违反 = 可能污染/覆盖队友)
|
|
80
|
+
|
|
81
|
+
| 方向 | 红线 | 正确做法 |
|
|
82
|
+
|------|------|---------|
|
|
83
|
+
| 拉取(禅道→本地) | ❌ 直接 `list_execution_tasks` 不过滤 → 拉到全队任务写进本地 | ✅ **强制** `assignedTo == 当前开发者禅道账号` 过滤 |
|
|
84
|
+
| 推送(本地→禅道) | ❌ 批量盲推 create/update → 覆盖同名队友任务 | ✅ **默认 `--dry-run`** + 仅推 `creator==我` 的 + 禅道同名任务 assignedTo 须一致才更新 |
|
|
85
|
+
| create | ❌ 用共享账号把任务派给别人 | ✅ 强制 `assignedTo = 当前开发者` |
|
|
86
|
+
| 幂等 | ❌ 重复 create 同一任务 | ✅ task.json 的 `zentao_id` 字段做主键,已有则跳过 |
|
|
87
|
+
|
|
88
|
+
### 3.2 归属字段对照(实现 zentao_sync 的依据)
|
|
89
|
+
|
|
90
|
+
| 字段 | 用途 | 能否区分「我的 vs 别人的」 |
|
|
91
|
+
|------|------|------------------------|
|
|
92
|
+
| `assignedTo`(指派人) | 禅道任务核心归属字段 | ✅ **最可靠,拉取主过滤以此为准** |
|
|
93
|
+
| `openedBy`(创建人) | 谁建的(改派后不变) | ⚠️ 辅助,语义不同 |
|
|
94
|
+
| `account` | 工时记录字段(list_effort) | ❌ 不是任务归属,别用 |
|
|
95
|
+
|
|
96
|
+
### 3.3 本地 developer ↔ 禅道 account 映射
|
|
97
|
+
|
|
98
|
+
- 本地 developer 名(如 `hupan56`)与禅道 account(如 `hupan`)**不一致**,需映射表。
|
|
99
|
+
- 映射存于 member 注册信息(`zentao_account` 字段)。同步前先解析当前 developer → 禅道 account,再用 account 做过滤。
|
|
100
|
+
- **无映射 = 拒绝同步**(宁可不同步也不猜,避免拉错)。
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 四、违反契约的症状与自检
|
|
105
|
+
|
|
106
|
+
| 症状 | 含义 | 自检/恢复 |
|
|
107
|
+
|------|------|----------|
|
|
108
|
+
| 退出码 **4** | ACL 权限拒绝 | 你不是该任务的 creator/assignee/admin,确认是否选错任务 |
|
|
109
|
+
| 退出码 **3(SYNC_CONFLICT)** | 同步冲突 | AI 接 `team_sync.py` 输出的 6 步指南解决,无需用户碰 git |
|
|
110
|
+
| 退出码 **2(SYNC_BUSY)** | 同步锁竞争 | 等 5 分钟(stale_seconds=300)或确认无其它同步在跑 |
|
|
111
|
+
| `task.json.corrupt.<ts>` 出现 | task.json 曾损坏 | 已自动备份,原文件清空等重建;查 stderr 告警定位原因 |
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## 五、修改本契约的规则
|
|
116
|
+
|
|
117
|
+
- 本文件描述的保证**靠代码实现**(`task_utils.py` ACL/锁、`team_sync.py` 同步、`syncgate.py` 门禁、`zentao_sync.py` 归属过滤)。
|
|
118
|
+
- 若改了相关代码的行为,**必须同步更新本文件**,否则契约与实现脱节。
|
|
119
|
+
- 新增任何「多人共享数据」的操作(新命令、新脚本),都必须在本文件登记其隔离机制。
|