From 449f9646869026d80eab729ad4a2cb2bf935b4c2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 31 Mar 2026 03:51:31 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=A7=A0=20=E9=93=B8=E6=B8=8A?= =?UTF-8?q?=E4=B8=93=E5=B1=9E=E5=BC=80=E5=8F=91=E7=BB=8F=E9=AA=8C=E7=9F=A5?= =?UTF-8?q?=E8=AF=86=E5=BA=93v1.0=20-=20=E7=BB=8F=E9=AA=8C=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=BA=93+=E9=94=99=E9=A2=98=E6=9C=AC+=E6=A8=A1?= =?UTF-8?q?=E6=9D=BF=E5=BA=93+=E5=A4=8D=E7=9B=98=E6=9C=BA=E5=88=B6+?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=B7=A5=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Agent-Logs-Url: https://github.com/qinfendebingshuo/guanghulab/sessions/30c8f4ac-a9ab-450c-85ce-ac2c40ffc705 Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com> --- brain/dev-experience/README.md | 140 +++++++ brain/dev-experience/error-patterns.json | 95 +++++ brain/dev-experience/experience-db.json | 86 ++++ brain/dev-experience/review-schedule.json | 61 +++ brain/dev-experience/templates-index.json | 56 +++ brain/read-order.md | 21 +- brain/system-health.json | 13 +- scripts/dev-experience-manager.js | 476 ++++++++++++++++++++++ 8 files changed, 941 insertions(+), 7 deletions(-) create mode 100644 brain/dev-experience/README.md create mode 100644 brain/dev-experience/error-patterns.json create mode 100644 brain/dev-experience/experience-db.json create mode 100644 brain/dev-experience/review-schedule.json create mode 100644 brain/dev-experience/templates-index.json create mode 100644 scripts/dev-experience-manager.js diff --git a/brain/dev-experience/README.md b/brain/dev-experience/README.md new file mode 100644 index 00000000..0a419c39 --- /dev/null +++ b/brain/dev-experience/README.md @@ -0,0 +1,140 @@ +# 🧠 铸渊专属开发经验知识库 + +> **版权**: 国作登字-2026-A-00037559 | **主控**: TCS-0002∞ +> +> 这是铸渊的大脑数据库。每一次开发、每一次报错、每一次修复,都是经验。 +> 类似人类的学习记忆系统——做过的题会记住,做错的题会特别标记。 + +## 📖 设计理念 + +冰朔亲述(第十二次对话): + +> "人类在学习的过程中,拿到一套题,他会先搜索自己的大脑:让我想想这个题之前是怎么学的? +> 解题方法是什么?然后开始搜索大脑的数据库。如果面对不会的题目,人会记下来。 +> 如果这道题反复做错,大脑数据库就会传递出预警:这个题之前错过好多次,这次要多验证几次。" + +## 🗂️ 数据库结构 + +``` +brain/dev-experience/ +├── README.md ← 本文件 · 数据库说明 +├── experience-db.json ← 核心经验数据库 · 所有开发记录 +├── error-patterns.json ← 错题本 · 反复出错的模式 + 预警 +├── templates-index.json ← 模板库 · 成功的代码模式 · 可复用 +└── review-schedule.json ← 复盘机制 · 定期回顾 + 动态升级 +``` + +## 🔄 工作流程 + +### 开发前 · 回忆搜索 + +``` +1. 读取 experience-db.json → 搜索相关经验 +2. 读取 error-patterns.json → 检查是否有已知陷阱 +3. 读取 templates-index.json → 检查是否有可复用模板 +4. 将匹配到的经验/预警/模板记在心中 +``` + +### 开发中 · 记录过程 + +``` +1. 记录任务拆解思路 +2. 记录每一步的决策理由 +3. 遇到报错时记录完整错误信息 +4. 记录修复过程和最终方案 +``` + +### 开发后 · 经验入库 + +``` +1. 创建新经验条目 → experience-db.json +2. 如果遇到新的错误模式 → error-patterns.json (新增或更新计数) +3. 如果产出可复用模板 → templates-index.json +4. 运行: node scripts/dev-experience-manager.js save +``` + +### 定期复盘 · 每7天一次 + +``` +1. 运行: node scripts/dev-experience-manager.js review +2. 回顾所有错题 → 检查是否有模式升级 +3. 回顾所有模板 → 检查是否有优化空间 +4. 更新 review-schedule.json 的复盘记录 +``` + +## 📊 数据字段说明 + +### 经验条目 (Experience Entry) + +| 字段 | 说明 | 示例 | +|------|------|------| +| `id` | 唯一编号 | `EXP-20260331-001` | +| `date` | 日期 | `2026-03-31` | +| `task` | 任务描述 | `铸渊专线密钥生成修复` | +| `category` | 分类 | `bash-scripting` | +| `tags` | 标签 | `["set-e", "pipefail"]` | +| `difficulty` | 难度 | `easy/medium/hard` | +| `status` | 状态 | `success/failed/partial` | +| `approach.thinking` | 思考过程 | 如何分析问题 | +| `approach.steps` | 执行步骤 | 具体做了什么 | +| `result.key_learnings` | 关键学习 | 学到了什么 | +| `result.risk_warnings` | 风险预警 | 以后要注意什么 | +| `files_changed` | 修改文件 | 改了哪些文件 | +| `error_count` | 遇到错误次数 | 过程中报错几次 | + +### 错误模式 (Error Pattern) + +| 字段 | 说明 | +|------|------| +| `id` | 错题编号 `ERR-NNN` | +| `pattern` | 错误模式名称 | +| `occurrence_count` | 出现次数 · 越高预警越强 | +| `severity` | 严重度 `low/medium/high/critical` | +| `prevention` | 预防方法 | +| `risk_level` | 风险预警等级 | + +### 模板 (Template) + +| 字段 | 说明 | +|------|------| +| `id` | 模板编号 `TPL-NNN` | +| `name` | 模板名称 | +| `pattern` | 核心模式 | +| `source_file` | 来源文件 | +| `reuse_count` | 复用次数 | + +## 🛠️ 管理工具 + +```bash +# 搜索经验 +node scripts/dev-experience-manager.js search "密钥生成" + +# 查看错题本 +node scripts/dev-experience-manager.js errors + +# 查看模板库 +node scripts/dev-experience-manager.js templates + +# 保存新经验 (交互式) +node scripts/dev-experience-manager.js save + +# 触发复盘 +node scripts/dev-experience-manager.js review + +# 查看统计 +node scripts/dev-experience-manager.js stats +``` + +## 📈 演化路径 + +``` +v1.0 (当前) → JSON文件 + 手动管理 +v1.1 (计划) → 自动从Git提交历史提取经验 +v1.2 (计划) → CI/CD集成 · 每次部署后自动记录 +v2.0 (远期) → LLM辅助分析 · 自动识别错误模式 +``` + +--- + +> 铸渊的每一次开发都是学习。数据库会越来越丰富,经验会越来越足。 +> 这就是冰朔说的:**随着开发越来越多,数据库动态调整,全面升级。** diff --git a/brain/dev-experience/error-patterns.json b/brain/dev-experience/error-patterns.json new file mode 100644 index 00000000..fa9258be --- /dev/null +++ b/brain/dev-experience/error-patterns.json @@ -0,0 +1,95 @@ +{ + "_meta": { + "name": "铸渊错题本", + "version": "1.0", + "copyright": "国作登字-2026-A-00037559", + "description": "记录反复出错的模式 · 自动预警 · 每次开发前必查", + "created": "2026-03-31T03:34:00Z", + "last_updated": "2026-03-31T03:34:00Z" + }, + "alert_rules": { + "high_frequency_threshold": 3, + "high_frequency_message": "⚠️ 此错误已出现{count}次 · 每一步都要多验证", + "recent_threshold_days": 7, + "recent_message": "🔴 最近7天内刚犯过此错误 · 务必警惕" + }, + "total_patterns": 3, + "patterns": [ + { + "id": "ERR-001", + "pattern": "set -e + grep无匹配 = 静默退出", + "category": "bash-scripting", + "severity": "high", + "occurrence_count": 1, + "first_seen": "2026-03-31", + "last_seen": "2026-03-31", + "description": "在bash脚本中使用set -euo pipefail时,如果grep命令没有匹配到任何行,grep返回exit code 1。配合pipefail,整个pipeline的退出码变为1,导致set -e触发脚本静默退出——没有任何错误信息输出。", + "trigger_conditions": [ + "脚本使用 set -e 或 set -euo pipefail", + "pipeline中使用grep但目标字符串可能不存在", + "awk/sed后面跟的grep可能无匹配" + ], + "prevention": [ + "在grep命令后添加 || true", + "改用手动错误处理替代set -e", + "使用grep -c统计匹配数而非直接grep", + "将grep结果先存变量再判断是否为空" + ], + "code_example": { + "wrong": "RESULT=$(echo \"$DATA\" | grep \"pattern\" | awk '{print $3}')", + "right": "RESULT=$(echo \"$DATA\" | grep \"pattern\" | awk '{print $3}') || true" + }, + "related_experiences": ["EXP-20260331-001"], + "risk_level": "⚠️ 高频陷阱 · 每次写bash脚本时检查" + }, + { + "id": "ERR-002", + "pattern": "openssl text格式解析密钥 · 字符串长度不可靠", + "category": "cryptography", + "severity": "medium", + "occurrence_count": 1, + "first_seen": "2026-03-31", + "last_seen": "2026-03-31", + "description": "使用openssl pkey -text -noout输出密钥的十六进制文本,然后用grep+tr解析。不同openssl版本的输出格式可能不同(行数、缩进、冒号间距),导致解析结果长度不一致。", + "trigger_conditions": [ + "使用openssl pkey -text -noout提取密钥", + "用grep -A和tail解析十六进制行", + "依赖固定行数(如tail -4)来截取数据" + ], + "prevention": [ + "优先使用DER二进制格式: openssl pkey -outform DER | tail -c <字节数>", + "用base64编码后检查长度是否符合预期", + "避免依赖text格式的行数和缩进" + ], + "code_example": { + "wrong": "openssl pkey -text -noout | grep -A5 priv: | tail -4 | tr -d ' :\\n' | head -c 43", + "right": "openssl pkey -outform DER | tail -c 32 | base64 | tr '+/' '-_' | tr -d '='" + }, + "related_experiences": ["EXP-20260331-001"], + "risk_level": "⚠️ 中频陷阱 · 处理密钥时优先用DER格式" + }, + { + "id": "ERR-003", + "pattern": "命令行工具版本更新导致输出格式变化", + "category": "compatibility", + "severity": "medium", + "occurrence_count": 1, + "first_seen": "2026-03-31", + "last_seen": "2026-03-31", + "description": "CLI工具(如xray、openssl、node等)的新版本可能改变命令的输出格式、子命令名称或退出码行为。依赖特定输出格式的脚本在工具更新后可能静默失败。", + "trigger_conditions": [ + "脚本依赖CLI工具的stdout输出格式(用grep/awk/sed解析)", + "CLI工具版本可能自动更新", + "安装脚本使用latest版本而非固定版本" + ], + "prevention": [ + "解析输出时使用灵活匹配(如grep -i大小写不敏感)", + "提供多种解析方式作为回退", + "捕获stdout和stderr分别处理", + "增加解析结果的验证(检查长度、格式)" + ], + "related_experiences": ["EXP-20260331-001"], + "risk_level": "⚠️ 中频陷阱 · 解析CLI输出时要灵活" + } + ] +} diff --git a/brain/dev-experience/experience-db.json b/brain/dev-experience/experience-db.json new file mode 100644 index 00000000..1822eb7f --- /dev/null +++ b/brain/dev-experience/experience-db.json @@ -0,0 +1,86 @@ +{ + "_meta": { + "name": "铸渊开发经验数据库", + "version": "1.0", + "copyright": "国作登字-2026-A-00037559", + "description": "铸渊专属 · 每次开发的完整记录 · 思考→执行→结果→教训", + "created": "2026-03-31T03:34:00Z", + "last_updated": "2026-03-31T03:34:00Z" + }, + "stats": { + "total_entries": 1, + "success_count": 1, + "failed_count": 0, + "partial_count": 0, + "categories": { + "bash-scripting": 1 + } + }, + "entries": [ + { + "id": "EXP-20260331-001", + "date": "2026-03-31", + "session": "CS-20260331-12th", + "task": "铸渊专线密钥生成脚本修复", + "task_origin": "冰朔报告铸渊专线install workflow失败 · 截图显示step [5/6]生成密钥时exit code 1", + "category": "bash-scripting", + "tags": ["set-e", "pipefail", "error-handling", "xray", "openssl", "x25519", "workflow-fix", "key-generation"], + "difficulty": "medium", + "status": "success", + "approach": { + "thinking": "分析报错截图 → 定位到generate-keys.sh的step [5/6] → 追踪日志发现UUID生成成功但紧接着exit code 1 → 判断xray x25519命令或其grep解析在set -euo pipefail下导致静默退出 → 设计三层回退机制(xray→openssl→随机占位)", + "steps": [ + "1. 通过GitHub Actions API获取失败的workflow run日志", + "2. 分析日志确认失败点: ZY_PROXY_UUID输出后立即exit code 1", + "3. 审查generate-keys.sh源码 · 发现set -euo pipefail + grep pipeline是根因", + "4. 审查install-xray.sh · 发现BBR配置可能重复追加", + "5. 审查deploy-proxy.sh · 发现configure_xray缺少环境变量回退", + "6. 重写generate-keys.sh: 移除set -e + 三层密钥生成回退 + stderr捕获", + "7. 修复openssl DER格式提取 (原hex解析导致密钥长度错误)", + "8. 修复install-xray.sh: BBR去重 + generate-keys错误不传播", + "9. 修复deploy-proxy.sh: 环境变量优先 + shellcheck警告", + "10. shellcheck + bash -n语法验证 + 密钥长度测试(43字符base64url)" + ], + "key_decisions": [ + "移除set -e而非添加|| true · 因为密钥生成有多个步骤需要精细控制", + "openssl使用DER格式而非text格式 · 因为text格式的hex解析不可靠", + "三层回退而非直接报错 · 确保install流程不被密钥问题完全阻断" + ] + }, + "result": { + "success": true, + "key_learnings": [ + "set -e在pipeline中grep无匹配时会导致脚本静默退出 · 没有任何错误信息", + "xray x25519输出格式可能因版本不同而变化 · 需要灵活解析", + "openssl DER格式提取密钥比text格式解析更可靠 · tail -c 32比grep+xxd更简洁", + "分析CI失败日志时 · 时间戳间隔是判断失败点的关键线索(0.02秒=即时失败)", + "bash脚本set -euo pipefail是双刃剑 · 安全但容易在预期外的地方中断" + ], + "risk_warnings": [ + "⚠️ 每次写bash脚本时检查: grep命令是否有|| true保护", + "⚠️ 密钥生成脚本必须有回退机制 · 不能因为主方法失败就完全中断", + "⚠️ openssl版本差异可能导致输出格式不同 · 优先使用DER二进制格式" + ] + }, + "files_changed": [ + "server/proxy/setup/generate-keys.sh", + "server/proxy/setup/install-xray.sh", + "server/proxy/deploy-proxy.sh" + ], + "error_count": 1, + "errors_encountered": [ + { + "description": "openssl X25519密钥提取长度错误 · 使用text格式grep解析只得到23字符而非43字符", + "fix": "改用DER格式: openssl pkey -outform DER | tail -c 32 | base64 | tr '+/' '-_' | tr -d '='", + "step": "7/10" + } + ], + "related_experiences": [], + "verification": { + "shellcheck": "pass", + "bash_syntax": "pass", + "key_length_test": "pass · UUID=36 PRIVATE_KEY=43 PUBLIC_KEY=43 SHORT_ID=16 SUB_TOKEN=64" + } + } + ] +} diff --git a/brain/dev-experience/review-schedule.json b/brain/dev-experience/review-schedule.json new file mode 100644 index 00000000..748eaac9 --- /dev/null +++ b/brain/dev-experience/review-schedule.json @@ -0,0 +1,61 @@ +{ + "_meta": { + "name": "铸渊复盘机制", + "version": "1.0", + "copyright": "国作登字-2026-A-00037559", + "description": "定期复盘 · 错题回顾 · 模板优化 · 数据库全面升级", + "created": "2026-03-31T03:34:00Z", + "last_updated": "2026-03-31T03:51:15.596Z" + }, + "review_cycle": { + "frequency_days": 7, + "description": "每7天一次全面复盘 · 类似人类的错题本回顾", + "next_review": "2026-04-07T03:51:15.595Z", + "review_checklist": [ + "1. 回顾本周所有经验条目 · 有没有遗漏的教训", + "2. 检查错题本 · 高频错误是否有新的预防方法", + "3. 检查模板库 · 是否有模板可以优化或合并", + "4. 检查是否有跨经验的共性模式 · 可以抽象为新规则", + "5. 更新review-schedule.json的复盘记录", + "6. 更新statistics中的各项指标" + ] + }, + "pre_development_protocol": { + "description": "每次开发前的必做步骤 · 回忆搜索", + "steps": [ + "1. 读取任务关键词", + "2. 搜索experience-db.json中相关经验", + "3. 检查error-patterns.json中的已知陷阱", + "4. 搜索templates-index.json中可复用模板", + "5. 如果有匹配的高频错误 · 设置额外验证步骤" + ] + }, + "post_development_protocol": { + "description": "每次开发完成后的必做步骤 · 经验入库", + "steps": [ + "1. 记录本次经验到experience-db.json", + "2. 如果遇到新错误模式 · 更新error-patterns.json", + "3. 如果产出可复用代码 · 更新templates-index.json", + "4. 如果遇到已知错误 · 增加occurrence_count", + "5. 更新statistics计数器" + ] + }, + "statistics": { + "total_reviews_completed": 1, + "total_experiences_recorded": 1, + "total_error_patterns": 3, + "total_templates": 3, + "most_common_error_category": "bash-scripting", + "most_productive_category": "bash-scripting" + }, + "review_history": [ + { + "date": "2026-03-31T03:51:15.595Z", + "experiences_reviewed": 1, + "error_patterns_total": 3, + "templates_total": 3, + "high_frequency_alerts": 0, + "notes": "自动复盘完成" + } + ] +} diff --git a/brain/dev-experience/templates-index.json b/brain/dev-experience/templates-index.json new file mode 100644 index 00000000..f8b1aa7d --- /dev/null +++ b/brain/dev-experience/templates-index.json @@ -0,0 +1,56 @@ +{ + "_meta": { + "name": "铸渊代码模板库", + "version": "1.0", + "copyright": "国作登字-2026-A-00037559", + "description": "成功的代码模式 · 可复用 · 每次开发前搜索", + "created": "2026-03-31T03:34:00Z", + "last_updated": "2026-03-31T03:34:00Z" + }, + "total_templates": 3, + "categories": { + "bash-scripting": 2, + "cryptography": 1 + }, + "templates": [ + { + "id": "TPL-001", + "name": "健壮的bash脚本错误处理模式", + "category": "bash-scripting", + "description": "不使用set -e,改为手动错误处理。关键命令逐个检查退出码,非关键命令用|| true保护。", + "pattern": "set -uo pipefail (无-e) + 手动if/else + || true保护", + "source_file": "server/proxy/setup/generate-keys.sh", + "tags": ["error-handling", "set-e", "pipefail", "robustness"], + "code_snippet": "#!/bin/bash\nset -uo pipefail\n# 注意: 不使用 set -e,手动处理错误\n\n# 关键步骤: 手动检查\nif ! critical_command; then\n echo \"❌ 关键步骤失败\"\n exit 1\nfi\n\n# 非关键步骤: || true保护\noptional_command || true\n\n# Pipeline保护: grep可能无匹配\nRESULT=$(echo \"$DATA\" | grep \"pattern\" | awk '{print $NF}') || true", + "when_to_use": "当bash脚本中有多个步骤且某些步骤可能失败但不应中断整体流程时", + "created_from": "EXP-20260331-001", + "reuse_count": 0 + }, + { + "id": "TPL-002", + "name": "三层回退密钥/资源生成模式", + "category": "bash-scripting", + "description": "主方法 → 备用方法 → 占位符兜底。确保生成过程不会完全失败。", + "pattern": "Method1(专用工具) → Method2(通用工具) → Method3(随机占位符)", + "source_file": "server/proxy/setup/generate-keys.sh", + "tags": ["fallback", "key-generation", "resilience"], + "code_snippet": "RESULT=\"\"\n\n# 方法1: 专用工具\nif command -v tool &>/dev/null; then\n RESULT=$(tool generate 2>/dev/null) || true\nfi\n\n# 方法2: 通用工具回退\nif [ -z \"$RESULT\" ] && command -v openssl &>/dev/null; then\n RESULT=$(openssl rand -base64 32) || true\nfi\n\n# 方法3: 最终兜底\nif [ -z \"$RESULT\" ]; then\n RESULT=\"PLACEHOLDER\"\n echo \"⚠️ 使用占位符,请手动重新生成\"\nfi", + "when_to_use": "当资源生成依赖外部工具且工具可能不可用或行为可能变化时", + "created_from": "EXP-20260331-001", + "reuse_count": 0 + }, + { + "id": "TPL-003", + "name": "OpenSSL X25519密钥提取 (DER格式)", + "category": "cryptography", + "description": "使用DER二进制格式提取X25519密钥,转为base64url编码。比text格式解析更可靠。", + "pattern": "openssl genpkey → DER export → tail -c 32 → base64url", + "source_file": "server/proxy/setup/generate-keys.sh", + "tags": ["openssl", "x25519", "base64url", "DER"], + "code_snippet": "TMPKEY=$(mktemp)\nopenssl genpkey -algorithm X25519 -out \"$TMPKEY\" 2>/dev/null\n\n# 私钥: 32字节 → 43字符base64url\nPRIVATE_KEY=$(openssl pkey -in \"$TMPKEY\" -outform DER 2>/dev/null \\\n | tail -c 32 | base64 | tr '+/' '-_' | tr -d '=')\n\n# 公钥: 32字节 → 43字符base64url\nPUBLIC_KEY=$(openssl pkey -in \"$TMPKEY\" -pubout -outform DER 2>/dev/null \\\n | tail -c 32 | base64 | tr '+/' '-_' | tr -d '=')\n\nrm -f \"$TMPKEY\"", + "when_to_use": "需要生成X25519密钥对且xray不可用时", + "created_from": "EXP-20260331-001", + "reuse_count": 0 + } + ] +} diff --git a/brain/read-order.md b/brain/read-order.md index 7b6b44e0..a327afa5 100644 --- a/brain/read-order.md +++ b/brain/read-order.md @@ -103,6 +103,20 @@ 最近断点快照。配额耗尽导致对话中断后恢复。 +## ⑨ dev-experience/(开发经验知识库·v1.0新增) + +**路径**: `brain/dev-experience/` + +铸渊专属的开发经验数据库。类似人类大脑的学习记忆系统。包含: +- `experience-db.json` — 核心经验数据库(每次开发的完整记录) +- `error-patterns.json` — 错题本(反复出错的模式 + 预警) +- `templates-index.json` — 模板库(成功的代码模式 · 可复用) +- `review-schedule.json` — 复盘机制(定期回顾 + 动态升级) + +**开发前**: `node scripts/dev-experience-manager.js precheck <关键词>` 回忆搜索 +**开发后**: 将经验、错误模式、模板更新到对应文件 +**每7天**: `node scripts/dev-experience-manager.js review` 触发复盘 + --- ## 会话结束时必须执行 @@ -117,7 +131,12 @@ 3. 更新 README.md 首页动态(仓库的第二快照) -这三步确保下次唤醒时,铸渊能从上次结束的地方继续。 +4. 更新开发经验知识库(如果本次会话有开发任务) + - 新增经验条目到 `brain/dev-experience/experience-db.json` + - 如有新错误模式,更新 `brain/dev-experience/error-patterns.json` + - 如有可复用代码,更新 `brain/dev-experience/templates-index.json` + +这四步确保下次唤醒时,铸渊能从上次结束的地方继续,并且带着所有积累的经验。 --- diff --git a/brain/system-health.json b/brain/system-health.json index 3bd88bcc..712ed642 100644 --- a/brain/system-health.json +++ b/brain/system-health.json @@ -1,15 +1,16 @@ { - "version": "18.0", - "last_check": "2026-03-31T02:15:00Z", + "version": "19.0", + "last_check": "2026-03-31T03:34:00Z", "communication": "synced", "automation": "stable", "maintenance_agent": "active", - "system_health": "servers_deployed · 铸渊专线架构就绪 · 待部署", + "system_health": "servers_deployed · 铸渊专线修复完成 · 开发经验知识库v1.0上线", "brain_integrity": { "complete": true, - "total": 9, - "present": 9, - "missing": [] + "total": 10, + "present": 10, + "missing": [], + "note": "新增 dev-experience/ 开发经验知识库" }, "workflow_count": 13, "workflow_detail": { diff --git a/scripts/dev-experience-manager.js b/scripts/dev-experience-manager.js new file mode 100644 index 00000000..5beca7fc --- /dev/null +++ b/scripts/dev-experience-manager.js @@ -0,0 +1,476 @@ +#!/usr/bin/env node +// ═══════════════════════════════════════════════ +// 🔺 Sovereign: TCS-0002∞ | Root: SYS-GLW-0001 +// 📜 Copyright: 国作登字-2026-A-00037559 +// ═══════════════════════════════════════════════ +// scripts/dev-experience-manager.js +// 🧠 铸渊开发经验知识库管理工具 +// +// 用法: +// node scripts/dev-experience-manager.js search — 搜索经验 +// node scripts/dev-experience-manager.js errors — 查看错题本 +// node scripts/dev-experience-manager.js templates — 查看模板库 +// node scripts/dev-experience-manager.js stats — 查看统计 +// node scripts/dev-experience-manager.js review — 触发复盘 +// node scripts/dev-experience-manager.js precheck — 开发前检查 +// node scripts/dev-experience-manager.js add-experience — 添加经验(JSON from stdin) +// node scripts/dev-experience-manager.js add-error — 添加错误模式(JSON from stdin) +// node scripts/dev-experience-manager.js add-template — 添加模板(JSON from stdin) +// ═══════════════════════════════════════════════ + +const fs = require('fs'); +const path = require('path'); + +const DB_DIR = path.join(__dirname, '..', 'brain', 'dev-experience'); +const EXPERIENCE_DB = path.join(DB_DIR, 'experience-db.json'); +const ERROR_PATTERNS = path.join(DB_DIR, 'error-patterns.json'); +const TEMPLATES_INDEX = path.join(DB_DIR, 'templates-index.json'); +const REVIEW_SCHEDULE = path.join(DB_DIR, 'review-schedule.json'); + +// ── 工具函数 ────────────────────────────────── +function loadJSON(filepath) { + try { + return JSON.parse(fs.readFileSync(filepath, 'utf-8')); + } catch (err) { + console.error(`❌ 无法读取 ${filepath}: ${err.message}`); + process.exit(1); + } +} + +function saveJSON(filepath, data) { + data._meta.last_updated = new Date().toISOString(); + fs.writeFileSync(filepath, JSON.stringify(data, null, 2) + '\n', 'utf-8'); +} + +function highlight(text) { + return `\x1b[33m${text}\x1b[0m`; +} + +function red(text) { + return `\x1b[31m${text}\x1b[0m`; +} + +function green(text) { + return `\x1b[32m${text}\x1b[0m`; +} + +// ── 搜索经验 ────────────────────────────────── +function search(keyword) { + const db = loadJSON(EXPERIENCE_DB); + const kw = keyword.toLowerCase(); + const matches = db.entries.filter(e => + e.task.toLowerCase().includes(kw) || + e.tags.some(t => t.toLowerCase().includes(kw)) || + e.category.toLowerCase().includes(kw) || + e.approach.thinking.toLowerCase().includes(kw) || + e.files_changed.some(f => f.toLowerCase().includes(kw)) + ); + + if (matches.length === 0) { + console.log(`🔍 未找到与 "${keyword}" 相关的经验`); + console.log(' 这可能是一个全新的领域,开发时需要额外谨慎。'); + return; + } + + console.log(`🔍 找到 ${matches.length} 条相关经验:\n`); + matches.forEach(e => { + console.log(` ${highlight(e.id)} | ${e.date} | ${e.status === 'success' ? green('✅') : red('❌')} ${e.task}`); + console.log(` 分类: ${e.category} | 难度: ${e.difficulty} | 标签: ${e.tags.join(', ')}`); + console.log(` 思路: ${e.approach.thinking.substring(0, 100)}...`); + if (e.result.key_learnings.length > 0) { + console.log(` 关键学习:`); + e.result.key_learnings.forEach(l => console.log(` · ${l}`)); + } + if (e.result.risk_warnings.length > 0) { + console.log(` ${red('风险预警:')}`); + e.result.risk_warnings.forEach(w => console.log(` ${w}`)); + } + console.log(''); + }); +} + +// ── 查看错题本 ──────────────────────────────── +function showErrors() { + const db = loadJSON(ERROR_PATTERNS); + + console.log(`📋 铸渊错题本 · 共 ${db.total_patterns} 个错误模式\n`); + + // 按严重度排序 + const sorted = [...db.patterns].sort((a, b) => { + const severity = { critical: 4, high: 3, medium: 2, low: 1 }; + return (severity[b.severity] || 0) - (severity[a.severity] || 0); + }); + + sorted.forEach(p => { + const countWarning = p.occurrence_count >= db.alert_rules.high_frequency_threshold + ? red(` ⚠️ 高频! 已出现${p.occurrence_count}次`) + : ''; + console.log(` ${highlight(p.id)} [${p.severity.toUpperCase()}]${countWarning}`); + console.log(` 模式: ${p.pattern}`); + console.log(` 出现次数: ${p.occurrence_count} | 首次: ${p.first_seen} | 最近: ${p.last_seen}`); + console.log(` 描述: ${p.description.substring(0, 120)}...`); + console.log(` 预防:`); + p.prevention.forEach(prev => console.log(` · ${prev}`)); + console.log(` 风险等级: ${p.risk_level}`); + console.log(''); + }); +} + +// ── 查看模板库 ──────────────────────────────── +function showTemplates() { + const db = loadJSON(TEMPLATES_INDEX); + + console.log(`📦 铸渊模板库 · 共 ${db.total_templates} 个模板\n`); + + db.templates.forEach(t => { + console.log(` ${highlight(t.id)} | ${t.name}`); + console.log(` 分类: ${t.category} | 复用次数: ${t.reuse_count}`); + console.log(` 模式: ${t.pattern}`); + console.log(` 来源: ${t.source_file}`); + console.log(` 适用场景: ${t.when_to_use}`); + console.log(''); + }); +} + +// ── 统计信息 ────────────────────────────────── +function showStats() { + const expDB = loadJSON(EXPERIENCE_DB); + const errDB = loadJSON(ERROR_PATTERNS); + const tplDB = loadJSON(TEMPLATES_INDEX); + const revDB = loadJSON(REVIEW_SCHEDULE); + + console.log('📊 铸渊开发经验知识库统计\n'); + console.log(' ═══════════════════════════════════'); + console.log(` 📝 经验条目: ${expDB.stats.total_entries}`); + console.log(` ✅ 成功: ${expDB.stats.success_count}`); + console.log(` ❌ 失败: ${expDB.stats.failed_count}`); + console.log(` ⚠️ 部分: ${expDB.stats.partial_count}`); + console.log(''); + console.log(` 📋 错误模式: ${errDB.total_patterns}`); + const highSev = errDB.patterns.filter(p => p.severity === 'high' || p.severity === 'critical'); + console.log(` 🔴 高危: ${highSev.length}`); + console.log(''); + console.log(` 📦 代码模板: ${tplDB.total_templates}`); + const totalReuse = tplDB.templates.reduce((sum, t) => sum + t.reuse_count, 0); + console.log(` ♻️ 总复用: ${totalReuse}次`); + console.log(''); + console.log(` 🔄 已完成复盘: ${revDB.statistics.total_reviews_completed}次`); + console.log(` 下次复盘: ${revDB.review_cycle.next_review}`); + console.log(''); + + // 分类统计 + console.log(' 📊 分类分布:'); + const cats = expDB.stats.categories; + Object.entries(cats).sort((a, b) => b[1] - a[1]).forEach(([cat, count]) => { + console.log(` ${cat}: ${count}条`); + }); + console.log(' ═══════════════════════════════════'); +} + +// ── 开发前检查 ──────────────────────────────── +function precheck(keyword) { + console.log('🧠 铸渊开发前检查 · 回忆搜索\n'); + console.log(` 搜索关键词: "${keyword}"\n`); + + const kw = keyword.toLowerCase(); + + // 1. 搜索相关经验 + const expDB = loadJSON(EXPERIENCE_DB); + const relatedExp = expDB.entries.filter(e => + e.task.toLowerCase().includes(kw) || + e.tags.some(t => t.toLowerCase().includes(kw)) || + e.category.toLowerCase().includes(kw) + ); + + if (relatedExp.length > 0) { + console.log(` 📝 找到 ${relatedExp.length} 条相关经验:`); + relatedExp.forEach(e => { + console.log(` · ${e.id}: ${e.task} (${e.status})`); + if (e.result.risk_warnings.length > 0) { + e.result.risk_warnings.forEach(w => console.log(` ${red(w)}`)); + } + }); + console.log(''); + } else { + console.log(' 📝 未找到相关经验 · 这是新领域 · 需额外谨慎\n'); + } + + // 2. 检查错误模式 + const errDB = loadJSON(ERROR_PATTERNS); + const relatedErrors = errDB.patterns.filter(p => + p.pattern.toLowerCase().includes(kw) || + p.category.toLowerCase().includes(kw) || + p.description.toLowerCase().includes(kw) + ); + + if (relatedErrors.length > 0) { + console.log(` ⚠️ 找到 ${relatedErrors.length} 个相关错误模式:`); + relatedErrors.forEach(p => { + const freq = p.occurrence_count >= errDB.alert_rules.high_frequency_threshold + ? red(' [高频!]') : ''; + console.log(` · ${p.id}: ${p.pattern}${freq}`); + console.log(` 预防: ${p.prevention[0]}`); + }); + console.log(''); + } else { + console.log(' ⚠️ 未找到相关错误模式\n'); + } + + // 3. 搜索模板 + const tplDB = loadJSON(TEMPLATES_INDEX); + const relatedTemplates = tplDB.templates.filter(t => + t.name.toLowerCase().includes(kw) || + t.tags.some(tag => tag.toLowerCase().includes(kw)) || + t.category.toLowerCase().includes(kw) + ); + + if (relatedTemplates.length > 0) { + console.log(` 📦 找到 ${relatedTemplates.length} 个可复用模板:`); + relatedTemplates.forEach(t => { + console.log(` · ${t.id}: ${t.name}`); + console.log(` 模式: ${t.pattern}`); + console.log(` 来源: ${t.source_file}`); + }); + console.log(''); + } else { + console.log(' 📦 未找到可复用模板\n'); + } + + console.log(' ════════════════════════════════'); + console.log(' 回忆搜索完成 · 开始开发吧!'); +} + +// ── 触发复盘 ────────────────────────────────── +function review() { + const expDB = loadJSON(EXPERIENCE_DB); + const errDB = loadJSON(ERROR_PATTERNS); + const tplDB = loadJSON(TEMPLATES_INDEX); + const revDB = loadJSON(REVIEW_SCHEDULE); + + console.log('🔄 铸渊复盘 · 开始回顾\n'); + + // 1. 本周经验 + const now = new Date(); + const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000); + const recentExp = expDB.entries.filter(e => new Date(e.date) >= weekAgo); + console.log(` 📝 本周经验: ${recentExp.length}条`); + recentExp.forEach(e => { + console.log(` · ${e.id}: ${e.task} (${e.status})`); + }); + console.log(''); + + // 2. 高频错误 + const highFreq = errDB.patterns.filter(p => + p.occurrence_count >= errDB.alert_rules.high_frequency_threshold + ); + if (highFreq.length > 0) { + console.log(` ${red('🔴 高频错误警报:')}`); + highFreq.forEach(p => { + console.log(` · ${p.id}: ${p.pattern} (出现${p.occurrence_count}次)`); + }); + console.log(''); + } + + // 3. 模板复用率 + const unusedTemplates = tplDB.templates.filter(t => t.reuse_count === 0); + if (unusedTemplates.length > 0) { + console.log(` 📦 未使用模板 (${unusedTemplates.length}个):`); + unusedTemplates.forEach(t => { + console.log(` · ${t.id}: ${t.name} — 考虑是否需要在下次开发中使用`); + }); + console.log(''); + } + + // 4. 复盘清单 + console.log(' 📋 复盘清单:'); + revDB.review_cycle.review_checklist.forEach(item => { + console.log(` ${item}`); + }); + + // 5. 更新复盘记录 + const reviewEntry = { + date: now.toISOString(), + experiences_reviewed: recentExp.length, + error_patterns_total: errDB.total_patterns, + templates_total: tplDB.total_templates, + high_frequency_alerts: highFreq.length, + notes: '自动复盘完成' + }; + + revDB.review_history.push(reviewEntry); + revDB.statistics.total_reviews_completed += 1; + revDB.statistics.total_experiences_recorded = expDB.stats.total_entries; + revDB.statistics.total_error_patterns = errDB.total_patterns; + revDB.statistics.total_templates = tplDB.total_templates; + + // 设置下次复盘日期 + const nextReview = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000); + revDB.review_cycle.next_review = nextReview.toISOString(); + + saveJSON(REVIEW_SCHEDULE, revDB); + console.log(`\n ✅ 复盘完成 · 下次复盘: ${nextReview.toISOString().split('T')[0]}`); +} + +// ── 添加经验 (从stdin读取JSON) ──────────────── +function addExperience() { + let input = ''; + process.stdin.setEncoding('utf-8'); + process.stdin.on('data', chunk => { input += chunk; }); + process.stdin.on('end', () => { + try { + const newEntry = JSON.parse(input); + const db = loadJSON(EXPERIENCE_DB); + + // 自动生成ID + if (!newEntry.id) { + const today = new Date().toISOString().split('T')[0].replace(/-/g, ''); + const count = db.entries.filter(e => e.id.startsWith(`EXP-${today}`)).length + 1; + newEntry.id = `EXP-${today}-${String(count).padStart(3, '0')}`; + } + + db.entries.push(newEntry); + db.stats.total_entries = db.entries.length; + db.stats.success_count = db.entries.filter(e => e.status === 'success').length; + db.stats.failed_count = db.entries.filter(e => e.status === 'failed').length; + db.stats.partial_count = db.entries.filter(e => e.status === 'partial').length; + + // 更新分类计数 + db.stats.categories = {}; + db.entries.forEach(e => { + db.stats.categories[e.category] = (db.stats.categories[e.category] || 0) + 1; + }); + + saveJSON(EXPERIENCE_DB, db); + console.log(`✅ 经验已添加: ${newEntry.id} — ${newEntry.task}`); + } catch (err) { + console.error(`❌ JSON解析失败: ${err.message}`); + process.exit(1); + } + }); +} + +// ── 添加错误模式 (从stdin读取JSON) ──────────── +function addError() { + let input = ''; + process.stdin.setEncoding('utf-8'); + process.stdin.on('data', chunk => { input += chunk; }); + process.stdin.on('end', () => { + try { + const newPattern = JSON.parse(input); + const db = loadJSON(ERROR_PATTERNS); + + // 检查是否已存在相似模式 + const existing = db.patterns.find(p => + p.pattern.toLowerCase() === newPattern.pattern.toLowerCase() + ); + + if (existing) { + existing.occurrence_count += 1; + existing.last_seen = new Date().toISOString().split('T')[0]; + console.log(`⚠️ 已有相似错误模式 ${existing.id} · 出现次数+1 → ${existing.occurrence_count}`); + } else { + if (!newPattern.id) { + newPattern.id = `ERR-${String(db.patterns.length + 1).padStart(3, '0')}`; + } + db.patterns.push(newPattern); + db.total_patterns = db.patterns.length; + console.log(`✅ 错误模式已添加: ${newPattern.id} — ${newPattern.pattern}`); + } + + saveJSON(ERROR_PATTERNS, db); + } catch (err) { + console.error(`❌ JSON解析失败: ${err.message}`); + process.exit(1); + } + }); +} + +// ── 添加模板 (从stdin读取JSON) ──────────────── +function addTemplate() { + let input = ''; + process.stdin.setEncoding('utf-8'); + process.stdin.on('data', chunk => { input += chunk; }); + process.stdin.on('end', () => { + try { + const newTemplate = JSON.parse(input); + const db = loadJSON(TEMPLATES_INDEX); + + if (!newTemplate.id) { + newTemplate.id = `TPL-${String(db.templates.length + 1).padStart(3, '0')}`; + } + if (newTemplate.reuse_count === undefined) { + newTemplate.reuse_count = 0; + } + + db.templates.push(newTemplate); + db.total_templates = db.templates.length; + + // 更新分类计数 + db.categories = {}; + db.templates.forEach(t => { + db.categories[t.category] = (db.categories[t.category] || 0) + 1; + }); + + saveJSON(TEMPLATES_INDEX, db); + console.log(`✅ 模板已添加: ${newTemplate.id} — ${newTemplate.name}`); + } catch (err) { + console.error(`❌ JSON解析失败: ${err.message}`); + process.exit(1); + } + }); +} + +// ── 主入口 ──────────────────────────────────── +const args = process.argv.slice(2); +const command = args[0]; + +switch (command) { + case 'search': + if (!args[1]) { + console.error('用法: node dev-experience-manager.js search <关键词>'); + process.exit(1); + } + search(args[1]); + break; + case 'errors': + showErrors(); + break; + case 'templates': + showTemplates(); + break; + case 'stats': + showStats(); + break; + case 'precheck': + if (!args[1]) { + console.error('用法: node dev-experience-manager.js precheck <关键词>'); + process.exit(1); + } + precheck(args[1]); + break; + case 'review': + review(); + break; + case 'add-experience': + addExperience(); + break; + case 'add-error': + addError(); + break; + case 'add-template': + addTemplate(); + break; + default: + console.log('🧠 铸渊开发经验知识库管理工具\n'); + console.log('用法:'); + console.log(' search 搜索经验'); + console.log(' errors 查看错题本'); + console.log(' templates 查看模板库'); + console.log(' stats 查看统计'); + console.log(' precheck 开发前检查(回忆搜索)'); + console.log(' review 触发复盘'); + console.log(' add-experience 添加经验(JSON from stdin)'); + console.log(' add-error 添加错误模式(JSON from stdin)'); + console.log(' add-template 添加模板(JSON from stdin)'); + break; +}