@michaelxwb/code-flow 0.6.5 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/README.md +75 -110
  2. package/bin/code-flow.js +12 -0
  3. package/docs/README.md +19 -0
  4. package/docs/USAGE.md +268 -0
  5. package/docs/v1-design.md +1858 -0
  6. package/docs/v1-implementation.md +186 -0
  7. package/lib/adapters.js +126 -0
  8. package/lib/cli.js +258 -0
  9. package/lib/config.js +85 -0
  10. package/lib/doctor.js +283 -0
  11. package/lib/frontmatter.js +42 -0
  12. package/lib/fs.js +141 -0
  13. package/lib/glob.js +23 -0
  14. package/lib/hook.js +99 -0
  15. package/lib/init.js +132 -0
  16. package/lib/learn.js +170 -0
  17. package/lib/locks.js +52 -0
  18. package/lib/markdown.js +13 -0
  19. package/lib/process.js +116 -0
  20. package/lib/render.js +115 -0
  21. package/lib/repo.js +48 -0
  22. package/lib/runs.js +155 -0
  23. package/lib/session.js +40 -0
  24. package/lib/spec.js +80 -0
  25. package/lib/task.js +258 -0
  26. package/lib/taskdoc.js +308 -0
  27. package/lib/toml.js +140 -0
  28. package/lib/verify.js +168 -0
  29. package/lib/worktree.js +930 -0
  30. package/package.json +21 -9
  31. package/templates/adapters/opencode.mjs +65 -0
  32. package/templates/config.json +39 -0
  33. package/templates/instructions.md +13 -0
  34. package/templates/launcher/bridge.cjs +295 -0
  35. package/templates/launcher/hook.cmd +15 -0
  36. package/templates/launcher/hook.ps1 +10 -0
  37. package/templates/launcher/hook.sh +20 -0
  38. package/templates/skills/cf-check.md +19 -0
  39. package/templates/skills/cf-init.md +16 -0
  40. package/templates/skills/cf-spec.md +20 -0
  41. package/templates/skills/cf-task-align.md +19 -0
  42. package/templates/skills/cf-task-archive.md +20 -0
  43. package/templates/skills/cf-task-plan.md +31 -0
  44. package/templates/skills/cf-task-prd.md +14 -0
  45. package/templates/skills/cf-task-start.md +41 -0
  46. package/{src/core/code-flow/specs/shared/design → templates/workflow}/design-frontend.md +22 -19
  47. package/{src/core/code-flow/specs/shared/design → templates/workflow}/design-full.md +36 -28
  48. package/{src/core/code-flow/specs/shared/design → templates/workflow}/design-lite.md +27 -17
  49. package/{src/core/code-flow/specs/shared/prd-template.md → templates/workflow/prd.md} +1 -1
  50. package/templates/workflow/project-guidelines.md +48 -0
  51. package/templates/workflow/scenarios.md +67 -0
  52. package/templates/workflow/task.md +56 -0
  53. package/docs/migrations/spec-workflow-0.6.0.md +0 -42
  54. package/src/adapters/claude/CLAUDE.md +0 -45
  55. package/src/adapters/claude/commands/cf-init.md +0 -264
  56. package/src/adapters/claude/commands/cf-learn.md +0 -291
  57. package/src/adapters/claude/commands/cf-spec.md +0 -67
  58. package/src/adapters/claude/commands/cf-stats.md +0 -86
  59. package/src/adapters/claude/commands/cf-sync.md +0 -25
  60. package/src/adapters/claude/commands/cf-task/align.md +0 -309
  61. package/src/adapters/claude/commands/cf-task/archive.md +0 -161
  62. package/src/adapters/claude/commands/cf-task/block.md +0 -36
  63. package/src/adapters/claude/commands/cf-task/graph.md +0 -80
  64. package/src/adapters/claude/commands/cf-task/note.md +0 -236
  65. package/src/adapters/claude/commands/cf-task/plan.md +0 -363
  66. package/src/adapters/claude/commands/cf-task/prd.md +0 -162
  67. package/src/adapters/claude/commands/cf-task/start.md +0 -304
  68. package/src/adapters/claude/commands/cf-task/status.md +0 -59
  69. package/src/adapters/claude/commands/cf-task/verify-e2e.md +0 -115
  70. package/src/adapters/claude/commands/cf-validate.md +0 -75
  71. package/src/adapters/claude/settings.local.json +0 -50
  72. package/src/adapters/codex/AGENTS.md +0 -45
  73. package/src/adapters/codex/config.toml +0 -3
  74. package/src/adapters/codex/hooks.json +0 -50
  75. package/src/adapters/codex/skills/cf-init/SKILL.md +0 -273
  76. package/src/adapters/codex/skills/cf-learn/SKILL.md +0 -296
  77. package/src/adapters/codex/skills/cf-spec/SKILL.md +0 -60
  78. package/src/adapters/codex/skills/cf-stats/SKILL.md +0 -87
  79. package/src/adapters/codex/skills/cf-sync/SKILL.md +0 -30
  80. package/src/adapters/codex/skills/cf-task-align/SKILL.md +0 -310
  81. package/src/adapters/codex/skills/cf-task-archive/SKILL.md +0 -162
  82. package/src/adapters/codex/skills/cf-task-block/SKILL.md +0 -37
  83. package/src/adapters/codex/skills/cf-task-graph/SKILL.md +0 -81
  84. package/src/adapters/codex/skills/cf-task-note/SKILL.md +0 -233
  85. package/src/adapters/codex/skills/cf-task-plan/SKILL.md +0 -324
  86. package/src/adapters/codex/skills/cf-task-prd/SKILL.md +0 -163
  87. package/src/adapters/codex/skills/cf-task-start/SKILL.md +0 -305
  88. package/src/adapters/codex/skills/cf-task-status/SKILL.md +0 -60
  89. package/src/adapters/codex/skills/cf-task-verify-e2e/SKILL.md +0 -111
  90. package/src/adapters/codex/skills/cf-validate/SKILL.md +0 -76
  91. package/src/adapters/costrict/CLAUDE.md +0 -45
  92. package/src/adapters/costrict/commands/cf-init.md +0 -264
  93. package/src/adapters/costrict/commands/cf-learn.md +0 -291
  94. package/src/adapters/costrict/commands/cf-spec.md +0 -67
  95. package/src/adapters/costrict/commands/cf-stats.md +0 -86
  96. package/src/adapters/costrict/commands/cf-sync.md +0 -25
  97. package/src/adapters/costrict/commands/cf-task/align.md +0 -309
  98. package/src/adapters/costrict/commands/cf-task/archive.md +0 -161
  99. package/src/adapters/costrict/commands/cf-task/block.md +0 -36
  100. package/src/adapters/costrict/commands/cf-task/graph.md +0 -80
  101. package/src/adapters/costrict/commands/cf-task/note.md +0 -236
  102. package/src/adapters/costrict/commands/cf-task/plan.md +0 -363
  103. package/src/adapters/costrict/commands/cf-task/prd.md +0 -162
  104. package/src/adapters/costrict/commands/cf-task/start.md +0 -304
  105. package/src/adapters/costrict/commands/cf-task/status.md +0 -59
  106. package/src/adapters/costrict/commands/cf-task/verify-e2e.md +0 -115
  107. package/src/adapters/costrict/commands/cf-validate.md +0 -75
  108. package/src/adapters/costrict/settings.local.json +0 -50
  109. package/src/adapters/opencode/AGENTS.md +0 -45
  110. package/src/adapters/opencode/commands/cf-init.md +0 -281
  111. package/src/adapters/opencode/commands/cf-learn.md +0 -295
  112. package/src/adapters/opencode/commands/cf-spec.md +0 -59
  113. package/src/adapters/opencode/commands/cf-stats.md +0 -90
  114. package/src/adapters/opencode/commands/cf-sync.md +0 -29
  115. package/src/adapters/opencode/commands/cf-task/align.md +0 -314
  116. package/src/adapters/opencode/commands/cf-task/archive.md +0 -166
  117. package/src/adapters/opencode/commands/cf-task/block.md +0 -40
  118. package/src/adapters/opencode/commands/cf-task/graph.md +0 -84
  119. package/src/adapters/opencode/commands/cf-task/note.md +0 -240
  120. package/src/adapters/opencode/commands/cf-task/plan.md +0 -363
  121. package/src/adapters/opencode/commands/cf-task/prd.md +0 -167
  122. package/src/adapters/opencode/commands/cf-task/start.md +0 -309
  123. package/src/adapters/opencode/commands/cf-task/status.md +0 -63
  124. package/src/adapters/opencode/commands/cf-task/verify-e2e.md +0 -115
  125. package/src/adapters/opencode/commands/cf-validate.md +0 -79
  126. package/src/adapters/opencode/opencode.json +0 -3
  127. package/src/adapters/opencode/plugins/code-flow/index.js +0 -213
  128. package/src/adapters/opencode/plugins/code-flow/package.json +0 -6
  129. package/src/cli.js +0 -1023
  130. package/src/core/code-flow/config.yml +0 -158
  131. package/src/core/code-flow/scripts/cf_acceptance_evidence.py +0 -100
  132. package/src/core/code-flow/scripts/cf_acceptance_manifest.py +0 -294
  133. package/src/core/code-flow/scripts/cf_acceptance_runner.py +0 -192
  134. package/src/core/code-flow/scripts/cf_acceptance_schema.py +0 -83
  135. package/src/core/code-flow/scripts/cf_checks.py +0 -336
  136. package/src/core/code-flow/scripts/cf_core.py +0 -787
  137. package/src/core/code-flow/scripts/cf_exec_base.py +0 -112
  138. package/src/core/code-flow/scripts/cf_feedback.py +0 -56
  139. package/src/core/code-flow/scripts/cf_log.py +0 -154
  140. package/src/core/code-flow/scripts/cf_post_hook.py +0 -196
  141. package/src/core/code-flow/scripts/cf_pre_tool_hook.py +0 -104
  142. package/src/core/code-flow/scripts/cf_scan.py +0 -295
  143. package/src/core/code-flow/scripts/cf_session_state.py +0 -37
  144. package/src/core/code-flow/scripts/cf_spec_context.py +0 -1746
  145. package/src/core/code-flow/scripts/cf_spec_gate.py +0 -264
  146. package/src/core/code-flow/scripts/cf_spec_metadata.py +0 -384
  147. package/src/core/code-flow/scripts/cf_spec_migrate.py +0 -512
  148. package/src/core/code-flow/scripts/cf_spec_resolver.py +0 -347
  149. package/src/core/code-flow/scripts/cf_spec_router.py +0 -244
  150. package/src/core/code-flow/scripts/cf_spec_session.py +0 -119
  151. package/src/core/code-flow/scripts/cf_spec_verify.py +0 -559
  152. package/src/core/code-flow/scripts/cf_stats.py +0 -506
  153. package/src/core/code-flow/scripts/cf_stop_hook.py +0 -381
  154. package/src/core/code-flow/scripts/cf_sync.py +0 -140
  155. package/src/core/code-flow/scripts/cf_task_index.py +0 -148
  156. package/src/core/code-flow/scripts/cf_task_parallel.py +0 -394
  157. package/src/core/code-flow/scripts/cf_task_runtime.py +0 -304
  158. package/src/core/code-flow/scripts/cf_task_state.py +0 -3
  159. package/src/core/code-flow/scripts/cf_task_workflow.py +0 -205
  160. package/src/core/code-flow/scripts/cf_user_prompt_hook.py +0 -178
  161. package/src/core/code-flow/scripts/cf_validation.py +0 -81
  162. package/src/core/code-flow/scripts/cf_workflow_service.py +0 -366
  163. package/src/core/code-flow/scripts/cf_workflow_transaction.py +0 -96
  164. package/src/core/code-flow/specs/backend/_map.md +0 -56
  165. package/src/core/code-flow/specs/backend/code-quality-performance.md +0 -59
  166. package/src/core/code-flow/specs/backend/database.md +0 -51
  167. package/src/core/code-flow/specs/backend/directory-structure.md +0 -54
  168. package/src/core/code-flow/specs/backend/logging.md +0 -50
  169. package/src/core/code-flow/specs/backend/platform-rules.md +0 -55
  170. package/src/core/code-flow/specs/frontend/_map.md +0 -52
  171. package/src/core/code-flow/specs/frontend/component-specs.md +0 -68
  172. package/src/core/code-flow/specs/frontend/directory-structure.md +0 -53
  173. package/src/core/code-flow/specs/frontend/quality-standards.md +0 -58
  174. package/src/core/code-flow/specs/shared/_map.md +0 -57
  175. package/src/core/code-flow/tasks/.gitkeep +0 -0
  176. package/src/core/code-flow/validation.yml +0 -53
  177. package/src/migrate/spec-workflow.js +0 -238
