From fc8557f2a9062faeaa61271faf8563dfe68ea0f7 Mon Sep 17 00:00:00 2001 From: "Shin@HOME" Date: Tue, 21 Apr 2026 17:08:42 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .cursor/changelog/changelog-full.md | 5 + .cursor/changelog/changelog-headlines.md | 3 + .cursor/changelog/changelog-recent.md | 4 + .cursor/deferred/registry.md | 11 + .cursor/distillery/golden-rules.md | 5 + .cursor/distillery/insights.md | 8 + .cursor/distillery/problems.md | 5 + .cursor/hooks.json | 18 + .cursor/hooks/README.md | 38 + .cursor/hooks/check-changelog.ps1 | 105 +++ .cursor/hooks/check-changelog.sh | 58 ++ .cursor/hooks/run-hook.ps1 | 35 + .cursor/hooks/session-init.ps1 | 23 + .cursor/hooks/session-init.sh | 15 + .cursor/local-env.example.json | 5 + .cursor/pitfalls/pitfalls.md | 6 + .cursor/profile/project-profile-log.md | 5 + .cursor/profile/project-profile.md | 9 + .cursor/rules/common/baserule.mdc | 43 + .cursor/rules/common/changelog-recall.mdc | 125 +++ .cursor/rules/common/cursor-init-recall.mdc | 79 ++ .cursor/rules/common/deferred-recall.mdc | 21 + .cursor/rules/common/distillery-recall.mdc | 44 + .cursor/rules/common/epee-orchestrator.mdc | 70 ++ .cursor/rules/common/pitfall-recall.mdc | 31 + .cursor/rules/common/profile-recall.mdc | 46 + .cursor/skills/cursor-init/SKILL.md | 830 +++++++++++++++++++ .cursor/skills/deferred-decisions/SKILL.md | 151 ++++ .cursor/skills/dev-changelog/SKILL.md | 259 ++++++ .cursor/skills/epee-orchestrator/SKILL.md | 127 +++ .cursor/skills/epee-orchestrator/registry.md | 70 ++ .cursor/skills/pitfall-journal/SKILL.md | 122 +++ .cursor/skills/problem-distillery/SKILL.md | 232 ++++++ .cursor/skills/profile-memory/SKILL.md | 271 ++++++ .gitignore | 52 ++ .vscode/settings.json | 3 + 36 files changed, 2934 insertions(+) create mode 100644 .cursor/changelog/changelog-full.md create mode 100644 .cursor/changelog/changelog-headlines.md create mode 100644 .cursor/changelog/changelog-recent.md create mode 100644 .cursor/deferred/registry.md create mode 100644 .cursor/distillery/golden-rules.md create mode 100644 .cursor/distillery/insights.md create mode 100644 .cursor/distillery/problems.md create mode 100644 .cursor/hooks.json create mode 100644 .cursor/hooks/README.md create mode 100644 .cursor/hooks/check-changelog.ps1 create mode 100644 .cursor/hooks/check-changelog.sh create mode 100644 .cursor/hooks/run-hook.ps1 create mode 100644 .cursor/hooks/session-init.ps1 create mode 100644 .cursor/hooks/session-init.sh create mode 100644 .cursor/local-env.example.json create mode 100644 .cursor/pitfalls/pitfalls.md create mode 100644 .cursor/profile/project-profile-log.md create mode 100644 .cursor/profile/project-profile.md create mode 100644 .cursor/rules/common/baserule.mdc create mode 100644 .cursor/rules/common/changelog-recall.mdc create mode 100644 .cursor/rules/common/cursor-init-recall.mdc create mode 100644 .cursor/rules/common/deferred-recall.mdc create mode 100644 .cursor/rules/common/distillery-recall.mdc create mode 100644 .cursor/rules/common/epee-orchestrator.mdc create mode 100644 .cursor/rules/common/pitfall-recall.mdc create mode 100644 .cursor/rules/common/profile-recall.mdc create mode 100644 .cursor/skills/cursor-init/SKILL.md create mode 100644 .cursor/skills/deferred-decisions/SKILL.md create mode 100644 .cursor/skills/dev-changelog/SKILL.md create mode 100644 .cursor/skills/epee-orchestrator/SKILL.md create mode 100644 .cursor/skills/epee-orchestrator/registry.md create mode 100644 .cursor/skills/pitfall-journal/SKILL.md create mode 100644 .cursor/skills/problem-distillery/SKILL.md create mode 100644 .cursor/skills/profile-memory/SKILL.md create mode 100644 .gitignore create mode 100644 .vscode/settings.json diff --git a/.cursor/changelog/changelog-full.md b/.cursor/changelog/changelog-full.md new file mode 100644 index 0000000..389f6d4 --- /dev/null +++ b/.cursor/changelog/changelog-full.md @@ -0,0 +1,5 @@ +# Dev Changelog — Full + +完整的开发改动记录,按时间倒序排列。作为主动 RAG 的数据源,用户手动唤醒时读取。 + +## 记录 diff --git a/.cursor/changelog/changelog-headlines.md b/.cursor/changelog/changelog-headlines.md new file mode 100644 index 0000000..b03e961 --- /dev/null +++ b/.cursor/changelog/changelog-headlines.md @@ -0,0 +1,3 @@ +# Dev Changelog — Headlines + +最近 ~50 次改动的一句话概要,按时间倒序排列。每次会话自动注入上下文。 diff --git a/.cursor/changelog/changelog-recent.md b/.cursor/changelog/changelog-recent.md new file mode 100644 index 0000000..9883ef1 --- /dev/null +++ b/.cursor/changelog/changelog-recent.md @@ -0,0 +1,4 @@ +# Dev Changelog — Recent + +最近 ~10 次改动的摘要记录,按时间倒序排列。 +当 Agent 检测到当前任务与近期改动相关时自动读取。 diff --git a/.cursor/deferred/registry.md b/.cursor/deferred/registry.md new file mode 100644 index 0000000..c592c87 --- /dev/null +++ b/.cursor/deferred/registry.md @@ -0,0 +1,11 @@ +# Deferred Decisions Registry + +## Active Items + +(暂无延期方案) + +--- + +## Completed / Cancelled Items + +(暂无已完成或已废弃的方案) diff --git a/.cursor/distillery/golden-rules.md b/.cursor/distillery/golden-rules.md new file mode 100644 index 0000000..9b0d868 --- /dev/null +++ b/.cursor/distillery/golden-rules.md @@ -0,0 +1,5 @@ +# Golden Rules + +经过实践验证(权重 >= 5)的精炼认知,每次新会话自动注入。 + + diff --git a/.cursor/distillery/insights.md b/.cursor/distillery/insights.md new file mode 100644 index 0000000..4cf7343 --- /dev/null +++ b/.cursor/distillery/insights.md @@ -0,0 +1,8 @@ +# Problem Distillery — Insights + +从已解决的顽固问题中蒸馏出的精炼方法论。 + + + +--- +last_distill_date: 2026-04-21 diff --git a/.cursor/distillery/problems.md b/.cursor/distillery/problems.md new file mode 100644 index 0000000..c27e8f4 --- /dev/null +++ b/.cursor/distillery/problems.md @@ -0,0 +1,5 @@ +# Problem Distillery — Problems + +反复出现的顽固问题追踪记录,按时间倒序排列。 + + diff --git a/.cursor/hooks.json b/.cursor/hooks.json new file mode 100644 index 0000000..b289cdb --- /dev/null +++ b/.cursor/hooks.json @@ -0,0 +1,18 @@ +{ + "version": 1, + "hooks": { + "sessionStart": [ + { + "command": "powershell -ExecutionPolicy Bypass -File .cursor/hooks/run-hook.ps1 session-init", + "timeout": 5 + } + ], + "stop": [ + { + "command": "powershell -ExecutionPolicy Bypass -File .cursor/hooks/run-hook.ps1 check-changelog", + "timeout": 10, + "loop_limit": 1 + } + ] + } +} diff --git a/.cursor/hooks/README.md b/.cursor/hooks/README.md new file mode 100644 index 0000000..51f3c71 --- /dev/null +++ b/.cursor/hooks/README.md @@ -0,0 +1,38 @@ +# Cursor Hooks 说明 + +## 结构 + +``` +hooks/ +├── run-hook.ps1 # Windows dispatcher(读取 local-env.json 后分发) +├── session-init.ps1 # sessionStart hook(PowerShell 版) +├── session-init.sh # sessionStart hook(bash 版) +├── check-changelog.ps1 # stop hook(PowerShell 版) +├── check-changelog.sh # stop hook(bash 版) +└── README.md # 本文件 +``` + +## 跨平台适配 + +`hooks.json` 中的 `command` 字段是**平台绑定的**——Windows 用 `powershell`,macOS/Linux 用 `bash`。 + +### Windows(当前) + +hooks.json 使用 `powershell ... run-hook.ps1` 作为入口,dispatcher 根据 +`.cursor/local-env.json` 的 `shell` 字段决定执行 `.ps1` 还是 `.sh` 脚本。 + +### 迁移到 macOS / Linux + +将 hooks.json 的 command 改为直接调用 `.sh` 脚本: + +```json +{ + "version": 1, + "hooks": { + "sessionStart": [{ "command": "bash .cursor/hooks/session-init.sh", "timeout": 5 }], + "stop": [{ "command": "bash .cursor/hooks/check-changelog.sh", "timeout": 10, "loop_limit": 1 }] + } +} +``` + +同时更新 `.cursor/local-env.json` 的 `shell` 字段为 `bash` 或 `zsh`。 diff --git a/.cursor/hooks/check-changelog.ps1 b/.cursor/hooks/check-changelog.ps1 new file mode 100644 index 0000000..9243fc2 --- /dev/null +++ b/.cursor/hooks/check-changelog.ps1 @@ -0,0 +1,105 @@ +# Changelog sync guard — 统一 stop hook +# +# 用确定性逻辑检查: +# 1. 源文件是否比 changelog 更新(mtime 比较) +# 2. stdin 中的 agent 上下文是否显示有源文件编辑操作 +# +# 静默条件(不触发提醒): +# 1. 环境变量 CURSOR_SKIP_CHANGELOG 被设置(sessionStart 在非 agent 模式设置) +# 2. stdin JSON 中 composer_mode 不是 "agent"(如 debug/ask/edit 模式) +# 3. changelog 文件不存在 +# 4. .changelog-ack 标记文件存在且足够新(本会话已确认过 changelog 状态) +# 5. 没有源文件比 changelog 更新 +# 6. stdin 上下文中没有文件编辑操作的证据(防止跨会话残留 mtime 误触发) + +$input = [Console]::In.ReadToEnd() + +# === 豁免检查 1:环境变量跳过标志 === +if ($env:CURSOR_SKIP_CHANGELOG) { + Write-Output '{}' + exit 0 +} + +# === 豁免检查 2:从 stdin 解析 composer_mode === +try { + $data = $input | ConvertFrom-Json + $mode = $data.composer_mode + if ($mode -and $mode -ne "agent") { + Write-Output '{}' + exit 0 + } +} catch { + # JSON 解析失败,继续后续检查 +} + +# === 豁免检查 3:从 stdin 文本匹配 debug 上下文关键词 === +# stop hook 的 $ARGUMENTS 可能包含对话/工具上下文,检测 debug 相关信号 +if ($input -match '"mode"\s*:\s*"debug"' -or + $input -match 'debug[\s_-]?mode' -or + $input -match 'Debug Mode') { + Write-Output '{}' + exit 0 +} + +$changelog = ".cursor\changelog\changelog-headlines.md" +$srcDir = "art-agent" + +# === 豁免检查 4:changelog 文件不存在 === +if (-not (Test-Path $changelog)) { + Write-Output '{}' + exit 0 +} + +$clMtime = (Get-Item $changelog).LastWriteTime + +# === 豁免检查 5:ack 标记文件足够新 === +$ackFile = ".cursor\changelog\.changelog-ack" +if ((Test-Path $ackFile) -and (Get-Item $ackFile).LastWriteTime -ge $clMtime) { + Write-Output '{}' + exit 0 +} + +# === 豁免检查 6:stdin 中无文件编辑证据 === +# 防止跨会话残留 mtime 差异导致误触发:如果 ack 文件不存在(或过旧), +# 但 stdin 上下文中也没有任何文件写入/编辑操作的痕迹,说明本次会话 +# 没有进行代码改动,不应触发提醒。 +$hasEditEvidence = ( + $input -match 'StrReplace|Write\s*tool|edit_file|file_write|write_to_file' -or + $input -match 'Created file|Modified file|Wrote contents' -or + $input -match '"tool"\s*:\s*"(str_replace|write|edit)"' +) +if (-not $hasEditEvidence) { + Write-Output '{}' + exit 0 +} + +# === 核心检查:是否有源文件比 changelog 更新 === +$extensions = @("*.py", "*.tsx", "*.ts", "*.css") +$excludeDirs = @("node_modules", ".next", "__pycache__", "venv") + +$newerFile = $null +foreach ($ext in $extensions) { + $files = Get-ChildItem -Path $srcDir -Filter $ext -Recurse -ErrorAction SilentlyContinue | + Where-Object { + $skip = $false + foreach ($ex in $excludeDirs) { + if ($_.FullName -like "*\$ex\*") { $skip = $true; break } + } + -not $skip -and $_.LastWriteTime -gt $clMtime + } | + Select-Object -First 1 + + if ($files) { + $newerFile = $files.Name + break + } +} + +if ($newerFile) { + $msg = "[Hook] Source file updated (e.g. $newerFile) but changelog not synced. Run dev-changelog Skill operation A NOW to write all three changelog layers." + $json = '{"followup_message":"' + $msg.Replace('"','\"') + '"}' + Write-Output $json +} else { + Write-Output '{}' +} +exit 0 diff --git a/.cursor/hooks/check-changelog.sh b/.cursor/hooks/check-changelog.sh new file mode 100644 index 0000000..5265952 --- /dev/null +++ b/.cursor/hooks/check-changelog.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +# Changelog sync guard — stop hook (bash 版) + +input=$(cat) + +# === 豁免检查 1:环境变量跳过标志 === +if [ -n "$CURSOR_SKIP_CHANGELOG" ]; then + echo '{}'; exit 0 +fi + +# === 豁免检查 2:从 stdin 解析 composer_mode === +mode=$(echo "$input" | python3 -c "import sys,json; print(json.load(sys.stdin).get('composer_mode',''))" 2>/dev/null || echo "") +if [ -n "$mode" ] && [ "$mode" != "agent" ]; then + echo '{}'; exit 0 +fi + +# === 豁免检查 3:从 stdin 文本匹配 debug 上下文关键词 === +if echo "$input" | grep -qiE '"mode"\s*:\s*"debug"|debug[\s_-]?mode|Debug Mode'; then + echo '{}'; exit 0 +fi + +changelog=".cursor/changelog/changelog-headlines.md" +srcDir="art-agent" + +# === 豁免检查 4:changelog 文件不存在 === +if [ ! -f "$changelog" ]; then + echo '{}'; exit 0 +fi + +clMtime=$(stat -c %Y "$changelog" 2>/dev/null || stat -f %m "$changelog" 2>/dev/null) + +# === 豁免检查 5:ack 标记文件足够新 === +ackFile=".cursor/changelog/.changelog-ack" +if [ -f "$ackFile" ]; then + ackMtime=$(stat -c %Y "$ackFile" 2>/dev/null || stat -f %m "$ackFile" 2>/dev/null) + if [ "$ackMtime" -ge "$clMtime" ] 2>/dev/null; then + echo '{}'; exit 0 + fi +fi + +# === 豁免检查 6:stdin 中无文件编辑证据 === +if ! echo "$input" | grep -qE 'StrReplace|Write\s*tool|edit_file|file_write|write_to_file|Created file|Modified file|Wrote contents|"tool"\s*:\s*"(str_replace|write|edit)"'; then + echo '{}'; exit 0 +fi + +# === 核心检查:是否有源文件比 changelog 更新 === +newerFile=$(find "$srcDir" -type f \( -name "*.py" -o -name "*.tsx" -o -name "*.ts" -o -name "*.css" \) \ + ! -path "*/node_modules/*" ! -path "*/.next/*" ! -path "*/__pycache__/*" ! -path "*/venv/*" \ + -newer "$changelog" -print -quit 2>/dev/null) + +if [ -n "$newerFile" ]; then + fname=$(basename "$newerFile") + msg="[Hook] Source file updated (e.g. $fname) but changelog not synced. Run dev-changelog Skill operation A NOW to write all three changelog layers." + echo "{\"followup_message\":\"$msg\"}" +else + echo '{}' +fi +exit 0 diff --git a/.cursor/hooks/run-hook.ps1 b/.cursor/hooks/run-hook.ps1 new file mode 100644 index 0000000..a6b726b --- /dev/null +++ b/.cursor/hooks/run-hook.ps1 @@ -0,0 +1,35 @@ +# run-hook.ps1 — 通用 hook dispatcher +# 从 .cursor/local-env.json 读取 shell 类型,决定执行 .ps1 还是 .sh 脚本 +# 用法:powershell -ExecutionPolicy Bypass -File .cursor/hooks/run-hook.ps1 +# 示例:run-hook.ps1 session-init → 执行 session-init.ps1 或 session-init.sh + +param([string]$HookName) + +$localEnvPath = ".cursor\local-env.json" +$shell = "powershell" + +if (Test-Path $localEnvPath) { + try { + $config = Get-Content $localEnvPath -Raw | ConvertFrom-Json + if ($config.shell) { $shell = $config.shell } + } catch {} +} + +$hookDir = ".cursor\hooks" +$input = [Console]::In.ReadToEnd() + +if ($shell -eq "powershell") { + $scriptPath = Join-Path $hookDir "$HookName.ps1" + if (Test-Path $scriptPath) { + $input | powershell -ExecutionPolicy Bypass -File $scriptPath + } else { + Write-Output '{}' + } +} else { + $scriptPath = Join-Path $hookDir "$HookName.sh" + if (Test-Path $scriptPath) { + $input | bash $scriptPath + } else { + Write-Output '{}' + } +} diff --git a/.cursor/hooks/session-init.ps1 b/.cursor/hooks/session-init.ps1 new file mode 100644 index 0000000..de54553 --- /dev/null +++ b/.cursor/hooks/session-init.ps1 @@ -0,0 +1,23 @@ +# session-init.ps1 — 会话启动时检测 composer_mode,非 agent 模式设置跳过标志 +# +# sessionStart input 包含 composer_mode 字段("agent" / "ask" / "edit" / "debug" 等) +# 通过 env 输出的环境变量会传递给同会话内所有后续 hook + +$input = [Console]::In.ReadToEnd() + +try { + $data = $input | ConvertFrom-Json + $mode = $data.composer_mode +} catch { + $mode = $null +} + +Remove-Item ".cursor\changelog\.changelog-ack" -ErrorAction SilentlyContinue + +if ($mode -and $mode -ne "agent") { + $json = '{"env":{"CURSOR_SKIP_CHANGELOG":"1","CURSOR_COMPOSER_MODE":"' + $mode + '"}}' + Write-Output $json +} else { + Write-Output '{}' +} +exit 0 diff --git a/.cursor/hooks/session-init.sh b/.cursor/hooks/session-init.sh new file mode 100644 index 0000000..34bc498 --- /dev/null +++ b/.cursor/hooks/session-init.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +# session-init.sh — 会话启动时检测 composer_mode,非 agent 模式设置跳过标志 + +input=$(cat) + +mode=$(echo "$input" | python3 -c "import sys,json; print(json.load(sys.stdin).get('composer_mode',''))" 2>/dev/null || echo "") + +rm -f ".cursor/changelog/.changelog-ack" + +if [ -n "$mode" ] && [ "$mode" != "agent" ]; then + echo "{\"env\":{\"CURSOR_SKIP_CHANGELOG\":\"1\",\"CURSOR_COMPOSER_MODE\":\"$mode\"}}" +else + echo "{}" +fi +exit 0 diff --git a/.cursor/local-env.example.json b/.cursor/local-env.example.json new file mode 100644 index 0000000..963a16f --- /dev/null +++ b/.cursor/local-env.example.json @@ -0,0 +1,5 @@ +{ + "_comment": "设备绑定的本地环境配置。复制为 local-env.json 并修改为本机实际值。", + "nodejs_path": "C:\\Users\\\\AppData\\Local\\nodejs", + "shell": "powershell" +} diff --git a/.cursor/pitfalls/pitfalls.md b/.cursor/pitfalls/pitfalls.md new file mode 100644 index 0000000..faaebf1 --- /dev/null +++ b/.cursor/pitfalls/pitfalls.md @@ -0,0 +1,6 @@ +# Pitfall Journal + +开发过程中踩过的坑,按时间倒序排列。 +Agent 进入 Debug mode 或遇到运行时错误时自动检索匹配。 + +--- diff --git a/.cursor/profile/project-profile-log.md b/.cursor/profile/project-profile-log.md new file mode 100644 index 0000000..5796dbe --- /dev/null +++ b/.cursor/profile/project-profile-log.md @@ -0,0 +1,5 @@ +# Project Profile Log + +详细记录每次项目画像更新的完整上下文,按时间正序追加。 + +## 记录 diff --git a/.cursor/profile/project-profile.md b/.cursor/profile/project-profile.md new file mode 100644 index 0000000..cedb7e9 --- /dev/null +++ b/.cursor/profile/project-profile.md @@ -0,0 +1,9 @@ +# Project Profile + +## 项目定位 + +## 技术栈与架构 + +## 设计约定 + +## 产品方向 diff --git a/.cursor/rules/common/baserule.mdc b/.cursor/rules/common/baserule.mdc new file mode 100644 index 0000000..b017d8f --- /dev/null +++ b/.cursor/rules/common/baserule.mdc @@ -0,0 +1,43 @@ +--- +description: 跨项目底层通用约定(语言、目录归属) +alwaysApply: true +--- + +## 语言约定 + +Agent回复时使用简体中文。 +代码注释时尽量使用简体中文。 +写SKILL的时候文档部分也尽量使用简体中文。 +专业术语和项目专有名词不受此语言限制,通常是英文则保留。 + +## Rules / Skills 目录归属约定 + +本项目使用以下目录结构区分跨项目通用内容与项目专属内容: + +### Rules + +| 目录 | 用途 | 示例 | +|------|------|------| +| `.cursor/rules/common/` | 跨项目通用规则,开新项目时可直接复制 | 语言约定、Orchestrator 触发、延期方案回忆 | +| `.cursor/rules/project/` | 当前项目专属规则 | 项目架构约定、框架特定规范、项目专属工作流 | + +### Skills + +| 位置 | 用途 | 示例 | +|------|------|------| +| `.cursor/skills/` | **所有 Skill 的主存储位置**(含通用和项目专属) | epee-orchestrator、deferred-decisions、项目特定 Skill | +| `~/.cursor/skills/` | 跨项目通用 Skill 的全局副本(可选,方便其他项目复用) | epee-orchestrator、deferred-decisions | + +> **重要**:无论 Skill 是通用还是项目专属,都**必须**在项目的 `.cursor/skills/` 下保留一份, +> 以确保能被 Git 管理和版本控制。全局目录 `~/.cursor/skills/` 仅作为跨项目共享的便利副本, +> 不作为唯一存储位置。 + +### Agent 创建 Rule 或 Skill 时必须遵守 + +1. **先判断归属**:新建 Rule 或 Skill 前,评估其是否为跨项目通用内容 +2. **如果不确定,必须询问用户**:"这个 Rule/Skill 是通用的还是项目专属的?" +3. 确认后放入对应目录: + - 通用 Rule → `.cursor/rules/common/` + - 项目专属 Rule → `.cursor/rules/project/` + - **所有 Skill(含通用)→ `.cursor/skills/`**(必须,确保 Git 可管理) + - 通用 Skill 额外同步 → `~/.cursor/skills/`(可选,方便其他项目使用) diff --git a/.cursor/rules/common/changelog-recall.mdc b/.cursor/rules/common/changelog-recall.mdc new file mode 100644 index 0000000..951433b --- /dev/null +++ b/.cursor/rules/common/changelog-recall.mdc @@ -0,0 +1,125 @@ +--- +description: 每次会话开始时注入开发日志概要(L3),并在检测到任务与近期改动相关时自动读取中期记录(L2) +alwaysApply: true +--- + +## 开发日志上下文注入 + +每次会话处理用户第一个任务前,执行以下操作: + +1. 读取 `.cursor/changelog/changelog-headlines.md`(不存在则跳过) +2. 如文件存在且有实质内容(不仅是模板头部),将全部条目作为背景知识注入上下文 +3. 这些信息帮助 Agent 快速建立位置感:项目进展到什么阶段、最近的工作重心在哪个模块 +4. 在后续回复中自然参考,不显式提及"根据开发日志" + +## 主动定位辅助 + +L3 概要的核心价值之一是帮助 Agent 在**冷启动**(新会话、无上下文)时理解用户意图。 +当用户的请求缺少具体文件名或模块名时,Agent 应主动利用 L3 进行推断: + +### 典型场景 + +1. **隐式延续**:用户说"继续做昨天那个"、"把那个功能完善一下" + → 从 L3 中找到最近的相关条目,上溯到 L2 获取具体文件列表 +2. **模糊指代**:用户说"那个组件有 bug"、"之前改的那个接口" + → 用 L3 中的关键词匹配用户描述,定位到具体改动 +3. **上下文补全**:用户直接提出一个任务,没有背景说明 + → 用 L3 判断该任务是否与近期某个改动有关联(如同一模块、同一功能线) + +### 流程 + +``` +1. 解析用户请求,识别是否存在隐式引用或模糊指代 +2. 在 L3 概要中查找语义最匹配的 1-3 条记录 +3. 提取匹配条目的锚点 ID,上溯到 L2 获取 affected_files 和 tags +4. 如有必要,继续上溯到 L1 获取完整的决策背景 +5. 将定位到的文件/模块作为任务的起点,开始执行 +``` + +如果 L3 中没有匹配到任何相关记录,正常处理即可——不是所有任务都与近期改动有关。 + +## L2 自动触发 + +Agent 开始处理一个新任务时,判断是否需要读取近期详细记录: + +1. 从当前任务中提取涉及的文件路径和语义关键词 +2. 与 L3 概要中的内容做快速比对——如果近期有相关模块/文件的改动记录 +3. 命中时,读取 `.cursor/changelog/changelog-recent.md`,将相关条目纳入上下文 +4. 匹配策略: + - 硬匹配:当前任务涉及的文件出现在 L2 条目的 `affected_files` 中 + - 软匹配:当前任务的语义关键词与条目的 `tags` 有交集 + - 任一命中即触发读取 + +### 注意 + +- L3 注入是低成本操作(~50 句话),每次会话都执行 +- L2 读取按需触发,只在检测到关联时才读取 +- 开发日志是事实性记录,直接使用即可,不像画像那样需要"自然融入"的措辞考量 +- 记录的写入和管理由 `dev-changelog` Skill 负责,本 Rule 只负责读取和注入 + +## 逐级上溯 + +当 L3 中某条记录的一句话描述**语义模糊**(无法判断具体范围或与当前任务的关系), +按以下步骤精准上溯,**禁止全文读取 L1**: + +1. 提取该条目的锚点 ID(`CL-xxx`) +2. 用 Grep 在 `changelog-recent.md`(L2)中搜索该 ID → 找到则读取该条目 +3. 如 L2 中未找到或仍有歧义 → 用 Grep 在 `changelog-full.md`(L1)中搜索该 ID, + 获取行号后用 Read 工具读取该行号 ±20 行范围 +4. 一次上溯通常只涉及 1-3 条记录,不批量上溯 + +## 任务完成 Checklist(强制) + +Agent 在即将输出最终回复前,**必须**逐项检查以下清单。 +这是硬性要求,不是建议——**跳过任何一项都视为执行错误**。 + +### 前置项(每次回复前无条件执行) + +**A. 画像信号扫描(短路版)** + +目的:以最小 token 成本维持 `profile-memory` Skill 的被动检测通路。 + +步骤: + +1. **快判(词表匹配)**:扫描本次对话中**用户消息**,检查是否**明显**出现以下偏好/决策触发词族之一: + + - 个人偏好信号:`我喜欢` / `我倾向` / `我不喜欢` / `我讨厌` / `以后都` / `以后别` / + `别再` / `不要再` / `我的风格` / `我的偏好` / `太花哨` / `minimal` / + `简洁` / `精炼` / `啰嗦` + - 项目决策信号:`这个项目是` / `目标用户是` / `技术栈` / `架构上` / + `产品方向` / `定位是` + +2. **分支**: + - 无匹配 → **直接跳过**,进入下一 checklist 项(thinking 应在 50 token 内结束) + - 有匹配 → 读取 `.cursor/skills/profile-memory/SKILL.md` 并执行操作 A 的确认流程 + +3. **约束**:本项不做全量语义判断——漏记隐式信号是可接受的权衡。 + 用户如需记录隐式偏好可显式说"把这条记入画像"。 + +### 变更检查项(仅当本次有代码/配置文件改动时执行) + +1. **本次是否有代码/配置文件改动?**(不含 `.cursor/` 下的基础设施文件) + - 否 → 跳过本组后续项,直接进入"收尾项" + - 是 → 继续 + +2. **是否已写入三层开发日志?** + - 否 → **立即**读取 `dev-changelog` Skill 并执行操作 A,写入 L1 + L2 + L3 后再输出回复 + - 是 → 继续 + +3. **是否修改了任何 Skill?**(包括 SKILL.md 内容变更) + - 否 → 跳过 + - 是 → 检查是否已同步 `epee-orchestrator` 的 `registry.md`,未同步则立即执行 + +4. **本次是否有 Skill 使用异常?**(遗漏、误触、产物与用户预期偏差) + - 否 → 跳过 + - 是 → 执行 `epee-orchestrator.mdc` 中的自迭代确认流程 + +### 收尾项(每次回复前无条件执行) + +**Z. 静默 Hook ack** + +- 用 Write 工具创建空文件 `.cursor/changelog/.changelog-ack` +- 这会更新 ack 文件的 mtime,阻止 `check-changelog.ps1` hook 在后续回复中重复提醒 + +**执行原则**:先完成 checklist 中的所有写入动作,再输出面向用户的回复文本。 +回复末尾如果执行了变更检查项第 2 项,附 `[已记录到开发日志]`。 diff --git a/.cursor/rules/common/cursor-init-recall.mdc b/.cursor/rules/common/cursor-init-recall.mdc new file mode 100644 index 0000000..5e711e1 --- /dev/null +++ b/.cursor/rules/common/cursor-init-recall.mdc @@ -0,0 +1,79 @@ +--- +description: 引导 Agent 在首次会话自动、后续通过关键词手动触发 cursor-init Skill +globs: +alwaysApply: true +--- + +## 首次初始化自检(最高优先级 · 必须最先执行) + +**每一次会话的首次用户消息响应之前**,Agent 必须先检查工作区是否存在 `.cursor/.init-done`: + +### 判定逻辑 + +``` +IF .cursor/.init-done 不存在: + → 本仓库是"clone 模板后的首次会话" + → 必须在处理用户原始请求之前先完成 cursor-init +ELSE: + → 已 init 过,跳过本自检 + → 仅当用户命中下方"手动触发关键词"时才再次执行本 Skill +``` + +### 首次触发的执行方式 + +1. **暂存用户原始请求**,明确告诉用户: + > "检测到当前仓库刚从模板 clone 下来,还未完成 .cursor 初始化。需要先跑一遍 cursor-init + > (清理模板遗留数据、配置项目画像、可选生成 .gitignore)。完成后再处理你的请求:{原始请求概要}。" +2. 等用户明确回复"继续/OK"后,读取 `.cursor/skills/cursor-init/SKILL.md` 并严格执行阶段 0 → 7 +3. **init 完成后**(阶段 7 写入 `.init-done` 成功后),回到被暂存的用户原始请求继续处理 +4. 若用户说"先不做 init,就处理我的请求": + - 尊重用户选择,跳过本次 init + - 但仍在本次回复中明确说明 sentinel 缺失,并提示"下次会话还会再次提醒" + +### 自检成本说明 + +已 init 项目:每次会话仅多一次 `Read .cursor/.init-done`(极低成本)。 +若 Read 失败或路径不存在,即按"首次"处理。 + +--- + +## 手动触发关键词(任意时刻,已 init 仓库也可用) + +### A. 全流程重置(阶段 0 → 7) + +匹配任一: +- "初始化 cursor" / "初始化cursor" / "cursor 初始化" +- "重置 cursor" / "reset cursor" +- "cursor init" / "init cursor" +- "把复制过来的 .cursor 清理一下" / "按 baserule 归位一下" + +**执行方式**:读取 `.cursor/skills/cursor-init/SKILL.md`,按阶段 0 → 7 执行。 +若 `.cursor/.init-done` 已存在,阶段 0 会展示其元数据并要求用户二次确认。 + +### B. 仅补 .gitignore(只跑阶段 5.5) + +匹配任一: +- "补 gitignore" / "补一下 gitignore" / "补个 gitignore" +- "生成 gitignore" / "生成 .gitignore" +- "gitignore 模板" / "来份 gitignore" + +**执行方式**:读取 SKILL.md 的**阶段 5.5 章节**单独执行,不触碰其他阶段。 +完成后更新 `.init-done` 中的 `gitignore_generated: true`。 + +--- + +## 执行原则 + +1. **稳定准确优先于 token 成本** +2. 破坏性操作(删除、重置、移动)前必须给用户 dry-run 清单 +3. 分类不清的文件必须逐条询问用户,不要猜 +4. 开始前先执行 `git status` 并提醒用户 commit/stash +5. 设计为幂等——重复运行在已干净状态下不应造成破坏 + +--- + +## 不触发本 Skill 的情况 + +- 用户只是问"cursor 有什么 skill" —— 这是浏览需求,走 `epee-orchestrator` 的操作 A +- 用户只是想初始化某个具体数据文件(如"初始化画像")—— 走对应 Skill(`profile-memory` 等),不涉及全局重置 +- `.cursor/.init-done` 存在 且 用户请求中**没有**任一 A/B 组关键词 —— 正常响应用户,不提 init diff --git a/.cursor/rules/common/deferred-recall.mdc b/.cursor/rules/common/deferred-recall.mdc new file mode 100644 index 0000000..1f66c76 --- /dev/null +++ b/.cursor/rules/common/deferred-recall.mdc @@ -0,0 +1,21 @@ +--- +description: 每次会话开始时扫描延期方案记录,在任务与已有 deferred item 关联时主动提醒用户 +alwaysApply: true +--- + +## 延期方案主动回忆 + +每次会话处理用户第一个任务前,执行以下检查: + +1. 读取 `.cursor/deferred/registry.md`(不存在则跳过) +2. 扫描所有 `status: deferred` 的条目 +3. 将每个条目的 **tags** 和 **related_files** 与当前任务的关键词/文件做匹配 +4. 如果匹配到关联条目,在回复开头简要提醒: + > 提醒:你之前有一个延期方案 **[标题]** 与当前任务相关(tags: xxx)。要一并处理吗? +5. 每个条目每次会话最多提醒一次,不重复打扰 + +### 注意 + +- 只匹配 `status: deferred` 的条目(`reminded` / `in_progress` 不再提醒) +- 提醒应简洁,不超过 2 行,不打断用户主线任务 +- 具体的记录/管理操作请参考 `deferred-decisions` Skill diff --git a/.cursor/rules/common/distillery-recall.mdc b/.cursor/rules/common/distillery-recall.mdc new file mode 100644 index 0000000..f47815f --- /dev/null +++ b/.cursor/rules/common/distillery-recall.mdc @@ -0,0 +1,44 @@ +## Problem Distillery 上下文注入 + +### Golden Rules 注入 + +每次会话处理用户第一个任务前,执行以下操作: + +1. 读取 `.cursor/distillery/golden-rules.md`(不存在则跳过) +2. 如文件存在且有实质条目(不仅是标题),将全部条目作为背景知识注入上下文 +3. 这些是经过实践反复验证的精炼认知,Agent 在分析和解决问题时应自然参考 +4. 不需要在回复中显式提及"根据 Golden Rule" + +### 蒸馏提醒检查 + +每次会话处理用户第一个任务前,额外检查: + +1. 读取 `.cursor/distillery/insights.md`(不存在则跳过) +2. 检查文件尾部的 `last_distill_date` 字段 +3. 如果距今超过 7 天,读取 `.cursor/distillery/problems.md` +4. 统计 `status: resolved` 且无 `distilled:` 标记的条目数量 +5. 如有未蒸馏的已解决条目,提醒用户: + > 你有 N 个已解决的顽固问题尚未总结,要花几分钟蒸馏一下吗? +6. 每次会话最多提醒一次 + +### 顽固问题检测 + +Agent 在整个对话过程中应保持对以下信号的被动感知: + +1. 用户表达问题未解决:"还有问题"、"没解决"、"还是一样"、"又出现了"、"不行"、"没用" +2. Agent 自身意识到同一问题已尝试 2 次以上仍未解决 +3. pitfall-journal 中已有记录的问题再次出现 + +检测到上述信号时,读取 `problem-distillery` Skill 并执行其操作 A。 + +### 验证触发 + +当操作 A 触发时(追踪新的或再次出现的顽固问题),如果 `insights.md` 非空, +还应执行操作 D 的被动验证流程——匹配是否有相关的已蒸馏经验可供参考。 + +### 注意 + +- Golden Rules 注入是极轻量操作(预期 < 30 行),每次会话都执行 +- 蒸馏提醒按需触发,只在条件满足时提醒 +- problems.md 的详细记录**不主动读取**,仅在操作 A/B/C 时按需读取 +- 本 Rule 只负责触发和注入,具体操作流程由 `problem-distillery` Skill 定义 diff --git a/.cursor/rules/common/epee-orchestrator.mdc b/.cursor/rules/common/epee-orchestrator.mdc new file mode 100644 index 0000000..1162057 --- /dev/null +++ b/.cursor/rules/common/epee-orchestrator.mdc @@ -0,0 +1,70 @@ +--- +description: >- + EPEE Skill Orchestrator 触发入口。检测当前任务是否可由已有 Skill 处理, + 或是否值得创建新 Skill。同时管理 Skill 变更后的 Registry 同步和自迭代经验积累。 +alwaysApply: true +--- + +## EPEE Skill Orchestrator — 触发雷达 + +### 被动检测 + +Agent 在制定方案或执行任务过程中,如果发现当前任务符合以下**任意一条**特征, +必须读取 `epee-orchestrator` Skill 的 SKILL.md 并执行其分流流程: + +1. **手动配置密集**:任务需要用户在 IDE 或工具中进行大量手动配置 + (如批量填写配置字段、逐一调整参数等) +2. **重复模式明确**:同类操作预计会反复出现(如批量创建同结构的配置文件、 + 批量设置同类模块等) +3. **手工指引过长**:Agent 发现自己正在生成超过 10 步的"手动操作步骤" + 而非直接产出代码或配置文件 + +### Registry 同步(强制) + +每次**创建**或**修改**任何 Skill(包括 SKILL.md 内容变更、新增 Skill 等)后, +Agent **必须**执行以下操作: + +1. 读取 `epee-orchestrator` Skill 目录下的 `registry.md` +2. 更新或新增对应 Skill 的条目(格式参见 registry.md 中的条目结构) +3. 确保条目中的能力描述和触发场景与 Skill 实际内容一致 + +> **注意**:此项已纳入 `changelog-recall.mdc` 的"任务完成 Checklist"第 3 项。 +> 如果 Agent 在 checklist 阶段发现遗漏,必须立即补执行。 + +### Skill 自迭代(强制) + +每个 SKILL.md 必须包含一个"自迭代日志"章节,用于记录使用该 Skill 过程中发现的经验教训。 + +**触发条件** — 在创建或使用任何 Skill 时,遇到以下情况应触发自迭代流程: + +1. 因信息缺失导致生成结果错误或构建失败 +2. 用户需要反复补充同类信息 +3. 生成产物与用户预期存在系统性偏差 + +> **注意**:此项已纳入 `changelog-recall.mdc` 的"任务完成 Checklist"第 4 项。 +> Agent 不应等到"下次使用 Skill 时"才想起自迭代——当次就应检查。 + +**流程**: + +1. 识别问题根因,归纳为一条简明的检查项 +2. 向用户确认:"是否要将此项记录到该 Skill 的自迭代日志中?" +3. 用户同意后,追加到对应 SKILL.md 的"已知必要检查"列表 +4. 后续使用该 Skill 时,必须遵守日志中已记录的所有检查项 + +**SKILL.md 中的格式**: + +```markdown +## 自迭代日志 + +本节记录使用本 Skill 过程中发现的必要检查项。 + +### 已知必要检查 + +1. **检查项名称** — 简要说明原因和应对方式。 +``` + +**原则**: + +- 每条检查项应当**具体可执行**,而非泛泛的提醒 +- 检查项只增不删,除非用户明确要求移除 +- 新建 Skill 时须预置空的自迭代日志章节 diff --git a/.cursor/rules/common/pitfall-recall.mdc b/.cursor/rules/common/pitfall-recall.mdc new file mode 100644 index 0000000..da8fb39 --- /dev/null +++ b/.cursor/rules/common/pitfall-recall.mdc @@ -0,0 +1,31 @@ +## 踩坑经验自动检索 + +### 被动检测触发 + +Agent 在以下场景中,应自动读取 `.cursor/pitfalls/pitfalls.md` 并进行匹配检索: + +1. **进入 Debug mode**:读取全部条目,将当前错误症状与已有记录比对 +2. **遇到运行时错误**:提取错误信息关键词,在"症状"字段中检索匹配 +3. **同一问题第二次出现**:如果当前会话中某个错误已出现过一次且未解决,强制检索 + +### 匹配策略 + +``` +1. 提取当前问题的信号:错误信息关键词、涉及文件/模块、技术栈 +2. 在 pitfalls.md 中匹配: + - 硬匹配:错误关键词出现在条目的"症状"中 + - 软匹配:模块/技术栈出现在条目的"关联"中 +3. 命中时在分析开头提示: + > 注意:之前遇到过类似问题 [PF-xxx]:[标题]。根因是 [xxx],先排查这个方向。 +``` + +### 写入提醒 + +Agent 在完成涉及 debug/修复的任务后,应读取 `pitfall-journal` Skill 并执行其"操作 A:写入记录"流程。 +判断标准:问题的根因是否"非显而易见"——如果只看代码逻辑觉得应该没问题,但实际运行时才暴露,就值得记录。 + +### 注意 + +- 检索结果是**辅助参考**,不是确定性答案——匹配到不代表根因一定相同 +- pitfalls.md 不存在时跳过,不报错 +- 每次会话中对同一条 pitfall 最多提醒一次 diff --git a/.cursor/rules/common/profile-recall.mdc b/.cursor/rules/common/profile-recall.mdc new file mode 100644 index 0000000..6dec597 --- /dev/null +++ b/.cursor/rules/common/profile-recall.mdc @@ -0,0 +1,46 @@ +--- +description: 每次会话开始时读取用户画像和项目画像,将精简 Profile 注入上下文以指导 Agent 行为 +alwaysApply: true +--- + +## 画像上下文注入 + +每次会话处理用户第一个任务前,执行以下操作: + +1. 读取 `~/.cursor/profile/user-profile.md`(不存在记为 user_missing) +2. 读取 `.cursor/profile/project-profile.md`(不存在记为 project_missing) +3. **冷启动检测**:如果 user_missing 或 project_missing 为真,在回复开头简要提醒: + > 画像系统尚未初始化(缺少:user-profile / project-profile)。 + > 如需启用画像功能,请说"初始化画像",我会引导你完成。 + - 每次会话最多提醒一次,不重复打扰 + - 如用户回应"初始化画像",读取 `profile-memory` Skill 并按其模板创建文件, + 然后引导用户填写基本信息 +4. 如文件存在且有实质内容(非空模板),将其内容作为背景知识纳入考量 +5. 在后续回复中,Agent 应自然地参考画像信息,无需显式引用 + +### 注意 + +- 画像信息是背景参考,不是硬性约束——当用户当前指令与画像冲突时,以当前指令为准 +- 不要在回复中提及"根据你的画像"之类的措辞,自然融入即可 +- 画像的记录和管理由 `profile-memory` Skill 负责,本 Rule 只负责读取和注入 + +### 逐级上溯 + +当精简版 Profile 中某条记录**语义模糊**(无法判断偏好的具体适用场景), +按以下步骤精准查找详细 Log,**禁止全文读取 Log 文件**: + +1. 提取该条目的锚点 ID(HTML 注释中的 `PF-xxx`) +2. 用 Grep 在对应的 Log 文件中搜索该 ID,获取行号 +3. 用 Read 工具读取该行号 ±15 行范围,获取原始上下文和来源信息 +4. 一次上溯通常只涉及 1-2 条记录,不批量上溯 + +## 被动检测触发点 + +被动检测不在本 Rule 执行,而是由 `changelog-recall.mdc` 的 +**任务完成 Checklist 前置项 A(画像信号扫描)** 统一触发。 + +理由:本 Rule 仅负责上下文注入(低成本、每次必做);被动检测需要挂入 +已有强制力的 checklist 中才能避免被 Agent 遗漏,该 checklist 由 +`changelog-recall` 维护,两者分工清晰。 + +具体触发词族和短路逻辑详见 `changelog-recall.mdc` 中的前置项 A 定义。 diff --git a/.cursor/skills/cursor-init/SKILL.md b/.cursor/skills/cursor-init/SKILL.md new file mode 100644 index 0000000..fcbbe33 --- /dev/null +++ b/.cursor/skills/cursor-init/SKILL.md @@ -0,0 +1,830 @@ +--- +name: cursor-init +description: >- + 初始化新项目的 .cursor 结构。两种触发方式: + (1)首次自动触发 —— 当 `.cursor/.init-done` sentinel 不存在时,`cursor-init-recall.mdc` + 会在会话首次响应前引导 Agent 主动执行本 Skill; + (2)关键词手动触发 —— "初始化cursor"、"cursor init"、"重置 cursor"、"补 gitignore" 等。 + 流程:识别并迁移目标项目原有的 rules/skills,清理模板残留的项目专用数据 + (changelog/deferred/pitfalls/profile/distillery/local-env/项目级 rules 与 skills), + 可选生成 .gitignore 模板,最后写入 `.cursor/.init-done` 标记完成。 + 已 init 仓库不会再自动触发,除非用户主动通过关键词请求。 +--- + +# Cursor Init Skill + +把从其它项目复制过来(或通过 git clone 模板仓库获得)的 `.cursor/` 目录重置为当前新项目的干净起点。 + +## 使用场景 + +### 场景 A:克隆模板仓库后的首次会话 + +``` +1. 用户把本模板作为 git 仓库发布 +2. 其他人 `git clone <模板仓库>` 得到新项目骨架 +3. 用户打开 Cursor,在该仓库发出任意第一条消息 +4. `cursor-init-recall.mdc`(alwaysApply)检测 .cursor/.init-done 不存在 + → 引导 Agent 暂停用户原始请求,先执行本 Skill +5. Agent 按阶段 0 → 7 跑完,写入 .init-done +6. 后续会话 sentinel 已存在,不再自动触发 +``` + +### 场景 B:从已有项目直接复制 .cursor 目录 + +``` +1. 用户在 "源项目 A" 中使用本 .cursor 模板开发 +2. 用户开 "新项目 B",把 A 的 .cursor/ 整体拷贝到 B +3. B 原先可能也有自己零散的 rules/SKILL 文件(未必标准) +4. 用户在 B 中说"初始化cursor"(或首次会话被 recall 触发) +5. 本 Skill 把 B 原有的 rules/skills 按 baserule 归位,清空 A 遗留的项目数据, + 重建 registry,生成 .gitignore,写入 sentinel +``` + +### 场景 C:只补 .gitignore + +``` +init 后用户说"补一下 gitignore"或"生成 gitignore" → 只跑阶段 5.5 +``` + +## 触发条件 + +本 Skill 由 `cursor-init-recall.mdc` 触发,两类入口: + +### A. 全流程(阶段 0 → 7) + +- `.cursor/.init-done` 不存在 → 会话首次响应前由 recall 规则自动引导 +- 用户关键词:`初始化cursor` / `cursor init` / `重置 cursor` / `reset cursor` 等 +- 口头描述"把复制过来的 .cursor 清理一下"、"按 baserule 归位一下" + +### B. 仅补 .gitignore(只跑阶段 5.5) + +- 用户关键词:`补 gitignore` / `生成 gitignore` / `gitignore 模板` +- 跳过阶段 1-5 和阶段 7 的除"更新 gitignore_generated 字段"外的其他操作 + +## 执行原则(不可协商) + +1. **稳定准确 > token 成本**:每一步可以多读、多确认、让用户点头,不要图快 +2. **破坏性操作必须 dry-run**:删除、重置必须先列清单给用户确认 +3. **不可逆操作前提醒 git**:开始前先提示用户确认工作区已 commit/stash +4. **模糊就问**:分类不清的文件一律问用户,不要猜 +5. **幂等**:反复运行应当无害(第二次在已干净状态下不会做破坏) +6. **中断可恢复**:任何阶段异常 abort **不写入** `.init-done`,下次会话仍会被 recall 触发从头继续 + +## 核心流程 + +### 阶段 0:前置确认 + 幂等判断 + +``` +1. 检查当前工作目录下存在 .cursor/ + - 不存在 → 直接结束,提示用户先复制模板 +2. 读取 .cursor/.init-done + - 不存在 → 继续,按"首次 init"路径执行 + - 已存在 → 展示其元数据(initialized_at、project_type 等),提示: + "检测到本仓库已于 {initialized_at} 完成初始化(project_type: {type})。 + 继续执行会清空 deferred / pitfalls / distillery 等数据文件。确认要继续吗?" + 等用户明确回复"继续"再往下 +3. 运行 `git status`: + - 不是 git 仓库 → 警告但不阻塞,建议手动备份 + - 有未提交改动 → 提醒"建议先 commit 或 stash,便于回滚",等用户明确回复"继续" +4. 向用户声明本次操作范围(见"分组规则"),请求口头确认启动 +``` + +### 阶段 1:递归扫描 `.cursor/` + +``` +1. 用 shell 列出 .cursor 下所有文件(含子目录) +2. 把每个文件对照"规范清单"和"清理清单"分成三组: + - A 组(canonical):在规范清单中,原样保留 + - B 组(template-data):在清理清单中,需要删除或重置 + - C 组(foreign):两张清单都没覆盖到的,视作目标项目原有文件或未知项 +3. 把分组结果用表格汇报给用户: + | 组 | 路径 | 处理动作 | +``` + +### 阶段 2:处理 C 组(目标项目原有文件归位) + +对 C 组中的每个文件,按 baserule.mdc 的归属约定分类,逐条询问用户(可一次性列清单批量确认): + +| 文件特征 | 建议归属 | 目标路径 | +|----------|----------|----------| +| `.mdc` 且内容是跨项目通用规则 | 通用 Rule | `.cursor/rules/common/.mdc` | +| `.mdc` 且内容是当前新项目专属规则 | 项目 Rule | `.cursor/rules/project/.mdc` | +| 包含 `SKILL.md` 的目录 | Skill(无论通用/项目专属) | `.cursor/skills//` | +| 看不出归属 | 询问用户 | — | +| 明显是临时/垃圾文件(`*.log`、`*.tmp`、缓存等) | 删除(需用户确认) | — | + +执行要点: + +- **先列清单一次性确认**,然后批量执行移动/删除,避免交互过于频繁 +- **重名冲突**:C 组文件若与 A 组规范文件重名,**保留 A 组版本**,把 C 组备份到 `.cursor/_init-backup/` 下让用户自行 diff,不直接覆盖 +- **Skill 归属提示**:通用 Skill 建议用户之后手动同步到 `~/.cursor/skills/`(跨项目便利副本,可选) +- **迁移后核查**:移动完成后重新扫描,确认 C 组已清空 + +### 阶段 3:处理 B 组(源项目项目专用数据清理/重置) + +按"清理清单"执行: + +**A. 直接删除** + +- `.cursor/rules/project/*.mdc`(全部)—— 源项目的项目级 rules,新项目不适用 +- `.cursor/skills/<非规范 skill 目录>/` —— 源项目的项目级 Skills(不在白名单的所有 skill 目录) +- `.cursor/plans/` 下所有文件(目录保留,内容清空) +- `.cursor/debug-*.log`、`.cursor/*.log` —— 调试日志 +- `.cursor/local-env.json` —— 设备绑定,需新设备重新生成(`local-env-check.mdc` 自动探测) + +**B. 重置为空模板**(保留文件,仅清内容) + +| 文件 | 模板(见"模板内容"节) | +|------|------------------------| +| `.cursor/changelog/changelog-full.md` | L1 模板 | +| `.cursor/changelog/changelog-recent.md` | L2 模板 | +| `.cursor/changelog/changelog-headlines.md` | L3 模板 | +| `.cursor/changelog/.changelog-ack` | 空文件(touch) | +| `.cursor/deferred/registry.md` | deferred 模板 | +| `.cursor/pitfalls/pitfalls.md` | pitfalls 模板 | +| `.cursor/distillery/problems.md` | problems 模板 | +| `.cursor/distillery/insights.md` | insights 模板 | +| `.cursor/distillery/golden-rules.md` | golden-rules 模板 | +| `.cursor/profile/project-profile.md` | project-profile 模板 | +| `.cursor/profile/project-profile-log.md` | project-profile-log 模板 | + +执行要点: + +- 每个重置前**先 Read 现有内容预览前 10 行**给用户,避免误删有价值数据(特别是 deferred/pitfalls 用户可能想保留) +- 如用户对某个数据文件明确说"保留"(例如 golden-rules 想带过去),跳过该文件的重置 + +### 阶段 4:重建 registry + +打开 `.cursor/skills/epee-orchestrator/registry.md`: + +1. 解析现有条目(每条 `### ` 块) +2. 删除所有 `类型: 项目级` 的条目 +3. 遍历 `.cursor/skills/` 目录,对照 registry: + - registry 有条目但 skill 目录不存在 → 删除条目 + - skill 目录存在但 registry 无条目 → 读取该 skill 的 SKILL.md frontmatter,新增条目 +4. **确保 `cursor-init` 条目本身存在**(类型: 基础设施) +5. 写回 registry.md + +### 阶段 5:同步 `hooks.json`(跨平台保守处理) + +- 读取 `.cursor/hooks.json` +- 若 `command` 字段硬编码为 `powershell ...`,且目标新项目声明/探测到的 shell 不是 powershell(参考 `local-env-check.mdc`),**提醒用户**需要按 `hooks/README.md` 手动改为 `bash .cursor/hooks/xxx.sh` +- 本阶段不自动改 hooks.json,避免误判 + +### 阶段 5.5:`.gitignore` 交互式生成 + +#### 5.5.1 前置检测 + +``` +检测项目根 .gitignore: + 不存在 → 进入 5.5.2 问卷 + 已存在且非空 → Read 前 30 行展示给用户,询问: + [覆盖 / 追加到文件末尾 / 跳过本阶段] + 用户选"跳过" → 本阶段结束,.init-done 里标记 gitignore_generated: false +``` + +#### 5.5.2 问卷(一次性批量 AskQuestion 收集) + +必问 3 项 + 可选 1 项: + +| 编号 | 问题 | 类型 | 选项 | +|------|------|------|------| +| Q1 | 项目主要技术栈 | 多选 | Unity / Node.js / Python / Rust / Go / C# 非 Unity / Web 静态站点 / 其他 / **不确定(跳过语言段)** | +| Q2 | IDE 偏好 | 多选 | Cursor(预勾)/ VSCode / JetBrains 全家桶 / Visual Studio / Vim+Emacs | +| Q3 | 操作系统 | 多选 | Windows / macOS / Linux(按探测到的当前 OS 预勾) | +| Q4(可选)| 其他要忽略的路径 | 自由文本 | 用户可跳过 | + +#### 5.5.3 片段组装 + +按问卷选择拼装,片段内容见下方"模板内容 · .gitignore 片段库"。拼装顺序固定: + +``` +# === Cursor(固定,所有项目都包含) === +# === OS === +# === IDE === +# === Language / Framework === +# === Custom === +``` + +若 Q1 选"不确定" → 跳过 Language 段,其他段正常拼装(极简版仍可用)。 + +#### 5.5.4 预览与确认 + +1. 把组装结果写到 `.cursor/_gitignore-preview`(临时文件) +2. 给用户完整展示(超过 60 行则折叠中段) +3. AskQuestion:`[写入 .gitignore / 让我调整再确认 / 放弃本阶段]` +4. "写入"→ move 到项目根 `.gitignore`(已存在时按 5.5.1 的选择做覆盖或追加),删除预览文件 +5. "调整"→ 根据用户描述修改后重复步骤 2-3 +6. "放弃"→ 删除预览文件,`.init-done` 标记 `gitignore_generated: false` + +### 阶段 6:验证与报告 + +``` +1. 重新递归扫描 .cursor/,再次分组 +2. 期望状态: + - A 组:全部保留,文件内容未被动过 + - B 组:数据文件仅含模板内容;项目级 rules/skills/日志 已删除 + - C 组:为空(或仅剩用户明确要求保留的文件) + - 项目根 .gitignore:按用户选择存在或被放弃(状态记到报告里) +3. 给用户一份结构化报告,至少包含: + - 移动的文件(from → to) + - 删除的文件 + - 重置的文件 + - 新注册/移除的 registry 条目 + - .gitignore 的处理结果(新建/追加/覆盖/放弃) + - 未处理的文件(如果有,逐条说明原因) +``` + +### 阶段 7:写入 `.init-done` sentinel + +**仅在阶段 6 验证全部通过后执行**。任何前序阶段异常中断都不写入此文件,确保下次会话 recall 能再次触发。 + +``` +1. 按"模板内容 · .init-done"格式,填充实际值写入 .cursor/.init-done +2. 向用户输出收尾提示: + > 初始化完成。建议现在执行: + > git add .cursor/ .gitignore + > git diff --cached -- .cursor/ + > git commit -m "chore(cursor): initialize .cursor from template" + > + > ⚠️ .cursor/.init-done 必须 commit,否则团队其他成员 clone 后会被再次触发 init。 +``` + +**仅跑阶段 5.5 时**(用户说"补 gitignore"): +- 若 `.init-done` 存在 → 更新其中的 `gitignore_generated: true` 字段,保留其他字段 +- 若 `.init-done` 不存在 → 提示用户"仓库尚未完整 init,只补 gitignore 不会写 sentinel。是否改为跑完整 init?" + +--- + +## 规范清单(canonical) + +下列文件构成本 `.cursor` 模板的"主干",初始化后必须都在、内容不被删改(数据文件除外): + +### 顶层 + +- `.cursor/hooks.json` +- `.cursor/local-env.example.json` +- `.cursor/.init-done` —— **阶段 7 写入**;模板仓库自身不应包含此文件 + +### Rules(通用) + +- `.cursor/rules/common/baserule.mdc` +- `.cursor/rules/common/changelog-recall.mdc` +- `.cursor/rules/common/deferred-recall.mdc` +- `.cursor/rules/common/distillery-recall.mdc` +- `.cursor/rules/common/epee-orchestrator.mdc` +- `.cursor/rules/common/pitfall-recall.mdc` +- `.cursor/rules/common/profile-recall.mdc` +- `.cursor/rules/common/cursor-init-recall.mdc` + +### Rules(项目专属目录) + +- `.cursor/rules/project/`(保留**空目录**;源项目的 `.mdc` 内容一律删除) + +### Skills(规范 Skill 目录白名单) + +- `.cursor/skills/cursor-init/` +- `.cursor/skills/deferred-decisions/` +- `.cursor/skills/dev-changelog/` +- `.cursor/skills/epee-orchestrator/`(含 `registry.md`,见阶段 4) +- `.cursor/skills/pitfall-journal/` +- `.cursor/skills/problem-distillery/` +- `.cursor/skills/profile-memory/` + +> **任何不在此白名单中的 skill 目录**,在阶段 3 中一律删除(视为源项目的项目级 Skill)。 + +### Hooks + +- `.cursor/hooks/README.md` +- `.cursor/hooks/run-hook.ps1` +- `.cursor/hooks/session-init.ps1` +- `.cursor/hooks/session-init.sh` +- `.cursor/hooks/check-changelog.ps1` +- `.cursor/hooks/check-changelog.sh` + +### 数据占位目录(保留目录,文件重置为模板内容) + +- `.cursor/changelog/{changelog-full.md, changelog-recent.md, changelog-headlines.md, .changelog-ack}` +- `.cursor/deferred/registry.md` +- `.cursor/pitfalls/pitfalls.md` +- `.cursor/distillery/{problems.md, insights.md, golden-rules.md}` +- `.cursor/profile/{project-profile.md, project-profile-log.md}` +- `.cursor/plans/`(空目录) + +--- + +## 清理清单(cleanup list) + +### 强制删除 + +| 路径 | 原因 | +|------|------| +| `.cursor/rules/project/*.mdc` | 源项目的项目级 Rules | +| `.cursor/skills/<非白名单>/` | 源项目的项目级 Skills | +| `.cursor/plans/*`(内容) | 源项目规划文档 | +| `.cursor/*.log`、`.cursor/debug-*.log` | 调试日志遗留 | +| `.cursor/local-env.json` | 设备绑定配置,需由新设备重新生成 | +| `.cursor/_init-backup/`(如果是上一轮残留) | 仅阶段 2 冲突备份用,运行前应不存在 | +| `.cursor/_gitignore-preview`(如果是上一轮残留) | 阶段 5.5 临时文件 | + +### 重置为模板 + +见"模板内容"节。 + +--- + +## 模板内容 + +重置数据文件时使用以下内容。带 `{{DATE}}` 的占位符替换为当天日期(`YYYY-MM-DD`)。 + +### changelog-full.md + +```markdown +# Dev Changelog — Full + +完整的开发改动记录,按时间倒序排列。作为主动 RAG 的数据源,用户手动唤醒时读取。 + +## 记录 +``` + +### changelog-recent.md + +```markdown +# Dev Changelog — Recent + +最近 ~10 次改动的摘要记录,按时间倒序排列。 +当 Agent 检测到当前任务与近期改动相关时自动读取。 +``` + +### changelog-headlines.md + +```markdown +# Dev Changelog — Headlines + +最近 ~50 次改动的一句话概要,按时间倒序排列。每次会话自动注入上下文。 +``` + +### .changelog-ack + +空文件(0 字节),只用于更新 mtime 阻止 hook 重复提醒。 + +### deferred/registry.md + +```markdown +# Deferred Decisions Registry + +## Active Items + +(暂无延期方案) + +--- + +## Completed / Cancelled Items + +(暂无已完成或已废弃的方案) +``` + +### pitfalls/pitfalls.md + +```markdown +# Pitfall Journal + +开发过程中踩过的坑,按时间倒序排列。 +Agent 进入 Debug mode 或遇到运行时错误时自动检索匹配。 + +--- +``` + +### distillery/problems.md + +```markdown +# Problem Distillery — Problems + +反复出现的顽固问题追踪记录,按时间倒序排列。 + + +``` + +### distillery/insights.md + +```markdown +# Problem Distillery — Insights + +从已解决的顽固问题中蒸馏出的精炼方法论。 + + + +--- +last_distill_date: {{DATE}} +``` + +### distillery/golden-rules.md + +```markdown +# Golden Rules + +经过实践验证(权重 >= 5)的精炼认知,每次新会话自动注入。 + + +``` + +### profile/project-profile.md + +```markdown +# Project Profile + +## 项目定位 + +## 技术栈与架构 + +## 设计约定 + +## 产品方向 +``` + +### profile/project-profile-log.md + +```markdown +# Project Profile Log + +详细记录每次项目画像更新的完整上下文,按时间正序追加。 + +## 记录 +``` + +### .init-done + +阶段 7 写入的 sentinel,YAML 格式,字段固定: + +```yaml +# .cursor/.init-done — cursor-init Skill 写入的初始化标记文件 +# 本文件的存在表示本仓库已完成 .cursor 模板初始化 +# 请务必 git commit 此文件,避免团队成员 clone 后被再次触发 init +initialized_at: {{ISO_DATETIME}} # 如 2026-04-21T16:30:00+08:00 +initialized_by: cursor-init +skill_version: 2 +project_type: {{PROJECT_TYPE}} # 阶段 5.5 问卷 Q1 结果;多选逗号分隔;"不确定"写 unknown +gitignore_generated: {{BOOL}} # true / false +``` + +**写入时机**: +- 全流程跑完(阶段 6 验证通过)时由阶段 7 写入 +- "补 gitignore" 单独跑阶段 5.5 时,若已存在则只更新 `gitignore_generated` 字段 + +--- + +## 模板内容 · .gitignore 片段库 + +阶段 5.5 按用户问卷选择拼接以下片段。每段前后各空一行,保证可读性。 + +### 固定段:Cursor + +```gitignore +# === Cursor === +# 设备绑定配置,不同机器需独立生成 +.cursor/local-env.json + +# Hook 运行态标记(仅影响本地会话) +.cursor/changelog/.changelog-ack + +# cursor-init 临时产物 +.cursor/_init-backup/ +.cursor/_gitignore-preview +``` + +### OS 段(按问卷 Q3 多选拼接) + +**Windows** + +```gitignore +# === OS: Windows === +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db +Desktop.ini +$RECYCLE.BIN/ +*.stackdump +*.lnk +``` + +**macOS** + +```gitignore +# === OS: macOS === +.DS_Store +.AppleDouble +.LSOverride +Icon +._* +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent +``` + +**Linux** + +```gitignore +# === OS: Linux === +*~ +.fuse_hidden* +.directory +.Trash-* +.nfs* +``` + +### IDE 段(按问卷 Q2 多选拼接) + +**VSCode** + +```gitignore +# === IDE: VSCode === +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets +.history/ +*.vsix +``` + +**JetBrains** + +```gitignore +# === IDE: JetBrains === +.idea/ +*.iml +*.ipr +*.iws +.idea_modules/ +atlassian-ide-plugin.xml +``` + +**Visual Studio** + +```gitignore +# === IDE: Visual Studio === +.vs/ +*.user +*.suo +*.userprefs +bin/ +obj/ +[Dd]ebug/ +[Rr]elease/ +x64/ +x86/ +``` + +**Vim/Emacs** + +```gitignore +# === IDE: Vim / Emacs === +*.swp +*.swo +*.swn +Session.vim +.netrwhist +*~ +\#*\# +.\#* +``` + +**Cursor**:固定段已覆盖,无需额外片段。 + +### Language / Framework 段(按问卷 Q1 多选拼接) + +**Unity** + +```gitignore +# === Language: Unity === +[Ll]ibrary/ +[Tt]emp/ +[Oo]bj/ +[Bb]uild/ +[Bb]uilds/ +[Ll]ogs/ +[Uu]ser[Ss]ettings/ +[Mm]emoryCaptures/ +[Rr]ecordings/ +sysinfo.txt +*.apk +*.aab +*.unitypackage +*.app +*.csproj +*.unityproj +*.sln +*.suo +*.tmp +*.user +*.userprefs +*.pidb +*.booproj +*.svd +*.pdb +*.mdb +*.opendb +*.VC.db +``` + +**Node.js** + +```gitignore +# === Language: Node.js === +node_modules/ +.npm/ +.yarn/ +.pnp.* +dist/ +build/ +out/ +.next/ +.nuxt/ +.cache/ +.parcel-cache/ +coverage/ +.env +.env.local +.env.*.local +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +.turbo/ +``` + +**Python** + +```gitignore +# === Language: Python === +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +dist/ +*.egg-info/ +*.egg +.venv/ +venv/ +env/ +.pytest_cache/ +.mypy_cache/ +.ruff_cache/ +.coverage +.coverage.* +htmlcov/ +.tox/ +.nox/ +.hypothesis/ +.ipynb_checkpoints/ +``` + +**Rust** + +```gitignore +# === Language: Rust === +target/ +**/*.rs.bk +*.pdb +# Cargo.lock:lib crate 建议忽略,bin crate 建议提交,默认不忽略 +# Cargo.lock +``` + +**Go** + +```gitignore +# === Language: Go === +bin/ +vendor/ +*.exe +*.exe~ +*.dll +*.so +*.dylib +*.test +*.out +go.work +``` + +**C# 非 Unity** + +```gitignore +# === Language: C# (non-Unity) === +bin/ +obj/ +*.user +*.suo +*.pdb +*.cache +[Dd]ebug/ +[Rr]elease/ +x64/ +x86/ +[Bb]uild/ +*.dll +*.pdb +``` + +**Web 静态站点** + +```gitignore +# === Language: Web Static === +node_modules/ +dist/ +build/ +public/build/ +.cache/ +.tmp/ +.sass-cache/ +.parcel-cache/ +``` + +**其他**:不拼接语言段,用户在 `# === Custom ===` 段自行补充。 + +### Custom 段(固定尾部) + +```gitignore +# === Custom === +# 在此段追加项目专属需要忽略的路径 +``` + +若用户在问卷 Q4 填了自由文本,按行拆分后追加到 Custom 段下方。 + +--- + +## 冲突与边界情况处理 + +| 场景 | 处理 | +|------|------| +| C 组某文件与 A 组重名 | 保留 A 组;C 组移到 `.cursor/_init-backup/`,告知用户自行 diff | +| C 组有 `SKILL.md` 且 skill 名与 A 组白名单同名 | 保留 A 组 skill;C 组整个 skill 目录移到 `_init-backup/` | +| 数据文件(如 `pitfalls.md`)用户明确说"保留" | 跳过该文件重置 | +| `local-env.json` 存在且用户说"我就在这台机器上开 B,保留它" | 跳过删除,但提醒其已在 `.gitignore` | +| `.cursor/rules/project/` 为空目录 | 保留空目录(便于未来放项目级 rules) | +| 扫描到 `.cursor/_init-backup/`(上轮残留) | 警告用户并询问:删除 / 保留 / 重命名 | +| `git status` 不能执行(不是 git 仓库) | 警告但不阻塞,改为建议用户手动备份 | +| `.cursor/.init-done` 已存在且用户触发了全流程 | 阶段 0 展示其元数据并要求二次确认 | +| 阶段 5.5 项目根已有 `.gitignore` 且用户选"追加" | 把拼装结果追加到现有文件末尾(用 `\n\n# --- 以下由 cursor-init 追加 ---\n` 分隔) | +| 阶段 5.5 中途异常或用户放弃 | 不写入 `.gitignore`,`.init-done` 的 `gitignore_generated` 记 false | +| 阶段 7 写 `.init-done` 前前序阶段已 abort | 不写入 sentinel,下次会话 recall 会重新触发 | +| 用户说"补 gitignore" 但 `.init-done` 不存在 | 提醒"仓库尚未完整 init",询问是否改为跑全流程 | + +--- + +## 与其他系统的协作 + +| 系统 | 关系 | 说明 | +|------|------|------| +| `baserule.mdc` | 分类权威 | 阶段 2 归位目录严格按 baserule 约定 | +| `cursor-init-recall.mdc` | 触发器 | 负责首次自动触发(alwaysApply + sentinel 检查)和关键词触发 | +| `epee-orchestrator` Skill | 双向 | 本 Skill 被 Orchestrator 在 registry 里注册;同时本 Skill 负责清理 registry | +| `dev-changelog` / `pitfall-journal` / `deferred-decisions` / `problem-distillery` / `profile-memory` | 下游数据主人 | 本 Skill 只在阶段 3 重置其数据文件,不改动 SKILL.md | +| `local-env-check.mdc` | 后继 | 本 Skill 删除 `local-env.json`,后续新会话由 `local-env-check` 自动重新探测并生成 | + +--- + +## 一次运行的最终状态(验收标准) + +全流程(阶段 0 → 7)完成后 `.cursor/` 应当满足: + +1. 规范清单中列出的所有文件/目录都存在 +2. 所有数据文件(changelog/deferred/pitfalls/distillery/profile)仅含模板内容 +3. `.cursor/rules/project/` 为空目录 +4. `.cursor/skills/` 下仅有白名单中的 skill 目录 +5. `.cursor/skills/epee-orchestrator/registry.md` 中只有:基础设施 + 个人级 skill 条目,且包含 `cursor-init` 条目 +6. 不存在 `*.log`、`local-env.json`、`_init-backup/`、`_gitignore-preview` +7. `.cursor/.init-done` 已写入,字段完整且值有效 +8. 项目根 `.gitignore` 状态明确(存在且有内容 / 被用户显式放弃) +9. `git status .cursor/ .gitignore` 能让用户清楚看到所有改动 + +仅跑阶段 5.5("补 gitignore")完成后: + +1. 项目根 `.gitignore` 存在或被显式放弃 +2. 若 `.init-done` 已存在,其 `gitignore_generated` 字段被更新 +3. 其他 `.cursor/` 内容**零改动** + +--- + +## 自迭代日志 + +本节记录使用本 Skill 过程中发现的必要检查项。 + +### 已知必要检查 + +1. **阶段 2 的 C 组归位前必须先做 dry-run 展示** —— 批量移动 .mdc / SKILL 文件是高破坏性操作,只要有一条分类错误就会污染 canonical 结构,必须让用户在列表上逐条过一遍再执行。 + +2. **重名冲突不许直接覆盖** —— C 组与 A 组重名时,A 组(模板版本)永远是 source of truth,冲突文件只能进 `_init-backup/`,让用户自行决定是否把差异合并回 common rule。 + +3. **registry 重建时先读后写** —— 阶段 4 不要直接用硬编码模板覆盖 registry.md,必须先解析现有条目,只移除项目级条目、补齐缺失条目,避免丢失用户自己添加的个人级 Skill 条目。 + +4. **`.init-done` 是完成度契约** —— 只有阶段 6 验证通过后才能写入此文件。中途 abort 必须让 sentinel 缺失,这是保证下次会话能恢复触发的关键设计。 + +5. **`.gitignore` 用户主导** —— 阶段 5.5 对语言栈/IDE/OS 的判断完全来自用户问卷,不要根据文件探测"智能推断",因为新项目此时通常还是空白,推断不准反而会填错条目。 diff --git a/.cursor/skills/deferred-decisions/SKILL.md b/.cursor/skills/deferred-decisions/SKILL.md new file mode 100644 index 0000000..ee982b6 --- /dev/null +++ b/.cursor/skills/deferred-decisions/SKILL.md @@ -0,0 +1,151 @@ +--- +name: deferred-decisions +description: >- + 记录开发中被延期的技术方案/决策,并在关联任务出现时主动提醒用户。 + 当对话中出现"以后再做"、"先不做"、"defer"、"延期方案"、"备选方案"、 + "递进方案"等语义时触发。也用于浏览、管理已有的 deferred items。 +--- + +# Deferred Decisions Skill + +追踪开发中被延期的技术方案,在合适时机主动提醒用户。 + +## 存储 + +**数据文件**: `.cursor/deferred/registry.md` + +该文件是 Agent 的结构化记忆,不是面向人类的文档。每个 deferred item 是一个 H3 级标题块。 + +## 操作 A:记录延期方案 + +### 触发识别 + +当对话中出现以下模式时,Agent 应主动提议记录: +- 讨论了多种方案,选择了一种,明确说其余"以后再做" +- 实现了基础版本,提到了可递进升级的高级版本 +- 发现了可以改进的点,但当前优先级不够 + +### 流程 + +``` +1. 从对话中提炼: + - 选择了什么方案(chosen_alternative) + - 延期了什么(标题 + context) + - 为什么延期(deferred_reason) + - 什么时候可以做(prerequisite) + - 涉及哪些领域(tags)和文件(related_files) +2. 生成 slug 形式的唯一 ID(如 ecosystem-lod-switching) +3. 读取 .cursor/deferred/registry.md(不存在则用模板创建) +4. 在 "## Active Items" 区域末尾、"---" 分隔线之前追加新条目 +5. 向用户确认已记录,展示条目摘要 +``` + +### 条目模板 + +```markdown +### [item-slug] 简短标题 +- **status**: deferred +- **tags**: tag1, tag2, tag3 +- **recorded**: YYYY-MM-DD +- **source_chat**: [简短描述](chat-uuid) +- **prerequisite**: 实施前提条件(可选,无则写 "无") +- **related_files**: + - path/to/file1.cs + - path/to/file2.cs +- **context**: | + 延期方案的具体内容,2-5 行描述。 + 包含方案的要点和实施思路。 +- **chosen_alternative**: 当时选择的方案简述 +- **deferred_reason**: 延期的原因 +``` + +### 字段说明 + +| 字段 | 必填 | 说明 | +|---|---|---| +| ID(方括号内) | 是 | slug 形式,全局唯一 | +| status | 是 | `deferred` / `reminded` / `in_progress` / `done` / `cancelled` | +| tags | 是 | 逗号分隔的领域标签,用于关联匹配 | +| recorded | 是 | 记录日期 | +| source_chat | 否 | 来源对话标识 | +| prerequisite | 否 | 实施前提条件 | +| related_files | 否 | 关联代码文件路径 | +| context | 是 | 延期方案的具体内容 | +| chosen_alternative | 是 | 当时选择了什么 | +| deferred_reason | 是 | 延期原因 | + +## 操作 B:关联提醒 + +### 触发条件 + +由 `.cursor/rules/common/deferred-recall.mdc` 触发,或当用户任务涉及已有 deferred item 的领域时自动触发。 + +### 流程 + +``` +1. 读取 .cursor/deferred/registry.md +2. 提取当前任务的关键词和涉及文件 +3. 匹配 status=deferred 的 items: + - tags 与当前任务关键词有交集 + - related_files 与当前任务涉及文件有重叠 + - prerequisite 描述的条件可能已满足 +4. 如匹配到,在回复开头简要提醒: + "提醒:你之前有一个延期方案 [item-title] 与当前任务相关。要一并处理吗?" +5. 如用户同意,将该 item 的 status 改为 in_progress +``` + +### 提醒原则 + +- 每个 item 在同一会话中最多提醒一次 +- 只提醒 status=deferred 的 items(reminded/in_progress 不重复提醒) +- 提醒应简洁,不打断用户的主线任务 + +## 操作 C:状态管理 + +| 用户动作 | 状态变更 | 额外操作 | +|---|---|---| +| "开始做 X" | deferred → in_progress | 无 | +| "X 完成了" | in_progress → done | 移到 "Completed / Cancelled Items" 区域 | +| "X 不需要了" | any → cancelled | 移到 "Completed / Cancelled Items" 区域 | +| Agent 提醒后用户确认 | deferred → in_progress | 无 | + +### 移动条目 + +将条目从 "Active Items" 剪切到 "Completed / Cancelled Items" 区域时,保留完整内容,仅修改 status。 + +## 操作 D:浏览/回顾 + +当用户问"有哪些延期方案"、"deferred list"、"待办方案"等时: + +``` +1. 读取 registry.md +2. 列出所有 status=deferred 的 items 摘要表: + | ID | 标题 | Tags | 记录日期 | 前提条件 | +3. 如用户要求按 tag 过滤,只展示匹配项 +``` + +## Registry 文件模板 + +当 `.cursor/deferred/registry.md` 不存在时,用此模板创建: + +```markdown +# Deferred Decisions Registry + +## Active Items + +(暂无延期方案) + +--- + +## Completed / Cancelled Items + +(暂无已完成或已废弃的方案) +``` + +## 自迭代日志 + +本节记录使用本 Skill 过程中发现的必要检查项。 + +### 已知必要检查 + +(暂无) diff --git a/.cursor/skills/dev-changelog/SKILL.md b/.cursor/skills/dev-changelog/SKILL.md new file mode 100644 index 0000000..f31c4a9 --- /dev/null +++ b/.cursor/skills/dev-changelog/SKILL.md @@ -0,0 +1,259 @@ +--- +name: dev-changelog +description: >- + 三层开发进程记录系统。在 Agent 完成代码改动后自动记录,提供从一句话概要到完整日志的 + 多级上下文,帮助 Agent 在跨会话场景下保持对项目开发进展的感知。 + 当用户提到"开发日志"、"changelog"、"最近改了什么"、"回顾改动"等时触发。 +--- + +# Dev Changelog + +三层开发进程记录系统,解决 Agent 跨会话的上下文断裂问题。 + +## 三层架构 + +| 层级 | 文件 | 信息密度 | 条目数量 | 注入方式 | +|------|------|---------|---------|---------| +| L1 完整版 | `changelog-full.md` | 高(5-15 行/条) | 无上限,只追加 | 用户手动唤醒 | +| L2 中期版 | `changelog-recent.md` | 中(3-5 行/条) | 滚动窗口 ~20 条 | 检测到关联时自动读取 | +| L3 概要版 | `changelog-headlines.md` | 低(1 行/条) | 滚动窗口 ~50 条 | 每次会话自动注入 | + +所有数据文件存放在 `.cursor/changelog/` 目录下。 + +## 锚点 ID 机制 + +每条记录在写入时生成一个**锚点 ID**,格式为 `CL-YYYYMMDD-HHMM`(如 `CL-20260412-1430`)。 +同一分钟内有多条时追加字母后缀(`CL-20260412-1430a`、`CL-20260412-1430b`)。 + +锚点 ID 在三层文件中保持一致,用于跨层精准定位: +- L3 一句话条目以 `[CL-xxx]` 开头 +- L2 摘要条目的 H3 标题包含 `[CL-xxx]` +- L1 完整条目的 H3 标题包含 `[CL-xxx]` + +这使得从 L3 → L2 → L1 的逐级查找可以通过 Grep 精准定位,无需全文读取。 + +## 逐级上溯机制 + +当 Agent 在使用 L3 概要作为上下文时,如果某条记录的一句话描述**语义模糊** +(如无法判断改动的具体范围、与当前任务的关系不明确),执行以下逐级查找: + +``` +1. 从 L3 条目中提取锚点 ID(如 CL-20260412-1430) +2. 在 changelog-recent.md(L2)中 Grep 该 ID + - 找到 → 读取该条目的 3-5 行摘要,通常足以消除歧义 + - 未找到(已滚出 L2 窗口)→ 进入步骤 3 +3. 在 changelog-full.md(L1)中 Grep 该 ID + - 找到 → 用 Read 工具读取该 ID 所在行号 ±20 行范围(精准读取,不读全文) + - 未找到 → 放弃上溯,该条目上下文不可用 +``` + +### 上溯原则 + +- **按需触发**:只有在 L3 信息不足以支撑当前任务判断时才上溯,不预防性地批量读取 +- **精准读取**:对 L1 的访问必须通过 Grep 定位行号 + Read 局部读取,禁止全文读取 +- **最小化**:一次上溯通常只涉及 1-3 条记录,不批量上溯 + +## 操作 A:记录写入(核心流程) + +### 触发条件 + +Agent 完成了一个涉及**代码或配置文件实质性改动**的任务后,自动触发。 + +以下情况**不触发**: +- 纯对话讨论、方案设计、问题解答(无文件改动) +- 只读操作(查看文件、搜索代码) +- 只改动了 `.cursor/` 目录下的基础设施文件(如画像、延期方案、changelog 自身) + +### 写入流程 + +``` +1. 生成锚点 ID:CL-YYYYMMDD-HHMM(检查是否与已有 ID 冲突,冲突则追加字母后缀) + +2. 从刚完成的任务中提取以下信息: + - 做了什么(what):一句话概括 + - 为什么这样做(why):动机和背景 + - 改了哪里(where):受影响的文件/模块列表 + - 关键决策(decisions):如果有方案选择,记录选了什么、放弃了什么 + - 注意事项(notes):后续可能受影响的地方、已知限制等 + +3. 生成三层内容(共享同一个锚点 ID): + - L1 完整条目(包含以上全部信息) + - L2 摘要条目(what + why + where,3-5 行) + - L3 一句话(what,不超过 80 字) + +4. 写入三个文件(按以下顺序): + a. 读取 changelog-full.md,在 "## 记录" 下方追加 L1 条目 + b. 读取 changelog-recent.md,在顶部插入 L2 条目,如超过 20 条则移除最旧的(与下方「L2 窗口」一致) + c. 读取 changelog-headlines.md,在顶部插入 L3 条目,如超过 50 条则移除最旧的 + +5. 在回复末尾附一行提示:"[已记录到开发日志]" +``` + +### 静默写入原则 + +- **不需要用户确认**——Agent 自己做的改动,对"做了什么"的认知是一手的 +- 用户如果觉得记录不准确,可通过操作 D 修改或删除 +- 回滚操作也要记录("回退了 XX 改动"),真实反映开发过程 + +## 操作 B:L2 自动触发读取 + +### 触发条件 + +由 `changelog-recall.mdc` Rule 调度。当 Agent 开始处理一个新任务时,判断该任务是否 +与近期改动相关。 + +### 匹配策略(文件 + 标签双匹配) + +``` +1. 从当前任务中提取: + - 涉及的文件路径 + - 语义关键词(模块名、功能领域等) + +2. 读取 changelog-recent.md,逐条检查: + - 硬匹配:当前任务涉及的文件出现在条目的 affected_files 中 + - 软匹配:当前任务的语义关键词与条目的 tags 有交集 + +3. 任一匹配命中 → 将匹配到的 L2 条目作为上下文纳入考量 +4. 在回复中自然融入,不显式提及"根据开发日志" +``` + +## 操作 C:L1 手动检索 + +### 触发条件 + +用户主动要求回顾完整改动记录时触发。典型话语: +- "回顾一下最近的改动" +- "XX 模块之前改过什么" +- "查看开发日志" +- "changelog" + +### 流程 + +``` +1. 读取 changelog-full.md +2. 根据用户需求过滤: + - 按时间范围 + - 按模块/文件 + - 按 tags +3. 展示匹配的条目摘要表,用户可以进一步查看某条的完整内容 +``` + +## 操作 D:记录管理 + +用户可以对已有记录进行管理: + +| 操作 | 说明 | +|------|------| +| 删除 | 从三层文件中同步移除对应条目 | +| 修改 | 修改某条记录的描述(三层同步更新) | +| 清理 | 手动触发 L1 的归档(如按月分文件,暂不实现,作为演进方向) | + +## 条目格式 + +### L1 完整条目 + +```markdown +### [CL-20260412-1430] YYYY-MM-DD HH:MM — 一句话标题 +- **tags**: tag1, tag2, tag3 +- **affected_files**: + - path/to/file1 + - path/to/file2 +- **what**: 做了什么的简要描述 +- **why**: 动机和背景 +- **decisions**: 选择了 A 方案(放弃了 B 因为 xxx) +- **notes**: 后续注意事项 +- **source_chat**: [对话简述](chat-uuid) +``` + +### L2 摘要条目 + +```markdown +### [CL-20260412-1430] YYYY-MM-DD — 一句话标题 +- **tags**: tag1, tag2, tag3 +- **affected_files**: file1, file2 +- **summary**: 做了什么 + 为什么(3-5 行) +``` + +### L3 一句话条目 + +```markdown +- [CL-20260412-1430] 一句话描述改动内容(不超过 80 字) +``` + +## 滚动窗口维护 + +### L2 窗口(~20 条) + +``` +写入新条目后,检查总条目数: +- <= 20 条:不做处理 +- > 20 条:移除文件底部(最旧的)条目,直到恰好 20 条 +``` + +### L3 窗口(~50 条) + +``` +写入新条目后,检查总行数(排除文件头部的标题和说明): +- <= 50 条:不做处理 +- > 50 条:移除文件底部(最旧的)条目,直到恰好 50 条 +``` + +被移除的条目不需要额外归档——L1 完整版保留了所有历史。 + +## 数据文件模板 + +首次写入时,如对应文件不存在,按以下模板创建。 + +### changelog-full.md + +```markdown +# Dev Changelog — Full + +完整的开发改动记录,按时间倒序排列。作为主动 RAG 的数据源,用户手动唤醒时读取。 + +## 记录 +``` + +### changelog-recent.md + +```markdown +# Dev Changelog — Recent + +最近 ~10 次改动的摘要记录,按时间倒序排列。 +当 Agent 检测到当前任务与近期改动相关时自动读取。 +``` + +### changelog-headlines.md + +```markdown +# Dev Changelog — Headlines + +最近 ~50 次改动的一句话概要,按时间倒序排列。每次会话自动注入上下文。 +``` + +## 与其他系统的协作 + +| 系统 | 关系 | 说明 | +|------|------|------| +| `changelog-recall` Rule | 下游消费者 | 每次会话注入 L3,自动触发 L2 读取 | +| `deferred-decisions` Skill | 互补 | deferred 记"没做什么",changelog 记"做了什么" | +| `profile-memory` Skill | 结构对称 | profile 是"是什么",changelog 是"做了什么" | +| `epee-orchestrator` | 注册 | 在 registry.md 中注册本 Skill | + +## 自迭代日志 + +本节记录使用本 Skill 过程中发现的必要检查项。 + +### 已知必要检查 + +1. **大任务收尾遗漏风险** — 当单次任务涉及 5+ 个文件改动时,Agent 容易在输出总结回复后遗漏被动写入流程。应在生成最终回复前,先执行 `changelog-recall.mdc` 中的"任务完成 Checklist",确认三层日志已写入后再输出回复。绝不能"先回复再补写"。 + +2. **L3/L2 滚动窗口必须落地** — 操作 A 第 4 步不是「插入即结束」:写入后必须数清条目(L3 为以 `- [` 开头的列表行,L2 为 `### [CL-` 标题行)。L3 超过 50 条、L2 超过 20 条时,必须从**文件底部(最旧)**整段删除条目直至恰好满足上限;禁止长期只追加不修剪。若发现 `changelog-headlines.md` 列表行多于 50,说明上次写入未执行本项,本次补修剪并自检。 + +3. **顶部插入 StrReplace 范式(L1/L2)** — L1 和 L2 的每个条目都是多行结构(标题 + 多条 `- **字段**:`)。使用 StrReplace 在顶部插入新条目时,anchor(`old_string`)有且仅有两种合法选择: + (a) 只包含新条目之前的"稳定前缀"(如 L1 的 `## 记录\n\n` 或 L2 的整段文件头说明),**不触及任何已有条目的任何一行**;`new_string` = 稳定前缀 + 新条目完整内容 + 空行。 + (b) 把旧首条目的**完整多行内容**(标题行 + 全部字段行)都纳入 `old_string`;`new_string` = 新条目完整内容 + 空行 + 旧首条目完整内容。 + + **绝对禁止**:只把旧首条目的标题行(或前 1-2 字段)当 anchor 而不带上剩余字段行——StrReplace 会吞掉这些 anchor 行但不动剩余字段,造成"旧标题丢失、字段游离"的半损坏状态(2026-04-20 在 `pitfall-journal` 的写入中已实际踩过此坑)。 + + **写入后自检**:Read 文件头部 30 行,确认看到新条目完整 + 旧首条目标题行仍存在且字段完整跟随。L3 的一行条目不受本条约束(它就是单行,天然无此风险)。 diff --git a/.cursor/skills/epee-orchestrator/SKILL.md b/.cursor/skills/epee-orchestrator/SKILL.md new file mode 100644 index 0000000..b239b5c --- /dev/null +++ b/.cursor/skills/epee-orchestrator/SKILL.md @@ -0,0 +1,127 @@ +--- +name: epee-orchestrator +description: >- + EPEE Skill Orchestrator:元层调度系统。检测任务是否可由已有 Skill 处理并分流, + 或发现 Skill 缺口并引导创建新 Skill。当 Agent 遇到手动配置密集、重复模式明确、 + 手工指引过长的任务时触发。也用于 Skill Registry 的维护和同步。 +--- + +# EPEE Skill Orchestrator + +元层调度系统,负责 Skill 分流、缺口发现和 Registry 维护。 + +## 操作 A:Skill 分流(匹配已有 Skill) + +### 流程 + +``` +1. 读取 registry.md 获取所有已注册 Skill 的摘要 +2. 将当前任务特征与每个 Skill 的"触发场景"关键词匹配 +3. 如果匹配到: + a. 告知用户"此任务可以通过 [Skill名] 高效完成" + b. 简述该 Skill 的能力及与当前任务的契合点 + c. 用户确认后,读取并激活对应 Skill 的 SKILL.md +``` + +### 匹配规则 + +- 优先匹配触发场景关键词与当前任务描述的交集 +- 如有多个 Skill 匹配,按相关度排序推荐,由用户选择 +- `deferred-decisions` 等标记为"基础设施"类型的 Skill 不参与任务分流匹配, + 仅作为 Orchestrator 的下游工具使用 + +## 操作 B:Skill 缺口发现 + 创建引导 + +### 触发条件 + +操作 A 未找到匹配的 Skill,且当前任务满足"Skill 创建价值判断标准"中至少 2 条。 + +### 流程 + +``` +1. 向用户提出建议: + "这类任务可以通过创建一个 [建议 Skill 名] 来自动化" +2. 给出 1-3 句方案概要: + - 这个 Skill 会做什么 + - 核心工作机制(如 DSL 生成、YAML 直写、MCP 调用等) + - 预估能节省的重复劳动 +3. 询问用户选择: + a) "继续讨论并创建" → 进入创建流程 + b) "以后再说" → 进入延期记录流程 + c) "不需要" → 结束,正常执行当前任务 +``` + +### a) 创建流程 + +``` +1. 委托给 create-skill Skill(路径: ~/.cursor/skills-cursor/create-skill/SKILL.md) +2. 将以下上下文传递给 create-skill 流程: + - 触发创建的原始任务描述 + - Orchestrator 的方案概要 + - 建议的 Skill 名称 +3. 按 create-skill 的标准流程完成 Discovery → Design → Implementation → Verification +4. 创建完成后,要求用户对新 Skill 进行实际测试 +5. 测试通过后,执行操作 C 同步 Registry +``` + +### b) 延期记录流程 + +``` +1. 读取 deferred-decisions Skill(路径: .cursor/skills/deferred-decisions/SKILL.md) +2. 按其"操作 A:记录延期方案"流程,将 Skill 创建建议记录为 deferred item +3. tags 中包含 "skill-creation" 和相关领域标签 +4. context 中记录方案概要,便于未来回忆 +``` + +## 操作 C:Registry 同步 + +### 触发条件 + +- 新 Skill 被创建后 +- 已有 Skill 的 SKILL.md 被实质性修改后(如能力范围变化、触发场景变化) + +### 流程 + +``` +1. 读取目标 Skill 的 SKILL.md +2. 从 frontmatter 提取 name 和 description +3. 从正文提取核心能力和触发场景关键词 +4. 读取 registry.md +5. 新增或更新对应条目,遵循 registry.md 中定义的条目格式 +6. 写回 registry.md +``` + +### 条目格式 + +参见 [registry.md](registry.md) 中的条目结构。 + +## Skill 创建价值判断标准 + +当操作 A 无匹配时,Agent 使用以下标准评估是否建议创建新 Skill。 +满足 **2 条及以上** 即认为值得建议: + +1. **频次**:该类任务预计会出现 3 次以上 +2. **模式明确**:任务有明确的输入/输出模式(输入 X → 产出 Y) +3. **步骤繁多**:手动操作步骤 >= 5 步,或涉及 >= 3 个文件的协调修改 +4. **易错**:存在容易出错的重复性操作(如 GUID 填写、格式对齐等) +5. **可自动化**:可以通过生成 DSL / YAML / 配置文件 / MCP 调用来替代手动操作 + +不满足标准时,Agent 正常执行任务,不提出创建建议。 + +## 与其他系统的协作 + +| 系统 | 关系 | 说明 | +|------|------|------| +| `create-skill` Skill | 下游委托 | 操作 B 创建流程的执行者 | +| `deferred-decisions` Skill | 下游工具 | 操作 B 延期记录的执行者 | +| `skill-self-iteration` Rule | 并行 | 它负责单个 Skill 的经验积累,Orchestrator 负责 Skill 间的调度 | +| `deferred-recall` Rule | 协同 | Orchestrator 延期的建议通过 deferred-recall 在未来自动提醒 | +| `forskill-convention` Rule | 兼容 | 新 Skill 如需 Editor 脚本,仍遵循 ForSkill 约定 | + +## 自迭代日志 + +本节记录使用本 Skill 过程中发现的必要检查项。 + +### 已知必要检查 + +1. **收尾动作级联遗漏** — 当 Agent 遗漏了一个收尾动作(如 changelog 写入)后,后续的收尾动作(自迭代、Registry 同步)也会被一并遗漏,因为它们都在同一个"收尾阶段"。`changelog-recall.mdc` 中的 Checklist 化设计可以打断这种级联——每项独立检查,不依赖前一项的执行记忆。 diff --git a/.cursor/skills/epee-orchestrator/registry.md b/.cursor/skills/epee-orchestrator/registry.md new file mode 100644 index 0000000..1a0e537 --- /dev/null +++ b/.cursor/skills/epee-orchestrator/registry.md @@ -0,0 +1,70 @@ +# EPEE Skill Registry + +> 本文件由 EPEE Skill Orchestrator 维护,记录所有已实现 Skill 的摘要信息。 +> 每次创建/修改 Skill 后必须同步更新(参见 `epee-orchestrator.mdc` Rule)。 + +## 条目格式说明 + +每个条目包含以下字段: +- **类型**:项目级 / 个人级 / 基础设施 +- **能力**:1 句话核心能力描述 +- **触发场景**:逗号分隔的关键词/短语,用于与任务特征匹配 +- **输出**:该 Skill 的产出物 +- **路径**:SKILL.md 的相对路径 +- **备注**(可选):特殊说明 + +--- + +## 已注册 Skill + +### cursor-init +- **类型**: 基础设施 +- **能力**: 把从模板 clone 或复制过来的 .cursor/ 重置为新项目的干净起点——按 baserule 归位原有 rules/skills,清理源项目的项目专用数据,重建 registry,交互式生成 .gitignore,最后写入 `.cursor/.init-done` sentinel +- **触发场景**: 首次会话自动触发(.cursor/.init-done 缺失时由 cursor-init-recall 规则引导);关键词:"初始化cursor"、"cursor init"、"重置 cursor"、"reset cursor"、"按 baserule 归位"、"补 gitignore"、"生成 gitignore"、"gitignore 模板" +- **输出**: 清理后的 `.cursor/` 结构(规范清单完整、项目级内容已清、数据文件为模板、registry 仅含通用条目)、项目根 `.gitignore`(可选)、`.cursor/.init-done` sentinel +- **路径**: .cursor/skills/cursor-init/SKILL.md +- **备注**: 首次通过 sentinel 自动触发一次,之后仅关键词手动触发;破坏性操作必须 dry-run;设计为幂等,重复运行无害;阶段 7 失败时不写 sentinel 保证可恢复 + +### deferred-decisions +- **类型**: 基础设施 +- **能力**: 记录和追踪延期的技术方案/决策,在关联任务出现时主动提醒 +- **触发场景**: "以后再做"、"先不做"、"defer"、延期方案管理、延期回顾 +- **输出**: .cursor/deferred/registry.md 条目 +- **路径**: .cursor/skills/deferred-decisions/SKILL.md +- **备注**: 不参与任务分流匹配,仅作为 Orchestrator 的下游工具 + +### dev-changelog +- **类型**: 基础设施 +- **能力**: 三层开发进程记录系统,Agent 完成代码改动后自动记录,提供一句话概要到完整日志的多级上下文 +- **触发场景**: "开发日志"、"changelog"、"最近改了什么"、"回顾改动"、"查看开发记录"、代码改动后自动写入 +- **输出**: .cursor/changelog/ 下的 changelog-full.md、changelog-recent.md、changelog-headlines.md +- **路径**: .cursor/skills/dev-changelog/SKILL.md + +### pitfall-journal +- **类型**: 基础设施 +- **能力**: 记录开发中踩过的坑(非显而易见的问题),在遇到同类问题时自动检索匹配已有经验 +- **触发场景**: debug 完成后、"踩坑"、"之前遇到过"、"坑"、进入 Debug mode、同类错误反复出现 +- **输出**: .cursor/pitfalls/pitfalls.md 条目 +- **路径**: .cursor/skills/pitfall-journal/SKILL.md + +### problem-distillery +- **类型**: 基础设施 +- **能力**: 追踪反复出现的顽固问题,记录解决过程和弯路,定期蒸馏精炼方法论,经实践验证后自动升级为新会话常规注入 +- **触发场景**: "还有问题"、"没解决"、"还是一样"、"又出现了"、"试了好多次"、"反复出现"、Agent 意识到同一问题尝试 2 次以上未解决、"蒸馏"、"总结经验" +- **输出**: .cursor/distillery/ 下的 problems.md、insights.md、golden-rules.md +- **路径**: .cursor/skills/problem-distillery/SKILL.md + +### profile-memory +- **类型**: 个人级 +- **能力**: 在对话中被动检测用户个人特质和项目信息,经确认后持久化为精简画像和详细日志 +- **触发场景**: "画像"、"profile"、"我的偏好"、"查看画像"、"项目信息"、"查看项目画像"、用户主动管理画像 +- **输出**: ~/.cursor/profile/user-profile.md、.cursor/profile/project-profile.md 及对应 log 文件 +- **路径**: .cursor/skills/profile-memory/SKILL.md + +### epee-orchestrator +- **类型**: 基础设施 +- **能力**: 元层调度系统,检测任务是否可由已有 Skill 处理并分流,或发现 Skill 缺口并引导创建新 Skill;同时负责 Skill Registry 维护 +- **触发场景**: 手动配置密集、重复模式明确、手工指引过长的任务、Skill 缺口发现、Registry 同步维护 +- **输出**: 分流决策(调用已有 Skill / 创建新 Skill)、.cursor/skills/epee-orchestrator/registry.md 维护 +- **路径**: .cursor/skills/epee-orchestrator/SKILL.md +- **备注**: 元层 Skill,自身注册以便其他 Agent 了解调度能力的可用性 diff --git a/.cursor/skills/pitfall-journal/SKILL.md b/.cursor/skills/pitfall-journal/SKILL.md new file mode 100644 index 0000000..a107ad7 --- /dev/null +++ b/.cursor/skills/pitfall-journal/SKILL.md @@ -0,0 +1,122 @@ +--- +name: pitfall-journal +description: >- + 踩坑经验记录系统。在调试完成或发现非显而易见的坑后记录根因和解决方式, + 后续遇到同类问题时自动检索匹配,避免重复踩坑。 + 当 debug 完成、问题反复出现、或用户提到"踩坑"、"之前遇到过"、"坑"时触发。 +--- + +# Pitfall Journal + +记录开发过程中遇到的"坑"——那些不看代码逻辑觉得应该没问题、但实际运行时才暴露的问题。 +与 dev-changelog 互补:changelog 记"做了什么",pitfall-journal 记"踩了什么坑、怎么爬出来的"。 + +## 数据文件 + +所有记录存放在 `.cursor/pitfalls/pitfalls.md`。 + +## 条目格式 + +```markdown +### [PF-YYYYMMDD-HHMM] 一句话标题 +- **症状**: 用户/系统看到的错误表现 +- **根因**: 技术层面的真正原因 +- **解法**: 具体怎么修的 +- **防御**: 以后如何避免(可选,如果有通用性的话) +- **关联**: 相关文件、模块、技术栈标签 +``` + +## 操作 A:写入记录 + +### 触发条件 + +以下任一场景触发: + +1. **调试完成后** — 经历了 debug 过程并找到了非显而易见的根因 +2. **用户主动提及** — "记录一下这个坑"、"以后别再犯" +3. **Agent 识别到经验价值** — 问题涉及框架/库的隐式行为、配置陷阱、环境差异等 + +以下情况**不触发**: +- 纯拼写错误、简单语法错误 +- 问题原因一目了然(如变量名打错) +- 纯业务逻辑调整(不涉及"坑"的语义) + +### 流程 + +``` +1. 生成条目 ID:PF-YYYYMMDD-HHMM +2. 从调试过程中提取:症状、根因、解法 +3. 归纳防御措施(如果有通用性) +4. 读取 pitfalls.md,在顶部追加新条目 +5. 在回复末尾附:[已记录到踩坑日志] +``` + +### 静默写入原则 + +与 dev-changelog 一致——Agent 自己调试出来的问题,不需要用户确认就可以记录。 + +## 操作 B:自动匹配检索 + +### 触发条件 + +当 Agent 在当前任务中遇到以下情况时,应主动检索 pitfalls.md: + +1. **进入 Debug mode** — 读取 pitfalls.md,扫描是否有与当前错误症状匹配的记录 +2. **同类错误再现** — 错误信息关键词与已有条目的"症状"匹配 +3. **涉及已知高危区域** — 当前操作涉及的模块/技术栈在已有条目的"关联"中出现 + +### 匹配策略 + +``` +1. 提取当前问题的关键信号: + - 错误信息关键词 + - 涉及的文件/模块 + - 涉及的技术栈/框架 + +2. 在 pitfalls.md 中匹配: + - 硬匹配:错误信息关键词出现在条目的"症状"中 + - 软匹配:涉及的模块/技术栈出现在条目的"关联"中 + +3. 命中时,在分析中优先考虑已有经验: + > 注意:之前遇到过类似问题 [PF-xxx]:[一句话描述]。 + > 上次的根因是 [xxx],先排查这个方向。 +``` + +## 操作 C:手动检索 + +### 触发条件 + +用户主动要求回顾踩坑记录。典型话语: +- "之前那个坑是什么来着" +- "看看踩坑日志" +- "有遇到过类似的问题吗" + +### 流程 + +``` +1. 读取 pitfalls.md +2. 根据用户描述匹配相关条目 +3. 展示匹配结果 +``` + +## 与其他系统的协作 + +| 系统 | 关系 | 说明 | +|------|------|------| +| `dev-changelog` | 互补 | changelog 记改动事实,pitfall 记经验教训 | +| `pitfall-recall` Rule | 下游消费者 | 进入 Debug mode 或遇到错误时自动触发检索 | +| `epee-orchestrator` | 注册 | 在 registry.md 中注册本 Skill | + +## 自迭代日志 + +本节记录使用本 Skill 过程中发现的必要检查项。 + +### 已知必要检查 + +1. **顶部插入必须保持旧首条目完整性** — 使用 StrReplace 在文件顶部插入新条目时(操作 A 第 4 步),anchor(`old_string`)有且仅有两种合法选择: + (a) 只包含新条目之前的"稳定前缀"(如 `---\n\n` 或整个文件头部说明段),**不触及任何已有条目的任何一行**;然后 `new_string` = 稳定前缀 + 新条目完整内容 + 空行。 + (b) 把旧首条目的**完整多行内容**(标题行 + 全部字段行)都纳入 `old_string`;然后 `new_string` = 新条目完整内容 + 空行 + 旧首条目完整内容。 + + **绝对禁止**:把旧首条目的"标题行"单独当 anchor 而不带上它紧跟的字段行——StrReplace 是精确替换,这样做会删掉标题、让字段"无主"残留在新条目之后,造成半损坏状态(2026-04-20 实际踩过此坑)。 + + **写入后自检**:Read 文件头 25 行,确认看到 `### [PF-新ID]` 后紧跟其 5 字段,再往下能看到 `### [PF-旧首条目ID]` 标题行且字段完整跟随。 diff --git a/.cursor/skills/problem-distillery/SKILL.md b/.cursor/skills/problem-distillery/SKILL.md new file mode 100644 index 0000000..5dfa12e --- /dev/null +++ b/.cursor/skills/problem-distillery/SKILL.md @@ -0,0 +1,232 @@ +--- +name: problem-distillery +description: >- + 从顽固问题中蒸馏方法论的渐进式知识系统。追踪反复出现且未被彻底解决的问题, + 记录解决过程和弯路,定期提炼精炼认知,经实践验证后自动升级为常规注入。 + 当用户表达"还有问题"、"没解决"、"还是一样"、"又出现了"等语义, + 或 Agent 自身意识到同一问题已尝试 2 次以上仍未解决时触发。 +--- + +# Problem Distillery + +从反复出现的顽固问题中,经过"追踪 → 解决 → 蒸馏 → 验证 → 注入"的完整生命周期, +蒸馏出经过实践验证的精炼认知和方法论。 + +与其他系统的区别: +- **pitfall-journal**:互补。pitfall 是事后快照(debug 完记一笔),distillery 是过程追踪 + 知识提炼 +- **dev-changelog**:不重叠。changelog 记事实改动,distillery 记问题解决过程和认知沉淀 + +## 数据文件 + +``` +.cursor/distillery/ + problems.md -- 问题记录(open + resolved),操作 A/B 写入 + insights.md -- 蒸馏后的精炼方法论,操作 C 写入 + golden-rules.md -- 权重达标后升级的条目,操作 D 管理,新会话自动注入 +``` + +## 条目格式 + +### problems.md 条目 + +```markdown +### [PD-YYYYMMDD-HHMM] 一句话标题 +- **status**: open | resolved +- **fingerprint**: 关键特征词列表(用于匹配同一问题) +- **category**: tech | workflow | decision | other +- **first_seen**: YYYY-MM-DD HH:MM +- **attempts**: + 1. [YYYY-MM-DD HH:MM] 尝试了什么 → 结果如何 + 2. [YYYY-MM-DD HH:MM] 又尝试了什么 → 结果如何 +- **resolution**: (解决后填写)最终解决方案 +- **dead_ends**: (解决后填写)走过的弯路及其失败原因 +- **spark**: (解决后填写)一句话启发——这个问题教会了什么 +- **distilled**: (蒸馏后填写)IN-xxx +``` + +### insights.md 条目 + +```markdown +### [IN-YYYYMMDD-NN] 一句话方法论 +- **source_problems**: [PD-xxx, PD-yyy] +- **weight**: 0 +- **promoted**: false | true | demoted +- **content**: 2-3 句精炼认知 +``` + +文件尾部保留元数据: + +```markdown +--- +last_distill_date: YYYY-MM-DD +``` + +### golden-rules.md + +```markdown +# Golden Rules + +经过实践验证(权重 >= 5)的精炼认知,每次新会话自动注入。 + +1. [GR-001] 一句话认知(来源: IN-xxx, 累计验证 N 次) +2. [GR-002] ... +``` + +硬上限 15 条。超出时按权重排序保留 top-15,被淘汰的条目降回 insights.md(promoted 改为 demoted)。 + +## 操作 A:追踪记录(问题进行中) + +### 触发条件 + +以下**任一**场景触发: + +1. **用户明确表达**问题未解决: + - "还有问题"、"问题没有解决"、"还是一样"、"又出现了" + - "试了好多次了"、"这个问题反复出现"、"不行"、"没用" + - 以及其他表达"问题反复发生、Agent 没有完全解决"的语义 +2. **Agent 自身意识到**同一问题已经尝试了 2 次以上仍未解决 + +### 适用范围 + +不限于技术问题——工作流设计、产品决策等各类反复纠结的问题均适用。 + +### 流程 + +``` +1. 提取当前问题的指纹: + - 技术问题:错误信息关键词、涉及文件/模块、症状描述 + - 非技术问题:核心矛盾点、涉及领域、反复出现的决策困境 + +2. 读取 problems.md,用指纹匹配 status=open 的条目 + +3. 匹配到已有条目 → 在 attempts 中追加本次尝试记录 + +4. 无匹配 → 创建新条目: + - 生成 ID:PD-YYYYMMDD-HHMM + - status: open + - 记录首次尝试 + +5. 告知用户:"已开始追踪这个问题 [PD-xxx]"(首次) + 或 "已更新追踪记录 [PD-xxx],这是第 N 次尝试"(后续) +``` + +### 与 pitfall-journal 的衔接 + +当 pitfall-journal 中某个条目的同一问题反复出现(用户再次报告相同症状), +Agent 应意识到这已超出 pitfall 的"一次性记录"范畴,主动触发操作 A 建立追踪。 + +## 操作 B:解决记录 + +### 触发条件 + +存在 status=open 的追踪条目,且满足以下**任一**: +- 用户确认问题已解决:"好了"、"解决了"、"终于可以了" +- Agent 判断问题已解决(测试通过、错误消失等) + +### 流程 + +``` +1. 填写 resolution:最终的解决方案 +2. 填写 dead_ends:走过的弯路及其失败原因(从 attempts 中归纳) +3. 填写 spark:一句话启发——这个问题教会了什么 +4. status 改为 resolved +5. 回复末尾附 [顽固问题已解决并记录] +``` + +### 注意 + +- 如果问题在当前会话中从发现到解决只花了 1-2 次尝试,不需要走 distillery 流程 + (那是 pitfall-journal 的范畴) +- 只有经历了"反复尝试"的问题才值得 distillery 追踪 + +## 操作 C:定期蒸馏 + +### 触发条件 + +由 `distillery-recall` Rule 在每次会话开头检查: +- 读取 insights.md 尾部的 `last_distill_date` +- 如果距今超过 7 天,且 problems.md 中有未标记 `distilled` 的 resolved 条目 +- 则提醒用户:"你有 N 个已解决的顽固问题尚未总结,要花几分钟蒸馏一下吗?" +- 每次会话最多提醒一次 + +### 流程(用户同意后) + +``` +1. 读取所有 status=resolved 且无 distilled 标记的条目 +2. Agent 分析这些问题的共性,提出归纳建议: + - 哪些问题有共同的根因模式? + - 能提炼出什么通用的认知或方法论? + - 建议的表述(2-3 句精炼认知) +3. 用户确认/修改后: + - 写入 insights.md(ID 格式:IN-YYYYMMDD-NN,NN 为当日序号) + - weight 初始为 0 + - promoted: false +4. 更新 insights.md 尾部的 last_distill_date +5. 在对应 problems.md 条目上标记 distilled: IN-xxx +``` + +## 操作 D:验证与升级 + +### 被动验证 + +当操作 A 触发时(遇到新的或再次出现的顽固问题),额外执行: + +``` +1. 读取 insights.md,对当前问题做语义匹配 +2. 如有相关条目,向用户展示: + "之前总结过一条相关经验 [IN-xxx]: [内容摘要],可能对当前问题有帮助。" +3. 在问题解决流程中,跟踪该经验是否发挥了作用: + - 用户确认"这个提示有用" + - 或 Agent 判断解决方案与该 insight 的方向一致 +4. 确认有用 → weight += 1,在 insights.md 中更新 +5. 确认无用 → 不扣分(weight 只增不减,避免偶然失误惩罚好经验) +``` + +### 升级为 Golden Rule + +``` +1. 当某条 insight 的 weight >= 5: + a. 检查 golden-rules.md 当前条目数 + b. 如 < 15 → 直接升级: + - 在 golden-rules.md 中追加条目(ID: GR-NNN,NNN 为递增序号) + - insights.md 中 promoted 改为 true + c. 如 = 15 → 比较权重: + - 新条目权重 > golden-rules.md 中最低权重条目 → 替换 + - 被替换的条目降回 insights.md(promoted 改为 demoted) + - 否则不升级 +2. 升级后告知用户: + "经验 [IN-xxx] 已累计验证 N 次,升级为 Golden Rule [GR-NNN],后续新会话将自动注入。" +``` + +### 新会话注入 + +由 `distillery-recall` Rule 负责: +- 每次会话开头读取 `golden-rules.md` +- 如果非空,将全部条目作为背景知识注入上下文 +- 注入方式与 `changelog-headlines` 同级别——轻量、不显式提及来源 + +## 容量与性能控制 + +| 文件 | 策略 | 阈值 | +|------|------|------| +| problems.md | resolved 且已 distilled 的条目超过 50 条时,归档到 problems-archive.md | 50 条 | +| insights.md | 无上限(条目本身是精炼的,每条 3-5 行) | — | +| golden-rules.md | 硬上限,按权重淘汰 | 15 条 | +| 新会话注入成本 | 只读 golden-rules.md(预期 < 30 行) | 极轻量 | + +## 与其他系统的协作 + +| 系统 | 关系 | 说明 | +|------|------|------| +| `pitfall-journal` | 上游来源 | pitfall 条目反复出现时,升级为 distillery 追踪 | +| `dev-changelog` | 不重叠 | changelog 记事实改动,distillery 记过程和认知 | +| `distillery-recall` Rule | 下游消费者 | 负责 golden-rules 注入和蒸馏提醒 | +| `epee-orchestrator` | 注册 | 在 registry.md 中注册本 Skill | + +## 自迭代日志 + +本节记录使用本 Skill 过程中发现的必要检查项。 + +### 已知必要检查 + +(暂无) diff --git a/.cursor/skills/profile-memory/SKILL.md b/.cursor/skills/profile-memory/SKILL.md new file mode 100644 index 0000000..0ed3b49 --- /dev/null +++ b/.cursor/skills/profile-memory/SKILL.md @@ -0,0 +1,271 @@ +--- +name: profile-memory +description: >- + 渐进式用户/项目画像系统。两条触发路径: + (1)被动检测(主路径)——由 `changelog-recall` checklist 前置项 A 触发短路扫描, + 命中偏好/项目决策触发词时执行操作 A(总结 + 用户确认 + 写入)。 + (2)显式管理——当用户提到"画像"、"profile"、"查看画像"、"我的偏好"、"项目信息"等时 + 执行操作 B(浏览、修改、删除已有条目)。 +--- + +# Profile Memory + +渐进式画像系统,被动收集并持久化用户个人特质与项目信息。 + +## 存储结构 + +| 文件 | 位置 | 用途 | 注入上下文 | +|------|------|------|-----------| +| user-profile.md | `~/.cursor/profile/` | 个人画像精简版 | 是(每次会话) | +| user-profile-log.md | `~/.cursor/profile/` | 个人画像详细日志 | 否 | +| project-profile.md | `.cursor/profile/` | 项目画像精简版 | 是(每次会话) | +| project-profile-log.md | `.cursor/profile/` | 项目画像详细日志 | 否 | + +精简版 Profile 是 Agent 每次会话的上下文输入,必须极度精简。 +详细 Log 保留完整上下文,供用户主动查阅和溯源。 + +## 锚点 ID 机制 + +每条画像记录在写入时生成一个**锚点 ID**,格式为 `PF-YYYYMMDD-NN`(如 `PF-20260412-01`), +其中 NN 为当天的序号。 + +锚点 ID 在精简版和 Log 中保持一致: +- 精简版条目格式:`- 条目内容 `(HTML 注释,不影响可读性) +- Log 条目的 H3 标题:`### [PF-20260412-01] YYYY-MM-DD — 简短标题` + +这使得从精简版到 Log 的查找可以通过 Grep 精准定位,无需全文读取 Log。 + +## 逐级上溯机制 + +当 Agent 在使用精简版 Profile 作为上下文时,如果某条记录**语义模糊** +(如无法判断偏好的具体适用场景、与当前任务的关系不明确),执行以下查找: + +``` +1. 从精简版条目中提取锚点 ID(HTML 注释中的 PF-xxx) +2. 在对应的 Log 文件中 Grep 该 ID + - 找到 → 用 Read 工具读取该 ID 所在行号 ±15 行范围(精准读取,不读全文) + - Log 中包含原始上下文、来源对话等完整信息,通常足以消除歧义 +``` + +### 上溯原则 + +- **按需触发**:只有在精简版信息不足以支撑当前判断时才上溯 +- **精准读取**:通过 Grep 定位行号 + Read 局部读取,禁止全文读取 Log +- **最小化**:一次上溯通常只涉及 1-2 条记录 + +## 硬上限 + +- user-profile.md:不超过 **50 行** +- project-profile.md:不超过 **30 行** +- 每条信息一行,`- ` 开头,措辞客观中立 + +## 操作 A:被动检测 + 对话结束前确认 + +### 检测范围 + +在正常对话中被动检测以下信号(**不主动询问**): + +**个人特质**: +- 审美/设计偏好("太花哨了"、"我喜欢 minimal") +- 技术偏好("以后都用 X"、"我不喜欢 class 写法") +- 做事风格("先讨论再动手"、"不要自作主张") +- 沟通偏好("给我简短的回答"、"多解释一下原理") +- 产品理解/思维方式 + +**项目信息**: +- 项目定位和目标("这个项目是做 X 的") +- 技术栈与架构决策 +- 设计约定和规范 +- 产品方向和目标用户 + +### 检测原则 + +- **保守而非激进**:宁可漏记也不误记 +- 只记录**持久性**的偏好/特质,忽略一次性的临时需求 +- 区分"个人"和"项目"两个维度 + +### 变更分类 + +检测到的新信息与已有条目的关系分为三类,处理方式不同: + +| 类型 | 定义 | 示例 | 提示强度 | +|------|------|------|---------| +| **新增** | 全新维度,无已有条目 | 首次提到审美偏好 | 常规 | +| **演进** | 已有条目的深化、细化或自然发展 | "偏好 React" → "偏好 React + Next.js 全栈" | 常规,展示前后对比 | +| **转向** | 与已有条目方向性矛盾或根本性变化 | "偏好 React" → "想转 Vue";项目方向从 B2C 转 B2B | **加强提醒**,展示前后对比 | + +### 确认流程 + +``` +1. 在对话过程中将检测到的信息在内部缓存,分类为"个人"或"项目" +2. 对每条缓存信息,与已有 Profile 比对,标记变更类型(新增/演进/转向) +3. 当用户的主线任务完成后,统一提出,格式如下: + + "本次对话中我注意到以下可记录的画像信息:" + + **个人画像:** + - [新增][分类] 条目内容 + - [演进][分类] 旧:xxx → 新:yyy + - [转向][分类] 旧:xxx → 新:yyy ⚠️ + + **项目画像:** + - (同上格式) + + 转向类条目额外标注 ⚠️ 并附一句说明: + "⚠️ 以下条目与已有记录存在方向性变化,请特别关注:" + + "是否记录?你可以全部确认、逐条修改或跳过。" + +4. 用户确认后执行写入流程 +5. 如本次对话未检测到任何画像信息,则不触发此流程 +``` + +### 写入流程 + +``` +1. 读取对应的精简 Profile 和详细 Log(不存在则用模板创建) +2. 为每条新记录生成锚点 ID:PF-YYYYMMDD-NN(检查 Log 中已有 ID 避免冲突) +3. 按变更类型执行: + - 新增:在对应分类下追加条目,带锚点 ID 注释 + - 演进:替换对应旧条目为新措辞,沿用旧条目的锚点 ID(或生成新 ID,视变化程度而定) + - 转向:替换对应旧条目为新措辞,生成新锚点 ID(用户已在确认流程中审核) +4. 写入精简 Profile(条目格式:`- 内容 `) +5. 追加详细 Log(标题格式:`### [PF-xxx] YYYY-MM-DD — 简短标题`),其中: + - 新增条目:操作记为"新增" + - 演进条目:操作记为"更新(旧值 → 新值)" + - 转向条目:操作记为"转向(旧值 → 新值)",便于溯源重大变化 +6. 检查精简 Profile 是否超过硬上限,超过则提醒用户精简 +``` + +## 操作 B:用户主动管理 + +当用户说"查看我的画像"、"profile"、"查看项目画像"、"我的偏好"等: + +``` +1. 读取对应的精简 Profile,展示给用户 +2. 如用户要看详细版或溯源,读取对应 Log 展示 +3. 用户可要求: + - 删除某条记录(同步删除精简版条目,Log 中标记为已删除) + - 修改某条记录的措辞 + - 合并/重组分类 + - 新增分类 +``` + +## 操作 C:变更比对与冲突处理 + +### 比对逻辑 + +``` +对每条新检测到的信息,在同分类下的已有条目中查找语义相近项: +1. 无相近条目 → 标记为"新增" +2. 有相近条目且方向一致(深化/细化/补充) → 标记为"演进" +3. 有相近条目且方向矛盾(替代/转向/否定) → 标记为"转向" +``` + +### 前后对比格式 + +演进和转向类条目在确认流程中必须展示前后对比: + +``` +- [演进][技术偏好] 旧:偏好 React → 新:偏好 React + Next.js 全栈开发 +- [转向][产品方向] 旧:面向 C 端个人用户 → 新:转向 B 端企业客户 ⚠️ +``` + +### 用户选择 + +对每条演进/转向条目,用户可以: +- **确认更新**:用新条目替换旧条目 +- **保留两者**:旧条目不动,新条目作为补充追加(适用于不同细分维度) +- **放弃**:不记录本条 + +## 数据文件模板 + +首次使用时,如对应文件不存在,按以下模板创建。 + +### user-profile.md + +```markdown +# User Profile + +## 审美与设计 + +## 技术偏好 + +## 做事风格 + +## 沟通偏好 + +## 产品理解 +``` + +### user-profile-log.md + +```markdown +# User Profile Log + +详细记录每次画像更新的完整上下文,按时间正序追加。 + +## 记录 +``` + +### project-profile.md + +```markdown +# Project Profile + +## 项目定位 + +## 技术栈与架构 + +## 设计约定 + +## 产品方向 +``` + +### project-profile-log.md + +```markdown +# Project Profile Log + +详细记录每次项目画像更新的完整上下文,按时间正序追加。 + +## 记录 +``` + +### Log 条目格式 + +每次写入 Log 时,追加以下格式的条目: + +```markdown +### [PF-20260412-01] YYYY-MM-DD — 简短标题 +- **分类**: 对应的精简 Profile 分类名 +- **精简版**: 写入精简 Profile 的那一行内容 +- **原始上下文**: 用户原话或对话中的关键语句 +- **来源对话**: [对话简述](chat-uuid) +- **操作**: 新增 / 演进(旧值 → 新值)/ 转向(旧值 → 新值)/ 删除 +``` + +## 分类扩展 + +预设的分类列表可以扩展。当检测到的信息不属于任何现有分类时: + +``` +1. 在确认流程中标注"建议新增分类: [分类名]" +2. 用户确认后在精简 Profile 中新增该分类的 H2 标题 +3. 注意硬上限,新增分类会占用行数 +``` + +## 与其他系统的协作 + +| 系统 | 关系 | 说明 | +|------|------|------| +| `profile-recall` Rule | 下游消费者 | 每次会话读取精简 Profile 并注入上下文 | +| `epee-orchestrator` | 注册 | 在 registry.md 中注册本 Skill | + +## 自迭代日志 + +本节记录使用本 Skill 过程中发现的必要检查项。 + +### 已知必要检查 + +(暂无) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..abc6607 --- /dev/null +++ b/.gitignore @@ -0,0 +1,52 @@ +# === Cursor === +# 设备绑定配置,不同机器需独立生成 +.cursor/local-env.json + +# Hook 运行态标记(仅影响本地会话) +.cursor/changelog/.changelog-ack + +# cursor-init 运行时临时产物 +.cursor/_init-backup/ +.cursor/_gitignore-preview + +# 注意:不要忽略 .cursor/.init-done +# 本模板仓库自身应当 **不包含** 此文件(让 clone 者首次会话触发 init) +# 下游项目 init 完成后需要 commit 它 + +# === OS === +# Windows +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db +Desktop.ini +$RECYCLE.BIN/ + +# macOS +.DS_Store +._* +.Spotlight-V100 +.Trashes + +# Linux +*~ +.fuse_hidden* +.directory +.Trash-* + +# === IDE === +# VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +# JetBrains +.idea/ +*.iml + +# === Custom === +# 本模板仓库自身的临时文件 +*.log +*.tmp diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..68d1f85 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "AndreaNovelHelper.workspaceDisabled": true +} \ No newline at end of file