From 95cb3ae814d2611c44db99edd0e6f8fa056c3921 Mon Sep 17 00:00:00 2001 From: rui Date: Fri, 3 Jul 2026 21:54:20 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20v0.3.1=20=E5=B7=A5=E4=BD=9C=E6=B5=81?= =?UTF-8?q?=E7=98=A6=E8=BA=AB=20+=20=E5=93=81=E7=89=8C=E8=84=B1=E6=95=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删 ai-behavior 强制存档 / 归档守卫;工作流交回 AI 内置计划能力 - reference/management/{plans,tasks,walkthroughs,reports}/ → reference/decisions/(ADR) - 规则真源 frontmatter 精简为仅 order;正文与产物头部去品牌自称 + emoji - 模板骨架大瘦身:删 manifesto-origin.md、experience/、README 重写为派生仓骨架版 - upgrade 加 v0.3.0 → v0.3.1 slim 迁移分支;含用户内容子目录保留 + 建议 - doctor 检查列表更新至新目录约定;删灵枢宣言检查,改查基线产物 - CLI 仓 README 5 处过时描述修正 - smoke +5 用例(17 → 22 全绿) --- CHANGELOG.md | 170 +++++++++++++++++ README.md | 12 +- package.json | 2 +- src/commands/doctor.mjs | 32 ++-- src/commands/upgrade.mjs | 179 ++++++++++++++++-- src/core/hooks.mjs | 4 +- src/core/registry.mjs | 6 +- .../.github/workflows/rules-consistency.yml | 6 +- templates/default/README.md | 153 +++------------ templates/default/_gitignore | 12 +- templates/default/reference/README.md | 28 +-- .../default/reference/decisions/README.md | 38 ++++ templates/default/reference/docs/README.md | 28 ++- .../default/reference/experience/README.md | 8 - .../pitfalls/001-port-drifting-fix.md | 36 ---- .../pitfalls/002-agent-browser-blind-retry.md | 24 --- .../experience/pitfalls/backend-sync.md | 8 - .../experience/prompts/ui-generation.md | 12 -- .../management/plans/ITERATION_TEMPLATE.md | 21 -- .../reference/management/plans/README.md | 11 -- .../reference/management/reports/README.md | 11 -- .../reference/management/tasks/README.md | 10 - .../management/walkthroughs/README.md | 10 - .../default/reference/manifesto-origin.md | 30 --- .../default/reference/rules/ai-behavior.md | 61 ++---- .../default/reference/rules/lingshu-core.md | 56 +++--- tests/smoke.test.mjs | 132 ++++++++++++- 27 files changed, 628 insertions(+), 472 deletions(-) create mode 100644 templates/default/reference/decisions/README.md delete mode 100644 templates/default/reference/experience/README.md delete mode 100644 templates/default/reference/experience/pitfalls/001-port-drifting-fix.md delete mode 100644 templates/default/reference/experience/pitfalls/002-agent-browser-blind-retry.md delete mode 100644 templates/default/reference/experience/pitfalls/backend-sync.md delete mode 100644 templates/default/reference/experience/prompts/ui-generation.md delete mode 100644 templates/default/reference/management/plans/ITERATION_TEMPLATE.md delete mode 100644 templates/default/reference/management/plans/README.md delete mode 100644 templates/default/reference/management/reports/README.md delete mode 100644 templates/default/reference/management/tasks/README.md delete mode 100644 templates/default/reference/management/walkthroughs/README.md delete mode 100644 templates/default/reference/manifesto-origin.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 2163922..64a543d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,175 @@ 格式遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/), 版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。 +## [0.3.1] - 2026-07-03 + +> **主题:工作流瘦身(Slim Workflow)** —— 连自己写的规矩也开始做减法。 + +### 背景 + +v0.3 之后的用户反馈聚焦在同一件事:**AI 工作流约束过繁**。 +`reference/rules/ai-behavior.md` 中的"强制存档(CRITICAL)"与"自动化归档守卫" +四件套(plans / tasks / walkthroughs / reports)与 Claude Code、Codex 的内置计划 +能力高度重叠;证据是模板 6 个月来 `reference/management/` 零真实产物——流程本身 +从未被落地。 + +### Changed(非 BREAKING) + +- **`reference/rules/ai-behavior.md` 真源大瘦身**:删除"强制存档 (CRITICAL)"与 + "自动化归档守卫"两段;措辞由"必须 / CRITICAL"改为"建议 / 可选"。保留寻源、 + 跨端同步、原子化三条软建议;交付规约(中文、Commit 格式、分支约束)保持硬约束。 +- **"计划与追踪"改用通用措辞**:不再点名 `TaskCreate` / `Plan 模式` + 等 Claude Code 专属术语,改为"使用工具自身的规划机制",兼容 Cursor / Codex / + Trae / Qoder 等所有分发目标;从引用块提到正文与其它软建议并列。 +- **`reference/rules/lingshu-core.md`**: + - §2 Git 隔离规则中"允许追踪 `reference/management/`"改为 + "允许追踪 `reference/` 治理资产(含可选 `decisions/`)"。 + - **§4 Stack Standard 整段删除**——Python `uv --link-mode copy` / Node `npm` + 等技术栈偏好属模板作者视角,不进中枢真源;派生仓的技术栈约定应写在 + `reference/docs/` 下自主定义。规则真源保持技术中立。 +- **模板骨架瘦身**: + - `templates/default/reference/management/` 四子目录整体删除; + 新增 `templates/default/reference/decisions/README.md`(ADR 说明)。 + - `templates/default/reference/experience/` 整体删除——原示例内容 + (`pitfalls/*.md`、`prompts/*.md`)属模板作者积累的经验,派生仓拿到会 + 分不清是自己的还是模板的;改为按需自建(呼应 `decisions/` 的"可选目录"模式)。 +- **`reference/decisions/README.md` 技术中立化**:删除"灵枢的档案目录" + "v0.3.1 引入,取代原 management 四件套"等模板作者视角落款,避免派生仓 + 看到不属于自己的演进史;`upgrade` 命令内嵌的同版本 README 同步修正。 +- **`reference/docs/README.md` 增加可选扩展建议**:列出 `prd/` / `tad/` / + `api/` / `schema/` 等推荐子目录约定,供仓库承担"设计文档 + 编码过程"两职 + 时按需自建;不预置骨架、不强制、不使用数字前缀。 +- **`reference/README.md` 与模板 README**:目录说明去 experience/、去 + management 四件套;`docs/` 描述带上可扩张子目录的注脚。 +- **`ai-behavior.md` §1 去掉"计划与追踪"软建议条**:属于"否定式历史包袱" + ——只有从旧规则迁移来的仓库才有"曾经被要求 `.plan.md`"的背景,全新派生仓的 + 开发者读到"**不再**要求…"会疑惑"我什么时候被要求过?"。AI 用不用自身规划 + 能力它自己知道,不需要中枢真源"授权"。§1 至此仅剩寻源 / 跨端同步 / 原子化 + 三条软建议。 +- **CLI 模板 `README.md` 大瘦身为"派生仓骨架版"**:删除灵枢架构宣言、核心特性 + 表、"若白知行出品"、`MIT © 2026 imrui` 版权段、"手动接入 / 项目变身"教程等 + 仅对**初次访问灵枢仓库的人**有意义的内容——派生仓开发者已完成 init,这些 + 是历史噪音。保留:项目结构、AI 工具矩阵、目录导航、命令速查、日常工作流、 + 开发流程、三条核心约定。顶部改为项目名占位(`lingshu-template` → init 时 + 替换)+ 一句话定位占位;底部保留一句技术出处脚注。 +- **CLI 模板 `reference/manifesto-origin.md` 删除**:灵枢名称溯源(《黄帝内经》 + 典故 + 三重架构隐喻)属**灵枢品牌资产**,派生仓在自己产品仓里看到"为什么 + 有黄帝内经"会疑惑。本仓 `lingshu-template` 保留(作为主仓品牌介绍)。 +- **CI 工作流注释中性化**:`.github/workflows/rules-consistency.yml` + 第 6 行硬编码 `v0.3 零侵入` 改为"通过 npx 调用全局 CLI",去掉版本号。 +- **规则真源 frontmatter 精简为仅 `order`**:5 字段(`order` / `name` / + `description` / `globs` / `trigger`)缩到 1 字段。 + - `name` 引擎从未读取(sources 从文件名派生)——纯冗余; + - `globs: **/*` 与 `trigger: always_on` 是 Cursor 默认值——占位样板; + - `description` 仅对 Cursor UI 有意义,可由用户按需自加(逃生舱思路); + - `order` 控制多规则合并顺序,是引擎唯一必需字段,保留。 + 副作用:Cursor `.mdc` 产物不再带 frontmatter(当规则真源只有保留字段时)。 + 功能不减——Cursor 会按文件名展示、默认 `always_on`。 +- **`upgrade` v0.2 → v0.3 迁移时也只注入 `order`**:不再迁入旧 + `.lingshu/config/adapters.mjs` 中的 cursor `description/globs/trigger` + ——那些属"模板作者视角"的默认样板,从旧仓库带过来只会让新真源变脏。 +- **smoke 测试**:`生成的 cursor 产物含规则文件自身的 frontmatter` 用例 + 换语义为"order 是保留字段、不输出到 .mdc";`upgrade v0.2 → v0.3 机械迁移` + 用例断言旧 description 不再迁入。测试数仍为 22(净变化 0)。 + +### Debranding(规则真源与产物去品牌自称) + +派生仓 AI 每次读 CLAUDE.md 都会看到"# 灵枢 (LingShu) — Claude Code 项目指令" +和"# 灵枢架构核心准则"作为主标题,会误把架构名当项目名("我在做灵枢项目吗?")。 +本次将品牌自称从**所有会进入派生仓文件系统的位置**移除,保留"中枢-肢体"作为 +技术隐喻。 + +- **产物头部去品牌**:`registry.mjs` 的 `fileHeader` 从 + ``# 灵枢 (LingShu) — ${title}`` 改为 ``# ${title}``;CLAUDE.md/AGENTS.md + 主标题现分别为"Claude Code 项目指令" / "AI Agents 项目指令",无品牌前缀。 +- **规则真源标题脱敏**: + - `lingshu-core.md`:`# 灵枢架构核心准则 (LingShu Core Principles)` + → `# 架构核心准则`;正文 `本仓库遵循 **LingShu** 架构` 改为 + `本仓库采用"中枢-肢体"分层结构`。 + - `ai-behavior.md`:`# 🤖 灵枢智能体行为准则 (Agentic Workflow)` + → `# AI 智能体行为准则`。 +- **规则真源 emoji 去除**:🧠 / 💪 / 🚫 / ✅ / 🛡️ / 🤖 装饰性 emoji + 从两份规则真源移除(呼应 v0.2.1 "去 emoji" 决策,本轮才彻底贯彻到规则文件)。 +- **"中枢-肢体" 技术隐喻保留**:作为分层结构的准确技术描述词 + (中枢仓 = 顶层父仓、肢体仓 = 嵌套子仓),不属品牌口号。 +- **模板 `reference/README.md` 中性化**:从"灵枢架构 (LingShu Architecture)" + + `> "中枢一动,全栈皆通。"` 改为纯目录说明"reference/ — 治理资产"。 +- **模板 `_gitignore` 头注释脱敏**:`# 灵枢架构 (LingShu) 核心忽略规则` + → `# 核心忽略规则`;`# 灵枢架构采用嵌套克隆模式` 去品牌自称; + 基线工具列表的 ✅ 装饰改为 `-`。 +- **`hooks.mjs` post-merge 脚本头脱敏**:`# 灵枢 post-merge hook` → + `# post-merge hook`;echo 消息 `检测到灵枢规则变更` → `检测到规则变更`。 +- **CI workflow 去品牌**:`.github/workflows/rules-consistency.yml` + 头部注释 `# 灵枢架构 — CI 一致性守护` → `# CI 一致性守护`;job name + `校验灵枢规则一致性` → `校验规则一致性`。 +- **模板 `README.md` 底部脚注瘦身**:从 + `> _本仓由 [灵枢架构](https://github.com/imrui/lingshu-cli) 初始化..._` + 改为 `> _修改 reference/rules/ 真源后运行 lingshu sync 重新分发。_`—— + 去掉品牌链接,只留纯技术说明。 + +**保留(合理自我标识,不进派生仓文件系统)**: +- CLI 命令输出的 `log.banner('灵枢项目初始化')` 等——用户主动装的 CLI 工具的 + 自我标识,类似 `docker`/`git` 命令输出带工具名。 +- `lingshu sync` / `lingshu doctor` 等命令名——技术必要引用。 +- CLI 源码 JSDoc 与错误消息——不进派生仓文件系统。 +- 本仓 `lingshu-template` 的 `reference/README.md` 与 `manifesto-origin.md`—— + 本仓是灵枢主仓门面,保留品牌合理。 + +### Fixed(顺手修复的技术债) + +- **`doctor.mjs` 目录检查列表过时**:仍检查已删除的 + `reference/management/{plans,tasks,walkthroughs,reports}/` 四子目录—— + 本轮 v0.3.1 已删 management/,doctor 会全部报"缺失",是 bug。 + 重写检查逻辑为: + - [1/3] 物理完整性:仅 `reference/rules` + `reference/docs` 必需; + `reference/decisions/` 存在时提示(可选目录)。 + - [2/3] SSoT 真源:`ai-behavior.md` + `lingshu-core.md`。 + - [3/3] **基线产物**(取代原"灵枢宣言"检查):`CLAUDE.md` + `AGENTS.md`; + 缺失只 warn(可由 `lingshu sync --baseline` 补齐)。 +- **`doctor.mjs` 品牌宣言检查删除**:原 [3/3] `if (txt.includes('中枢一动,全栈皆通'))` + 依赖旧品牌口号存在于 `reference/README.md`——本轮模板已去该口号,此检查 + 必然失败。改为基线产物检查后彻底解耦品牌。 +- **CLI 仓 `README.md` 5 处过时描述修正**(非品牌问题,是随本轮改动的 + 漂移债): + - Git 直装示例锁定版本 `v0.3.0` → `v0.3.1`; + - `lingshu doctor` 描述从 "SSoT 真源 + 灵枢宣言" 改为 + "物理完整性 + SSoT 真源 + 基线产物"(与新 doctor 三步逻辑对齐); + - `lingshu upgrade` 迁移路径补充 v0.3.0 → v0.3.1 slim 说明; + - 路线图删除 `archive 🚧 待规划`(已由 `reference/decisions/` ADR 取代); + - "smoke 测试(17 项)" → "smoke 测试(22 项)"。 +- **本仓 `lingshu-template` 的 CI workflow 与 CLI 模板对齐**: + 本仓 `.github/workflows/rules-consistency.yml` 上轮遗漏同步,仍为 + `# 灵枢架构 — CI 一致性守护` + `校验灵枢规则一致性`。本轮同步为 + 模板脱敏版,避免两份事实副本漂移。 + +### Added + +- **`reference/decisions/`(ADR)**:架构决策记录目录,**可选**。仅记录架构级 + 技术选型、数据库迁移、破坏性 API 变更、跨仓协议变更、事故复盘的决策链条; + 日常任务不写 ADR,走 Git commit + PR 描述即可。 +- **`lingshu upgrade` v0.3.0 → v0.3.1 分支**:自动瘦身派生仓工作流。 + - 空的 `reference/management/{plans,tasks,walkthroughs,reports}/` 直接删除; + - 含用户内容的子目录**保留** + 输出迁移建议; + - 若 `reference/decisions/` 不存在则创建 + 写入 ADR README; + - 规则真源仍含旧措辞("自动化归档守卫" / "CRITICAL" / `reference/management/`) + 时**输出手动更新提示**,本命令不改写用户规则内容; + - 支持 `--dry-run` 预览。 +- smoke 测试 17 → 22(+5):覆盖 slim 迁移全路径与幂等性。 + +### Migration + +从 v0.3.0 升级到 v0.3.1: + +```bash +npm i -g @ruobai/lingshu@latest +cd path/to/lingshu-project +lingshu upgrade --dry-run # 预览 +lingshu upgrade # 执行 +``` + +派生仓中已归档的自定义方案文件(`reference/management/plans/*.plan.md` 等) +**不会被删除**,只是输出建议,可自行决定是否迁至 `reference/decisions/`。 + ## [0.3.0] - 2026-05-31 > **主题:零侵入 (Zero-Intrusion)** —— CLI 即唯一引擎,派生仓只保留治理资产。 @@ -92,6 +261,7 @@ - 核心命令 `init` / `sync` / `doctor` / `tool` / `limb`。 - 包名 `@ruobai/lingshu`(若白知行 npm scope)。 +[0.3.1]: https://github.com/imrui/lingshu-cli/compare/v0.3.0...v0.3.1 [0.3.0]: https://github.com/imrui/lingshu-cli/compare/v0.2.6...v0.3.0 [0.2.6]: https://github.com/imrui/lingshu-cli/compare/v0.2.5...v0.2.6 [0.2.5]: https://github.com/imrui/lingshu-cli/compare/v0.2.4...v0.2.5 diff --git a/README.md b/README.md index aca95a8..b62b0a8 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ npm install -g @ruobai/lingshu npm install -g git+ssh://git@github.com/imrui/lingshu-cli.git # 锁定版本 -npm install -g git+ssh://git@github.com/imrui/lingshu-cli.git#v0.3.0 +npm install -g git+ssh://git@github.com/imrui/lingshu-cli.git#v0.3.1 ``` > 团队协作提示:v0.3 起派生仓不含 `package.json`,同步统一走全局 `lingshu sync`。**团队每位成员各全局安装一次**即可;CI 用 `npx -y @ruobai/lingshu` 临时调用。 @@ -90,7 +90,7 @@ lingshu init my-lingshu-app \ ### `lingshu doctor` -架构健康检查(物理结构 + SSoT 真源 + 灵枢宣言)。 +架构健康检查:物理完整性(`reference/rules` + `reference/docs`)+ SSoT 真源(`ai-behavior.md` + `lingshu-core.md`)+ 基线产物(`CLAUDE.md` + `AGENTS.md`)。 ### `lingshu tool ` @@ -129,7 +129,8 @@ lingshu init my-lingshu-app \ | `--dry-run` | 仅预览将执行的动作,不写盘 | | `--force` | 即使检测到风险(如 `package.json` 含业务依赖)也继续 | -- **v0.2.x → v0.3**:删除 `.lingshu/`、删除/瘦身 `package.json`、把原 `adapters.mjs` 的 cursor frontmatter 迁入 `reference/rules/*.md`、改造 CI 为 `npx`、重装 hooks、重生成基线产物。 +- **v0.2.x → v0.3**:删除 `.lingshu/`、删除/瘦身 `package.json`、把原 `adapters.mjs` 的 cursor frontmatter 迁入 `reference/rules/*.md`(v0.3.1 起仅注入 `order`)、改造 CI 为 `npx`、重装 hooks、重生成基线产物。 +- **v0.3.0 → v0.3.1(工作流瘦身)**:删除空的 `reference/management/{plans,tasks,walkthroughs,reports}/`;含用户内容的子目录保留 + 输出迁移建议;新建 `reference/decisions/README.md`(ADR);规则真源含旧措辞(`自动化归档守卫` / `CRITICAL` / `reference/management/`)时**输出手动更新提示**,本命令不改写用户规则内容。 - **灵枢 1.0**(规则散落在产物、无 `reference/rules/` 真源):无法无损自动迁移,给出明确的手动迁移指引。 --- @@ -168,8 +169,7 @@ lingshu init my-lingshu-app \ | `tool`(track/untrack) | ✅ | | `limb` | ✅ | | `hooks` | ✅ | -| `upgrade` | ✅ | -| `archive` | 🚧 待规划 | +| `upgrade` | ✅(v0.2.x → v0.3、v0.3.0 → v0.3.1) | --- @@ -179,7 +179,7 @@ lingshu init my-lingshu-app \ git clone git@github.com:imrui/lingshu-cli.git cd lingshu-cli -npm test # 运行 smoke 测试(17 项) +npm test # 运行 smoke 测试(22 项) node bin/lingshu.mjs --help # 本地试运行 npm link # 全局链接,方便调试 ``` diff --git a/package.json b/package.json index 77a5166..99b8a48 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@ruobai/lingshu", - "version": "0.3.0", + "version": "0.3.1", "description": "灵枢架构 CLI — AI 原生项目脚手架 | 若白知行出品", "type": "module", "bin": { diff --git a/src/commands/doctor.mjs b/src/commands/doctor.mjs index 1d81168..b9cd020 100644 --- a/src/commands/doctor.mjs +++ b/src/commands/doctor.mjs @@ -4,33 +4,31 @@ * 在当前灵枢项目目录执行健康检查。 */ -import { existsSync, readFileSync } from 'node:fs'; +import { existsSync } from 'node:fs'; import { join } from 'node:path'; import { log, c } from '../utils/log.mjs'; export default async function doctor() { const root = process.cwd(); - log.banner('灵枢架构健康检查'); + log.banner('架构健康检查'); let errors = 0, warnings = 0; const ok = m => console.log(c.green(` ✓ ${m}`)); const warn = m => { console.log(c.yellow(` ⚠ ${m}`)); warnings++; }; const fail = m => { console.log(c.red (` ✗ ${m}`)); errors++; }; - // 1. 物理完整性 + // 1. 物理完整性(必需目录) console.log(c.cyan('[1/3] 物理完整性')); const requiredDirs = [ 'reference/rules', 'reference/docs', - 'reference/management/plans', - 'reference/management/tasks', - 'reference/management/walkthroughs', - 'reference/management/reports', ]; for (const d of requiredDirs) { if (existsSync(join(root, d))) ok(d); else fail(`${d} 缺失`); } + // decisions/ 是可选目录,仅当存在时提示 + if (existsSync(join(root, 'reference/decisions'))) ok('reference/decisions(可选)'); // 2. SSoT 真源 console.log(c.cyan('\n[2/3] SSoT 真源')); @@ -43,20 +41,20 @@ export default async function doctor() { else fail(`${f} 缺失`); } - // 3. 灵枢宣言 - console.log(c.cyan('\n[3/3] 灵枢宣言')); - const manifesto = join(root, 'reference/README.md'); - if (existsSync(manifesto)) { - const txt = readFileSync(manifesto, 'utf8'); - if (txt.includes('中枢一动,全栈皆通')) ok('灵枢宣言已注入'); - else warn('reference/README.md 缺少核心宣言口号'); - } else { - fail('reference/README.md (灵枢宣言) 缺失'); + // 3. 基线产物 + console.log(c.cyan('\n[3/3] 基线产物')); + const baselineFiles = [ + 'CLAUDE.md', + 'AGENTS.md', + ]; + for (const f of baselineFiles) { + if (existsSync(join(root, f))) ok(f); + else warn(`${f} 缺失(可运行 lingshu sync --baseline 生成)`); } log.blank(); if (errors === 0 && warnings === 0) { - log.ok('灵枢架构健康度:优秀'); + log.ok('架构健康度:优秀'); } else if (errors === 0) { log.warn(`通过,但有 ${warnings} 处提醒`); } else { diff --git a/src/commands/upgrade.mjs b/src/commands/upgrade.mjs index b0398f9..6b710a3 100644 --- a/src/commands/upgrade.mjs +++ b/src/commands/upgrade.mjs @@ -4,17 +4,14 @@ * --dry-run 仅打印将要执行的迁移动作,不写盘 * --force 即使检测到风险也继续(如 package.json 含业务依赖) * - * 将存量灵枢项目迁移到 v0.3 零侵入结构: - * - 删除 .lingshu/ 引擎目录 - * - 删除/瘦身 package.json(仅当是同步脚手架) - * - 把原 adapters.mjs 中 cursor 的 frontmatter 迁入 reference/rules/*.md - * - 重装内置 git hooks、改造 CI、重生成基线产物 + * 迁移路径: + * - v0.2.x → v0.3 零侵入结构(删 .lingshu、瘦 package.json、注入 frontmatter…) + * - v0.3.0 → v0.3.1 工作流瘦身(删 reference/management/ 四件套、建 decisions/) * - * 仅支持 v0.2.x → v0.3 的机械迁移;灵枢 1.0(规则散落在产物、无 reference/rules 真源) - * 无法无损自动迁移,会给出明确指引。 + * 灵枢 1.0(规则散落在产物、无 reference/rules 真源)无法无损自动迁移,仅给出手动指引。 */ -import { existsSync, readFileSync, writeFileSync, rmSync, readdirSync } from 'node:fs'; +import { existsSync, readFileSync, writeFileSync, rmSync, readdirSync, mkdirSync } from 'node:fs'; import { join } from 'node:path'; import { pathToFileURL } from 'node:url'; import { parseArgs } from '../utils/args.mjs'; @@ -40,6 +37,120 @@ function hasFrontmatter(content) { return /^---\r?\n/.test(content); } +/** ADR 目录 README(内嵌,避免依赖模板路径;与模板保持一致,技术中立) */ +function decisionsReadme() { + return `# Architectural Decision Records (ADR) + +> 记录本仓库**架构级决策**的目录,**可选**——只在需要时创建条目。 + +## 何时写 ADR + +- 架构级技术选型 +- 数据库 Schema / Migration 决策 +- 破坏性 API 变更 +- 跨仓协议变更 +- 事故复盘的关键决策链条 + +**日常任务不写 ADR**——决策链条走 Git commit message 与 PR 描述即可。 + +## 命名与格式 + +- 文件名:\`ADR-NNNN-.md\`(例:\`ADR-0001-.md\`) +- 编号连续递增,不跳号;被 Superseded 的条目保留原文件不删。 +- 建议章节:**Context** / **Decision** / **Consequences** / **Alternatives** +- 参考: + +## 状态字段(frontmatter 建议) + +\`\`\`yaml +--- +adr: 0001 +title: <决策标题> +status: Accepted # Proposed | Accepted | Superseded | Deprecated +date: YYYY-MM-DD +supersedes: null +superseded_by: null +--- +\`\`\` + +## 与 Git / PR 的分工 + +- **一次编辑背后的"为什么"** → PR 描述 +- **一个决策背后的"权衡"** → ADR(跨越多次编辑,可被后来的决策 Supersede) +`; +} + +/** v0.3 结构下是否需要 slim(工作流瘦身)迁移 */ +function needsSlimMigration(root) { + return existsSync(join(root, 'reference/management')) + || !existsSync(join(root, 'reference/decisions')); +} + +/** 判定 management/ 子目录是否可视为"空"(无内容或仅有 README.md/占位文件) */ +function isSubdirEmpty(subPath) { + if (!existsSync(subPath)) return true; + const items = readdirSync(subPath).filter((f) => f !== 'README.md'); + return items.length === 0; +} + +/** + * 规划 v0.3.0 → v0.3.1 迁移动作。 + * 返回 { actions, warnings, willDelete, createDecisions, staleRules } + */ +function planSlimMigration(root) { + const mgmtDir = join(root, 'reference/management'); + const decisionsDir = join(root, 'reference/decisions'); + const rulesDir = join(root, 'reference/rules'); + + const actions = []; + const warnings = []; + const willDelete = []; + let createDecisions = false; + + if (existsSync(mgmtDir)) { + let allEmpty = true; + const subs = readdirSync(mgmtDir); + for (const sub of subs) { + const subPath = join(mgmtDir, sub); + if (isSubdirEmpty(subPath)) { + actions.push(`删除空目录 reference/management/${sub}/`); + willDelete.push(subPath); + } else { + allEmpty = false; + warnings.push( + `reference/management/${sub}/ 含用户内容,已保留;建议评估是否迁移至 reference/decisions/(ADR)`, + ); + } + } + if (allEmpty) { + actions.push('删除空的 reference/management/'); + willDelete.push(mgmtDir); + } + } + + if (!existsSync(decisionsDir)) { + actions.push('新建 reference/decisions/README.md(ADR 说明)'); + createDecisions = true; + } + + // 规则真源含旧措辞时给出手动指引(不改动,规则真源属项目自主内容) + const staleRules = []; + if (existsSync(rulesDir)) { + for (const f of readdirSync(rulesDir).filter((n) => n.endsWith('.md'))) { + const txt = readFileSync(join(rulesDir, f), 'utf8'); + if ( + txt.includes('自动化归档守卫') + || txt.includes('强制存档 (CRITICAL)') + || txt.includes('reference/management/') + ) { + staleRules.push(`reference/rules/${f}`); + } + } + } + + return { actions, warnings, willDelete, createDecisions, staleRules }; +} + /** 序列化 frontmatter(与引擎一致的 YAML 子集) */ function renderFrontmatter(meta) { const lines = ['---']; @@ -62,7 +173,48 @@ export default async function upgrade({ args }) { } if (version === 'v0.3') { - log.ok('当前已是 v0.3 零侵入结构,无需迁移'); + // v0.3.0 → v0.3.1 工作流瘦身 + if (!needsSlimMigration(root)) { + log.ok('当前已是 v0.3.1 零仪式结构,无需迁移'); + return; + } + log.hint(`检测到结构版本: ${c.bold('v0.3.0')}(含 reference/management/ 四件套)`); + log.hint('将迁移到 v0.3.1(工作流瘦身:management → decisions/ADR)'); + log.blank(); + + const plan = planSlimMigration(root); + console.log(c.cyan('将执行以下迁移动作:')); + for (const a of plan.actions) console.log(` • ${a}`); + log.blank(); + + if (dryRun) { + log.ok('dry-run:以上动作未执行'); + if (plan.warnings.length) { log.blank(); for (const w of plan.warnings) log.warn(w); } + if (plan.staleRules.length) { + log.blank(); + log.warn('以下规则真源仍含旧措辞(自动化归档守卫 / CRITICAL / reference/management/):'); + for (const f of plan.staleRules) log.hint(` - ${f}`); + log.hint(' 建议手动更新真源;本命令不改写用户规则内容。'); + } + return; + } + + for (const p of plan.willDelete) rmSync(p, { recursive: true, force: true }); + if (plan.createDecisions) { + const decisionsDir = join(root, 'reference/decisions'); + mkdirSync(decisionsDir, { recursive: true }); + writeFileSync(join(decisionsDir, 'README.md'), decisionsReadme(), 'utf8'); + } + + log.blank(); + log.ok('迁移完成(v0.3.0 → v0.3.1,工作流瘦身)'); + if (plan.warnings.length) { log.blank(); for (const w of plan.warnings) log.warn(w); } + if (plan.staleRules.length) { + log.blank(); + log.warn('以下规则真源仍含旧措辞(自动化归档守卫 / CRITICAL / reference/management/):'); + for (const f of plan.staleRules) log.hint(` - ${f}`); + log.hint(' 建议手动更新真源;本命令不改写用户规则内容。'); + } return; } @@ -93,7 +245,8 @@ export default async function upgrade({ args }) { warnings.push(`读取旧 adapters.mjs 失败(将用默认 frontmatter): ${e.message}`); } - // 2. 为缺 frontmatter 的规则文件注入(order 按 sources 顺序,元数据取自旧 cursor 配置) + // 2. 为缺 frontmatter 的规则文件注入(仅 order,其余字段回归引擎默认; + // 自 v0.3.1 起 frontmatter 精简为只含 order,旧 cursor 元信息不再迁入) const rulesDir = join(root, 'reference/rules'); const ruleFiles = existsSync(rulesDir) ? readdirSync(rulesDir).filter((f) => f.endsWith('.md')) @@ -107,14 +260,12 @@ export default async function upgrade({ args }) { const idx = oldSources.findIndex((s) => s.name === name); const meta = { order: idx >= 0 ? idx + 1 : 99, - name, - description: cursorFm[name]?.description ?? `${name} 规则`, - globs: cursorFm[name]?.globs ?? '**/*', - trigger: cursorFm[name]?.trigger ?? 'always_on', }; fmInjections.push({ full, file, meta, body: content }); actions.push(`注入 frontmatter → reference/rules/${file}`); } + // cursorFm 在此路径下不再使用(旧字段 description/globs/trigger 由引擎默认承担) + void cursorFm; // 3. 删除 .lingshu/ actions.push('删除 .lingshu/'); diff --git a/src/core/hooks.mjs b/src/core/hooks.mjs index a41264e..898bdea 100644 --- a/src/core/hooks.mjs +++ b/src/core/hooks.mjs @@ -10,13 +10,13 @@ import { join } from 'node:path'; /** post-merge:git pull/merge 后若规则真源变更,自动用全局 CLI 重新分发 */ const POST_MERGE = `#!/bin/sh -# 灵枢 post-merge hook(由 lingshu 安装) +# post-merge hook(由 lingshu 安装) # git pull / merge 后,若 reference/rules/ 变更,自动重新分发规则到本地工具。 CHANGED=$(git diff HEAD@{1} HEAD --name-only 2>/dev/null) if echo "$CHANGED" | grep -qE "^reference/rules/"; then - echo "检测到灵枢规则变更,正在重新分发..." + echo "检测到规则变更,正在重新分发..." lingshu sync fi `; diff --git a/src/core/registry.mjs b/src/core/registry.mjs index 3aba54b..9477a1c 100644 --- a/src/core/registry.mjs +++ b/src/core/registry.mjs @@ -12,16 +12,16 @@ * (仅 Cursor 的 .mdc 需要;其余 .md 仅输出正文)。 */ -/** 单文件型产物的统一头部 */ +/** 单文件型产物的统一头部(技术中立,不带品牌自称) */ function fileHeader(title) { return [ '', '', '', '', - `# 灵枢 (LingShu) — ${title}`, + `# ${title}`, '', - '> 本文件由 `lingshu sync` 自动生成。所有规则的真理来源位于 `reference/rules/`。', + '> 本文件由 `lingshu sync` 自动生成,真源位于 `reference/rules/`。', '', ].join('\n'); } diff --git a/templates/default/.github/workflows/rules-consistency.yml b/templates/default/.github/workflows/rules-consistency.yml index fb624ce..18d90ce 100644 --- a/templates/default/.github/workflows/rules-consistency.yml +++ b/templates/default/.github/workflows/rules-consistency.yml @@ -1,9 +1,9 @@ # ========================================== -# 灵枢架构 — CI 一致性守护 (GitHub Actions) +# CI 一致性守护 (GitHub Actions) # ========================================== # 防止 reference/rules/ 真源与基线工具产物(CLAUDE.md / AGENTS.md)发生漂移。 # 仅校验 baseline 工具,因为只有它们入库;个人偏好工具产物在 .gitignore 中。 -# v0.3 零侵入:通过 npx 调用全局 CLI,仓库内不再携带同步引擎。 +# 通过 npx 调用全局 CLI,仓库内不携带同步引擎。 name: rules-consistency @@ -18,7 +18,7 @@ on: jobs: rules-consistency: - name: 校验灵枢规则一致性(baseline 工具) + name: 校验规则一致性(baseline 工具) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/templates/default/README.md b/templates/default/README.md index 812f1fd..5f57ee5 100644 --- a/templates/default/README.md +++ b/templates/default/README.md @@ -1,33 +1,13 @@ -# 灵枢 | LingShu +# lingshu-template -> **中枢一动,全栈皆通。** -> *The Central Hub Acts, The Full-Stack Synchronizes.* +> _请将本行替换为项目一句话定位。_ --- -## 架构宣言 (Manifesto) +## 项目结构 -在 AI 原生工程时代,代码的生成速度已远超人类的维护速度。传统的开发模式正面临"逻辑碎片化"挑战。 - -**灵枢架构 (LingShu)** 提出一种全新的协同方式:**"逻辑收敛于中枢,执行弥散于全栈"**。 -通过建立唯一的 **同步基座**,将产品的"逻辑灵魂"从"技术肢体"中抽离 —— 拨动"中枢"这根琴弦,让所有的执行端(AI Agents)产生同频共振。 - -👉 [**深入了解"灵枢"名称释义与设计哲学**](./reference/manifesto-origin.md) - ---- - -## 核心特性 - -| 特性 | 说明 | -|------|------| -| 🧠 **中枢-肢体解耦** | 文档/规则集中于中枢仓,业务代码分散于嵌套肢体仓 | -| 📜 **规则 SSoT** | 所有 AI 行为规则统一写在 `reference/rules/`,避免多副本漂移 | -| 🤖 **多 AI 工具适配** | 一处定义,自动分发至 6 大主流 AI 编码工具 | -| 🪶 **零侵入** | 同步引擎在全局 CLI 内,仓库只留治理资产,无 `.lingshu/`、无 `package.json` | -| 🛡️ **CI 守护** | GitHub Actions 自动校验真源与产物的一致性 | -| ⚙️ **拉取自动重分发** | `git pull` 后 post-merge hook 自动重新分发规则 | - ---- +- **中枢仓**(当前根目录):定义业务真源(`reference/docs/`)与 AI 规则(`reference/rules/`)。 +- **肢体仓**(`*-server/` / `*-ui/` / `*-mobile/` / `*-web/` 等嵌套子目录):承载业务代码,各自独立提交。 ## AI 工具支持矩阵 @@ -40,116 +20,37 @@ | Qoder | `.qoder/rules/*.md` | ❌ | 个人偏好 | | Antigravity | `.agent/rules/*.md` | ❌ | 个人偏好 | -> **是否入库由 `.gitignore` 决定**,可用 `lingshu tool track/untrack <工具>` 调整。 -> 内置工具不满足需求时,可在 `reference/.lingshu.json` 声明自定义适配器(可选逃生舱)。 +> 是否入库由 `.gitignore` 决定,可用 `lingshu tool track/untrack <工具>` 调整。 --- -## 目录导航 (Project Structure) +## 目录导航 ```text . -├── reference/ # 真源 (Reference) — 中枢的全部资产 +├── reference/ # 治理资产(中枢真源) │ ├── rules/ # AI 规则 SSoT │ │ ├── lingshu-core.md # 架构核心准则 │ │ └── ai-behavior.md # 智能体行为准则 -│ ├── docs/ # 静态真理:PRD、契约、架构 -│ ├── experience/ # 经验复利:高分 Prompt、避坑笔记 -│ └── management/ # 动态治理 -│ ├── plans/ # 战略:原始方案 (.plan.md) -│ ├── tasks/ # 战术:执行 Checklists -│ ├── walkthroughs/ # 存证:逻辑决策、代码演练 -│ └── reports/ # 审计:汇总报告、数据库变更 +│ ├── docs/ # 真源文档:PRD、契约、架构(可扩张 prd/、tad/) +│ └── decisions/ # ADR:架构决策记录(可选,仅架构级决策才写) │ -├── CLAUDE.md # Claude Code 入口(基线,由 lingshu sync 生成) -├── AGENTS.md # Codex / 通用 Agents 入口(基线,由 lingshu sync 生成) +├── CLAUDE.md # Claude Code 入口(基线产物,由 lingshu sync 生成) +├── AGENTS.md # Codex / 通用 Agents 入口(基线产物) │ ├── .cursor/ .trae/ .qoder/ # AI 工具规则目录(按需生成 / gitignore) ├── .agent/ # Antigravity 规则目录 │ -├── .github/workflows/ # GitHub Actions:CI 一致性守护 -├── .gitignore # 灵枢版忽略规则(物理隔绝肢体仓 + 个人产物) +├── .github/workflows/ # CI 一致性守护 +├── .gitignore # 忽略规则(物理隔绝肢体仓 + 个人产物) └── README.md ``` -> 同步引擎不在仓库内,而在全局 CLI [@ruobai/lingshu](https://www.npmjs.com/package/@ruobai/lingshu)。仓库保持纯净的开发资产。 - ---- - -## 快速开始 (Getting Started) - -### 推荐方式:使用 @ruobai/lingshu CLI(一条命令) - -[@ruobai/lingshu](https://www.npmjs.com/package/@ruobai/lingshu) 是灵枢架构的官方脚手架(若白知行出品),把下方手动流程压缩为 1 条命令: - -```bash -# 一次性安装(团队每位成员各装一次) -npm install -g @ruobai/lingshu - -# 一键创建项目(请将 your-org 替换为你的 GitHub 组织或用户名) -lingshu init my-lingshu-app \ - --remote=git@github.com:your-org/my-lingshu-app.git \ - --tools=claude-code,codex \ - --limbs="my-lingshu-app-server:git@github.com:your-org/my-lingshu-app-server.git,my-lingshu-app-ui:git@github.com:your-org/my-lingshu-app-ui.git" -``` - -详见 [@ruobai/lingshu 安装与命令文档](https://github.com/imrui/lingshu-cli)。 - -### 手动接入(高级用户 / CLI 不可用时) - -在 GitHub 上创建新空白仓库(如 `my-lingshu-app`),然后: - -```bash -# 1. 拉取灵枢模版 -mkdir my-lingshu-app && cd my-lingshu-app -git init --initial-branch=master -git remote add template git@github.com:imrui/lingshu-template.git -git pull template master - -# 2. 推送到自己的远程仓库(请将 your-org 替换为你的 GitHub 组织或用户名) -git remote add origin git@github.com:your-org/my-lingshu-app.git -git push -u origin master - -# 3. 嵌套拉取肢体仓(已在 .gitignore 中物理隔离) -git clone git@github.com:your-org/my-lingshu-app-server.git my-lingshu-app-server -git clone git@github.com:your-org/my-lingshu-app-ui.git my-lingshu-app-ui - -# 4. 生成基线产物 + 安装 hooks(需先全局安装 @ruobai/lingshu) -lingshu sync --baseline # 分发规则到 CLAUDE.md / AGENTS.md -lingshu hooks install # 安装 git hooks -lingshu doctor # 架构健康检查 -``` - -### 项目结构概览(接入后) - -```text -my-lingshu-app/ # [中枢仓] 逻辑定义与 AI 指令中心 -├── my-lingshu-app-server/ # [肢体仓 A] 后端代码(嵌套子仓) -├── my-lingshu-app-ui/ # [肢体仓 B] 前端代码(嵌套子仓) -├── reference/ # 真理之源 -├── CLAUDE.md / AGENTS.md # 基线 AI 指令 -└── README.md # 项目指挥总纲 -``` - -### 项目变身(替换占位符,仅手动接入需要) - -模版含 `lingshu-template` 字样的占位符。接入后批量替换: - -```bash -# Linux/macOS(或 Windows Git Bash) -grep -rl "lingshu-template" --exclude-dir=node_modules . | xargs sed -i 's/lingshu-template/my-lingshu-app/g' - -# 或交给 AI 工具: -# "请将仓库内所有文件中的 'lingshu-template' 替换为 'my-lingshu-app'" -``` - -替换后执行 `lingshu sync` 重新生成基线产物。 - --- ## 日常工作流 -### 修改 AI 规则(核心流程) +### 修改 AI 规则 ``` reference/rules/*.md ← 编辑这里(唯一真源) @@ -178,30 +79,26 @@ grep -rl "lingshu-template" --exclude-dir=node_modules . | xargs sed -i 's/lings ### 自动化机制 -- ⚡ **`git pull` 后** → `post-merge` hook 检测 `reference/rules/` 变更,自动 `lingshu sync` -- 🛡️ **PR 提交时** → GitHub Actions 校验 baseline 产物一致性,漂移即拒绝合并 +- **`git pull` 后** → `post-merge` hook 检测 `reference/rules/` 变更,自动 `lingshu sync` +- **PR 提交时** → GitHub Actions 校验 baseline 产物一致性,漂移即拒绝合并 --- -## 开发流程 (Core Workflow) +## 开发流程 -1. **定策 (Define)**:在 `reference/docs/` 修改功能逻辑或 API 协议 -2. **对齐 (Align)**:若涉及 AI 行为规则,更新 `reference/rules/` 真源 -3. **触动 (Trigger)**:唤醒 AI(Claude Code / Codex / Cursor),发出指令"请根据中枢文档同步更新肢体逻辑" -4. **皆通 (Sync)**:检查全栈代码逻辑闭环,并产出 `reference/management/walkthroughs/` 存证 +1. **定策**:在 `reference/docs/` 修改功能逻辑或 API 协议 +2. **对齐**:若涉及 AI 行为规则,更新 `reference/rules/` 真源 +3. **触动**:唤醒 AI 工具,发出指令"请根据中枢文档同步更新肢体逻辑" +4. **皆通**:检查全栈代码逻辑闭环;架构级决策才写 `reference/decisions/`(ADR) --- -## 三条核心约定 (Three Rules) +## 三条核心约定 1. **文档先行**:禁止在没有更新中枢文档(`reference/docs/`)的情况下直接修改业务代码 2. **脑体解耦**:中枢仓严禁提交任何属于肢体仓(`*-server/`、`*-ui/` 等)的业务代码 -3. **同频交付**:所有交付报告或技术存证必须记录在 `reference/management/walkthroughs/`,作为逻辑对齐的凭证 +3. **同频交付**:日常任务走 Git commit + PR 描述;仅**架构级决策**记录到 `reference/decisions/`(ADR,可选) --- -## License - -[MIT](./LICENSE) © 2026 imrui - -> 注:本仓库为架构模板。基于本模板派生的新项目可自行选择协议。 +> _修改 `reference/rules/` 真源后运行 `lingshu sync` 重新分发。_ diff --git a/templates/default/_gitignore b/templates/default/_gitignore index 84b980b..ee8d539 100644 --- a/templates/default/_gitignore +++ b/templates/default/_gitignore @@ -1,10 +1,10 @@ # ========================================== -# 灵枢架构 (LingShu) 核心忽略规则 +# 核心忽略规则 # ========================================== # --- 肢体仓库 (Sub-repos) --- -# 灵枢架构采用嵌套克隆模式,此处忽略所有具体的代码实现仓。 -# 所有的业务代码应当由对应的 Server-Group 或 Web-Group 仓库管理。 +# 采用嵌套克隆模式,此处忽略所有具体的代码实现仓。 +# 所有的业务代码应当由对应的子仓库独立管理。 *-server/ *-ui/ *-backend/ @@ -38,13 +38,13 @@ out/ .tmp/ # ========================================== -# 🤖 AI 工具规则产物(由 reference/rules/ 自动生成) +# AI 工具规则产物(由 reference/rules/ 自动生成) # 修改请编辑 reference/rules/ 真源,然后执行 `lingshu sync` # ========================================== # # 团队基线工具(入库,保证克隆即用): -# ✅ CLAUDE.md (Claude Code 项目指令) -# ✅ AGENTS.md (Codex / 通用 Agents 指令) +# - CLAUDE.md (Claude Code 项目指令) +# - AGENTS.md (Codex / 通用 Agents 指令) # # 个人偏好工具(每位开发者本地生成,不污染 git): .cursor/rules/ diff --git a/templates/default/reference/README.md b/templates/default/reference/README.md index ce90316..eeee364 100644 --- a/templates/default/reference/README.md +++ b/templates/default/reference/README.md @@ -1,26 +1,14 @@ -# 灵枢架构 (LingShu Architecture) +# reference/ — 治理资产 -> **"中枢一动,全栈皆通。"** +本目录是仓库的**真源层**——业务契约、AI 规则、架构决策统一收敛于此, +代码作为文档的投影 (Projection)。 ---- - -## 📜 灵枢宣言 (The Manifesto) - -我们坚持 **Single Source of Truth** 原则。 - -在灵枢架构中,`reference/` 是所有微服务、前端组件、数据库与 AI Agents 的共同上游。 - -1. **中枢权威性**:`reference/docs/` 定义业务真源;代码是文档的投影 (Projection)。 -2. **代码对齐**:代码与文档应保持一致;偏离时及时校正其中一方。 -3. **AI 原生**:本架构在设计上考虑 AI 上下文友好——人类在 `reference/` 中定义"意图",AI 据此实现。 - -## 📂 目录结构 +## 目录 -- **`docs/`**: **真源文档**。存储 PRD、API 契约、状态机定义。 -- **`experience/`**: **经验沉淀**。存储 Pitfalls(避坑指南)和 Best Practices。 -- **`management/`**: **动态治理层**。下设 `plans/`(战略方案)、`tasks/`(战术任务)、`walkthroughs/`(变更存证)与 `reports/`(审计报告)。 +- **`rules/`**:AI 规则真源。分发到 `CLAUDE.md`、`AGENTS.md` 等产物。 +- **`docs/`**:真源文档。存储 PRD、API 契约、状态机定义;可按需扩张 `prd/`、`tad/` 等子目录(见 [docs/README.md](./docs/README.md))。 +- **`decisions/`**:架构决策记录 (ADR),可选。仅记录架构级决策;日常任务走 Git commit 与 PR 描述。 --- -> [!NOTE] -> 本项目所有对话回复与 Git 提交信息须使用 **简体中文**。 +> 修改 `rules/` 真源后运行 `lingshu sync` 重新分发。 diff --git a/templates/default/reference/decisions/README.md b/templates/default/reference/decisions/README.md new file mode 100644 index 0000000..4ea8e3f --- /dev/null +++ b/templates/default/reference/decisions/README.md @@ -0,0 +1,38 @@ +# Architectural Decision Records (ADR) + +> 记录本仓库**架构级决策**的目录,**可选**——只在需要时创建条目。 + +## 何时写 ADR + +- 架构级技术选型 +- 数据库 Schema / Migration 决策 +- 破坏性 API 变更 +- 跨仓协议变更 +- 事故复盘的关键决策链条 + +**日常任务不写 ADR**——决策链条走 Git commit message 与 PR 描述即可。 + +## 命名与格式 + +- 文件名:`ADR-NNNN-.md`(例:`ADR-0001-.md`) +- 编号连续递增,不跳号;被 Superseded 的条目保留原文件不删。 +- 建议章节:**Context** / **Decision** / **Consequences** / **Alternatives** +- 参考: + +## 状态字段(frontmatter 建议) + +```yaml +--- +adr: 0001 +title: <决策标题> +status: Accepted # Proposed | Accepted | Superseded | Deprecated +date: YYYY-MM-DD +supersedes: null +superseded_by: null +--- +``` + +## 与 Git / PR 的分工 + +- **一次编辑背后的"为什么"** → PR 描述 +- **一个决策背后的"权衡"** → ADR(跨越多次编辑,可被后来的决策 Supersede) diff --git a/templates/default/reference/docs/README.md b/templates/default/reference/docs/README.md index 0c8abd4..77a4d75 100644 --- a/templates/default/reference/docs/README.md +++ b/templates/default/reference/docs/README.md @@ -1,15 +1,25 @@ -# 📜 灵枢之源 (Source of Truth) +# 真源文档 (Source of Truth) -> **"所有流向海洋的河,都必须记得源头的方向。"** +本目录是项目的**真源文档层**——PRD、API 契约、状态机、数据库 Schema 等 +"技术契约"应在此定义。代码是文档的投影 (Projection)。 -本目录 `contracts/` 是项目的 **唯一真理 (Single Source of Truth)**。 +## 目录扩张建议(可选) -请在开始阅读具体的契约前,先阅读 [灵枢宣言](../README.md) 以理解我们的核心哲学。 +当仓库需要同时承担"设计文档"与"编码过程"两职时,可参考以下子目录约定 +(**按需自建**,模板不预置骨架): -## 📖 文档索引 +- **`prd/`** — 产品需求文档(PRD / RFC) +- **`tad/`** — 技术架构文档(TAD / 系统设计) +- **`api/`** — API 契约(OpenAPI / GraphQL Schema) +- **`schema/`** — 数据库 Schema / 迁移 +- **`assets/`** — 附属图片、图表源文件 -- [项目全局架构](./architecture.md) -- [API 契约与数据模型](./api-contract.md) -- [业务状态机逻辑](./state-machines.md) -- [业务逻辑说明 (PRD)](./prd-template.md) +### 约定 +- **命名**:`.md`(例:`prd/user-login.md`)。Git 已记录时间线, + 文件名无需日期前缀。 +- **架构决策 (ADR)**:统一放**顶层** `reference/decisions/`,不要在此 + 嵌套 `docs/prd/decisions/` 之类的子目录。 +- **不使用数字前缀**(`01-`/`02-`)——排序交给分类与命名意图,避免手动维护顺序。 + +> 上述结构仅为建议。不需要设计文档承载能力的仓库可让本目录保持扁平。 diff --git a/templates/default/reference/experience/README.md b/templates/default/reference/experience/README.md deleted file mode 100644 index 4e85d1c..0000000 --- a/templates/default/reference/experience/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# 🧠 经验复利 (Knowledge Base) - -本目录记录在本项目开发中,调优 AI (Cursor/Trae/Qoder) 的实战经验。 - -## 目录指南 - -- `/prompts/`: 经过验证的高分 Prompt。 -- `/pitfalls/`: 记录 AI 容易犯的错误和解决方案(避坑指南)。 diff --git a/templates/default/reference/experience/pitfalls/001-port-drifting-fix.md b/templates/default/reference/experience/pitfalls/001-port-drifting-fix.md deleted file mode 100644 index af7fa74..0000000 --- a/templates/default/reference/experience/pitfalls/001-port-drifting-fix.md +++ /dev/null @@ -1,36 +0,0 @@ -# 避坑指南 001:全栈端口冲突与“禁止漂移”原则 - -- **关联领域**: #DevOps #Networking #Antigravity -- **适用 Agent**: Antigravity, Cursor, Trae, Qoder -- **创建日期**: 2026-01-16 - ---- - -## 1. 陷阱描述 (The Pitfall) -AI 在检测到默认端口(后端 5000, 前端 5173)被占用时,会**自动递增端口**(如尝试 5001 或 5174)以绕过错误,而不是解决冲突。 - -## 2. 负面影响 (Impact) -- **跨域失效**: 前端 Proxy 指向 5000,后端漂移到 5001 导致 API 请求全部失败。 -- **孤儿进程堆积**: 端口占用通常是旧进程(Flask Reloader)未释放,逃避导致系统资源持续耗损。 -- **环境一致性破坏**: 导致前后端链路无法对齐,浪费大量调试时间。 - -## 3. 根因分析 (Root Cause) -Agent 的默认决策树中,“启动成功”的权重高于“清理环境”。它不感知 Windows 11 下 Python/Node 进程树的复杂性,误以为旧进程已死。 - -## 4. 解决方案 (Lingshu Solution) - -### 强制原则:端口归位 (Port Anchoring) -严禁任何形式的端口漂移。必须执行 **“检查 -> 强杀 -> 校验 -> 重启”** 的原子流。 - -### 避坑指令 (Windows 11): -- **后端 (5000)**: `taskkill /F /IM python.exe /T` (强制清理进程树) -- **前端 (5173)**: `taskkill /F /IM node.exe /T` -- **校验**: 必须执行 `netstat -ano | findstr :` 确保输出为空后方可重新启动。 - -## 5. 规则同步 (Rules Sync) -该指南已固化至: -- `.agent/rules/network_guard.md` -- `.agent/workflows/service_reboot.md` - ---- -**[架构师笔记]**: 这是灵枢架构的第一块基石。以后凡是涉及环境重启,必须先调用此守卫逻辑。 diff --git a/templates/default/reference/experience/pitfalls/002-agent-browser-blind-retry.md b/templates/default/reference/experience/pitfalls/002-agent-browser-blind-retry.md deleted file mode 100644 index 6fe5536..0000000 --- a/templates/default/reference/experience/pitfalls/002-agent-browser-blind-retry.md +++ /dev/null @@ -1,24 +0,0 @@ -# 避坑指南 002:Agent 浏览器模式的“死循环”陷阱 - -- **关联领域**: #Agent #Antigravity #Automation -- **适用 Agent**: Antigravity (Agent Mode) -- **创建日期**: 2026-01-16 - ---- - -## 1. 陷阱描述 (The Pitfall) - -当 Antigravity 修改完 UI 代码后,会尝试以 Agent 模式启动浏览器预览。若此时前后端服务未启动或已崩溃,浏览器会陷入死循环刷新,Agent 不会自动检查终端服务状态。 - -## 2. 根因分析 (Root Cause) - -Agent 模式下的浏览器组件与 IDE 终端组件存在“感知断层”。浏览器 Agent 认为访问失败是网络抖动或渲染问题,而不具备“检查服务器进程”的联想逻辑。 - -## 3. 灵枢解决方案 (Lingshu Solution) - -- **硬性约束**: 所有的浏览器交互指令前,必须插入一步“终端服务存活校验”。 -- **判断逻辑**: 使用 `curl` 或 `Invoke-WebRequest` 探测端口响应,而非等待页面超时报错。 - ---- - -**[架构师笔记]**: 不要让 Agent 在前台空转,必须让它先低头看一眼后台的命脉。 diff --git a/templates/default/reference/experience/pitfalls/backend-sync.md b/templates/default/reference/experience/pitfalls/backend-sync.md deleted file mode 100644 index b5016e5..0000000 --- a/templates/default/reference/experience/pitfalls/backend-sync.md +++ /dev/null @@ -1,8 +0,0 @@ -# ⚠️ 避坑指南:FastAPI 异步锁问题 - -**问题描述**: Cursor 在生成异步接口时,偶尔会忽略数据库连接池的释放。 - -**解决方案**: - -- 在 `.cursor/rules/tech-stack-py.mdc` 中强制要求使用 `async with` 语法。 -- 每次生成的代码必须包含单元测试以验证并发稳定性。 diff --git a/templates/default/reference/experience/prompts/ui-generation.md b/templates/default/reference/experience/prompts/ui-generation.md deleted file mode 100644 index 8397dc1..0000000 --- a/templates/default/reference/experience/prompts/ui-generation.md +++ /dev/null @@ -1,12 +0,0 @@ -# 🎭 UI 高分 Prompt:Shadcn 复杂表格生成 - -**场景**: 当需要生成带复杂过滤和分页的表格时。 - -**Prompt 文本**: - -> "请基于 shadcn-vue 的 DataTable 组件,实现一个支持服务端分页和多条件搜索的表格。要求: -> 1. 使用 Vue3 defineProps 定义响应式数据。 -> 2. 必须符合 reference/docs/api-contract.md 中的数据结构。 -> 3. 样式参考现有风格,保持简洁。" - -**效果**: 能够减少 80% 的样式微调时间。 diff --git a/templates/default/reference/management/plans/ITERATION_TEMPLATE.md b/templates/default/reference/management/plans/ITERATION_TEMPLATE.md deleted file mode 100644 index ea915e2..0000000 --- a/templates/default/reference/management/plans/ITERATION_TEMPLATE.md +++ /dev/null @@ -1,21 +0,0 @@ -# 📅 迭代计划:[项目名] - [版本/特性名] - -**执行周期**:2026-XX-XX ~ 2026-XX-XX -**状态**:🏃 进行中 / 📝 评审中 - -## 🎯 核心目标 - -- [ ] 目标 1:中枢定义 [XX 逻辑] -- [ ] 目标 2:驱动 [Server] 实现 [XX 接口] -- [ ] 目标 3:驱动 [UI] 实现 [XX 交互] - -## 🧠 灵枢变更预设 (枢机动作) - -1. **文档更新**:修改 `reference/docs/api-contract.md` 增加 [X] 字段。 -2. **规则调整**:在 `.cursor/rules/` 中增加对 [X] 业务逻辑的特殊约束。 - -## 🤖 AI 协作策略 - -- **主驱动**:Cursor (逻辑) / Trae (界面) -- **重点关注**:确保跨端字段命名完全对齐。 - diff --git a/templates/default/reference/management/plans/README.md b/templates/default/reference/management/plans/README.md deleted file mode 100644 index 90d95fe..0000000 --- a/templates/default/reference/management/plans/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# 战略方案 (Strategic Plans) - -**路径**: `reference/management/plans/` - -## 📂 用途 -存放由 Agent 生成的原始方案文件 (`.plan.md`)。 - -## 📝 归档规约 -- 任务初始化时创建临时方案。 -- 任务进入 Done 状态时,必须将最终版方案固化至此目录。 -- 命名格式: `YYYYMMDD_ID_TaskName.plan.md` diff --git a/templates/default/reference/management/reports/README.md b/templates/default/reference/management/reports/README.md deleted file mode 100644 index 8375018..0000000 --- a/templates/default/reference/management/reports/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# 审计报告 (Audit Reports) - -**路径**: `reference/management/reports/` - -## 📂 用途 -存放审计汇总、部署清单、质量报告以及数据库变更报告 (`.report.md`)。 - -## 📝 归档规约 -- 包含月度/季度汇总。 -- **强制约束**: 若任务涉及数据库变更,需在此生成 `Migration_Report`。 -- 命名格式: `YYYYMMDD_ID_TaskName.report.md` diff --git a/templates/default/reference/management/tasks/README.md b/templates/default/reference/management/tasks/README.md deleted file mode 100644 index eeb46f6..0000000 --- a/templates/default/reference/management/tasks/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# 战术执行 (Tactical Tasks) - -**路径**: `reference/management/tasks/` - -## 📂 用途 -存放由 Agent 拆解的执行 Checklists (`.tasks.md`),用于追踪原子化步骤。 - -## 📝 归档规约 -- 记录任务的详细执行过程、状态与复盘。 -- 命名格式: `YYYYMMDD_ID_TaskName.tasks.md` diff --git a/templates/default/reference/management/walkthroughs/README.md b/templates/default/reference/management/walkthroughs/README.md deleted file mode 100644 index f71db53..0000000 --- a/templates/default/reference/management/walkthroughs/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# 技术存证 (Walkthroughs) - -**路径**: `reference/management/walkthroughs/` - -## 📂 用途 -存放重构逻辑、代码演练、决策记录以及交付报告 (`.walkthrough.md`)。 - -## 📝 归档规约 -- 任务完成后必须强制生成,记录本次迭代的核心逻辑决策。 -- 命名格式: `YYYYMMDD_ID_TaskName.walkthrough.md` diff --git a/templates/default/reference/manifesto-origin.md b/templates/default/reference/manifesto-origin.md deleted file mode 100644 index 6808321..0000000 --- a/templates/default/reference/manifesto-origin.md +++ /dev/null @@ -1,30 +0,0 @@ -# 📜 灵枢:名称释义与架构哲学 - -> **文件路径:`reference/manifesto-origin.md`** - -## 1. 溯源 (Origin) - -“灵枢”一词源自中国最早的医学典籍 **《黄帝内经·灵枢》**。 - -* **灵**:指神灵、精微、不可见之逻辑; -* **枢**:指枢轴、门户之轴、控制全身转动的关键。 - -在古籍中,《灵枢》主要论述经络、气血与针灸,强调通过精准刺入“穴位”来调理全身。这与我们架构中“通过微调中枢文档(穴位)来控制全栈代码(全身)”的思路不谋而合。 - -## 2. 架构释义 (Architectural Metaphor) - -在 **LingShu** 体系中,“灵枢”具有三重含义: - -* **其一:逻辑之枢 (Hub of Logic)** -正如门户的转动依赖于“枢”,现代应用的稳定性取决于逻辑的收敛。我们拒绝将业务逻辑碎片化地散落在后端、前端或移动端,而是将其收敛于此中枢仓库。 -* **其二:神灵之感 (Spiritual Intelligence)** -“灵”代表了 AI 的灵性。在 AI 原生开发时代,AI 是我们的执行肢体。本架构通过提供高质量的上下文(Context),让 AI 具备“灵气”,能够感知中枢意图。 -* **其三:一动皆通 (Singular Activation)** -《灵枢·九针十二原》云:“微针通其经脉,调其血气。” 在本架构中,**中枢一动,全栈皆通**。只需拨动中枢文档,便能通过同步机制让全栈执行端(Server, UI, Agent)同频共振。 - -## 3. 灵枢架构观 (The LingShu Vision) - -我们认为,理想的代码管理不是对“肢体”的死记硬背,而是对“中枢”的精微控制。 - -* **脑(Lingshu Base)**:定义真理、制定规则。 -* **体(Sub-repos)**:承载实现、扩散执行。 diff --git a/templates/default/reference/rules/ai-behavior.md b/templates/default/reference/rules/ai-behavior.md index 1065d67..db01a27 100644 --- a/templates/default/reference/rules/ai-behavior.md +++ b/templates/default/reference/rules/ai-behavior.md @@ -1,53 +1,30 @@ --- order: 2 -name: ai-behavior -description: 灵枢智能体行为准则:Plan 模式存档、真理同步流与原子化交付 -globs: **/* -trigger: always_on --- +# AI 智能体行为准则 -# 🤖 灵枢智能体行为准则 (Agentic Workflow) +## 1. 工作模式:真理驱动(软建议) -## 1. 思考模式:真理驱动 (Truth Driven) -在 **Ask 模式** 或 **Composer 模式** 中,遵循以下逻辑链: +- **寻源优先**:遇到需求变更,先看 `reference/docs/` 下的 API 契约、Schema、PRD; + 文档未定义时,建议先更新文档再动代码。 +- **跨端同步**:后端契约变动时主动提示前端影响。 +- **原子化**:一次专注一个逻辑闭环,避免跨模块混合变更。 -1. **🔍 寻源 (Locate Truth)**: - - 遇到需求变更,**首先** 检查 `reference/docs/` 下的 API 契约、数据库 Schema 或 PRD。 - - 若文档未定义,先建议用户更新文档,而不是直接写代码。 - - **口号**: "逻辑不入中枢,代码不动分毫。" +## 2. 归档(可选,仅架构决策) -2. **📝 规划 (Planning)**: - - 进入 Composer (Plan) 模式后,必须生成/更新 `.plan.md`。 - - **强制存档 (CRITICAL)**: 在执行代码修改前,必须将当前的 `.plan.md` 完整复制备份到 `reference/management/plans/` 目录下,并更新 `reference/management/tasks/` 中的执行清单。文件名格式建议:`YYYYMMDD-TaskName.md`。 +- **值得留档的场景**:架构决策、数据库迁移、破坏性 API 变更、跨仓协议变更、 + 事故复盘的决策链条。 +- **载体**:`reference/decisions/`(ADR 格式,命名 `ADR-NNNN-.md`)。 +- **日常任务不归档**——决策链条走 Git commit message + PR 描述即可。 +- **判断权**:由 AI 或用户显式判定是否值得写 ADR,不再强制。 -3. **⚡ 执行 (Execution)**: - - **跨端同步**: 始终检查后端变更对前端的影响(如 API 字段变动),并主动提示同步修改。 - - **原子化**: 每次只处理一个具体的逻辑闭环,避免跨多个不相关的功能模块修改。 +## 3. 交付规约 -## 2. 自动化归档守卫 (Archival Guard) -每当一个任务进入 **Done** 状态,AI 必须强制执行以下同步操作: - -1. **方案固化**: 将最终修订的 `.plan.md` 完整备份至 `reference/management/plans/`。 -2. **存证生成**: 生成一份详尽的 `Walkthrough`,记录本次重构的逻辑决策、核心代码变更及验证结果,存放至 `reference/management/walkthroughs/`。 -3. **任务闭环**: 更新 `reference/management/tasks/` 中的执行记录,标注所有步骤已完成。 -4. **专项审计 (Conditional)**: - - 若本次任务涉及 **数据库变更** (Schema/Migration),必须在 `reference/management/reports/` 中生成一份 `Migration_Report`。 - - 文件命名标准: `YYYYMMDD_ID_TaskName.[plan|tasks|walkthrough|report].md` - -## 3. 交付规约 (Delivery Protocol) - -- **交互语言**: 始终使用 **简体中文** 进行对话回复。 -- **Git 提交信息格式**: - - **语言**: 必须使用 **简体中文** 描述变更。 - - **中枢仓**: `docs: <描述>`, `chore: <描述>`, `plan: <描述>` - - *示例*: `docs: 更新发票 API 契约` - - **肢体仓**: `(): <描述>` - - *示例*: `feat(storage): 实现文件生命周期管理` - -- **分支管理**: - - 开发工作必须在 `feat/*` 或 `refactor/*` 分支进行,严禁直推 `master/main`。 - -- **自我修正 (Self-Correction)**: - - 如果用户指出代码与文档不符,**必须** 优先以文档(中枢真理)为准进行修正,或者询问用户是否需要反向更新文档。 +- **交互语言**:始终使用简体中文。 +- **Git 提交信息**(中文描述): + - 中枢仓:`docs: <描述>` / `chore: <描述>` + - 肢体仓:`(): <描述>`(例:`feat(storage): 实现文件生命周期管理`) +- **分支管理**:开发在 `feat/*` 或 `refactor/*` 分支进行,严禁直推 `master/main`。 +- **自我修正**:代码与文档不符时优先以文档为准,或询问用户是否反向更新文档。 --- diff --git a/templates/default/reference/rules/lingshu-core.md b/templates/default/reference/rules/lingshu-core.md index 4fe01a6..9587180 100644 --- a/templates/default/reference/rules/lingshu-core.md +++ b/templates/default/reference/rules/lingshu-core.md @@ -1,53 +1,41 @@ --- order: 1 -name: lingshu-core -description: 灵枢架构核心准则:脑体解耦、Git 物理隔离与路径映射 -globs: **/* -trigger: always_on --- +# 架构核心准则 -# 灵枢架构核心准则 (LingShu Core Principles) +## 1. 拓扑定义 +本仓库采用"中枢-肢体"分层结构: -## 1. 架构拓扑定义 (Architecture Topology) -本仓库遵循 **LingShu** 架构,实行"逻辑中枢"与"执行肢体"的物理分离。 +- **中枢仓 (The Brain)**: + - **路径**:当前根目录 `./` + - **职责**:定义真源(Reference)、规则(Rules)与架构决策(Decisions)。 + - **特征**:仅追踪文档与配置,不包含业务源代码。 -- **🧠 中枢仓 (The Brain)**: - - **路径**: 当前根目录 `./` - - **职责**: 定义真理 (Reference)、规则 (Rules)、计划 (Plans) 与审计 (Audit)。 - - **特征**: 仅追踪文档与配置,不应包含业务源代码。 +- **肢体仓 (The Limbs)**: + - **路径**:根目录下的具体工程子目录(通常命名为 `*-server`、`*-ui`、`*-mobile`、`*-web`)。 + - **职责**:承载具体的业务代码实现。 + - **识别规则**:AI 需自动扫描根目录,识别包含 `.git`(子模块 / 嵌套仓)或具体语言配置(如 `pyproject.toml`、`package.json`)的子文件夹作为"肢体"。 -- **💪 肢体仓 (The Limbs)**: - - **路径**: 根目录下的具体工程子目录(通常命名为 `*-server`, `*-ui`, `*-mobile`, `*-web`)。 - - **职责**: 承载具体的业务代码实现。 - - **识别规则**: AI 需自动扫描根目录,识别包含 `.git` (子模块/嵌套仓) 或具体语言配置(如 `pyproject.toml`, `package.json`)的子文件夹作为"肢体"。 - -## 2. Git 物理隔离规则 (Git Isolation Rules) +## 2. Git 物理隔离规则 由于采用嵌套仓库结构,必须严格遵守以下操作边界: -- **🚫 禁止根目录通配提交**: - - **严禁** 在根目录执行 `git add .` 或 `git commit -a`,这会导致肢体仓的代码被错误地纳入中枢仓版本控制。 - - 根目录 Git **仅允许** 追踪:`reference/`, AI 工具基线产物(`CLAUDE.md`, `AGENTS.md`),以及 `reference/management/` 下的任务文档。 +- **禁止根目录通配提交**: + - **严禁**在根目录执行 `git add .` 或 `git commit -a`——这会导致肢体仓的代码被错误地纳入中枢仓版本控制。 + - 根目录 Git **仅允许**追踪:`reference/` 治理资产(真源规则、docs、可选 decisions/),以及 AI 工具基线产物(`CLAUDE.md`、`AGENTS.md`)。 -- **✅ 肢体仓独立提交**: +- **肢体仓独立提交**: - 修改具体业务代码后,必须显式 `cd [limb-folder_name]/` 进入子目录。 - 确认 `git status` 显示的是子仓库的状态后,再执行提交。 -- **🛡️ 提交前自检 (Pre-commit Check)**: +- **提交前自检**: - AI 在生成 Git 指令前,必须判断当前变更的文件路径。 - 若路径属于 `*-server/` 或 `*-ui/`,必须输出 `cd` 指令作为前置操作。 -## 3. 规则真源约束 (SSoT for Rules) - -- **真源唯一**: 所有 AI 行为规则的真源位于 `reference/rules/`。 -- **产物只读**: `.cursor/rules/`、`.trae/rules/`、`.qoder/rules/`、`.agent/rules/`、`CLAUDE.md`、`AGENTS.md` 均为 **由 `lingshu sync` 自动生成的产物**,禁止手动编辑。 -- **变更流程**: 规则修改必须改动 `reference/rules/` 真源,再执行 `lingshu sync` 重新分发。 -- **CI 保障**: GitHub Actions 会校验入库产物与真源的一致性,防止漂移。 +## 3. 规则真源约束(SSoT) -## 4. 环境与依赖标准 (Stack Standard) -*(注:此部分定义模版默认技术栈,可随项目调整)* -- **Python 环境**: 推荐使用 `uv` 或 `pip` 管理依赖。 - - Windows 特殊指令: `uv` 相关命令须带 `--link-mode copy --no-install-project`。 -- **Node 环境**: 推荐使用 `npm` 管理依赖与脚本(团队统一标准)。 -- **交互语言**: 始终使用 **简体中文**。 +- **真源唯一**:所有 AI 行为规则的真源位于 `reference/rules/`。 +- **产物只读**:`.cursor/rules/`、`.trae/rules/`、`.qoder/rules/`、`.agent/rules/`、`CLAUDE.md`、`AGENTS.md` 均为**由 `lingshu sync` 自动生成的产物**,禁止手动编辑。 +- **变更流程**:规则修改必须改动 `reference/rules/` 真源,再执行 `lingshu sync` 重新分发。 +- **CI 保障**:GitHub Actions 会校验入库产物与真源的一致性,防止漂移。 --- diff --git a/tests/smoke.test.mjs b/tests/smoke.test.mjs index b9077f6..1772191 100644 --- a/tests/smoke.test.mjs +++ b/tests/smoke.test.mjs @@ -134,13 +134,13 @@ test('init --tools 只生成指定工具产物', () => { assert.ok(!existsSync(join(proj, '.trae/rules/lingshu-core.md')), '未指定的 trae 不应生成'); }); -test('生成的 cursor 产物含规则文件自身的 frontmatter', () => { +test('cursor 产物:order 是保留字段,不输出到 .mdc', () => { freshTmp(); runCli(['init', 'fm-test', '--all-tools', '--no-git', '--no-install-hooks']); const proj = join(TMP, 'fm-test'); const mdc = readFileSync(join(proj, '.cursor/rules/lingshu-core.mdc'), 'utf8'); - assert.match(mdc, /^---\n/, 'cursor .mdc 应以 frontmatter 开头'); - assert.match(mdc, /description: 灵枢架构核心准则/, '应含规则文件的 description'); + // v0.3.1 起 frontmatter 精简为仅 order;order 被过滤 → 产物不带 frontmatter + assert.ok(!mdc.startsWith('---'), '当规则真源仅含保留字段时,cursor .mdc 不应带 frontmatter'); assert.ok(!mdc.includes('order:'), '保留字段 order 不应输出到产物'); }); @@ -348,10 +348,10 @@ test('upgrade:v0.2.x → v0.3 机械迁移', () => { assert.ok(!existsSync(join(proj, '.lingshu')), '.lingshu/ 应被删除'); assert.ok(!existsSync(join(proj, 'package.json')), '纯脚手架 package.json 应被删除'); - // 规则文件应被注入 frontmatter(含原 cursor 的 description) + // 规则文件应被注入精简 frontmatter(v0.3.1 起仅注入 order;旧 cursor 元信息不迁) const core = readFileSync(join(proj, 'reference/rules/lingshu-core.md'), 'utf8'); - assert.match(core, /^---\r?\norder: 1/, '应注入 order: 1'); - assert.match(core, /description: 核心准则/, '应迁移原 cursor frontmatter 的 description'); + assert.match(core, /^---\r?\norder: 1\r?\n---/, '应注入仅含 order 的 frontmatter'); + assert.ok(!core.includes('description:'), '旧 cursor description 不应再被迁入'); // 基线产物应被重生成 assert.ok(existsSync(join(proj, 'CLAUDE.md')), '应重生成 CLAUDE.md'); @@ -403,6 +403,126 @@ test('upgrade --dry-run:只预览不写盘', () => { assert.ok(!/^---/.test(core), 'dry-run 不应注入 frontmatter'); }); +// ===== upgrade slim(v0.3.0 → v0.3.1,工作流瘦身)===== + +/** 构造 v0.3.0 结构:零侵入 + 遗留的 reference/management/ 四件套 */ +function buildV030LegacyProject(dir) { + mkdirSync(join(dir, 'reference/rules'), { recursive: true }); + mkdirSync(join(dir, 'reference/management/plans'), { recursive: true }); + mkdirSync(join(dir, 'reference/management/tasks'), { recursive: true }); + mkdirSync(join(dir, 'reference/management/walkthroughs'), { recursive: true }); + mkdirSync(join(dir, 'reference/management/reports'), { recursive: true }); + + writeFileSync(join(dir, 'reference/rules/lingshu-core.md'), + '---\norder: 1\nname: lingshu-core\ndescription: core\nglobs: **/*\ntrigger: always_on\n---\n# 核心\n', + 'utf8'); + writeFileSync(join(dir, 'reference/rules/ai-behavior.md'), + '---\norder: 2\nname: ai-behavior\ndescription: behavior\nglobs: **/*\ntrigger: always_on\n---\n# 行为\n', + 'utf8'); + + // 四子目录各留一份 README.md(视作"空") + writeFileSync(join(dir, 'reference/management/plans/README.md'), '# plans\n', 'utf8'); + writeFileSync(join(dir, 'reference/management/tasks/README.md'), '# tasks\n', 'utf8'); + writeFileSync(join(dir, 'reference/management/walkthroughs/README.md'), '# walkthroughs\n', 'utf8'); + writeFileSync(join(dir, 'reference/management/reports/README.md'), '# reports\n', 'utf8'); +} + +test('upgrade slim:v0.3.0 → v0.3.1(删空 management/、建 decisions/)', () => { + freshTmp(); + const proj = join(TMP, 'v030-legacy'); + buildV030LegacyProject(proj); + + const r = runCli(['upgrade'], { cwd: proj }); + if (r.status !== 0) { console.error('STDOUT:', r.stdout); console.error('STDERR:', r.stderr); } + assert.equal(r.status, 0, 'upgrade 应成功'); + assert.match(r.stdout, /v0\.3\.0/, '应识别为 v0.3.0'); + assert.match(r.stdout, /v0\.3\.1/, '应说明迁移到 v0.3.1'); + + assert.ok(!existsSync(join(proj, 'reference/management')), + '空 management/ 应被整体删除'); + assert.ok(existsSync(join(proj, 'reference/decisions/README.md')), + 'decisions/README.md 应被创建'); + + const readme = readFileSync(join(proj, 'reference/decisions/README.md'), 'utf8'); + assert.match(readme, /Architectural Decision Records/, 'README 内容应正确'); +}); + +test('upgrade slim:management/ 子目录含用户内容时保留 + 警告', () => { + freshTmp(); + const proj = join(TMP, 'v030-with-content'); + buildV030LegacyProject(proj); + writeFileSync( + join(proj, 'reference/management/plans/20250101_task.plan.md'), + '# 用户方案\n', 'utf8', + ); + + const r = runCli(['upgrade'], { cwd: proj }); + assert.equal(r.status, 0); + + // 含用户文件的子目录应保留 + assert.ok( + existsSync(join(proj, 'reference/management/plans/20250101_task.plan.md')), + 'plans/ 下用户文件应保留', + ); + // 空子目录应被删 + assert.ok(!existsSync(join(proj, 'reference/management/tasks')), + '空 tasks/ 应被删除'); + assert.ok(!existsSync(join(proj, 'reference/management/reports')), + '空 reports/ 应被删除'); + // decisions/ 应被建 + assert.ok(existsSync(join(proj, 'reference/decisions/README.md')), + 'decisions/README.md 应被创建'); + // warning 输出 + assert.match(r.stdout, /建议评估.*迁移至 reference\/decisions/, + '含内容子目录应输出迁移建议'); +}); + +test('upgrade slim:--dry-run 不写盘', () => { + freshTmp(); + const proj = join(TMP, 'v030-dry'); + buildV030LegacyProject(proj); + + const r = runCli(['upgrade', '--dry-run'], { cwd: proj }); + assert.equal(r.status, 0); + assert.match(r.stdout, /dry-run/); + assert.ok(existsSync(join(proj, 'reference/management')), + 'dry-run 不应删 management/'); + assert.ok(!existsSync(join(proj, 'reference/decisions')), + 'dry-run 不应建 decisions/'); +}); + +test('upgrade slim:规则真源含旧措辞时输出手动更新提示', () => { + freshTmp(); + const proj = join(TMP, 'v030-stale-rules'); + buildV030LegacyProject(proj); + // 让 ai-behavior.md 含旧措辞 + writeFileSync(join(proj, 'reference/rules/ai-behavior.md'), + '---\norder: 2\nname: ai-behavior\ndescription: legacy\nglobs: **/*\ntrigger: always_on\n---\n# 行为\n\n## 2. 自动化归档守卫\n', + 'utf8'); + + const r = runCli(['upgrade'], { cwd: proj }); + assert.equal(r.status, 0); + assert.match(r.stdout, /规则真源仍含旧措辞/, + '应提示规则真源含旧措辞'); + assert.match(r.stdout, /reference\/rules\/ai-behavior\.md/, + '应列出含旧措辞的文件路径'); +}); + +test('upgrade:init 出的新项目立即幂等(已是 v0.3.1)', () => { + freshTmp(); + runCli(['init', 'fresh-v031', '--no-git', '--no-install-hooks']); + const proj = join(TMP, 'fresh-v031'); + // 模板已带 decisions/README.md、无 management/ + assert.ok(existsSync(join(proj, 'reference/decisions/README.md')), + 'init 应带 decisions/README.md'); + assert.ok(!existsSync(join(proj, 'reference/management')), + 'init 不应带 management/'); + + const r = runCli(['upgrade'], { cwd: proj }); + assert.equal(r.status, 0); + assert.match(r.stdout, /v0\.3\.1.*无需迁移|无需迁移/, 'init 之后 upgrade 应立即幂等'); +}); + test.after(() => { if (existsSync(TMP)) rmSync(TMP, { recursive: true, force: true }); });