@@ -1,96 +0,0 @@
1
- """Recoverable two-file workflow commits under the active-task lock."""
2
- from __future__ import annotations
3
-
4
- import json
5
- from pathlib import Path
6
- from typing import Optional
7
-
8
- from cf_spec_context import _acquire_active_lock, _atomic_text, _release_active_lock
9
-
10
-
11
- def _read(path: Path) -> Optional[str]:
12
- try:
13
- return path.read_text(encoding="utf-8")
14
- except FileNotFoundError:
15
- return None
16
-
17
-
18
- def _write(path: Path, value: Optional[str]) -> None:
19
- if _read(path) == value:
20
- return
21
- if value is None:
22
- path.unlink()
23
- else:
24
- _atomic_text(path, value)
25
-
26
-
27
- def _journal_path(root: str) -> Path:
28
- return Path(root) / ".code-flow/.workflow-transition.json"
29
-
30
-
31
- def _records(root: str, data: object) -> list[dict[str, object]]:
32
- if not isinstance(data, dict) or data.get("version") != 1:
33
- raise ValueError("workflow recovery: invalid journal")
34
- rows = data.get("files")
35
- if not isinstance(rows, list) or len(rows) != 2:
36
- raise ValueError("workflow recovery: invalid files")
37
- base = Path(root).resolve()
38
- marker = base / ".code-flow/.active-task.json"
39
- for row in rows:
40
- if not isinstance(row, dict) or not isinstance(row.get("path"), str):
41
- raise ValueError("workflow recovery: invalid record")
42
- path = Path(row["path"]).resolve()
43
- if base not in path.parents or (path != marker and path.suffix != ".md"):
44
- raise ValueError("workflow recovery: out-of-scope path")
45
- for field in ("before", "after"):
46
- if field not in row or (row[field] is not None and not isinstance(row[field], str)):
47
- raise ValueError("workflow recovery: invalid contents")
48
- if _read(path) not in (row["before"], row["after"]):
49
- raise ValueError(f"workflow recovery: concurrent change to {path}")
50
- if Path(rows[1]["path"]).resolve() != marker or rows[0]["path"] == rows[1]["path"]:
51
- raise ValueError("workflow recovery: marker must be last")
52
- return rows
53
-
54
-
55
- def recover_transition(root: str) -> bool:
56
- journal = _journal_path(root)
57
- if not journal.exists():
58
- return False
59
- lock = _acquire_active_lock(root)
60
- try:
61
- if not journal.exists():
62
- return False
63
- rows = _records(root, json.loads(journal.read_text(encoding="utf-8")))
64
- for row in rows:
65
- _write(Path(row["path"]), row["after"])
66
- journal.unlink()
67
- return True
68
- finally:
69
- _release_active_lock(lock)
70
-
71
-
72
- def commit_transition(root: str, task: Path, before: str, after: str,
73
- marker_before: Optional[str], marker_after: Optional[str]) -> None:
74
- marker = Path(root).resolve() / ".code-flow/.active-task.json"
75
- rows = [{"path": str(task.resolve()), "before": before, "after": after},
76
- {"path": str(marker), "before": marker_before, "after": marker_after}]
77
- journal = _journal_path(root)
78
- lock = _acquire_active_lock(root)
79
- try:
80
- if journal.exists():
81
- raise ValueError("workflow recovery required before transition")
82
- _records(root, {"version": 1, "files": rows})
83
- if any(_read(Path(row["path"])) != row["before"] for row in rows):
84
- raise ValueError("workflow concurrent change; retry transition")
85
- _atomic_text(journal, json.dumps({"version": 1, "files": rows}, ensure_ascii=False))
86
- try:
87
- for row in rows:
88
- _write(Path(row["path"]), row["after"])
89
- except (OSError, ValueError):
90
- for row in reversed(rows):
91
- _write(Path(row["path"]), row["before"])
92
- journal.unlink()
93
- raise
94
- journal.unlink()
95
- finally:
96
- _release_active_lock(lock)
@@ -1,56 +0,0 @@
1
- # Backend Retrieval Map
2
-
3
- > AI 导航地图:定位后端代码结构和关键模块。可由 `/cf-learn --map` 重生成,建议按真实项目手动校准。
4
-
5
- ## Purpose
6
-
7
- 后端服务,负责 API 暴露、业务逻辑与数据持久化。默认假设为分层架构(API → Service → Model)。
8
-
9
- ## Architecture
10
-
11
- - Framework: 任意 Web 框架(FastAPI / Express / Spring / Gin 等)
12
- - ORM/Driver: 与数据库匹配的官方/主流驱动
13
- - Database: 关系型为主(PostgreSQL / MySQL),可叠加缓存(Redis)
14
- - Auth: Token-based(JWT / OAuth2 / Session)
15
- - Async: 必要时引入消息队列或后台任务(Celery / Bull / BullMQ)
16
-
17
- ## Key Files
18
-
19
- | File | Purpose |
20
- |------|---------|
21
- | `src/main.*` | 应用入口,初始化框架、路由、中间件 |
22
- | `src/api/router.*` | 路由注册,统一前缀与版本 |
23
- | `src/services/` | 业务逻辑实现,禁止跨层调用 ORM |
24
- | `src/models/` | 数据模型定义(ORM / Schema) |
25
- | `src/crud/`(或 `repositories/`) | 数据访问层,业务只依赖此抽象 |
26
- | `src/config/` | 配置加载,环境变量优先 |
27
-
28
- ## Module Map
29
-
30
- ```
31
- src/
32
- ├── api/ # 接口层:路由 + 请求/响应 schema 校验
33
- ├── services/ # 业务逻辑层:纯函数为主,便于测试
34
- ├── models/ # 数据模型(ORM 或 ODM)
35
- ├── crud/ # 数据访问层(repositories),业务只调 CRUD 不碰 ORM
36
- ├── migrations/ # DB 迁移脚本(可回滚或幂等)
37
- ├── errors/ # 错误码→message 常量,按业务模块拆分
38
- ├── schemas/ # DTO / 请求响应类型
39
- ├── middleware/ # 认证、日志、限流、CORS
40
- ├── utils/ # 工具函数,无业务依赖
41
- └── config/ # 配置与环境变量
42
- ```
43
-
44
- ## Data Flow
45
-
46
- ```
47
- Request → Middleware(auth/log) → Router → Handler(API)
48
- → Service(业务) → Model(DB/Cache) → Response
49
- ```
50
-
51
- ## Navigation Guide
52
-
53
- - 新增 API → `api/` 加路由 + `schemas/` 定义请求响应 + `services/` 实现业务
54
- - 新增表 → `models/` 定义模型 + `migrations/` 加迁移脚本
55
- - 错误处理 → 抛业务异常类,由中间件统一转 HTTP 响应
56
- - 配置项 → `config/` 集中管理,禁止散落 `os.environ`/`process.env`
@@ -1,59 +0,0 @@
1
- ---
2
- id: backend-code-quality-performance
3
- description: 写后端代码时适用:错误处理、测试、超时重试、缓存等质量与性能约束
4
- stages: [design, plan, code, review]
5
- enforcement: required
6
- verifiers:
7
- - rule: RULE-backend-quality-001
8
- type: manual
9
- config:
10
- checklist: Confirm all Guidance and Avoid items for this Spec.
11
- owner: project-owner
12
- ---
13
-
14
- # Backend Code Quality & Performance
15
-
16
- ## Examples
17
-
18
- > ✅/❌ 对照示例对 AI 的引导远强于规则条文——新写规范优先用这个格式(cf-learn 候选会自动生成草稿)。
19
-
20
- ✅ 显式错误处理
21
-
22
- ```python
23
- try:
24
- result = service.call()
25
- except ServiceError as exc:
26
- logger.warning("call failed: %s", exc)
27
- raise
28
- ```
29
-
30
- ❌ 静默吞异常
31
-
32
- ```python
33
- try:
34
- result = service.call()
35
- except Exception:
36
- pass
37
- ```
38
-
39
-
40
- ## Rules
41
- - [RULE-backend-quality-001] The implementation must satisfy every applicable item in Guidance and avoid every item in Avoid.
42
-
43
- ## Guidance
44
- - 所有公开函数 / 方法必须有类型注解(type hints / 类型签名)
45
- - 异常必须显式处理或显式上抛,禁止 `except Exception: pass` / `catch (e) {}` 静默吞掉
46
- - 外部依赖调用(HTTP / RPC / DB)必须设置超时,关键调用补重试 + 指数退避
47
- - 单元测试覆盖核心业务路径:happy path + 边界 + 错误分支,每个需求 ≥ 1 个用例
48
-
49
- ## Patterns
50
- - 缓存可计算结果以减少重复 IO,明确缓存 key、TTL 与失效策略
51
- - 重 IO 用异步或批处理,CPU 密集任务下沉到 worker / 队列
52
- - 资源(连接、文件、锁)使用 `with` / `using` / `defer` 确保释放
53
- - 性能敏感路径加监控指标(QPS / P95 延迟 / 错误率)
54
-
55
- ## Avoid
56
- - 禁止在请求链路中吞掉异常导致客户端拿到错误结果却无日志
57
- - 禁止无超时的外部调用(容易导致线程 / 协程泄漏)
58
- - 禁止用循环模拟批量操作(DB 批量 / 网络批量必须用原生批量 API)
59
- - 禁止把缓存失败当致命错误,缓存层必须可降级为直接查询
@@ -1,51 +0,0 @@
1
- ---
2
- id: backend-database
3
- description: 涉及数据库/ORM/迁移/查询时适用:schema 与数据访问约束
4
- stages: [design, plan, code, review]
5
- enforcement: required
6
- verifiers:
7
- - rule: RULE-backend-database-001
8
- type: manual
9
- config:
10
- checklist: Confirm all Guidance and Avoid items for this Spec.
11
- owner: project-owner
12
- ---
13
-
14
- # Backend Database
15
-
16
- ## Examples
17
-
18
- ✅ 参数化查询,明确列出字段
19
-
20
- ```python
21
- cur.execute("SELECT id, name FROM users WHERE email = %s", (email,))
22
- ```
23
-
24
- ❌ 字符串拼接用户输入(SQL 注入)+ `SELECT *`
25
-
26
- ```python
27
- cur.execute(f"SELECT * FROM users WHERE email = '{email}'")
28
- ```
29
-
30
- ## Rules
31
- - [RULE-backend-database-001] The implementation must satisfy every applicable item in Guidance and avoid every item in Avoid.
32
-
33
- ## Guidance
34
- - 所有 SQL 必须参数化,禁止字符串拼接 / 模板插值用户输入
35
- - 迁移脚本必须可回滚,或写成幂等脚本(`IF NOT EXISTS` / `ON CONFLICT`)
36
- - 事务边界明确:跨表写入必须在同一事务内,禁止"半提交"状态
37
- - 涉及索引/锁的 schema 变更必须评估线上影响,大表慎用 `ALTER TABLE` 阻塞操作
38
- - 每个 model 必须有对应 CRUD 抽象层(`crud/<model>.py` 或 `repositories/<Model>Repo`),业务代码只调 CRUD,禁止在 service / handler 直接写 ORM 查询或裸 SQL
39
-
40
- ## Patterns
41
- - 读写分离场景显式标注读库/写库,强一致读走主库
42
- - N+1 查询用预加载(`joinedload` / `include` / `Preload`)解决
43
- - 大批量写入分批 + commit,避免单事务过大
44
- - 缓存与数据库一致性:先写库再失效缓存(`cache-aside`)
45
- - CRUD 基类统一实现 `get / list / create / update / delete / bulk_*`,子类只扩展模型特有查询
46
-
47
- ## Avoid
48
- - 禁止在事务内发起外部 HTTP / RPC 调用,超时会导致连接池耗尽
49
- - 禁止在循环中执行单条 `INSERT` / `UPDATE`,必须批量化
50
- - 禁止在 ORM 之外手写 SQL 时绕过参数绑定
51
- - 禁止用 `SELECT *` 上线,明确列出字段控制传输与索引
@@ -1,54 +0,0 @@
1
- ---
2
- id: backend-directory-structure
3
- description: 新建/移动后端文件时适用:目录结构与模块组织约束
4
- stages: [design, plan, code, review]
5
- enforcement: required
6
- verifiers:
7
- - rule: RULE-backend-directory-001
8
- type: manual
9
- config:
10
- checklist: Confirm all Guidance and Avoid items for this Spec.
11
- owner: project-owner
12
- ---
13
-
14
- # Backend Directory Structure
15
-
16
- ## Examples
17
-
18
- ✅ 魔法值集中到 `constants/`,命名引用
19
-
20
- ```python
21
- # constants/order.py
22
- ORDER_PAID = 1
23
- # service:if order.status == ORDER_PAID: ...
24
- ```
25
-
26
- ❌ 业务代码散落硬编码字面量
27
-
28
- ```python
29
- if order.status == 1 and role == "admin": # 魔法数字 / 魔法字符串
30
- ...
31
- ```
32
-
33
- ## Rules
34
- - [RULE-backend-directory-001] The implementation must satisfy every applicable item in Guidance and avoid every item in Avoid.
35
-
36
- ## Guidance
37
- - 接口层放 `api/`,业务逻辑放 `services/`,数据模型放 `models/`,禁止跨层倒置依赖
38
- - 入口文件(`main.*`)只做框架装配,不写业务代码
39
- - 配置统一放 `config/`,禁止在业务代码中直接读 `os.environ` / `process.env`
40
- - 常量集中放 `constants/`,按业务模块拆分(`constants/order.py`、`constants/user.py`),禁止在业务代码中散落硬编码字面量(魔法数字 / 字符串 / 状态码)
41
- - 数据访问层独立放 `crud/` 或 `repositories/`,业务层依赖 CRUD 抽象,不直接依赖 ORM
42
- - 新增一级目录必须同步更新导航地图与 `__init__` / `index` 索引
43
-
44
- ## Patterns
45
- - 模块按业务域拆分(如 `services/order/`、`services/user/`),目录深度建议 ≤ 3 层
46
- - 公共工具放 `utils/`,无业务依赖;与业务相关的 helper 放对应 service 子目录
47
- - 常量命名用 UPPER_SNAKE_CASE,枚举优先使用语言原生 `Enum`
48
- - 测试目录与源码同构(`tests/services/order/test_*`)
49
-
50
- ## Avoid
51
- - 禁止在根目录堆放脚本与临时代码,临时脚本放 `scripts/` 并命名清晰
52
- - 禁止在 `models/` 里写业务逻辑,模型仅定义结构与简单关联
53
- - 禁止把常量直接写在业务代码里(如 `if status == 1` / `role == "admin"`),必须引用 `constants/` 中的命名常量
54
- - 禁止单文件超过 500 行或单函数超过 50 行
@@ -1,50 +0,0 @@
1
- ---
2
- id: backend-logging
3
- description: 涉及日志/调试/监控时适用:日志级别、格式、追踪约束
4
- stages: [design, plan, code, review]
5
- enforcement: required
6
- verifiers:
7
- - rule: RULE-backend-logging-001
8
- type: manual
9
- config:
10
- checklist: Confirm all Guidance and Avoid items for this Spec.
11
- owner: project-owner
12
- ---
13
-
14
- # Backend Logging
15
-
16
- ## Examples
17
-
18
- ✅ 结构化字段 + 脱敏 + 保留堆栈
19
-
20
- ```python
21
- logger.info("login", extra={"user_id": uid, "request_id": rid})
22
- logger.error("pay failed", exc_info=True)
23
- ```
24
-
25
- ❌ 明文 token + `print` 吞掉堆栈
26
-
27
- ```python
28
- print(f"login token={token}") # 泄露敏感字段 + 非日志框架
29
- logger.error("failed") # 丢失原始错误与上下文
30
- ```
31
-
32
- ## Rules
33
- - [RULE-backend-logging-001] The implementation must satisfy every applicable item in Guidance and avoid every item in Avoid.
34
-
35
- ## Guidance
36
- - 关键路径(请求入口、外部调用、DB 写入、异常分支)必须输出结构化日志
37
- - 日志中禁止出现明文密码、token、身份证号等敏感字段,需在记录前脱敏
38
- - 每条请求日志必须包含 `request_id`,串联整个调用链
39
- - 日志级别遵循:`DEBUG`(开发)/ `INFO`(业务事件)/ `WARN`(可恢复异常)/ `ERROR`(需告警)
40
-
41
- ## Patterns
42
- - 统一字段命名:`request_id`、`user_id`、`route`、`status`、`latency_ms`、`error`
43
- - 异常日志必须带堆栈(`exc_info=True` 或等价机制)
44
- - 高频路径用采样日志,避免 IO 阻塞主流程
45
- - 日志输出到 stdout/stderr,由部署环境采集,禁止业务代码写文件
46
-
47
- ## Avoid
48
- - 禁止在循环或热路径中无脱敏地打印请求体
49
- - 禁止用 `print` / `console.log` 替代日志框架
50
- - 禁止吞掉异常仅打 `logger.error("failed")`,必须保留原始错误与上下文
@@ -1,55 +0,0 @@
1
- ---
2
- id: backend-platform-rules
3
- description: 涉及 API 设计/部署/配置/版本兼容时适用:平台规则
4
- stages: [design, plan, code, review]
5
- enforcement: required
6
- verifiers:
7
- - rule: RULE-backend-platform-001
8
- type: manual
9
- config:
10
- checklist: Confirm all Guidance and Avoid items for this Spec.
11
- owner: project-owner
12
- ---
13
-
14
- # Backend Platform Rules
15
-
16
- ## Examples
17
-
18
- ✅ 走统一封装 + 错误码常量
19
-
20
- ```python
21
- return success(data)
22
- raise BizError(ORDER_NOT_FOUND) # 错误码定义在 errors/order.py
23
- ```
24
-
25
- ❌ handler 手拼响应结构 + 硬编码 message
26
-
27
- ```python
28
- return {"code": 1, "message": "order not found", "data": None}
29
- ```
30
-
31
- ## Rules
32
- - [RULE-backend-platform-001] The implementation must satisfy every applicable item in Guidance and avoid every item in Avoid.
33
-
34
- ## Guidance
35
- - API 变更必须保持向后兼容;破坏性变更走新版本路径(`/v2/...`)并保留旧版本至少一个发布周期
36
- - 配置项分环境管理(dev / staging / prod),敏感值走密钥管理服务,禁止入库
37
- - 新增外部依赖必须更新部署文档与 `requirements` / `package.json` 锁文件
38
- - 灰度 / 实验性功能必须由 feature flag 控制,默认关闭
39
- - API 响应必须走统一封装:`success(data)` / `fail(code, message?)`,handler 禁止手写 `{code, message, data}` 字面量
40
- - 错误码 → message 映射定义为常量,按业务模块拆分(`errors/order.py`、`errors/user.py`),错误码全局唯一,禁止重复
41
-
42
- ## Patterns
43
- - API 响应统一结构:`{ code, message, data }`(`code=0` 表示成功),全项目一致
44
- - 错误码命名空间:模块前缀 + 顺序号(如订单错误码 `10xxx`、用户 `20xxx`),便于定位归属
45
- - 异常 → 错误码:自定义业务异常类携带 `code`,由中间件统一转 `fail(code)` 响应
46
- - 配置加载优先级:环境变量 > 配置文件 > 默认值
47
- - 健康检查端点(`/healthz`、`/readyz`)必须独立于业务认证
48
- - 部署前跑 smoke test,覆盖核心路径
49
-
50
- ## Avoid
51
- - 禁止在生产环境开启 `DEBUG` / 详细堆栈输出
52
- - 禁止把 secret 写进代码库或 dev 配置文件
53
- - 禁止破坏性 API 变更不通知调用方直接发布
54
- - 禁止 feature flag 长期遗留,上线稳定后必须清理
55
- - 禁止在 handler 里直接拼响应结构或硬编码错误 message,必须引用 `errors/` 常量并走 `success / fail` 封装
@@ -1,52 +0,0 @@
1
- # Frontend Retrieval Map
2
-
3
- > AI 导航地图:定位前端代码结构和关键模块。可由 `/cf-learn --map` 重生成,建议按真实项目手动校准。
4
-
5
- ## Purpose
6
-
7
- 前端单页 / 多页应用,负责用户交互、页面渲染与 API 调用。默认假设为基于组件的 SPA。
8
-
9
- ## Architecture
10
-
11
- - Framework: 任意主流框架(React / Vue / Svelte / Solid 等)
12
- - Language: TypeScript(推荐)或 JavaScript + JSDoc
13
- - State: 局部状态优先,跨组件共享走集中式(Redux / Zustand / Pinia)
14
- - Routing: 框架官方路由(React Router / Vue Router / 文件路由)
15
- - Styling: 原子化(Tailwind)或模块化(CSS Modules / styled-components)
16
- - Build: Vite / Webpack / Next.js 等
17
-
18
- ## Key Files
19
-
20
- | File | Purpose |
21
- |------|---------|
22
- | `src/main.*` | 应用入口,挂载 Root |
23
- | `src/App.*` | 根组件,注册路由与全局 Provider |
24
- | `src/router.*` | 路由定义 |
25
- | `src/services/` | API 调用封装 |
26
-
27
- ## Module Map
28
-
29
- ```
30
- src/
31
- ├── components/ # 通用 UI 组件,无业务依赖
32
- ├── pages/ # 页面级组件(路由叶子)
33
- ├── hooks/ # 业务复用逻辑(React)/ composables(Vue)
34
- ├── stores/ # 状态管理
35
- ├── services/ # API 调用层
36
- ├── utils/ # 纯函数工具
37
- ├── types/ # 类型定义
38
- └── styles/ # 全局样式 / 主题
39
- ```
40
-
41
- ## Data Flow
42
-
43
- ```
44
- User Action → Event Handler → Service(API) → Store/State → Re-render
45
- ```
46
-
47
- ## Navigation Guide
48
-
49
- - 新增页面 → `pages/` 添加组件 + 路由配置
50
- - 新增组件 → `components/` 按业务域分子目录,复用优先
51
- - API 调用 → 统一走 `services/`,不在组件内裸 fetch
52
- - 状态管理 → 跨组件状态走 `stores/`,组件通过 hook / composable 消费
@@ -1,68 +0,0 @@
1
- ---
2
- id: frontend-component-specs
3
- description: 写/改组件时适用:props、hooks、渲染、UI 样式约束
4
- stages: [design, plan, code, review]
5
- enforcement: required
6
- verifiers:
7
- - rule: RULE-frontend-component-001
8
- type: manual
9
- config:
10
- checklist: Confirm all Guidance and Avoid items for this Spec.
11
- owner: project-owner
12
- ---
13
-
14
- # Component Specs
15
-
16
- ## Examples
17
-
18
- ✅ 稳定唯一 key + 改值经回调上抛
19
-
20
- ```tsx
21
- {items.map((it) => <Row key={it.id} item={it} onChange={onChange} />)}
22
- ```
23
-
24
- ❌ 用数组 index 作 key + 组件内直接改 props
25
-
26
- ```tsx
27
- {items.map((it, i) => { it.value = next; return <Row key={i} item={it} />; })}
28
- ```
29
-
30
- ✅ 容器/展示分离 + 样式走 token,展示组件不碰数据获取
31
-
32
- ```tsx
33
- // 展示组件:纯 props 驱动,样式用 class/token,无请求
34
- const OrderRow = ({ order, onSelect }: Props) =>
35
- <div className={styles.row} onClick={() => onSelect(order.id)}>{order.title}</div>;
36
- ```
37
-
38
- ❌ 展示组件内自取数据 + 内联魔法样式
39
-
40
- ```tsx
41
- const OrderRow = ({ id }) => {
42
- const [o, setO] = useState(); useEffect(() => { fetch(`/orders/${id}`)... }, []);
43
- return <div style={{ margin: 13, color: '#3a7' }}>{o?.title}</div>;
44
- };
45
- ```
46
-
47
- ## Rules
48
- - [RULE-frontend-component-001] The implementation must satisfy every applicable item in Guidance and avoid every item in Avoid.
49
-
50
- ## Guidance
51
- - Props 必须类型化(TS interface / PropTypes / defineProps),可选项给默认值
52
- - 组件文件名与导出组件名一致,使用 PascalCase
53
- - 单组件文件 ≤ 300 行,超出拆成子组件或提取 hook
54
- - 组件内禁止直接修改 props,需改值通过事件 / 回调上抛
55
- - **样式与逻辑/数据分离**:样式走 CSS Modules / 原子类 / 设计 token,不与数据获取或业务逻辑混在同一处;展示组件不发起请求
56
-
57
- ## Patterns
58
- - 拆分容器组件(数据获取 / 状态)与展示组件(纯 UI),便于测试和复用
59
- - 复用逻辑提取为 hook(`useXxx`)/ composable,禁止跨组件复制粘贴
60
- - 列表渲染必须给 `key`,且 `key` 稳定唯一,避免使用数组索引
61
- - 受控表单优先;非受控仅用于不需要回读值的场景
62
- - 样式遵循设计系统:间距用 4 的倍数,强调色 ≤ 2 种
63
-
64
- ## Avoid
65
- - 禁止在组件内直接修改 props 或 store 内部状态
66
- - 禁止把大量逻辑塞进 JSX 表达式,复杂条件提取变量或子组件
67
- - 禁止用 `index` 作为列表 `key`(顺序变更会触发错误复用)
68
- - 禁止省略 `alt` / `aria-*` 等可访问性属性
@@ -1,53 +0,0 @@
1
- ---
2
- id: frontend-directory-structure
3
- description: 新建/移动前端文件时适用:目录结构、路由/页面/组件存放约束
4
- stages: [design, plan, code, review]
5
- enforcement: required
6
- verifiers:
7
- - rule: RULE-frontend-directory-001
8
- type: manual
9
- config:
10
- checklist: Confirm all Guidance and Avoid items for this Spec.
11
- owner: project-owner
12
- ---
13
-
14
- # Frontend Directory Structure
15
-
16
- ## Examples
17
-
18
- ✅ 三层分离:service 发请求 → hook/composable 管状态 → 组件纯展示
19
-
20
- ```ts
21
- // services/order.ts — 只管 HTTP,不含状态
22
- export const fetchOrder = (id: string) => http.get(`/orders/${id}`);
23
- // hooks/useOrder.ts — 管 loading/error/data,复用逻辑收口于此
24
- export const useOrder = (id: string) => { /* 调 fetchOrder,返回 { data, loading, error } */ };
25
- // components/OrderCard.tsx — 纯展示,消费 hook
26
- const { data, loading, error } = useOrder(id);
27
- ```
28
-
29
- ❌ 组件内裸 `fetch`,请求/状态/样式糊在一处
30
-
31
- ```tsx
32
- const order = await fetch(`/orders/${id}`).then((r) => r.json());
33
- ```
34
-
35
- ## Rules
36
- - [RULE-frontend-directory-001] The implementation must satisfy every applicable item in Guidance and avoid every item in Avoid.
37
-
38
- ## Guidance
39
- - 通用组件放 `src/components/`,页面级组件放 `src/pages/`,业务复用逻辑放 `src/hooks/`(或 `composables/`)
40
- - **接口调用独立成层**:API 调用必须在 `src/services/` 封装;组件 / hook / composable 经 service 消费,**禁止组件或视图层内裸 `fetch` / `axios`**
41
- - 类型定义放 `src/types/`(共享)或与组件同目录(局部),禁止散落
42
- - 新增一级目录必须更新路由 / 入口索引与导航地图
43
-
44
- ## Patterns
45
- - 组件目录按业务域分子目录(`components/order/`、`components/user/`)
46
- - 页面与路由一一对应,路由配置集中在 `router.*`
47
- - 资源文件(图片 / 字体)放 `src/assets/`,构建工具处理 hash 与压缩
48
- - 测试文件与源码同目录(`Foo.test.tsx`)或镜像放 `tests/`
49
-
50
- ## Avoid
51
- - 禁止在 `src/` 下随意新增未登记的一级目录
52
- - 禁止页面与组件互相循环引用
53
- - 禁止把仅本组件用的 hook / 类型上提到全局目录
@@ -1,58 +0,0 @@
1
- ---
2
- id: frontend-quality-standards
3
- description: 写前端代码时适用:类型、lint、错误处理、测试、状态管理质量约束
4
- stages: [design, plan, code, review]
5
- enforcement: required
6
- verifiers:
7
- - rule: RULE-frontend-quality-001
8
- type: manual
9
- config:
10
- checklist: Confirm all Guidance and Avoid items for this Spec.
11
- owner: project-owner
12
- ---
13
-
14
- # Frontend Quality Standards
15
-
16
- ## Examples
17
-
18
- ✅ `unknown` 收敛 + 异步三态
19
-
20
- ```ts
21
- setState("loading");
22
- try {
23
- const raw: unknown = await api.fetch();
24
- setState("success", parse(raw));
25
- } catch (e) {
26
- setState("error", toMessage(e));
27
- }
28
- ```
29
-
30
- ❌ `any` + `@ts-ignore` + 只处理成功路径
31
-
32
- ```ts
33
- // @ts-ignore
34
- const data: any = await api.fetch();
35
- render(data);
36
- ```
37
-
38
- ## Rules
39
- - [RULE-frontend-quality-001] The implementation must satisfy every applicable item in Guidance and avoid every item in Avoid.
40
-
41
- ## Guidance
42
- - TypeScript 项目禁止使用 `any`,未知类型用 `unknown` 并显式收敛
43
- - 组件统一使用函数组件(React)/ 组合式 API(Vue 3),禁止类组件新增
44
- - 关键交互(提交 / 删除 / 支付)必须有错误提示与 loading 状态
45
- - 异步操作必须处理 loading / success / error 三态,禁止只处理成功路径
46
- - 提交前必须通过 lint 与 type check,禁止 `eslint-disable` / `@ts-ignore` 滥用
47
-
48
- ## Patterns
49
- - 跨组件状态用集中式状态管理,避免 prop drilling 超过 2 层
50
- - 表单校验在提交前完成,错误信息定位到具体字段
51
- - 网络请求统一处理 401 / 403 / 5xx,避免每个调用方重复
52
- - 关键路径补端到端测试或组件交互测试
53
-
54
- ## Avoid
55
- - 禁止在 render / setup 中发起未受控的副作用(用 `useEffect` / `onMounted`)
56
- - 禁止把后端错误直接抛给用户(如 SQL / stack trace)
57
- - 禁止用 `// @ts-ignore` 绕过类型错误,必须修复或改为 `@ts-expect-error` 加注释
58
- - 禁止在组件中直接修改 store 内部状态,必须走 action / mutation