commit aaaa70d8aff55a5cb5dddbda445a944860818a31 Author: Nostars Developer Date: Thu Apr 30 17:24:02 2026 +0800 version init diff --git a/.opencode/data/changelog/changelog-full.md b/.opencode/data/changelog/changelog-full.md new file mode 100644 index 0000000..389f6d4 --- /dev/null +++ b/.opencode/data/changelog/changelog-full.md @@ -0,0 +1,5 @@ +# Dev Changelog — Full + +完整的开发改动记录,按时间倒序排列。作为主动 RAG 的数据源,用户手动唤醒时读取。 + +## 记录 diff --git a/.opencode/data/changelog/changelog-headlines.md b/.opencode/data/changelog/changelog-headlines.md new file mode 100644 index 0000000..b03e961 --- /dev/null +++ b/.opencode/data/changelog/changelog-headlines.md @@ -0,0 +1,3 @@ +# Dev Changelog — Headlines + +最近 ~50 次改动的一句话概要,按时间倒序排列。每次会话自动注入上下文。 diff --git a/.opencode/data/changelog/changelog-recent.md b/.opencode/data/changelog/changelog-recent.md new file mode 100644 index 0000000..adff995 --- /dev/null +++ b/.opencode/data/changelog/changelog-recent.md @@ -0,0 +1,4 @@ +# Dev Changelog — Recent + +最近 ~10 次改动的摘要记录,按时间倒序排列。 +当 Agent 检测到当前任务与近期改动相关时自动读取。 diff --git a/.opencode/data/deferred/registry.md b/.opencode/data/deferred/registry.md new file mode 100644 index 0000000..c592c87 --- /dev/null +++ b/.opencode/data/deferred/registry.md @@ -0,0 +1,11 @@ +# Deferred Decisions Registry + +## Active Items + +(暂无延期方案) + +--- + +## Completed / Cancelled Items + +(暂无已完成或已废弃的方案) diff --git a/.opencode/data/distillery/golden-rules.md b/.opencode/data/distillery/golden-rules.md new file mode 100644 index 0000000..9b0d868 --- /dev/null +++ b/.opencode/data/distillery/golden-rules.md @@ -0,0 +1,5 @@ +# Golden Rules + +经过实践验证(权重 >= 5)的精炼认知,每次新会话自动注入。 + + diff --git a/.opencode/data/distillery/insights.md b/.opencode/data/distillery/insights.md new file mode 100644 index 0000000..830ed18 --- /dev/null +++ b/.opencode/data/distillery/insights.md @@ -0,0 +1,8 @@ +# Problem Distillery — Insights + +从已解决的顽固问题中蒸馏出的精炼方法论。 + + + +--- +last_distill_date: 2026-04-30 diff --git a/.opencode/data/distillery/problems.md b/.opencode/data/distillery/problems.md new file mode 100644 index 0000000..c27e8f4 --- /dev/null +++ b/.opencode/data/distillery/problems.md @@ -0,0 +1,5 @@ +# Problem Distillery — Problems + +反复出现的顽固问题追踪记录,按时间倒序排列。 + + diff --git a/.opencode/data/pitfalls/pitfalls.md b/.opencode/data/pitfalls/pitfalls.md new file mode 100644 index 0000000..faaebf1 --- /dev/null +++ b/.opencode/data/pitfalls/pitfalls.md @@ -0,0 +1,6 @@ +# Pitfall Journal + +开发过程中踩过的坑,按时间倒序排列。 +Agent 进入 Debug mode 或遇到运行时错误时自动检索匹配。 + +--- diff --git a/.opencode/data/profile/project-profile-log.md b/.opencode/data/profile/project-profile-log.md new file mode 100644 index 0000000..5796dbe --- /dev/null +++ b/.opencode/data/profile/project-profile-log.md @@ -0,0 +1,5 @@ +# Project Profile Log + +详细记录每次项目画像更新的完整上下文,按时间正序追加。 + +## 记录 diff --git a/.opencode/data/profile/project-profile.md b/.opencode/data/profile/project-profile.md new file mode 100644 index 0000000..cedb7e9 --- /dev/null +++ b/.opencode/data/profile/project-profile.md @@ -0,0 +1,9 @@ +# Project Profile + +## 项目定位 + +## 技术栈与架构 + +## 设计约定 + +## 产品方向 diff --git a/.opencode/data/profile/user-profile-log.md b/.opencode/data/profile/user-profile-log.md new file mode 100644 index 0000000..1ea8aa3 --- /dev/null +++ b/.opencode/data/profile/user-profile-log.md @@ -0,0 +1,5 @@ +# User Profile Log + +详细记录每次画像更新的完整上下文,按时间正序追加。 + +## 记录 diff --git a/.opencode/data/profile/user-profile.md b/.opencode/data/profile/user-profile.md new file mode 100644 index 0000000..17ba4df --- /dev/null +++ b/.opencode/data/profile/user-profile.md @@ -0,0 +1,11 @@ +# User Profile + +## 审美与设计 + +## 技术偏好 + +## 做事风格 + +## 沟通偏好 + +## 产品理解 diff --git a/.opencode/package-lock.json b/.opencode/package-lock.json new file mode 100644 index 0000000..30eb63c --- /dev/null +++ b/.opencode/package-lock.json @@ -0,0 +1,378 @@ +{ + "name": ".opencode", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@opencode-ai/plugin": "1.14.30" + } + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", + "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", + "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", + "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", + "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", + "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", + "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@opencode-ai/plugin": { + "version": "1.14.30", + "resolved": "https://registry.npmjs.org/@opencode-ai/plugin/-/plugin-1.14.30.tgz", + "integrity": "sha512-O1y6qR349R5XJtB76Vx4TO/uvLkqNvdsgxtj2ZpWoygb3rtrkuVMiBsrcL2WfuyyaLJnPmbnkeigcdm42r09Hg==", + "license": "MIT", + "dependencies": { + "@opencode-ai/sdk": "1.14.30", + "effect": "4.0.0-beta.57", + "zod": "4.1.8" + }, + "peerDependencies": { + "@opentui/core": ">=0.1.105", + "@opentui/solid": ">=0.1.105" + }, + "peerDependenciesMeta": { + "@opentui/core": { + "optional": true + }, + "@opentui/solid": { + "optional": true + } + } + }, + "node_modules/@opencode-ai/sdk": { + "version": "1.14.30", + "resolved": "https://registry.npmjs.org/@opencode-ai/sdk/-/sdk-1.14.30.tgz", + "integrity": "sha512-OgPEDvALekHZIjByo/okJ699aLPn+XtsVxgZxUqE8TlzAG7TtskMGFl0fro8O0T2p+nkOT/LstnKGbECvc0+YA==", + "license": "MIT", + "dependencies": { + "cross-spawn": "7.0.6" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/effect": { + "version": "4.0.0-beta.57", + "resolved": "https://registry.npmjs.org/effect/-/effect-4.0.0-beta.57.tgz", + "integrity": "sha512-rg32VgXnLKaPRs9tbRDaZ5jxmzNY7ojXt85gSHGUTwdlbWH5Ik+OCUY2q14TXliygPGoHwCAvNWS4bQJOqf00g==", + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "fast-check": "^4.6.0", + "find-my-way-ts": "^0.1.6", + "ini": "^6.0.0", + "kubernetes-types": "^1.30.0", + "msgpackr": "^1.11.9", + "multipasta": "^0.2.7", + "toml": "^4.1.1", + "uuid": "^13.0.0", + "yaml": "^2.8.3" + } + }, + "node_modules/fast-check": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-4.7.0.tgz", + "integrity": "sha512-NsZRtqvSSoCP0HbNjUD+r1JH8zqZalyp6gLY9e7OYs7NK9b6AHOs2baBFeBG7bVNsuoukh89x2Yg3rPsul8ziQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT", + "dependencies": { + "pure-rand": "^8.0.0" + }, + "engines": { + "node": ">=12.17.0" + } + }, + "node_modules/find-my-way-ts": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/find-my-way-ts/-/find-my-way-ts-0.1.6.tgz", + "integrity": "sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA==", + "license": "MIT" + }, + "node_modules/ini": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-6.0.0.tgz", + "integrity": "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==", + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/kubernetes-types": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/kubernetes-types/-/kubernetes-types-1.30.0.tgz", + "integrity": "sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q==", + "license": "Apache-2.0" + }, + "node_modules/msgpackr": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.10.tgz", + "integrity": "sha512-iCZNq+HszvF+fC3anCm4nBmWEnbeIAfpDs6IStAEKhQ2YSgkjzVG2FF9XJqwwQh5bH3N9OUTUt4QwVN6MLMLtA==", + "license": "MIT", + "optionalDependencies": { + "msgpackr-extract": "^3.0.2" + } + }, + "node_modules/msgpackr-extract": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz", + "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-gyp-build-optional-packages": "5.2.2" + }, + "bin": { + "download-msgpackr-prebuilds": "bin/download-prebuilds.js" + }, + "optionalDependencies": { + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" + } + }, + "node_modules/multipasta": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/multipasta/-/multipasta-0.2.7.tgz", + "integrity": "sha512-KPA58d68KgGil15oDqXjkUBEBYc00XvbPj5/X+dyzeo/lWm9Nc25pQRlf1D+gv4OpK7NM0J1odrbu9JNNGvynA==", + "license": "MIT" + }, + "node_modules/node-gyp-build-optional-packages": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", + "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.1" + }, + "bin": { + "node-gyp-build-optional-packages": "bin.js", + "node-gyp-build-optional-packages-optional": "optional.js", + "node-gyp-build-optional-packages-test": "build-test.js" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pure-rand": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-8.4.0.tgz", + "integrity": "sha512-IoM8YF/jY0hiugFo/wOWqfmarlE6J0wc6fDK1PhftMk7MGhVZl88sZimmqBBFomLOCSmcCCpsfj7wXASCpvK9A==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/toml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/toml/-/toml-4.1.1.tgz", + "integrity": "sha512-EBJnVBr3dTXdA89WVFoAIPUqkBjxPMwRqsfuo1r240tKFHXv3zgca4+NJib/h6TyvGF7vOawz0jGuryJCdNHrw==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/uuid": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.1.tgz", + "integrity": "sha512-9ezox2roIft6ExBVTVqibSd5dc5/47Sw/uY6b4SjQUT2TzQ0tltNquWA46y4xPQmdZYqvnio22SgWd41M86+jw==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist-node/bin/uuid" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/yaml": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", + "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/zod": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.8.tgz", + "integrity": "sha512-5R1P+WwQqmmMIEACyzSvo4JXHY5WiAFHRMg+zBZKgKS+Q1viRa0C1hmUKtHltoIFKtIdki3pRxkmpP74jnNYHQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/.opencode/package.json b/.opencode/package.json new file mode 100644 index 0000000..421b41c --- /dev/null +++ b/.opencode/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@opencode-ai/plugin": "1.14.30" + } +} diff --git a/.opencode/skills/deferred-decisions/SKILL.md b/.opencode/skills/deferred-decisions/SKILL.md new file mode 100644 index 0000000..2d05939 --- /dev/null +++ b/.opencode/skills/deferred-decisions/SKILL.md @@ -0,0 +1,151 @@ +--- +name: deferred-decisions +description: >- + 记录开发中被延期的技术方案/决策,并在关联任务出现时主动提醒用户。 + 当对话中出现"以后再做"、"先不做"、"defer"、"延期方案"、"备选方案"、 + "递进方案"等语义时触发。也用于浏览、管理已有的 deferred items。 +--- + +# Deferred Decisions Skill + +追踪开发中被延期的技术方案,在合适时机主动提醒用户。 + +## 存储 + +**数据文件**: `.opencode/data/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. 读取 .opencode/data/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:关联提醒 + +### 触发条件 + +由 AGENTS.md 中的"延期方案匹配"规则触发,或当用户任务涉及已有 deferred item 的领域时自动触发。 + +### 流程 + +``` +1. 读取 .opencode/data/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 文件模板 + +当 `.opencode/data/deferred/registry.md` 不存在时,用此模板创建: + +```markdown +# Deferred Decisions Registry + +## Active Items + +(暂无延期方案) + +--- + +## Completed / Cancelled Items + +(暂无已完成或已废弃的方案) +``` + +## 自迭代日志 + +本节记录使用本 Skill 过程中发现的必要检查项。 + +### 已知必要检查 + +(暂无) diff --git a/.opencode/skills/dev-changelog/SKILL.md b/.opencode/skills/dev-changelog/SKILL.md new file mode 100644 index 0000000..6d694dd --- /dev/null +++ b/.opencode/skills/dev-changelog/SKILL.md @@ -0,0 +1,258 @@ +--- +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 条 | 每次会话自动注入 | + +所有数据文件存放在 `.opencode/data/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 完成了一个涉及**代码或配置文件实质性改动**的任务后,自动触发。 + +以下情况**不触发**: +- 纯对话讨论、方案设计、问题解答(无文件改动) +- 只读操作(查看文件、搜索代码) +- 只改动了 `.opencode/` 目录下的基础设施文件(如画像、延期方案、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 条则移除最旧的 + c. 读取 changelog-headlines.md,在顶部插入 L3 条目,如超过 50 条则移除最旧的 + +5. 在回复末尾附一行提示:"[已记录到开发日志]" +``` + +### 静默写入原则 + +- **不需要用户确认**——Agent 自己做的改动,对"做了什么"的认知是一手的 +- 用户如果觉得记录不准确,可通过操作 D 修改或删除 +- 回滚操作也要记录("回退了 XX 改动"),真实反映开发过程 + +## 操作 B:L2 自动触发读取 + +### 触发条件 + +由 AGENTS.md 中的"开发日志上下文注入"和"L2 自动触发"规则调度。当 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 次改动的一句话概要,按时间倒序排列。每次会话自动注入上下文。 +``` + +## 与其他系统的协作 + +| 系统 | 关系 | 说明 | +|------|------|------| +| `AGENTS.md` | 下游消费者 | 每次会话注入 L3,自动触发 L2 读取 | +| `deferred-decisions` Skill | 互补 | deferred 记"没做什么",changelog 记"做了什么" | +| `profile-memory` Skill | 结构对称 | profile 是"是什么",changelog 是"做了什么" | +| `epee-orchestrator` Skill | 注册 | 在 registry.md 中注册本 Skill | + +## 自迭代日志 + +本节记录使用本 Skill 过程中发现的必要检查项。 + +### 已知必要检查 + +1. **大任务收尾遗漏风险** — 当单次任务涉及 5+ 个文件改动时,Agent 容易在输出总结回复后遗漏被动写入流程。应在生成最终回复前,先执行 AGENTS.md 中的"任务完成 Checklist",确认三层日志已写入后再输出回复。绝不能"先回复再补写"。 + +2. **L3/L2 滚动窗口必须落地** — 操作 A 第 4 步不是「插入即结束」:写入后必须数清条目(L3 为以 `- [` 开头的列表行,L2 为 `### [CL-` 标题行)。L3 超过 50 条、L2 超过 20 条时,必须从**文件底部(最旧)**整段删除条目直至恰好满足上限;禁止长期只追加不修剪。 + +3. **顶部插入必须保持旧首条目完整性** — 使用编辑工具在文件顶部插入新条目时,anchor(`old_string`)有且仅有两种合法选择: + (a) 只包含新条目之前的"稳定前缀"(如 L1 的 `## 记录\n\n` 或 L2 的整段文件头说明),**不触及任何已有条目的任何一行**;`new_string` = 稳定前缀 + 新条目完整内容 + 空行。 + (b) 把旧首条目的**完整多行内容**(标题行 + 全部字段行)都纳入 `old_string`;`new_string` = 新条目完整内容 + 空行 + 旧首条目完整内容。 + + **绝对禁止**:只把旧首条目的标题行(或前 1-2 字段)当 anchor 而不带上剩余字段行——编辑工具会吞掉这些 anchor 行但不动剩余字段,造成"旧标题丢失、字段游离"的半损坏状态。 + + **写入后自检**:Read 文件头部 30 行,确认看到新条目完整 + 旧首条目标题行仍存在且字段完整跟随。L3 的一行条目不受本条约束(它就是单行,天然无此风险)。 diff --git a/.opencode/skills/epee-orchestrator/SKILL.md b/.opencode/skills/epee-orchestrator/SKILL.md new file mode 100644 index 0000000..943bf6c --- /dev/null +++ b/.opencode/skills/epee-orchestrator/SKILL.md @@ -0,0 +1,123 @@ +--- +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 会做什么 + - 核心工作机制 + - 预估能节省的重复劳动 +3. 询问用户选择: + a) "继续讨论并创建" → 进入创建流程 + b) "以后再说" → 进入延期记录流程 + c) "不需要" → 结束,正常执行当前任务 +``` + +### a) 创建流程 + +``` +1. 按 Skill 创建标准流程完成 Discovery → Design → Implementation → Verification +2. 将以下上下文纳入考量: + - 触发创建的原始任务描述 + - Orchestrator 的方案概要 + - 建议的 Skill 名称 +3. 创建完成后,要求用户对新 Skill 进行实际测试 +4. 测试通过后,执行操作 C 同步 Registry +``` + +### b) 延期记录流程 + +``` +1. 读取 deferred-decisions Skill(路径: .opencode/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 / 配置文件来替代手动操作 + +不满足标准时,Agent 正常执行任务,不提出创建建议。 + +## 与其他系统的协作 + +| 系统 | 关系 | 说明 | +|------|------|------| +| `deferred-decisions` Skill | 下游工具 | 操作 B 延期记录的执行者 | +| AGENTS.md | 规则来源 | Skill 自迭代和 Registry 同步的强制要求由 AGENTS.md 定义 | + +## 自迭代日志 + +本节记录使用本 Skill 过程中发现的必要检查项。 + +### 已知必要检查 + +1. **收尾动作级联遗漏** — 当 Agent 遗漏了一个收尾动作(如 changelog 写入)后,后续的收尾动作(自迭代、Registry 同步)也会被一并遗漏,因为它们都在同一个"收尾阶段"。AGENTS.md 中的 Checklist 化设计可以打断这种级联——每项独立检查,不依赖前一项的执行记忆。 diff --git a/.opencode/skills/epee-orchestrator/registry.md b/.opencode/skills/epee-orchestrator/registry.md new file mode 100644 index 0000000..a8e1178 --- /dev/null +++ b/.opencode/skills/epee-orchestrator/registry.md @@ -0,0 +1,70 @@ +# EPEE Skill Registry + +> 本文件由 EPEE Skill Orchestrator 维护,记录所有已实现 Skill 的摘要信息。 +> 每次创建/修改 Skill 后必须同步更新(参见 AGENTS.md 中的"Registry 同步"章节)。 + +## 条目格式说明 + +每个条目包含以下字段: +- **类型**:项目级 / 个人级 / 基础设施 +- **能力**:1 句话核心能力描述 +- **触发场景**:逗号分隔的关键词/短语,用于与任务特征匹配 +- **输出**:该 Skill 的产出物 +- **路径**:SKILL.md 的相对路径(相对于 `.opencode/skills/`) +- **备注**(可选):特殊说明 + +--- + +## 已注册 Skill + +### opencode-init +- **类型**: 基础设施 +- **能力**: 把从模板 clone 或复制过来的 .opencode/ 重置为新项目的干净起点——清理源项目的项目专用数据,重建 registry,交互式生成 .gitignore,最后写入 `.opencode/.init-done` sentinel +- **触发场景**: 首次会话自动触发(.opencode/.init-done 缺失时由 AGENTS.md 引导);关键词:"初始化opencode"、"opencode init"、"重置 opencode"、"reset opencode"、"补 gitignore"、"生成 gitignore"、"gitignore 模板" +- **输出**: 清理后的 `.opencode/` 结构(规范清单完整、数据文件为模板、registry 仅含通用条目)、项目根 `.gitignore`(可选)、`.opencode/.init-done` sentinel +- **路径**: .opencode/skills/opencode-init/SKILL.md +- **备注**: 首次通过 sentinel 自动触发一次,之后仅关键词手动触发;破坏性操作必须 dry-run;设计为幂等,重复运行无害;阶段 7 失败时不写 sentinel 保证可恢复 + +### deferred-decisions +- **类型**: 基础设施 +- **能力**: 记录和追踪延期的技术方案/决策,在关联任务出现时主动提醒 +- **触发场景**: "以后再做"、"先不做"、"defer"、延期方案管理、延期回顾 +- **输出**: .opencode/data/deferred/registry.md 条目 +- **路径**: .opencode/skills/deferred-decisions/SKILL.md +- **备注**: 不参与任务分流匹配,仅作为 Orchestrator 的下游工具 + +### dev-changelog +- **类型**: 基础设施 +- **能力**: 三层开发进程记录系统,Agent 完成代码改动后自动记录,提供一句话概要到完整日志的多级上下文 +- **触发场景**: "开发日志"、"changelog"、"最近改了什么"、"回顾改动"、"查看开发记录"、代码改动后自动写入 +- **输出**: .opencode/data/changelog/ 下的 changelog-full.md、changelog-recent.md、changelog-headlines.md +- **路径**: .opencode/skills/dev-changelog/SKILL.md + +### pitfall-journal +- **类型**: 基础设施 +- **能力**: 记录开发中踩过的坑(非显而易见的问题),在遇到同类问题时自动检索匹配已有经验 +- **触发场景**: debug 完成后、"踩坑"、"之前遇到过"、"坑"、进入 Debug mode、同类错误反复出现 +- **输出**: .opencode/data/pitfalls/pitfalls.md 条目 +- **路径**: .opencode/skills/pitfall-journal/SKILL.md + +### problem-distillery +- **类型**: 基础设施 +- **能力**: 追踪反复出现的顽固问题,记录解决过程和弯路,定期蒸馏精炼方法论,经实践验证后自动升级为新会话常规注入 +- **触发场景**: "还有问题"、"没解决"、"还是一样"、"又出现了"、"试了好多次"、"反复出现"、Agent 意识到同一问题尝试 2 次以上未解决、"蒸馏"、"总结经验" +- **输出**: .opencode/data/distillery/ 下的 problems.md、insights.md、golden-rules.md +- **路径**: .opencode/skills/problem-distillery/SKILL.md + +### profile-memory +- **类型**: 个人级 +- **能力**: 在对话中被动检测用户个人特质和项目信息,经确认后持久化为精简画像和详细日志 +- **触发场景**: "画像"、"profile"、"我的偏好"、"查看画像"、"项目信息"、"查看项目画像"、用户主动管理画像 +- **输出**: .opencode/data/profile/user-profile.md、.opencode/data/profile/project-profile.md 及对应 log 文件 +- **路径**: .opencode/skills/profile-memory/SKILL.md + +### epee-orchestrator +- **类型**: 基础设施 +- **能力**: 元层调度系统,检测任务是否可由已有 Skill 处理并分流,或发现 Skill 缺口并引导创建新 Skill;同时负责 Skill Registry 维护 +- **触发场景**: 手动配置密集、重复模式明确、手工指引过长的任务、Skill 缺口发现、Registry 同步维护 +- **输出**: 分流决策(调用已有 Skill / 创建新 Skill)、.opencode/skills/epee-orchestrator/registry.md 维护 +- **路径**: .opencode/skills/epee-orchestrator/SKILL.md +- **备注**: 元层 Skill,自身注册以便其他 Agent 了解调度能力的可用性 diff --git a/.opencode/skills/opencode-init/SKILL.md b/.opencode/skills/opencode-init/SKILL.md new file mode 100644 index 0000000..f3e3e52 --- /dev/null +++ b/.opencode/skills/opencode-init/SKILL.md @@ -0,0 +1,795 @@ +--- +name: opencode-init +description: >- + 初始化新项目的 .opencode 结构。两种触发方式: + (1)首次自动触发 —— 当 `.opencode/.init-done` sentinel 不存在时, + AGENTS.md 会在会话首次响应前引导 Agent 主动执行本 Skill; + (2)关键词手动触发 —— "初始化opencode"、"opencode init"、"重置 opencode"、"补 gitignore" 等。 + 流程:清理模板残留的项目专用数据(changelog/deferred/pitfalls/profile/distillery), + 可选生成 .gitignore 模板,最后写入 `.opencode/.init-done` 标记完成。 + 已 init 仓库不会再自动触发,除非用户主动通过关键词请求。 +--- + +# OpenCode Init Skill + +把从其它项目复制过来(或通过 git clone 模板仓库获得)的 `.opencode/` 目录重置为当前新项目的干净起点。 + +## 使用场景 + +### 场景 A:克隆模板仓库后的首次会话 + +``` +1. 用户把本模板作为 git 仓库发布 +2. 其他人 `git clone <模板仓库>` 得到新项目骨架 +3. 用户打开 OpenCode,在该仓库发出任意第一条消息 +4. AGENTS.md 检测 .opencode/.init-done 不存在 + → 引导 Agent 暂停用户原始请求,先执行本 Skill +5. Agent 按阶段 0 → 7 跑完,写入 .init-done +6. 后续会话 sentinel 已存在,不再自动触发 +``` + +### 场景 B:从已有项目直接复制 .opencode 目录 + +``` +1. 用户在 "源项目 A" 中使用本 .opencode 模板开发 +2. 用户开 "新项目 B",把 A 的 .opencode/ 整体拷贝到 B +3. 用户在 B 中说"初始化opencode"(或首次会话被 AGENTS.md 触发) +4. 本 Skill 清空 A 遗留的项目数据,重建 registry,生成 .gitignore,写入 sentinel +``` + +### 场景 C:只补 .gitignore + +``` +init 后用户说"补一下 gitignore"或"生成 gitignore" → 只跑阶段 5.5 +``` + +## 触发条件 + +本 Skill 由 AGENTS.md 触发,两类入口: + +### A. 全流程(阶段 0 → 7) + +- `.opencode/.init-done` 不存在 → 会话首次响应前由 AGENTS.md 自动引导 +- 用户关键词:`初始化opencode` / `opencode init` / `重置 opencode` / `reset opencode` 等 +- 口头描述"把复制过来的 .opencode 清理一下"、"按规范归位一下" + +### 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`,下次会话仍会被 AGENTS.md 触发从头继续 + +## 核心流程 + +### 阶段 0:前置确认 + 幂等判断 + +``` +1. 检查当前工作目录下存在 .opencode/ + - 不存在 → 直接结束,提示用户先复制模板 +2. 读取 .opencode/.init-done + - 不存在 → 继续,按"首次 init"路径执行 + - 已存在 → 展示其元数据(initialized_at、project_type 等),提示: + "检测到本仓库已于 {initialized_at} 完成初始化(project_type: {type})。 + 继续执行会清空 deferred / pitfalls / distillery 等数据文件。确认要继续吗?" + 等用户明确回复"继续"再往下 +3. 运行 `git status`: + - 不是 git 仓库 → 警告但不阻塞,建议手动备份 + - 有未提交改动 → 提醒"建议先 commit 或 stash,便于回滚",等用户明确回复"继续" +4. 向用户声明本次操作范围(见"分组规则"),请求口头确认启动 +``` + +### 阶段 1:递归扫描 `.opencode/` + +``` +1. 用 shell 列出 .opencode 下所有文件(含子目录) +2. 把每个文件对照"规范清单"和"清理清单"分成三组: + - A 组(canonical):在规范清单中,原样保留 + - B 组(template-data):在清理清单中,需要删除或重置 + - C 组(foreign):两张清单都没覆盖到的,视作未知项 +3. 把分组结果用表格汇报给用户: + | 组 | 路径 | 处理动作 | +``` + +### 阶段 2:处理 C 组(未知文件归位) + +对 C 组中的每个文件,逐条询问用户(可一次性列清单批量确认): + +| 文件特征 | 建议归属 | 目标路径 | +|----------|----------|----------| +| 包含 `SKILL.md` 的目录 | Skill(无论通用/项目专属) | `.opencode/skills//` | +| 看不出归属 | 询问用户 | — | +| 明显是临时/垃圾文件(`*.log`、`*.tmp`、缓存等) | 删除(需用户确认) | — | + +执行要点: +- **先列清单一次性确认**,然后批量执行移动/删除,避免交互过于频繁 +- **重名冲突**:C 组文件若与 A 组规范文件重名,**保留 A 组版本**,把 C 组备份到 `.opencode/_init-backup/` 下让用户自行 diff,不直接覆盖 +- **迁移后核查**:移动完成后重新扫描,确认 C 组已清空 + +### 阶段 3:处理 B 组(源项目数据清理/重置) + +按"清理清单"执行: + +**A. 直接删除** + +- `.opencode/data/` 下所有数据文件的内容(目录保留) +- `.opencode/node_modules/`(如有) +- `.opencode/*.log` —— 调试日志 + +**B. 重置为空模板**(保留文件,仅清内容) + +| 文件 | 模板(见"模板内容"节) | +|------|------------------------| +| `.opencode/data/changelog/changelog-full.md` | L1 模板 | +| `.opencode/data/changelog/changelog-recent.md` | L2 模板 | +| `.opencode/data/changelog/changelog-headlines.md` | L3 模板 | +| `.opencode/data/deferred/registry.md` | deferred 模板 | +| `.opencode/data/pitfalls/pitfalls.md` | pitfalls 模板 | +| `.opencode/data/distillery/problems.md` | problems 模板 | +| `.opencode/data/distillery/insights.md` | insights 模板 | +| `.opencode/data/distillery/golden-rules.md` | golden-rules 模板 | +| `.opencode/data/profile/user-profile.md` | user-profile 模板 | +| `.opencode/data/profile/user-profile-log.md` | user-profile-log 模板 | +| `.opencode/data/profile/project-profile.md` | project-profile 模板 | +| `.opencode/data/profile/project-profile-log.md` | project-profile-log 模板 | + +执行要点: +- 每个重置前**先 Read 现有内容预览前 10 行**给用户,避免误删有价值数据(特别是 deferred/pitfalls 用户可能想保留) +- 如用户对某个数据文件明确说"保留"(例如 golden-rules 想带过去),跳过该文件的重置 + +### 阶段 4:重建 registry + +打开 `.opencode/skills/epee-orchestrator/registry.md`: + +1. 解析现有条目(每条 `### ` 块) +2. 删除所有标记为"项目级"的条目 +3. 遍历 `.opencode/skills/` 目录,对照 registry: + - registry 有条目但 skill 目录不存在 → 删除条目 + - skill 目录存在但 registry 无条目 → 读取该 skill 的 SKILL.md frontmatter,新增条目 +4. **确保 `opencode-init` 条目本身存在**(类型: 基础设施) +5. 写回 registry.md + +### 阶段 5:同步 opencode.json 配置 + +- 读取 `opencode.json` +- 确认 `instructions` 字段中包含所有必要的数据文件路径(changelog-headlines、deferred/registry、golden-rules、project-profile) +- 如有缺失或路径不正确,更新之 + +### 阶段 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 偏好 | 多选 | OpenCode(预勾)/ VSCode / JetBrains 全家桶 / Visual Studio / Vim+Emacs | +| Q3 | 操作系统 | 多选 | Windows / macOS / Linux(按探测到的当前 OS 预勾) | +| Q4(可选)| 其他要忽略的路径 | 自由文本 | 用户可跳过 | + +#### 5.5.3 片段组装 + +按问卷选择拼装,片段内容见下方"模板内容 · .gitignore 片段库"。拼装顺序固定: + +``` +# === OpenCode(固定,所有项目都包含) === +# === OS === +# === IDE === +# === Language / Framework === +# === Custom === +``` + +若 Q1 选"不确定" → 跳过 Language 段,其他段正常拼装(极简版仍可用)。 + +#### 5.5.4 预览与确认 + +1. 把组装结果写到 `.opencode/_gitignore-preview`(临时文件) +2. 给用户完整展示(超过 60 行则折叠中段) +3. AskQuestion:`[写入 .gitignore / 让我调整再确认 / 放弃本阶段]` +4. "写入"→ move 到项目根 `.gitignore`(已存在时按 5.5.1 的选择做覆盖或追加),删除预览文件 +5. "调整"→ 根据用户描述修改后重复步骤 2-3 +6. "放弃"→ 删除预览文件,`.init-done` 标记 `gitignore_generated: false` + +### 阶段 6:验证与报告 + +``` +1. 重新递归扫描 .opencode/,再次分组 +2. 期望状态: + - A 组:全部保留,文件内容未被动过 + - B 组:数据文件仅含模板内容 + - C 组:为空(或仅剩用户明确要求保留的文件) + - 项目根 .gitignore:按用户选择存在或被放弃(状态记到报告里) + - project根 opencode.json:instructions 已正确配置 +3. 给用户一份结构化报告,至少包含: + - 删除的文件 + - 重置的文件 + - 新注册/移除的 registry 条目 + - .gitignore 的处理结果(新建/追加/覆盖/放弃) + - 未处理的文件(如果有,逐条说明原因) +``` + +### 阶段 7:写入 `.init-done` sentinel + +**仅在阶段 6 验证全部通过后执行**。任何前序阶段异常中断都不写入此文件,确保下次会话 AGENTS.md 能再次触发。 + +``` +1. 按"模板内容 · .init-done"格式,填充实际值写入 .opencode/.init-done +2. 向用户输出收尾提示: + > 初始化完成。建议现在执行: + > git add .opencode/ .gitignore + > git diff --cached -- .opencode/ + > git commit -m "chore(opencode): initialize .opencode from template" + > + > ⚠️ .opencode/.init-done 必须 commit,否则团队其他成员 clone 后会被再次触发 init。 +``` + +**仅跑阶段 5.5 时**(用户说"补 gitignore"): +- 若 `.init-done` 存在 → 更新其中的 `gitignore_generated: true` 字段,保留其他字段 +- 若 `.init-done` 不存在 → 提示用户"仓库尚未完整 init,只补 gitignore 不会写 sentinel。是否改为跑完整 init?" + +--- + +## 规范清单(canonical) + +下列文件构成本 `.opencode` 模板的"主干",初始化后必须都在、内容不被删改(数据文件除外): + +### 顶层 + +- `AGENTS.md` —— 项目规则文件(项目根目录) +- `opencode.json` —— OpenCode 配置文件 +- `.opencode/.init-done` —— **阶段 7 写入**;模板仓库自身不应包含此文件 +- `.opencode/.gitignore` —— node_modules 忽略规则 + +### Skills(规范 Skill 目录白名单) + +- `.opencode/skills/opencode-init/` +- `.opencode/skills/deferred-decisions/` +- `.opencode/skills/dev-changelog/` +- `.opencode/skills/epee-orchestrator/`(含 `registry.md`,见阶段 4) +- `.opencode/skills/pitfall-journal/` +- `.opencode/skills/problem-distillery/` +- `.opencode/skills/profile-memory/` + +> **任何不在此白名单中的 skill 目录**,在阶段 3 中一律删除(视为源项目的项目级 Skill)。 + +### 数据占位目录(保留目录,文件重置为模板内容) + +- `.opencode/data/changelog/{changelog-full.md, changelog-recent.md, changelog-headlines.md}` +- `.opencode/data/deferred/registry.md` +- `.opencode/data/pitfalls/pitfalls.md` +- `.opencode/data/distillery/{problems.md, insights.md, golden-rules.md}` +- `.opencode/data/profile/{user-profile.md, user-profile-log.md, project-profile.md, project-profile-log.md}` + +--- + +## 清理清单(cleanup list) + +### 强制删除 + +| 路径 | 原因 | +|------|------| +| `.opencode/*.log`、`.opencode/**/*.log` | 调试日志遗留 | +| `.opencode/_init-backup/`(如果是上一轮残留) | 仅阶段 2 冲突备份用,运行前应不存在 | +| `.opencode/_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 次改动的一句话概要,按时间倒序排列。每次会话自动注入上下文。 +``` + +### 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/user-profile.md + +```markdown +# User Profile + +## 审美与设计 + +## 技术偏好 + +## 做事风格 + +## 沟通偏好 + +## 产品理解 +``` + +### profile/user-profile-log.md + +```markdown +# User Profile Log + +详细记录每次画像更新的完整上下文,按时间正序追加。 + +## 记录 +``` + +### profile/project-profile.md + +```markdown +# Project Profile + +## 项目定位 + +## 技术栈与架构 + +## 设计约定 + +## 产品方向 +``` + +### profile/project-profile-log.md + +```markdown +# Project Profile Log + +详细记录每次项目画像更新的完整上下文,按时间正序追加。 + +## 记录 +``` + +### .init-done + +阶段 7 写入的 sentinel,YAML 格式,字段固定: + +```yaml +# .opencode/.init-done — opencode-init Skill 写入的初始化标记文件 +# 本文件的存在表示本仓库已完成 .opencode 模板初始化 +# 请务必 git commit 此文件,避免团队成员 clone 后被再次触发 init +initialized_at: {{ISO_DATETIME}} # 如 2026-04-30T16:30:00+08:00 +initialized_by: opencode-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 按用户问卷选择拼接以下片段。每段前后各空一行,保证可读性。 + +### 固定段:OpenCode + +```gitignore +# === OpenCode === +# opencode-init 临时产物 +.opencode/_init-backup/ +.opencode/_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 +*~ +\#*\# +.\#* +``` + +**OpenCode**:固定段已覆盖,无需额外片段。 + +### 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 组移到 `.opencode/_init-backup/`,告知用户自行 diff | +| C 组有 `SKILL.md` 且 skill 名与 A 组白名单同名 | 保留 A 组 skill;C 组整个 skill 目录移到 `_init-backup/` | +| 数据文件(如 `pitfalls.md`)用户明确说"保留" | 跳过该文件重置 | +| 扫描到 `.opencode/_init-backup/`(上轮残留) | 警告用户并询问:删除 / 保留 / 重命名 | +| `git status` 不能执行(不是 git 仓库) | 警告但不阻塞,改为建议用户手动备份 | +| `.opencode/.init-done` 已存在且用户触发了全流程 | 阶段 0 展示其元数据并要求二次确认 | +| 阶段 5.5 项目根已有 `.gitignore` 且用户选"追加" | 把拼装结果追加到现有文件末尾(用 `\n\n# --- 以下由 opencode-init 追加 ---\n` 分隔) | +| 阶段 5.5 中途异常或用户放弃 | 不写入 `.gitignore`,`.init-done` 的 `gitignore_generated` 记 false | +| 阶段 7 写 `.init-done` 前前序阶段已 abort | 不写入 sentinel,下次会话 AGENTS.md 会重新触发 | +| 用户说"补 gitignore" 但 `.init-done` 不存在 | 提醒"仓库尚未完整 init",询问是否改为跑全流程 | + +--- + +## 一次运行的最终状态(验收标准) + +全流程(阶段 0 → 7)完成后 `.opencode/` 应当满足: + +1. 规范清单中列出的所有文件/目录都存在 +2. 所有数据文件(changelog/deferred/pitfalls/distillery/profile)仅含模板内容 +3. `.opencode/skills/` 下仅有白名单中的 skill 目录 +4. `.opencode/skills/epee-orchestrator/registry.md` 中只有:基础设施 + 个人级 skill 条目,且包含 `opencode-init` 条目 +5. 不存在 `*.log`、`_init-backup/`、`_gitignore-preview` +6. `.opencode/.init-done` 已写入,字段完整且值有效 +7. `opencode.json` 的 `instructions` 字段配置正确 +8. 项目根 `.gitignore` 状态明确(存在且有内容 / 被用户显式放弃) +9. `git status .opencode/ .gitignore` 能让用户清楚看到所有改动 + +仅跑阶段 5.5("补 gitignore")完成后: + +1. 项目根 `.gitignore` 存在或被显式放弃 +2. 若 `.init-done` 已存在,其 `gitignore_generated` 字段被更新 +3. 其他 `.opencode/` 内容**零改动** + +--- + +## 自迭代日志 + +本节记录使用本 Skill 过程中发现的必要检查项。 + +### 已知必要检查 + +1. **阶段 2 的 C 组归位前必须先做 dry-run 展示** —— 批量移动文件是高破坏性操作,只要有一条分类错误就会污染 canonical 结构,必须让用户在列表上逐条过一遍再执行。 + +2. **重名冲突不许直接覆盖** —— C 组与 A 组重名时,A 组(模板版本)永远是 source of truth,冲突文件只能进 `_init-backup/`,让用户自行决定是否把差异合并回规范文件。 + +3. **registry 重建时先读后写** —— 阶段 4 不要直接用硬编码模板覆盖 registry.md,必须先解析现有条目,只移除项目级条目、补齐缺失条目,避免丢失已有条目。 + +4. **`.init-done` 是完成度契约** —— 只有阶段 6 验证通过后才能写入此文件。中途 abort 必须让 sentinel 缺失,这是保证下次会话能恢复触发的关键设计。 + +5. **`.gitignore` 用户主导** —— 阶段 5.5 对语言栈/IDE/OS 的判断完全来自用户问卷,不要根据文件探测"智能推断",因为新项目此时通常还是空白,推断不准反而会填错条目。 diff --git a/.opencode/skills/pitfall-journal/SKILL.md b/.opencode/skills/pitfall-journal/SKILL.md new file mode 100644 index 0000000..4312add --- /dev/null +++ b/.opencode/skills/pitfall-journal/SKILL.md @@ -0,0 +1,122 @@ +--- +name: pitfall-journal +description: >- + 踩坑经验记录系统。在调试完成或发现非显而易见的坑后记录根因和解决方式, + 后续遇到同类问题时自动检索匹配,避免重复踩坑。 + 当 debug 完成、问题反复出现、或用户提到"踩坑"、"之前遇到过"、"坑"时触发。 +--- + +# Pitfall Journal + +记录开发过程中遇到的"坑"——那些不看代码逻辑觉得应该没问题、但实际运行时才暴露的问题。 +与 dev-changelog 互补:changelog 记"做了什么",pitfall-journal 记"踩了什么坑、怎么爬出来的"。 + +## 数据文件 + +所有记录存放在 `.opencode/data/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 记经验教训 | +| AGENTS.md | 下游消费者 | 进入 Debug mode 或遇到错误时自动触发检索 | +| `epee-orchestrator` Skill | 注册 | 在 registry.md 中注册本 Skill | + +## 自迭代日志 + +本节记录使用本 Skill 过程中发现的必要检查项。 + +### 已知必要检查 + +1. **顶部插入必须保持旧首条目完整性** — 使用编辑工具在文件顶部插入新条目时(操作 A 第 4 步),anchor(`old_string`)有且仅有两种合法选择: + (a) 只包含新条目之前的"稳定前缀"(如 `---\n\n` 或整个文件头部说明段),**不触及任何已有条目的任何一行**;然后 `new_string` = 稳定前缀 + 新条目完整内容 + 空行。 + (b) 把旧首条目的**完整多行内容**(标题行 + 全部字段行)都纳入 `old_string`;然后 `new_string` = 新条目完整内容 + 空行 + 旧首条目完整内容。 + + **绝对禁止**:把旧首条目的"标题行"单独当 anchor 而不带上它紧跟的字段行——编辑工具是精确替换,这样做会删掉标题、让字段"无主"残留在新条目之后,造成半损坏状态。 + + **写入后自检**:Read 文件头 25 行,确认看到 `### [PF-新ID]` 后紧跟其 5 字段,再往下能看到 `### [PF-旧首条目ID]` 标题行且字段完整跟随。 diff --git a/.opencode/skills/problem-distillery/SKILL.md b/.opencode/skills/problem-distillery/SKILL.md new file mode 100644 index 0000000..870d475 --- /dev/null +++ b/.opencode/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 记问题解决过程和认知沉淀 + +## 数据文件 + +``` +.opencode/data/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:定期蒸馏 + +### 触发条件 + +由 AGENTS.md 中的"蒸馏提醒检查"在每次会话开头检查: +- 读取 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],后续新会话将自动注入。" +``` + +### 新会话注入 + +由 AGENTS.md 的"Golden Rules 注入"规则负责: +- 每次会话开头读取 `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 记过程和认知 | +| AGENTS.md | 下游消费者 | 负责 golden-rules 注入和蒸馏提醒 | +| `epee-orchestrator` Skill | 注册 | 在 registry.md 中注册本 Skill | + +## 自迭代日志 + +本节记录使用本 Skill 过程中发现的必要检查项。 + +### 已知必要检查 + +(暂无) diff --git a/.opencode/skills/profile-memory/SKILL.md b/.opencode/skills/profile-memory/SKILL.md new file mode 100644 index 0000000..bea6a01 --- /dev/null +++ b/.opencode/skills/profile-memory/SKILL.md @@ -0,0 +1,271 @@ +--- +name: profile-memory +description: >- + 渐进式用户/项目画像系统。两条触发路径: + (1)被动检测(主路径)——由 AGENTS.md checklist 前置项 A 触发短路扫描, + 命中偏好/项目决策触发词时执行操作 A(总结 + 用户确认 + 写入)。 + (2)显式管理——当用户提到"画像"、"profile"、"查看画像"、"我的偏好"、"项目信息"等时 + 执行操作 B(浏览、修改、删除已有条目)。 +--- + +# Profile Memory + +渐进式画像系统,被动收集并持久化用户个人特质与项目信息。 + +## 存储结构 + +| 文件 | 位置 | 用途 | 注入上下文 | +|------|------|------|-----------| +| user-profile.md | `.opencode/data/profile/` | 个人画像精简版 | 是(每次会话) | +| user-profile-log.md | `.opencode/data/profile/` | 个人画像详细日志 | 否 | +| project-profile.md | `.opencode/data/profile/` | 项目画像精简版 | 是(每次会话) | +| project-profile-log.md | `.opencode/data/profile/` | 项目画像详细日志 | 否 | + +精简版 Profile 是 Agent 每次会话的上下文输入,必须极度精简。 +详细 Log 保留完整上下文,供用户主动查阅和溯源。 + +## 锚点 ID 机制 + +每条画像记录在写入时生成一个**锚点 ID**,格式为 `PR-YYYYMMDD-NN`(如 `PR-20260412-01`), +其中 NN 为当天的序号。 + +锚点 ID 在精简版和 Log 中保持一致: +- 精简版条目格式:`- 条目内容 `(HTML 注释,不影响可读性) +- Log 条目的 H3 标题:`### [PR-20260412-01] YYYY-MM-DD — 简短标题` + +这使得从精简版到 Log 的查找可以通过 Grep 精准定位,无需全文读取 Log。 + +## 逐级上溯机制 + +当 Agent 在使用精简版 Profile 作为上下文时,如果某条记录**语义模糊** +(如无法判断偏好的具体适用场景、与当前任务的关系不明确),执行以下查找: + +``` +1. 从精简版条目中提取锚点 ID(HTML 注释中的 PR-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 的") +- 技术栈与架构决策 +- 设计约定和规范 +- 产品方向和目标用户 + +### 检测原则 + +- **保守而非激进**:宁可漏记也不误记 +- 只记录**持久性**的偏好/特质,忽略一次性的临时需求 +- 区分"个人"和"项目"两个维度,分别写入对应 Profile 文件 + +### 变更分类 + +检测到的新信息与已有条目的关系分为三类,处理方式不同: + +| 类型 | 定义 | 示例 | 提示强度 | +|------|------|------|---------| +| **新增** | 全新维度,无已有条目 | 首次提到审美偏好 | 常规 | +| **演进** | 已有条目的深化、细化或自然发展 | "偏好 React" → "偏好 React + Next.js 全栈" | 常规,展示前后对比 | +| **转向** | 与已有条目方向性矛盾或根本性变化 | "偏好 React" → "想转 Vue";项目方向从 B2C 转 B2B | **加强提醒**,展示前后对比 | + +### 确认流程 + +``` +1. 在对话过程中将检测到的信息在内部缓存,分类为"个人"或"项目" +2. 对每条缓存信息,与已有 Profile 比对,标记变更类型(新增/演进/转向) +3. 当用户的主线任务完成后,统一提出,格式如下: + + "本次对话中我注意到以下可记录的画像信息:" + + **个人画像:** + - [新增][分类] 条目内容 + - [演进][分类] 旧:xxx → 新:yyy + - [转向][分类] 旧:xxx → 新:yyy ⚠️ + + **项目画像:** + - (同上格式) + + 转向类条目额外标注 ⚠️ 并附一句说明: + "⚠️ 以下条目与已有记录存在方向性变化,请特别关注:" + + "是否记录?你可以全部确认、逐条修改或跳过。" + +4. 用户确认后执行写入流程 +5. 如本次对话未检测到任何画像信息,则不触发此流程 +``` + +### 写入流程 + +``` +1. 根据分类读取对应的精简 Profile 和详细 Log(不存在则用模板创建) +2. 为每条新记录生成锚点 ID:PR-YYYYMMDD-NN(检查 Log 中已有 ID 避免冲突) +3. 按变更类型执行: + - 新增:在对应分类下追加条目,带锚点 ID 注释 + - 演进:替换对应旧条目为新措辞,沿用旧条目的锚点 ID(或生成新 ID,视变化程度而定) + - 转向:替换对应旧条目为新措辞,生成新锚点 ID(用户已在确认流程中审核) +4. 写入精简 Profile(条目格式:`- 内容 `) +5. 追加详细 Log(标题格式:`### [PR-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 +### [PR-20260412-01] YYYY-MM-DD — 简短标题 +- **分类**: 对应的精简 Profile 分类名 +- **精简版**: 写入精简 Profile 的那一行内容 +- **原始上下文**: 用户原话或对话中的关键语句 +- **来源对话**: [对话简述](chat-uuid) +- **操作**: 新增 / 演进(旧值 → 新值)/ 转向(旧值 → 新值)/ 删除 +``` + +## 分类扩展 + +预设的分类列表可以扩展。当检测到的信息不属于任何现有分类时: + +``` +1. 在确认流程中标注"建议新增分类: [分类名]" +2. 用户确认后在精简 Profile 中新增该分类的 H2 标题 +3. 注意硬上限,新增分类会占用行数 +``` + +## 与其他系统的协作 + +| 系统 | 关系 | 说明 | +|------|------|------| +| AGENTS.md | 下游消费者 | 每次会话读取精简 Profile 并注入上下文 | +| `epee-orchestrator` Skill | 注册 | 在 registry.md 中注册本 Skill | + +## 自迭代日志 + +本节记录使用本 Skill 过程中发现的必要检查项。 + +### 已知必要检查 + +(暂无) diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..3a6bc48 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,156 @@ +# Research 项目规则 + +## AI 语言约定 +- 所有思考过程、回答、代码注释均使用中文 +- 专业术语和项目专有名词(Roblox API、Lua 关键字等)保持英文 + +## 会话启动自检(最高优先级) + +每次会话首次响应前,Agent 必须完成以下自检序列: + +### 0. 初始化 Sentinel 检查(必须最先执行) + +检查 `.opencode/.init-done` 是否存在: +- **不存在** → 暂存用户原始请求,提示用户需先完成 opencode 初始化,加载 `opencode-init` Skill 并执行阶段 0→7 +- **已存在** → 跳过,进入后续自检项 + +用户主动触发全流程的关键词:`初始化opencode` / `opencode init` / `重置 opencode` / `reset opencode` +仅补 gitignore 的关键词:`补 gitignore` / `生成 gitignore` / `gitignore 模板` + +### 1. 开发日志上下文注入 +读取 `.opencode/data/changelog/changelog-headlines.md`(不存在则跳过)。 +如有实质内容,将全部条目作为背景知识注入上下文,帮助快速建立项目进展的位置感。 + +### 2. 延期方案匹配 +读取 `.opencode/data/deferred/registry.md`(不存在则跳过)。 +扫描 `status: deferred` 的条目,将 tags/related_files 与当前任务关键词匹配。 +命中时简要提醒(不超过 2 行),每条每会话最多提醒一次。 + +### 3. Golden Rules 注入 +读取 `.opencode/data/distillery/golden-rules.md`(不存在则跳过)。 +如有实质条目,作为背景知识注入,自然参考,不显式提及来源。 + +### 4. 蒸馏提醒检查 +读取 `.opencode/data/distillery/insights.md`(不存在则跳过)。 +若 `last_distill_date` 距今超过 7 天,统计 problems.md 中未蒸馏的已解决条目,按需提醒。 + +### 5. 画像上下文注入 +读取 `.opencode/data/profile/project-profile.md` 和 `.opencode/data/profile/user-profile.md`(不存在则跳过)。 +如有实质内容,作为背景知识纳入考量,自然融入回复。 + +## L3 → L2 智能上溯 + +当 L3 概要中的某条记录语义模糊时(无法判断与当前任务的关系),按以下步骤精准上溯: +1. 提取锚点 ID(`CL-xxx`) +2. 在 `changelog-recent.md`(L2)中搜索该 ID → 命中则读取该条目 +3. 仍未消除歧义 → 在 `changelog-full.md`(L1)中搜索,获取行号后读取 ±20 行 +4. 禁止全文读取 L1。一次上溯通常 1-3 条,不批量操作 + +## 自主定位辅助 + +当用户请求缺少具体文件名/模块名时,Agent 应主动利用 L3 进行推断: +- "继续做昨天那个" → 从 L3 找最近的条目,上溯 L2 获取具体文件和决策 +- "那个组件有 bug" → 用 L3 关键词匹配用户描述,定位具体改动 +- 无背景的独立任务 → 用 L3 判断是否与近期改动有关联 + +## 开发日志 L2 自动触发 + +Agent 开始处理新任务时,判断是否需要读取近期详细记录: + +1. 从当前任务中提取涉及的文件路径和语义关键词 +2. 与 `.opencode/data/changelog/changelog-headlines.md`(L3)做快速比对 +3. 近期有相关模块/文件的改动记录 → 读取 `.opencode/data/changelog/changelog-recent.md`(L2) +4. 匹配策略: + - 硬匹配:当前任务涉及的文件出现在 L2 条目的 `affected_files` 中 + - 软匹配:当前任务的语义关键词与条目的 `tags` 有交集 + - 任一命中即触发读取 + +## 锚点 ID 前缀约定 + +各子系统使用独立的锚点 ID 前缀,确保跨文件检索无歧义: + +| 前缀 | 格式 | 所属系统 | 数据文件 | +|------|------|---------|---------| +| `CL-` | `CL-YYYYMMDD-HHMM` | dev-changelog | changelog-full/recent/headlines.md | +| `PF-` | `PF-YYYYMMDD-HHMM` | pitfall-journal | pitfalls.md | +| `PD-` | `PD-YYYYMMDD-HHMM` | problem-distillery(问题追踪)| problems.md | +| `IN-` | `IN-YYYYMMDD-NN` | problem-distillery(蒸馏洞察)| insights.md | +| `GR-` | `GR-NNN` | problem-distillery(Golden Rules)| golden-rules.md | +| `PR-` | `PR-YYYYMMDD-NN` | profile-memory | user-profile.md, project-profile.md | + +其中 `YYYYMMDD` = 年月日,`HHMM` = 时分,`NN` = 当日序号(01 起),`NNN` = 递增序号(001 起)。 + +## Skill 调度(Orchestrator) + +Agent 在制定方案或执行任务时,如果发现当前任务符合以下特征之一,应加载 `epee-orchestrator` Skill 并执行分流: +1. 手动配置密集(批量填写配置字段等) +2. 重复模式明确(预计同类操作反复出现) +3. 手工指引过长(Agent 正在生成超过 10 步的手动操作步骤) + +### Registry 同步(强制) +每次创建或修改任何 Skill 后,必须更新 `.opencode/skills/epee-orchestrator/registry.md`。 + +### Skill 自迭代(强制) +当 Skill 使用中出现信息缺失导致错误、用户需要反复补充同类信息、或生成产物与预期系统性偏差时,必须触发自迭代流程——识别根因、向用户确认、追加到对应 SKILL.md 的"自迭代日志"章节。 + +## 顽固问题检测 + +Agent 在对话中保持对以下信号的被动感知: +- 用户表达问题未解决:"还有问题"、"没解决"、"又出现了"、"不行" +- Agent 自身意识到同一问题已尝试 2 次以上仍未解决 +- pitfalls 中已有记录的问题再次出现 + +检测到上述信号时,加载 `problem-distillery` Skill 并执行操作 A。 + +## 踩坑经验自动检索 + +Agent 在以下场景中应自动检索 `.opencode/data/pitfalls/pitfalls.md`: +1. 进入 Debug mode — 将错误症状与已有记录比对 +2. 遇到运行时错误 — 提取错误信息关键词在"症状"字段中检索 +3. 同一问题第二次出现 — 强制检索 + +匹配策略:硬匹配(错误关键词出现在"症状"中)、软匹配(模块/技术栈出现在"关联"中)。 +命中时在分析开头提示:"注意:之前遇到过类似问题 [PF-xxx]:[标题]。先排查这个方向。" + +每次完成涉及 debug/修复的任务后,应加载 `pitfall-journal` Skill 并执行写入流程。 +判断标准:问题根因是否"非显而易见"——如果只看代码逻辑觉得应该没问题但运行时报错,就值得记录。 + +## 任务完成 Checklist(强制) + +Agent 在即将输出最终回复前,必须逐项检查。跳过任何一项视为执行错误。 + +### A. 画像信号扫描(短路版) +扫描本次对话中用户消息,检查是否出现以下触发词族: +- 个人偏好:`我喜欢` / `我倾向` / `我不喜欢` / `以后都` / `我的风格` / `太花哨` / `简洁` / `精炼` / `啰嗦` +- 项目决策:`这个项目是` / `目标用户是` / `技术栈` / `架构上` / `产品方向` / `定位是` + +无匹配 → 跳过(thinking 应在 50 token 内结束)。有匹配 → 加载 `profile-memory` Skill 执行记录流程。 + +### B. 变更检查项(仅当有代码/配置改动时) + +1. **本次是否有代码/配置文件改动?**(不含 `.opencode/` 基础设施文件) + - 否 → 跳过本组,进入收尾项 + - 是 → 继续 + +2. **是否已写入三层开发日志?** + - 否 → 立即加载 `dev-changelog` Skill 执行操作 A,写入 L1+L2+L3 后再输出回复 + - 是 → 继续 + +3. **是否修改了任何 Skill?**(含 SKILL.md 内容变更) + - 是 → 检查是否已同步 `epee-orchestrator` 的 `registry.md`,未同步则立即执行 + +4. **本次是否有 Skill 使用异常?**(遗漏、误触、产物与预期偏差) + - 是 → 执行 `epee-orchestrator` Skill 的自迭代确认流程 + +### C. 收尾 +先完成 checklist 中的所有写入动作,再输出面向用户的回复文本。 +如执行了 B2 项(开发日志写入),在回复末尾附 `[已记录到开发日志]`。 + +## 目录结构约定 + +| 路径 | 用途 | +|------|------| +| `AGENTS.md` | 项目规则(自动注入) | +| `opencode.json` | OpenCode 配置 | +| `.opencode/skills/` | 所有 Skill 定义(Git 管理) | +| `.opencode/data/` | Agent 运行时数据(changelog/deferred/pitfalls/distillery/profile) | diff --git a/opencode.json b/opencode.json new file mode 100644 index 0000000..509d130 --- /dev/null +++ b/opencode.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://opencode.ai/config.json", + "instructions": [ + "AGENTS.md", + ".opencode/data/changelog/changelog-headlines.md", + ".opencode/data/deferred/registry.md", + ".opencode/data/distillery/golden-rules.md", + ".opencode/data/profile/project-profile.md", + ".opencode/data/profile/user-profile.md" + ], + "plugin": [] +}