From e2a14f871a66a82e392677cc3ad4050aaa769983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E5=94=AF=20A06?= Date: Mon, 3 Aug 2026 03:00:39 +0800 Subject: [PATCH] auto-snapshot 2026-08-03 03:00:39 --- scripts/tdai-gateway-watchdog.sh | 25 --- skills/.usage.json | 187 +++++++++++------- .../hermes-self-improvement/SKILL.md | 18 +- skills/devops/devops-umbrella/SKILL.md | 2 +- .../references/gitea-operations.md | 168 +++++++++++++--- skills/devops/gitea-repo-mirroring/SKILL.md | 92 +++++++++ .../references/diygod-batch-mirror-2026-08.md | 51 +++++ .../references/gitea-api-notes.md | 49 +++++ skills/devops/llm-gateway-ops/SKILL.md | 34 ++++ .../self-healing-infrastructure/SKILL.md | 1 + ...memory-system-e2e-verification-20260802.md | 60 ++++++ .../devops/windows-home-server-ops/SKILL.md | 124 ++++++++++++ .../rsshub-windows-deploy-2026-08.md | 82 ++++++++ skills/email/himalaya/SKILL.md | 1 + skills/knowledge/cangjie-distill/SKILL.md | 42 ++-- skills/media/tts-stt-tools/SKILL.md | 34 +++- .../references/example-2026-08-02.md | 14 ++ .../research/github-project-research/SKILL.md | 52 ++++- .../2026-08-02-research-cases-batch3.md | 51 +++++ .../references/2026-08-02-research-diygod.md | 39 ++++ .../cbm-code-analysis/SKILL.md | 2 + skills/soulful/soulful-framework/SKILL.md | 22 +++ skills/whisper-stt/SKILL.md | 72 ++++--- skills/zhiyi/zhiyi/SKILL.md | 110 ++++++++++- .../references/gitea-mirroring-20260802.md | 65 ++++++ .../model-pool-rotation-20260802.md | 83 ++++++++ ...nhancement-trajectory-learning-20260802.md | 51 +++++ .../zhiyi-episodes-persistence-20260802.md | 125 ++++++++++++ 28 files changed, 1463 insertions(+), 193 deletions(-) delete mode 100755 scripts/tdai-gateway-watchdog.sh mode change 100755 => 100644 skills/devops/devops-umbrella/references/gitea-operations.md create mode 100644 skills/devops/gitea-repo-mirroring/SKILL.md create mode 100644 skills/devops/gitea-repo-mirroring/references/diygod-batch-mirror-2026-08.md create mode 100644 skills/devops/gitea-repo-mirroring/references/gitea-api-notes.md create mode 100644 skills/devops/self-healing-infrastructure/references/memory-system-e2e-verification-20260802.md create mode 100644 skills/devops/windows-home-server-ops/SKILL.md create mode 100644 skills/devops/windows-home-server-ops/references/rsshub-windows-deploy-2026-08.md mode change 100755 => 100644 skills/media/tts-stt-tools/SKILL.md create mode 100644 skills/productivity/daily-recap/references/example-2026-08-02.md create mode 100644 skills/research/github-project-research/references/2026-08-02-research-cases-batch3.md create mode 100644 skills/research/github-project-research/references/2026-08-02-research-diygod.md create mode 100644 skills/zhiyi/zhiyi/references/gitea-mirroring-20260802.md create mode 100644 skills/zhiyi/zhiyi/references/model-pool-rotation-20260802.md create mode 100644 skills/zhiyi/zhiyi/references/zhiyi-enhancement-trajectory-learning-20260802.md create mode 100644 skills/zhiyi/zhiyi/references/zhiyi-episodes-persistence-20260802.md diff --git a/scripts/tdai-gateway-watchdog.sh b/scripts/tdai-gateway-watchdog.sh deleted file mode 100755 index fcc9b4bc..00000000 --- a/scripts/tdai-gateway-watchdog.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash -# tdai-gateway 看门狗:检查 systemd 服务 active + 8420 端口监听 -# 正常 → 静默(空输出);异常 → 输出报警(no-agent cron 会发送) -# 创建:2026-08-02,修复 systemd 崩溃循环 2534 次后补的监控 - -ALERT="" - -if ! systemctl --user is-active tdai-gateway >/dev/null 2>&1; then - STATE=$(systemctl --user is-active tdai-gateway 2>/dev/null || echo unknown) - ALERT="tdai-gateway systemd 服务状态异常: ${STATE}" -fi - -if ! ss -tln 2>/dev/null | grep -q ':8420 '; then - ALERT="${ALERT}${ALERT:+ | }tdai-gateway 端口 8420 未监听" -fi - -if [ -n "$ALERT" ]; then - echo "🔴 tdai-gateway 异常 $(date '+%F %T')" - echo "$ALERT" - systemctl --user status tdai-gateway --no-pager 2>&1 | head -12 - exit 0 -fi - -# 正常:空输出 = 静默 -exit 0 diff --git a/skills/.usage.json b/skills/.usage.json index c4f8b343..dd8615c6 100644 --- a/skills/.usage.json +++ b/skills/.usage.json @@ -315,27 +315,27 @@ "archived_at": null, "created_at": "2026-07-17T03:43:05.089451+00:00", "created_by": null, - "last_patched_at": "2026-07-18T12:39:50.390388+00:00", - "last_used_at": "2026-07-30T01:50:00.175477+00:00", - "last_viewed_at": "2026-07-30T01:50:00.172165+00:00", - "patch_count": 22, + "last_patched_at": "2026-08-02T13:04:01.231703+00:00", + "last_used_at": "2026-08-02T14:39:17.213975+00:00", + "last_viewed_at": "2026-08-02T14:39:17.208148+00:00", + "patch_count": 26, "pinned": false, "state": "active", - "use_count": 20, - "view_count": 20 + "use_count": 24, + "view_count": 24 }, "cbm-code-analysis": { "archived_at": null, "created_at": "2026-07-30T03:28:33.803582+00:00", "created_by": null, - "last_patched_at": "2026-07-30T03:30:30.927634+00:00", - "last_used_at": "2026-07-30T03:30:47.215892+00:00", - "last_viewed_at": "2026-07-30T03:30:47.203869+00:00", - "patch_count": 3, + "last_patched_at": "2026-08-02T15:20:56.394720+00:00", + "last_used_at": "2026-08-02T15:20:48.942850+00:00", + "last_viewed_at": "2026-08-02T15:20:48.923159+00:00", + "patch_count": 4, "pinned": false, "state": "active", - "use_count": 3, - "view_count": 3 + "use_count": 4, + "view_count": 4 }, "claude-code": { "archived_at": null, @@ -510,14 +510,14 @@ "archived_at": null, "created_at": "2026-07-28T14:02:19.195060+00:00", "created_by": "agent", - "last_patched_at": "2026-08-01T16:57:06.438287+00:00", - "last_used_at": "2026-08-01T16:56:55.948370+00:00", - "last_viewed_at": "2026-08-01T16:56:55.945187+00:00", - "patch_count": 2, + "last_patched_at": "2026-08-02T14:02:20.150209+00:00", + "last_used_at": "2026-08-02T14:02:11.814838+00:00", + "last_viewed_at": "2026-08-02T14:02:11.811551+00:00", + "patch_count": 3, "pinned": false, "state": "active", - "use_count": 2, - "view_count": 2 + "use_count": 3, + "view_count": 3 }, "design-feasibility-review": { "archived_at": null, @@ -549,14 +549,14 @@ "archived_at": null, "created_at": "2026-05-05T15:53:48.597780+00:00", "created_by": "agent", - "last_patched_at": "2026-08-01T12:42:25.333652+00:00", - "last_used_at": "2026-08-01T12:41:48.920445+00:00", - "last_viewed_at": "2026-08-01T12:41:48.909106+00:00", - "patch_count": 94, + "last_patched_at": "2026-08-02T17:46:05.621521+00:00", + "last_used_at": "2026-08-02T17:45:20.632761+00:00", + "last_viewed_at": "2026-08-02T17:45:20.628433+00:00", + "patch_count": 96, "pinned": false, "state": "active", - "use_count": 79, - "view_count": 79 + "use_count": 81, + "view_count": 81 }, "devops/devops-umbrella": { "archived_at": null, @@ -779,6 +779,19 @@ "use_count": 0, "view_count": 0 }, + "gitea-repo-mirroring": { + "archived_at": null, + "created_at": "2026-08-02T18:24:34.438054+00:00", + "created_by": "agent", + "last_patched_at": "2026-08-02T18:29:21.655125+00:00", + "last_used_at": "2026-08-02T18:47:12.319098+00:00", + "last_viewed_at": "2026-08-02T18:47:12.312935+00:00", + "patch_count": 3, + "pinned": false, + "state": "active", + "use_count": 4, + "view_count": 4 + }, "github-auth": { "archived_at": null, "created_at": "2026-06-30T11:24:39.499832+00:00", @@ -835,27 +848,27 @@ "archived_at": null, "created_at": "2026-08-01T11:50:01.274771+00:00", "created_by": "agent", - "last_patched_at": "2026-08-01T14:21:36.844037+00:00", - "last_used_at": "2026-08-01T14:21:17.657665+00:00", - "last_viewed_at": "2026-08-01T14:21:17.646368+00:00", - "patch_count": 7, + "last_patched_at": "2026-08-02T16:21:17.978109+00:00", + "last_used_at": "2026-08-02T16:46:57.365738+00:00", + "last_viewed_at": "2026-08-02T16:46:57.362260+00:00", + "patch_count": 14, "pinned": false, "state": "active", - "use_count": 9, - "view_count": 9 + "use_count": 17, + "view_count": 17 }, "github-repo-management": { "archived_at": null, "created_at": "2026-06-30T11:24:39.513614+00:00", "created_by": null, "last_patched_at": null, - "last_used_at": "2026-08-01T11:48:58.058238+00:00", - "last_viewed_at": "2026-08-01T11:48:58.054196+00:00", + "last_used_at": "2026-08-02T18:23:21.668886+00:00", + "last_viewed_at": "2026-08-02T18:23:21.655030+00:00", "patch_count": 0, "pinned": false, "state": "active", - "use_count": 2, - "view_count": 2 + "use_count": 5, + "view_count": 5 }, "go-learning": { "archived_at": null, @@ -1017,14 +1030,14 @@ "archived_at": null, "created_at": "2026-05-13T12:27:05.593125+00:00", "created_by": null, - "last_patched_at": "2026-07-19T14:06:42.150955+00:00", - "last_used_at": "2026-07-26T01:00:46.496121+00:00", - "last_viewed_at": "2026-07-25T12:41:04.295275+00:00", - "patch_count": 78, + "last_patched_at": "2026-08-02T11:39:48.113545+00:00", + "last_used_at": "2026-08-02T17:46:14.064253+00:00", + "last_viewed_at": "2026-08-02T17:46:14.053177+00:00", + "patch_count": 80, "pinned": false, "state": "active", - "use_count": 112, - "view_count": 107 + "use_count": 118, + "view_count": 112 }, "hermes-venv-dependency-safety": { "archived_at": null, @@ -1186,14 +1199,14 @@ "archived_at": null, "created_at": "2026-08-01T13:47:26.532313+00:00", "created_by": "agent", - "last_patched_at": "2026-08-01T16:50:25.167129+00:00", - "last_used_at": "2026-08-01T17:12:32.828348+00:00", - "last_viewed_at": "2026-08-01T17:12:32.817004+00:00", - "patch_count": 3, + "last_patched_at": "2026-08-02T16:46:52.295411+00:00", + "last_used_at": "2026-08-02T16:46:44.045093+00:00", + "last_viewed_at": "2026-08-02T16:46:44.039236+00:00", + "patch_count": 4, "pinned": false, "state": "active", - "use_count": 3, - "view_count": 3 + "use_count": 5, + "view_count": 5 }, "llm-wiki": { "archived_at": null, @@ -1706,27 +1719,27 @@ "archived_at": null, "created_at": "2026-07-08T18:13:02.034240+00:00", "created_by": "agent", - "last_patched_at": "2026-08-01T12:52:39.447526+00:00", - "last_used_at": "2026-08-01T12:52:32.714172+00:00", - "last_viewed_at": "2026-08-01T12:52:32.703253+00:00", - "patch_count": 200, + "last_patched_at": "2026-08-02T15:20:41.501595+00:00", + "last_used_at": "2026-08-02T15:20:25.042403+00:00", + "last_viewed_at": "2026-08-02T15:20:25.024619+00:00", + "patch_count": 203, "pinned": false, "state": "active", - "use_count": 152, - "view_count": 152 + "use_count": 155, + "view_count": 155 }, "self-hosted-tunneling": { "archived_at": null, "created_at": "2026-06-19T19:06:08.909729+00:00", "created_by": "agent", "last_patched_at": "2026-07-08T13:51:56.997028+00:00", - "last_used_at": "2026-07-08T13:51:29.387565+00:00", - "last_viewed_at": "2026-07-08T13:51:29.376414+00:00", + "last_used_at": "2026-08-02T18:23:21.672286+00:00", + "last_viewed_at": "2026-08-02T18:23:21.665575+00:00", "patch_count": 10, "pinned": false, "state": "active", - "use_count": 12, - "view_count": 12 + "use_count": 13, + "view_count": 13 }, "serving-llms-vllm": { "archived_at": null, @@ -1836,14 +1849,14 @@ "archived_at": null, "created_at": "2026-07-09T17:36:29.269531+00:00", "created_by": "agent", - "last_patched_at": "2026-07-20T07:53:21.901753+00:00", - "last_used_at": "2026-07-20T07:52:12.152761+00:00", - "last_viewed_at": "2026-07-20T07:52:12.149565+00:00", - "patch_count": 21, + "last_patched_at": "2026-08-02T14:40:09.615607+00:00", + "last_used_at": "2026-08-02T15:20:08.440434+00:00", + "last_viewed_at": "2026-08-02T15:20:08.433000+00:00", + "patch_count": 22, "pinned": false, "state": "active", - "use_count": 21, - "view_count": 21 + "use_count": 23, + "view_count": 23 }, "spike": { "archived_at": null, @@ -1953,14 +1966,14 @@ "archived_at": null, "created_at": "2026-05-13T16:02:06.347617+00:00", "created_by": null, - "last_patched_at": "2026-05-23T07:36:35.113619+00:00", - "last_used_at": "2026-06-21T16:06:40.921285+00:00", - "last_viewed_at": "2026-06-21T16:06:40.918968+00:00", - "patch_count": 9, + "last_patched_at": "2026-08-02T18:47:10.025724+00:00", + "last_used_at": "2026-08-02T18:46:58.987740+00:00", + "last_viewed_at": "2026-08-02T18:46:58.975389+00:00", + "patch_count": 13, "pinned": false, "state": "active", - "use_count": 15, - "view_count": 15 + "use_count": 17, + "view_count": 17 }, "web-content-capture": { "archived_at": null, @@ -2027,6 +2040,32 @@ "use_count": 0, "view_count": 0 }, + "whisper-stt": { + "archived_at": null, + "created_at": "2026-08-02T18:46:00.920538+00:00", + "created_by": null, + "last_patched_at": "2026-08-02T18:46:53.592908+00:00", + "last_used_at": "2026-08-02T18:46:46.154338+00:00", + "last_viewed_at": "2026-08-02T18:46:46.143430+00:00", + "patch_count": 1, + "pinned": false, + "state": "active", + "use_count": 2, + "view_count": 2 + }, + "windows-home-server-ops": { + "archived_at": null, + "created_at": "2026-08-02T18:24:48.270464+00:00", + "created_by": "agent", + "last_patched_at": "2026-08-02T18:29:05.298341+00:00", + "last_used_at": "2026-08-02T18:46:00.923689+00:00", + "last_viewed_at": "2026-08-02T18:46:00.913991+00:00", + "patch_count": 2, + "pinned": false, + "state": "active", + "use_count": 3, + "view_count": 3 + }, "windows-python-pip": { "archived_at": null, "created_at": "2026-05-22T18:46:06.408227+00:00", @@ -2109,14 +2148,14 @@ "archived_at": null, "created_at": "2026-05-29T19:39:03.373231+00:00", "created_by": null, - "last_patched_at": "2026-07-20T07:45:33.845863+00:00", - "last_used_at": "2026-07-30T01:24:05.576220+00:00", - "last_viewed_at": "2026-07-30T01:24:05.569692+00:00", - "patch_count": 711, + "last_patched_at": "2026-08-02T16:46:29.637110+00:00", + "last_used_at": "2026-08-02T16:46:23.029923+00:00", + "last_viewed_at": "2026-08-02T16:46:23.016679+00:00", + "patch_count": 729, "pinned": false, "state": "active", - "use_count": 376, - "view_count": 350 + "use_count": 385, + "view_count": 359 }, "zhiyi-dev": { "archived_at": null, diff --git a/skills/autonomous-ai-agents/hermes-self-improvement/SKILL.md b/skills/autonomous-ai-agents/hermes-self-improvement/SKILL.md index b1f9bba6..386a25f7 100644 --- a/skills/autonomous-ai-agents/hermes-self-improvement/SKILL.md +++ b/skills/autonomous-ai-agents/hermes-self-improvement/SKILL.md @@ -412,5 +412,19 @@ python3 ~/.hermes/scripts/cangjie_distill.py distill ## 与 curator 的配合 - `--clean` 模式会查找 `absorbed_into` 标记并自动处理 -- 也会将无版本号 + 低分 + 小体积的技能移动到 `_archive/` -- 被吸收的 skill 移动到 `_quarantine/`(回收期 30 天) \ No newline at end of file +- 也会将无版本号 + 低分 + 小体积的技能移动到 `.archive/`(注意是点开头,不是下划线) +- 被吸收的 skill 移动到 `.quarantine/`(回收期 30 天) +- **保护名单**:被 cron / SOUL.md / 系统组件引用的技能在 `skill-curator.py` 的 `PROTECTED_SKILLS` 中声明,任何情况不进入归档/删除建议。新增核心/应急技能后如被 curator 误判,把它加入保护名单。 + +### curator 报告不可盲信 — 删除前必须验证(2026-08-02 教训) + +curator 周报(skill-curator-weekly cron)**可能产生严重误判**,绝不能直接执行删除/归档建议。2026-08-02 实例:报告建议删除 8 个技能,其中 4 个是核心技能(`hermes-venv-dependency-safety` / `cbm-code-analysis` / `bge-embed-crash-loop-fix` / `daily-recap`),实际全部被 cron/SOUL 引用;himalaya 被报"与 20+ 技能 100% 重叠",实际是通用词(available/readiness/status)没被 stopwords 过滤的幻觉。 + +**执行任何 curator 清理前,按序验证**: +1. **拉真实文件状态**:`find ~/.hermes/skills -type d -name "<技能名>"` — 确认技能是否真的存在、是否已在 `.archive/`(在 archive 里 = 早已归档,报告重复计数,忽略) +2. **查引用**:`grep -rln "<技能名>" ~/.hermes/SOUL.md ~/.hermes/AGENTS.md ~/.hermes/cron/` — 被 cron/系统文件引用 = 核心,绝不删 +3. **低频 ≠ 可删**:运维/应急技能(崩溃修复、铁律、复盘)低频使用是正常属性,不是删除理由 +4. **重叠报告看 common_terms**:Jaccard 打满但 common_terms 是通用词 = 幻觉,不是真重叠 +5. **只读优先**:默认 `--report`(dry run),确认无损后再谈 `--clean` + +**已修的 curator bug**(2026-08-02):① 加 `PROTECTED_SKILLS` 保护名单 ② stopwords 扩充(available/readiness/status 等)③ 修复 `.archive`(点)vs `_archive`(下划线)扫描 bug——已归档技能被重复扫描 ④ himalaya 补 version。修复后归档候选 8→0。 \ No newline at end of file diff --git a/skills/devops/devops-umbrella/SKILL.md b/skills/devops/devops-umbrella/SKILL.md index 39fb1a59..9787091b 100644 --- a/skills/devops/devops-umbrella/SKILL.md +++ b/skills/devops/devops-umbrella/SKILL.md @@ -680,7 +680,7 @@ journalctl --user -u xiaowei-startup.service | `references/gaokao-site/` | 116 个 session 参考文件(按主题分类的 bug 修复记录) | | `references/gaokao-site.md` | 旧版精简参考(保留向后兼容) | | `references/tencent-cloud-ssl-cert-20260618.md` | 腾讯云 DNSPod 免费 SSL 证书申请、HTTPS nginx 配置、外部 443 被封限制 | -| `references/gitea-operations.md` | Gitea 上传项目、Token 认证、shallow clone 陷阱 | +| `references/gitea-operations.md` | Gitea 操作全流程 — 认证(.netrc/API)、全量历史镜像(GitHub→Gitea)、shallow/deepen 陷阱、镜像代理、--all/--tags 拆分、RSSHub 本地验收(2026-08-03 15项目实战) | | `references/infra-state.md` | Current system infrastructure state (ports, services) | | `references/tailscale-install.md` | Tailscale 安装:正确 GPG 密钥 URL、静态二进制订用方案、Deepin 25 坑点 | | `references/sudo-password-pattern.md` | sudo 密码传递模式:heredoc 中 pipe 失效的原因和三种替代写法 | diff --git a/skills/devops/devops-umbrella/references/gitea-operations.md b/skills/devops/devops-umbrella/references/gitea-operations.md old mode 100755 new mode 100644 index d4952d38..8faa36a1 --- a/skills/devops/devops-umbrella/references/gitea-operations.md +++ b/skills/devops/devops-umbrella/references/gitea-operations.md @@ -1,56 +1,160 @@ # Gitea Operations Reference -> 本地 Gitea 实例操作注意事项。 +> 本地 Gitea 实例操作注意事项。2026-08-03 更新:批量镜像 15 个 GitHub 项目实战(RSSHub/Folo/xLog/DPlayer/APlayer 等),补全全量历史镜像流程。 ## 本地 Gitea 信息 - **地址**:http://192.168.123.11:3000 -- **Token**:见 `~/mc/小唯/记忆/MemoryFabric/技术细节.md`(Token: 9380e8e6...) +- **Token**:见 `~/mc/小唯/记忆/MemoryFabric/技术细节.md`(Token: 9380e8e6...)或 `~/.netrc`(`machine 192.168.123.11 login xiaoxue_admin password <token>`) - **用户**:xiaoxue_admin(非 muchen) -## 上传已有 Git 项目到 Gitea +## 认证(两种等价方式) -### 常见陷阱:Shallow Clone 问题 +```bash +# 从 ~/.netrc 提取 token(单行格式!不要用 getline 分行读) +TOKEN=$(awk '/^machine 192.168.123.11/{for(i=1;i<=NF;i++) if($i=="password") print $(i+1)}' ~/.netrc) -从 GitHub clone 的项目可能是 shallow clone(有 `--depth` 参数),导致: +# API Basic auth(token 当密码,验证连通): +curl -u "xiaoxue_admin:$TOKEN" "http://192.168.123.11:3000/api/v1/user" # 200 = OK + +# git push URL 嵌入: +git push "http://$OWNER:$TOKEN@$HOST/$OWNER/$name.git" --all +``` + +## 上传已有 Git 项目到 Gitea(保留完整历史 ✅) + +> 镜像场景(把 GitHub 项目归档到 Gitea)**必须保留完整 git 历史**。Gitea 拒绝浅克隆推送,但**不要用 `rm -rf .git` 重来**(那会丢掉历史!)。正确做法: + +### 1. 全量 clone(或把浅克隆补成全量) + +**浅克隆推送会报错:** ``` remote: shallow update not allowed ``` -或 force push 时失败。 -**解决步骤**: +**方案 A:全量 clone(直接)** +```bash +git clone https://github.com/OWNER/REPO.git # 不带 --depth! +``` + +**方案 B:浅克隆已存在 → 补成全量** +```bash +# 一次拉全(网络好时): +git fetch --unshallow origin + +# 网络不稳时:分段 deepen(每轮独立可续传,shallow 文件消失 = 完成) +for i in 1 2 3 4 5 6 7 8; do + timeout 240 git fetch --deepen=2000 origin 2>&1 | tail -2 + [ ! -f .git/shallow ] && break +done +[ -f .git/shallow ] && echo "STILL SHALLOW" || echo "FULL OK: $(git rev-list --count HEAD) commits" +# 实测:Folo (7011 commits) 第 8 轮才成功 —— 多轮重试是预期,不是 bug +``` + +### 2. GitHub 直连不稳 → 用镜像代理 + +本机实测(2026-08-03):github.com git 协议反复 `curl 28 Failed to connect ... port 443 after 133xxx ms`,但镜像代理可用: + +```bash +# ✅ 实测可用: +git clone https://gh-proxy.com/https://github.com/OWNER/REPO.git +git clone https://ghproxy.net/https://github.com/OWNER/REPO.git +# ❌ 当时超时:ghfast.top / mirror.ghproxy.com + +# 先探测哪个通(info/refs 返回 200 = 可用): +curl -s -o /dev/null -w "%{http_code}" "https://gh-proxy.com/https://github.com/OWNER/REPO.git/info/refs?service=git-upload-pack" +``` + +大仓库全量 clone 失败重试模式: +```bash +for i in 1 2 3 4 5; do + rm -rf REPO + timeout 500 git clone <url> 2>&1 | tail -2 + [ -d REPO/.git ] && break + sleep 20 +done +``` + +### 3. 创建远端仓库(Gitea API) + +```bash +curl -s -u "xiaoxue_admin:$TOKEN" -X POST \ + "http://192.168.123.11:3000/api/v1/user/repos" \ + -d "{\"name\":\"$name\",\"private\":true,\"auto_init\":false}" +# ⚠️ JSON 转义坑:description 带引号/emoji 会破坏 -d 参数 → 用固定值 +``` + +### 4. 推送(⚠️ --all 和 --tags 不能同时用) + +```bash +# ❌ fatal: options '--all' and '--tags' cannot be used together +git push URL --all --tags + +# ✅ 分两次: +git push "http://$OWNER:$TOKEN@$HOST/$OWNER/$name.git" --all +git push "http://$OWNER:$TOKEN@$HOST/$OWNER/$name.git" --tags +``` + +批量脚本骨架: +```bash +for d in BASE/*/; do + name=$(basename "$d") + [ -f "$d/.git/shallow" ] && { echo "SKIP $name (STILL SHALLOW)"; continue; } # 必须全量才能推 + (cd "$d" && git push "http://$OWNER:$TOKEN@$HOST/$OWNER/$name.git" --all \ + && git push "http://$OWNER:$TOKEN@$HOST/$OWNER/$name.git" --tags) \ + && echo "OK $name" || echo "FAIL $name" +done +``` + +### 5. 验证(推完必须查) + +```bash +curl -s -u "xiaoxue_admin:$TOKEN" "http://192.168.123.11:3000/api/v1/repos/$OWNER/$name" \ + | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('size'), d.get('default_branch'))" +# 对比本地 git rev-list --count HEAD 确认提交数一致 +``` + +## 性能参考(2026-08-03 实测) + +| 项目 | Commits | 备注 | +|------|---------|------| +| RSSHub | 17,321 | 镜像代理 clone 成功(直连 5 次全挂) | +| Folo | 7,011 | deepen 8 轮 | +| xLog | 2,731 | 直连成功 | +| DPlayer / APlayer | ~1,300 / 916 | 直连 unshallow 成功 | + +## RSSHub 本地安装测试(镜像后验收) + +```bash +npm install -g pnpm@9 # RSSHub 需要 pnpm(本机原本没有) +cd RSSHub && pnpm install # ~4min,peer 警告可忽略 +npm run build # 生成 dist/index.mjs(5s;eval 警告是项目自身代码) +PORT=1200 npm run start # 服务起来 +curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:1200/ # 200 +curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:1200/healthz # 200 +# ⚠️ 新版本路由已变:/github/release、/github/trending 已移除(404 是正常的) +# 用现存路由验证:/github/issue/:owner/:repo → 200 +``` +纯前端项目(DPlayer/APlayer)验收:`python3 -m http.server <port>` 起静态服务,curl 检查 demo 页 + dist 产物 200。 + +## 快速路径(历史无所谓时) + +如果确实不需要历史(普通上传小项目),旧方法仍可用: ```bash cd /path/to/repo -rm -rf .git # 删除原 Git 历史 -git init -b main # 重新初始化 -git add -A -git commit -m "Initial commit" +rm -rf .git && git init -b main +git add -A && git commit -m "Initial commit" git remote add origin http://TOKEN@192.168.123.11:3000/xiaoxue_admin/REPO.git git push -u origin main ``` -### Token 认证 - -URL 中嵌入 Token 避免交互式输入: -``` -http://TOKEN@192.168.123.11:3000/xiaoxue_admin/REPO.git -``` - -### 创建仓库 - -```bash -curl -s -X POST "http://192.168.123.11:3000/api/v1/user/repos" \ - -H "Authorization: token TOKEN" \ - -H "Content-Type: application/json" \ - -d '{"name":"REPO_NAME","description":"描述","private":false}' -``` - -返回 JSON 中 `clone_url` 字段含完整 URL(注意用户名前缀)。 - ## 关键教训 | 问题 | 教训 | |------|------| -| shallow clone 无法 push | 从 GitHub 克隆后必须 `rm -rf .git` 重新初始化 | -| 交互式输入失败 | URL 中嵌入 Token | -| 仓库用户不对 | API 创建时用 `xiaoxue_admin`,不是 muchen | \ No newline at end of file +| shallow clone 无法 push | **保留历史**:`git fetch --unshallow` 或 `--deepen=2000` 循环;**不要** `rm -rf .git`(丢历史) | +| GitHub 直连反复超时 | 用镜像代理 `gh-proxy.com` / `ghproxy.net`(URL 前加前缀) | +| `--all --tags` 同时用报错 | 分两次 push | +| 大仓库 clone 中断 | 重试循环 + 多轮 deepen(可续传) | +| 交互式输入失败 | URL 中嵌入 Token / `.netrc` Basic auth | +| 仓库用户不对 | API 创建时用 `xiaoxue_admin`,不是 muchen | diff --git a/skills/devops/gitea-repo-mirroring/SKILL.md b/skills/devops/gitea-repo-mirroring/SKILL.md new file mode 100644 index 00000000..fac1786f --- /dev/null +++ b/skills/devops/gitea-repo-mirroring/SKILL.md @@ -0,0 +1,92 @@ +--- +name: gitea-repo-mirroring +description: "把 GitHub/上游开源项目镜像到自建 Gitea(完整 git 历史)— clone→全量历史→建仓库→push 全流程,含浅克隆推送被拒、镜像加速、push 拆分等坑。" +version: 1.0.0 +author: 小唯 A06 +tags: [gitea, mirror, git, github, 镜像, 存档] +trigger: "推到gitea / 镜像到gitea / 把GitHub项目搬到gitea / 存档到gitea / mirror repo" +created: 2026-08-03 +updated: 2026-08-03 +--- + +# Gitea 仓库镜像(GitHub → 自建 Gitea,完整历史) + +把上游开源项目(GitHub 等)镜像到自建 Gitea(本环境:`192.168.123.11:3000`,用户 `xiaoxue_admin`),保留完整 git 历史。 + +## 核心铁律 + +1. **浅克隆不能推 Gitea**:`git clone --depth 1` 后 push 报 `shallow update not allowed`。Gitea 默认拒绝浅推送,必须完整历史。 +2. **`git push --all` 和 `--tags` 不能合并**:`fatal: options '--all' and '--tags' cannot be used together`。必须拆两次 push。 +3. **Gitea API 用 Basic auth**:`-u 用户名:token`,不是 `Authorization: token` 头(Gitea 返回 401)。 + +## 标准流程 + +### 1. 全量 clone(不要 --depth) + +```bash +mkdir -p ~/projects/diygod && cd ~/projects/diygod +git clone https://github.com/OWNER/REPO.git # 不加深度的完整克隆 +``` + +### 2. 已是浅克隆 → 转全量 + +```bash +cd REPO +git fetch --unshallow origin # 一次拉全 +# 网络不稳时用增量 deepen 循环(每次加深 2000 commit,断了续传) +for i in 1 2 3 4 5 6 7 8; do + timeout 240 git fetch --deepen=2000 origin 2>&1 | tail -2 + [ ! -f .git/shallow ] && break +done +# 验证 +git rev-list --count HEAD # 完整 commit 数 +[ -f .git/shallow ] && echo "STILL SHALLOW" || echo "FULL HISTORY OK" +``` + +### 3. 创建 Gitea 仓库 + push + +```bash +# token 从 ~/.netrc 提取(注意 awk 遍历字段,不是 getline) +TOKEN=$(awk '/^machine 192.168.123.11/{for(i=1;i<=NF;i++) if($i=="password") print $(i+1)}' ~/.netrc) + +# 创建仓库(API Basic auth) +curl -s -u "xiaoxue_admin:$TOKEN" -X POST \ + "http://192.168.123.11:3000/api/v1/user/repos" \ + -H "Content-Type: application/json" \ + -d '{"name":"REPO","description":"mirror of OWNER/REPO","private":false}' + +# push(--all 和 --tags 分开!) +git push "http://xiaoxue_admin:$TOKEN@192.168.123.11:3000/xiaoxue_admin/REPO.git" --all +git push "http://xiaoxue_admin:$TOKEN@192.168.123.11:3000/xiaoxue_admin/REPO.git" --tags +``` + +### 4. 验证 + +```bash +curl -s -u "xiaoxue_admin:$TOKEN" \ + "http://192.168.123.11:3000/api/v1/repos/xiaoxue_admin/REPO" | python3 -c \ + "import sys,json; d=json.load(sys.stdin); print(d.get('size'), d.get('default_branch'), d.get('created_at','')[:10])" +``` + +## 批量镜像模式 + +循环处理 N 个项目:写 `unshallow_all.sh`(逐个 unshallow)+ `push_all.sh`(逐个 push,`--all` 与 `--tags` 分两次),日志写 `push.log`,用 `grep -E "^(OK|FAIL)"` 汇总。后台跑(`background=true` + `notify_on_complete=true`)。 + +## Pitfalls + +1. **`shallow update not allowed`** — 浅克隆推送被拒。解法:`git fetch --unshallow origin`,确认 `.git/shallow` 消失再推。 +2. **GitHub 直连不稳定** — 表现为 `Failed to connect to github.com port 443 after 133xxx ms`。对策: + - 先 `git ls-remote https://github.com/... HEAD` 测连通 + - 直连不行换镜像:`git clone https://gh-proxy.com/https://github.com/OWNER/REPO.git`(实测可用)或 `https://ghproxy.net/...` + - `codeload.github.com`(HTTP 下载)常比 git 协议通,但下载的是无历史的 tar.gz +3. **`--all --tags` 合并报错** — 必须拆成两次 push。 +4. **Gitea API 401** — 用了 `Authorization: token` 头。改 `-u 用户名:token` Basic auth。 +5. **Gitea 仓库列表分页 50/页** — 仓库多时第 2 页起才有目标,`?limit=100&page=2` 翻页,别误判"仓库没建成功"。 +6. **README 含引号/emoji 导致创建 JSON 转义坏** — 创建仓库时 description 用固定值,不塞 README 内容。 +7. **Windows 上 git 命令管道** — 目标机是 Windows 时 `tail`/`findstr` 管道会吞输出,先不加过滤器看原始输出。 + +## 参考 + +- `references/gitea-api-notes.md` — Gitea API 细节、.netrc token 提取、验证命令 +- `references/diygod-batch-mirror-2026-08.md` — 15 项目批量镜像实录(镜像站实测对比、批量脚本模式、安装测试分层) +- 家庭服务器 Windows 部署流程见 `windows-home-server-ops` skill diff --git a/skills/devops/gitea-repo-mirroring/references/diygod-batch-mirror-2026-08.md b/skills/devops/gitea-repo-mirroring/references/diygod-batch-mirror-2026-08.md new file mode 100644 index 00000000..780b2abd --- /dev/null +++ b/skills/devops/gitea-repo-mirroring/references/diygod-batch-mirror-2026-08.md @@ -0,0 +1,51 @@ +# DIYgod 15 项目批量镜像实录(2026-08-03) + +批量把 DIYgod 的 15 个开源项目镜像到家庭服务器 Gitea 的完整实战记录。作为 gitea-repo-mirroring 的批量案例参考。 + +## 项目清单与规模 + +| 项目 | Commits | 备注 | +|------|---------|------| +| RSSHub | 17,321 | 最大,45.5K★,历史超长需镜像站 | +| Folo | 7,011 | RSSNext 组织项目(38.7K★) | +| xLog | 2,731 | Crossbell-Box 组织项目 | +| RSSHub-Radar | 1,331 | 浏览器扩展 | +| DPlayer | 1,302 | 弹幕播放器 | +| APlayer | 916 | 音乐播放器 | +| cloudflare-rsshub-deploy | 388 | | +| download-webhook | 39 | | +| edge-image-transformer | 23 | | +| cloudflare-edge-tts | 18 | | +| OwO / ttrss-theme-rsshub | 14 / 14 | | +| GoodNight / DIYgod-Obsidian-Starter | 6 / 5 | | +| ttrss-plugin-remove-iframe-sandbox | 3 | | + +## 关键经验 + +### 1. 网络策略:GitHub 直连 vs 镜像 +- GitHub 直连**时好时坏**:有时 `git ls-remote` 通、大仓库 clone 却挂(133s 超时) +- **镜像加速站实测**(2026-08-03): + - `https://gh-proxy.com/https://github.com/...` ✅ 通(clone RSSHub 17K commits 成功) + - `https://ghproxy.net/https://github.com/...` ✅ 通(refs 探测 200) + - `https://ghfast.top/...` ❌ 超时、`https://mirror.ghproxy.com/...` ❌ 超时 +- **决策规则**:小仓库直连优先;大仓库(历史 >2000 commits)或直连连续失败 → 直接换 gh-proxy.com + +### 2. 批量脚本模式 +- `unshallow_all.sh`:循环 `git fetch --unshallow`,Folo 网络不稳用 `--deepen=2000` 增量重试 8 轮成功 +- `push_all.sh`:循环 `git push --all` + `git push --tags` 分开推,日志写 push.log +- 后台跑 + notify_on_complete;用 `grep -E "^(OK|FAIL)"` 汇总 + +### 3. Gitea 仓库创建 JSON 陷阱 +- README 含引号/emoji 会破坏 `-d '{"description":"..."}'` 转义 → description 用固定值 +- 15 个仓库全部 `HTTP 200` 创建成功,但**第 1 页只显示 50 个**旧仓库,DIYgod 的 15 个在第 2 页(`?limit=100&page=2`)→ 验证时别误判"没建成功" + +### 4. 安装测试分层 +- **轻量项目**(纯前端 DPlayer/APlayer):直接 `python3 -m http.server` 起静态服务 + curl 验证 200 +- **有测试套件**(cloudflare-edge-tts):`npm install` + `npm run test` → 22/22 通过 +- **重量级**(RSSHub):`pnpm install`(3m55s)→ `npm run build`(5.4s)→ `npm start` → 路由实测 +- **RSSHub v1.0 路由变化**:`/github/release`、`/zhihu/hotlist`、`/github/trending` 已删(404 预期);现存 `/github/issue/DIYgod/RSSHub`、`/github/repos/DIYgod` 返回 200 + 真实 RSS 2.0 + +## 部署去向 +- RSSHub → 家庭服务器 Node 部署(见 windows-home-server-ops skill) +- cloudflare-edge-tts → 本地 wrangler dev --local 常驻(TTS API) +- 小唯语音 → Hermes 内置 edge TTS(zh-CN-XiaoxiaoNeural) diff --git a/skills/devops/gitea-repo-mirroring/references/gitea-api-notes.md b/skills/devops/gitea-repo-mirroring/references/gitea-api-notes.md new file mode 100644 index 00000000..dfb4889f --- /dev/null +++ b/skills/devops/gitea-repo-mirroring/references/gitea-api-notes.md @@ -0,0 +1,49 @@ +# Gitea API 笔记(2026-08-03 实测) + +## Token 提取(~/.netrc 单行格式) + +```bash +# ✅ awk 遍历字段提取(不要用 getline —— .netrc 是单行) +TOKEN=$(awk '/^machine 192.168.123.11/{for(i=1;i<=NF;i++) if($i=="password") print $(i+1)}' ~/.netrc) +``` + +## 认证方式 + +- ✅ **Basic auth**:`curl -u "xiaoxue_admin:$TOKEN"` → 200 +- ❌ `Authorization: token $TOKEN` 头 → **401**(Gitea 不认这种写法) + +## 常用 API + +```bash +# 创建仓库 +curl -s -u "user:$TOKEN" -X POST http://HOST:3000/api/v1/user/repos \ + -H "Content-Type: application/json" \ + -d '{"name":"REPO","description":"固定值(避免转义)","private":false}' + +# 查仓库(含 size/默认分支/创建时间) +curl -s -u "user:$TOKEN" http://HOST:3000/api/v1/repos/xiaoxue_admin/REPO + +# 列用户仓库 —— ⚠️ 分页 50/页!仓库多时目标在 page 2+ +curl -s -u "user:$TOKEN" "http://HOST:3000/api/v1/users/xiaoxue_admin/repos?limit=100&page=2" + +# 查用户 +curl -s -u "user:$TOKEN" http://HOST:3000/api/v1/user +``` + +## Push URL 格式 + +```bash +# Basic auth 内嵌 URL(注意 --all 和 --tags 必须分开) +git push "http://xiaoxue_admin:$TOKEN@192.168.123.11:3000/xiaoxue_admin/REPO.git" --all +git push "http://xiaoxue_admin:$TOKEN@192.168.123.11:3000/xiaoxue_admin/REPO.git" --tags +``` + +## 创建仓库 JSON 转义坑 + +README/description 含引号、emoji、换行会导致 `-d '{"name":"...","description":"..."}'` 转义坏(创建失败或字段错乱)。 +**解法:description 用固定值,不塞 README 内容。** 仓库建好后内容由 push 提供。 + +## 浅克隆 → Gitea + +- 现象:`git push` → `fatal: remote ... : shallow update not allowed` +- 解法:`git fetch --unshallow origin`(或 `--deepen=2000` 循环续传),`.git/shallow` 消失后再 push diff --git a/skills/devops/llm-gateway-ops/SKILL.md b/skills/devops/llm-gateway-ops/SKILL.md index e651da49..8ff4e257 100644 --- a/skills/devops/llm-gateway-ops/SKILL.md +++ b/skills/devops/llm-gateway-ops/SKILL.md @@ -139,5 +139,39 @@ cronjob action=update job_id=XXX model={"model": "openai/gpt-oss-120b", "provide - 修完 cron 后验证:`cronjob action=run job_id=XXX` → `execution_success: true`,或等下一个调度周期看 `last_status` - 排查 cron 失败第一动作:`cronjob action=list` 找 `last_status: error`,再读 `~/.hermes/cron/output/{job_id}/{date}*.md` 的 Error 段——504 类 SSE 超时一眼可见 +## ⚠️ 免费模型池会整体过期,skill 白名单记录会 stale(2026-08-02 实测) + +**模型池会整体大换血**:2026-07-27 当天 m2.7/step-flash/qwen3.5 全部 EOL,m3 空响应,gpt-oss 是 reasoning 模型。**skill/文档里的"可用模型"记录会过期**——任何模型判断都必须实测,不能信旧白名单。 + +**蒸馏任务 vs 对话任务的判定标准不同**: +- 对话任务:`choices[0].message.content` 非空即可 +- **蒸馏任务:content 必须是非空且可解析的 JSON**(剥离 ```json code fence 后)——"能对话 ≠ 能蒸馏" +- **reasoning 模型(gpt-oss 系)排除**:`content=null`,答案全在 `reasoning`/`reasoning_content` 字段——除非调用方显式读取该字段,否则 distill 永远 parse 失败降级 keyword + +**模型验证命令(候选模型上线前必跑)**: +```bash +KEY=$(grep -oP 'LLM_API_KEY=\K.*' ~/.config/systemd/user/zhiyid.service) +curl -s -m 30 http://127.0.0.1:3000/v1/chat/completions -H "Content-Type: application/json" \ + -H "Authorization: Bearer $KEY" -d '{"model":"<候选>","messages":[{"role":"system","content":"输出严格JSON"},{"role":"user","content":"提取实体:牧尘喜欢简洁。输出 {\"entities\":[],\"decisions\":[],\"conclusions\":[]} 格式"}],"max_tokens":150}' +# 期望: content 是纯 JSON(或可剥离的 code fence),且非空 +# 失败特征: content=null(reasoning 模型)/ 400 EOL / No available channel / system_cpu_overloaded / 空响应 +``` + +## 蒸馏模型双层看门狗(2026-08-02 上线,解决"免费模型挂了没人换") + +免费模型经常挂,单层 6h 巡检太慢 + 探针类型不对(测对话不测 JSON)。方案:**双层**: + +1. **30min 轻量探针**(no-agent cron):只测当前蒸馏模型的 JSON 输出能力(剥离 code fence 后可解析才算通过)→ 挂了立即按候选池切换 + 更新配置 + 重启 + 飞书报警 + - 参考实现:`~/.hermes/scripts/distill-model-watchdog.py`(cron `89de35dc35a7`) +2. **6h 深度巡检**(model-health.py 的 `_heal_distill_models`):同步守护蒸馏配置,识别 reasoning 模型 + +**候选池设计**:按优先级排序的可用模型列表(实测 JSON 可用),挂了顺序测下一个。当前蒸馏候选池:`google/gemma-4-31b-it` > `mistralai/mistral-nemotron` > `nvidia/llama-3.3-nemotron-super-49b-v1.5` > `meta/llama-3.1-8b-instruct` > `nvidia/nemotron-mini-4b-instruct` + +**⚠️ 自愈机制必须实测"失败路径"**(牧尘"都测试过了吧?"教训): +- 手动 `cronjob run <id>` 触发一次确认 `execution_success: true` +- **模拟失败场景**(把配置改成已知坏模型)→ 跑机制 → 确认切换+配置更新+服务重启+通知全链路 +- dry-run 单测判断逻辑(好模型判健康、坏模型判需替换、原文件未动) +- **陷阱:模型不在测试列表 ≠ 模型挂了**。探针主判(content 非空+JSON 可解析),巡检结果仅作辅助覆盖(明确 dead 才覆盖探针)——否则会把健康模型误替换(gemma 不在 ALL_MODELS → found=None → 误判需替换,2026-08-02 抓到并修复) + ## 参考 - `references/omniroute-notes.md` — 本次部署/踩坑细节 diff --git a/skills/devops/self-healing-infrastructure/SKILL.md b/skills/devops/self-healing-infrastructure/SKILL.md index c831d09b..bd5531a2 100644 --- a/skills/devops/self-healing-infrastructure/SKILL.md +++ b/skills/devops/self-healing-infrastructure/SKILL.md @@ -7,6 +7,7 @@ author: 小唯 A06 tags: [self-healing, monitoring, auto-rollback, evolution, watchdog, config-protection, daemon, backup, recovery] category: devops trigger: 系统部署、开机自启、配置更改、故障恢复场景、备份验证、恢复演练 + **2026-08-02 端到端验证法(核心)**:组件在跑 ≠ 链路在工作。zhiyid/sidecar/bge-embed 全 active 但 distill 一直 fallback(zhiyid.service 缺 LLM_ENDPOINT/MODEL/KEY 环境变量)→ commit 返回 201 但 20 分钟 recall 查不到。判"健康"必须验证写→蒸馏→检索全链路;判 systemd 服务正常要看 NRestarts 不是端口在听(tdai-gateway 曾崩溃循环 2534 次被手动进程掩盖)。记忆系统是四套(织忆/Soulful/TencentDB/CBM)不是一套。详见 references/memory-system-e2e-verification-20260802.md。 **2026-07-29 model-health.py 全覆盖**:自愈脚本覆盖 3 个配置格式——主(YAML) + prof-b(YAML) + OpenClaw(JSON)。死模型自动替补。gateway 内部无法 restart(强保护),需用户手动 systemctl restart。详见 references/model-health-multi-config-coverage.md。 **2026-08-01 model-health.py v3**:两个致命缺陷——①从不验证实际生效的 model.default(只查 providers 列表)→ prof-b 被写成 NewAPI 不存在的模型全挂 503;②排名公式丢 context_score → 1M 长上下文排不上。v3 新增 `_verify_model_usable()` 替换前真实调用验证 + 探针 3 次取平均。铁律:修复必须闭环测试(故意改坏→跑→确认)。详见 references/model-health-v3-fixes-20260801.md。 **2026-08-01 ⚠️ model.default 铁律(牧尘连续 3 次手动改回,最高优先级)**:`_auto_promote_config` 的 B 段曾把 `model.default`(日常对话主模型)自动切成 NewAPI 排名第一的模型 → 对话直接挂。**model.default 是用户锁定的付费主模型(deepseek-v4-flash + api.deepseek.com),任何自动化脚本(model-health.py / self-evolve.py / optimizer.py)都不得修改**;NewAPI 免费模型只用于 cron/自动化。修复:B 段整体删除(只打印保护信息)、`_heal_config` 双重池内保护(model.default 不在 CANDIDATE_POOL 就跳过)。闭环测试 3 项:模拟排名切换/死模型,config.yaml 字节级未变(hash 一致)。commit 5bb8043。 diff --git a/skills/devops/self-healing-infrastructure/references/memory-system-e2e-verification-20260802.md b/skills/devops/self-healing-infrastructure/references/memory-system-e2e-verification-20260802.md new file mode 100644 index 00000000..5fc03923 --- /dev/null +++ b/skills/devops/self-healing-infrastructure/references/memory-system-e2e-verification-20260802.md @@ -0,0 +1,60 @@ +# 记忆系统端到端验证法(2026-08-02) + +> 触发:牧尘问"织忆很成熟么?",深挖发现组件全 active 但核心链路是断的。 +> 核心教训:**组件在跑 ≠ 链路在工作**。判断"健康/成熟"必须验证端到端链路。 + +## 事故还原 + +当时 zhiyid/sidecar/bge-embed 全部 active,`/api/v1/health` 全 ok,但: +- `POST /api/v1/commit` 返回 201 + episode_id(看似成功) +- **20 分钟后 recall 检索不到新写入内容** +- 日志铁证:`LLMEndpoint empty, fallback for ep_...` + `facts=1 entities=0` +- 根因:`~/.config/systemd/user/zhiyid.service` **缺少 `LLM_ENDPOINT` / `LLM_MODEL` / `LLM_API_KEY` 环境变量** → distill 每次走关键词提取 fallback → 产出低质记忆永远排不上检索 + +## 端到端验证 5 步 + +``` +1. 写:POST /api/v1/commit → 返回 episode_id(201)≠ 已入库可用 +2. 等:distill 是异步队列(batch<10 或 <5min 不 flush),等 5-10s 或查日志 flush START +3. 验:日志出现 "endpoint=... model=..."(真 LLM)而非 "LLMEndpoint empty, fallback" +4. 查:recall 同主题能命中新写入内容 +5. 量:total_memories 增长(memories 持久化);total_episodes 重启会归零(Rust sidecar 内存,非权威) +``` + +## 关键信号对照 + +| 信号 | 含义 | +|------|------| +| `LLMEndpoint empty, fallback` + `facts=1 entities=0` | **假健康**:写入成功但蒸馏=关键词提取,recall 排不上 | +| `LLM entities: N` + `score=0.8x` + `decisions/conclusions` | 真 LLM 蒸馏,记忆质量可用 | +| 进程/端口/health 全绿 | 只是"组件活着",不证明链路工作 | + +## systemd 服务崩溃循环 vs 手动进程撑场(TencentDB 案例) + +**症状**:`tdai-gateway.service` ExecStart 被写坏成 `/src/gateway/server.ts`(不存在)→ systemd 崩溃循环 **2534 次**,但**手动进程撑在 8420 端口**让服务"看起来活着"。 + +**诊断**:`systemctl --user show tdai-gateway -p NRestarts` → 重启计数几千 = 崩溃循环。**端口在听 ≠ systemd 服务正常**。 + +**修复**:修正 ExecStart 路径(`--require .../tsx/dist/preflight.cjs --import .../loader.mjs src/gateway/server.ts`)→ `systemctl --user daemon-reload` → 杀手动进程 → systemd 接管。验证:`systemctl --user is-active` + 端口 PID 变化 + `curl /health` uptime 从 5s 起跳。 + +## 四套记忆系统全景(牧尘纠正) + +| 系统 | 职责 | 端口/位置 | 数据量(2026-08-02) | +|------|------|----------|--------------------| +| 织忆 ZhiYi | 语义记忆 | :7821 | 5054 memories / 9075 图谱节点 | +| Soulful | 关系记忆 | daemon, ~/.hermes/soulful/ | 心迹13 / 牵挂 / 画像 | +| TencentDB TDAI | 人格蒸馏 | :8420 | L0 85K / L1 22(0.03% 是设计如此) | +| TencentDB TDAI | 人格蒸馏 | :8420 | L0 85K / **L1 2245 条(JSONL 真相源)** | + +- 四套独立进程,默认互不影响,诊断先确认哪一套 +- **L1 数据量测量铁律(2026-08-02 晚间修正)**:判 L1 是否工作**不要查 `l1_records` 表**(那是同步缓存,仅 19 行),真相源是 `~/.memory-tencentdb/memory-tdai/records/*.jsonl`(全量 2245 条:persona 459 / instruction 543 / episodic 1243,覆盖 15 天,每天正常产出)。查询:`sqlite3 ~/.memory-tencentdb/memory-tdai/vectors.db "SELECT COUNT(*) FROM l0_conversations"` 看 L0;L1 用 python 扫 `records/*.jsonl` 统计。曾因此误判"85K L0 只蒸馏 22 条 = 管道坏了",实际提取器每天健康运行。 +- **锁冲突 ≠ 故障**:pipeline 日志 `lock conflict 11 / success 5` 只是瞬时竞争(worker concurrency=10 + per-session 锁),无积压无丢任务——验证方式是看 records 每日产出,不是看冲突计数。 +- L0 60%+ 是 zhiyi-sync 自动同步的心迹(3834/6438 当日),这是"设计如此":L1 从心迹提取 episodic 反而有质量(如"7-10 上线每日复盘机制") +- **教训**:评估"记忆系统"时必须四套一起看(牧尘原话:"记忆系统可不止织忆"、"你还少了cbm") + +## 修复记录 + +- zhiyid.service 补 LLM 环境变量(LLM_ENDPOINT=http://127.0.0.1:3000/v1/chat/completions, LLM_MODEL=openai/gpt-oss-120b, LLM_API_KEY=<NewAPI key>) +- tdai-gateway.service ExecStart 修正 +- learner.py 轨迹学习门禁(支持度≥2 才写织忆)+ daemon.py 程序记忆分类(procedural) +- Soulful cares stale 即删(pending→14天→stale→下轮删除) diff --git a/skills/devops/windows-home-server-ops/SKILL.md b/skills/devops/windows-home-server-ops/SKILL.md new file mode 100644 index 00000000..7536157e --- /dev/null +++ b/skills/devops/windows-home-server-ops/SKILL.md @@ -0,0 +1,124 @@ +--- +name: windows-home-server-ops +description: "家庭服务器 (192.168.123.11 Windows) 部署与运维 — SSH 管理、Node 服务常驻(schtasks)、防火墙放行、Windows cmd/PowerShell 坑。替代 Docker(服务器没装)。" +version: 1.0.0 +author: 小唯 A06 +tags: [windows, server, schtasks, ssh, deploy, node, 家庭服务器, firewall] +trigger: "部署到家庭服务器 / 192.168.123.11 / Windows服务器上跑服务 / 服务器常驻服务 / schtasks" +created: 2026-08-03 +updated: 2026-08-03 +--- + +# Windows 家庭服务器部署与运维 + +家庭服务器 `192.168.123.11` 是 **Windows Server 2022**(不是 Linux!),账号 `administrator`(密码 xue.2538)。**没有 Docker**,但有 Node v24.14.1 + npm 11 + git 2.53 + Python 3.12。 + +## 环境事实(实测 2026-08-03) + +| 项 | 值 | +|----|----| +| OS | Windows Server 2022 (10.0.20348) | +| SSH | OpenSSH,可 `sshpass -p 'xue.2538' ssh administrator@192.168.123.11` | +| Docker | ❌ 无(`docker` 命令不存在) | +| Node | ✅ v24.14.1(RSSHub engines ^22.22.2 || ^24.15.0 勉强满足) | +| Gitea | ✅ 3000 端口 | +| SMB 共享 | ✅ `beifen` 等挂载于 `/mnt/server-backup` | + +## SSH 连接模板 + +```bash +# Windows OpenSSH 可用 sshpass 连接(需先装 sshpass) +sshpass -p 'xue.2538' ssh -o StrictHostKeyChecking=no -o ConnectTimeout=8 \ + -o UserKnownHostsFile=/dev/null administrator@192.168.123.11 "命令" + +# 中文输出乱码(GBK)先 chcp 65001 +"chcp 65001 >nul & 命令" +``` + +## 部署 Node 服务(核心流程:schtasks 常驻) + +**关键教训:SSH 会话里 `start /b` 或 PowerShell Start-Process 启动的子进程,SSH 断开后会被杀。** 必须用 Windows 任务计划程序(schtasks)托管才能常驻。 + +### 1. 克隆代码(走本地 Gitea 快) + +```bash +sshpass -p 'xue.2538' ssh ... administrator@192.168.123.11 \ + "cd C:\ && git clone http://xiaoxue_admin:TOKEN@192.168.123.11:3000/xiaoxue_admin/REPO.git rsshub" +``` + +### 2. 安装依赖 + 构建(Windows 无 tail,用 findstr) + +```bash +# pnpm 全局装 + install(native 模块缺 VS 构建工具会报 gyp 错,可选依赖可忽略) +"cd C:\rsshub && npm install -g pnpm@9 & pnpm install 2>&1 | findstr /C:Done /C:ERR /C:error" +# 构建(成功标志 Build complete) +"cd C:\rsshub && npm run build 2>&1 | findstr /C:\"Build complete\" /C:error" +``` + +### 3. 写启动 bat(用 PowerShell Set-Content,别用 echo 重定向——SSH 转义会截断) + +```bash +# ✅ 可靠写法:PowerShell 数组写文件(echo > 会被 SSH 转义吃掉 > 和 &) +sshpass ... "powershell -Command \"Set-Content -Path 'C:\rsshub\start-rsshub.bat' -Value @('@echo off','cd /d C:\rsshub','set PORT=1200','set NODE_ENV=production','node dist\index.mjs > C:\rsshub\rsshub.log 2>&1') -Encoding Ascii\"" +``` + +### 4. 创建并运行 schtasks 任务 + +```bash +# 创建(/sc once /st 00:00 占位,/f 覆盖)+ 运行 +sshpass ... "schtasks /create /tn RSSHub /tr \"C:\rsshub\start-rsshub.bat\" /sc once /st 00:00 /f & schtasks /run /tn RSSHub" +# 验证进程 +sshpass ... "tasklist | findstr /i node & netstat -ano | findstr :1200" +``` + +schtasks 起的进程跑在 **Services 会话**(`tasklist` 显示 `Services 0`),SSH 断开不掉。 + +### 4b. 开机自启(schtasks onstart,常驻服务必做) + +```bash +# 一次性任务 → 开机触发:删旧建新(/sc onstart + /ru SYSTEM) +schtasks /delete /tn RSSHub /f +schtasks /create /tn RSSHub /tr "C:\rsshub\start-rsshub.bat" /sc onstart /ru SYSTEM /f +# 验证类型(英文输出看这两个字段) +schtasks /query /tn RSSHub /fo list /v | findstr /C:"Schedule Type" /C:"Run As User" +# 期望: Schedule Type: At system start up / Run As User: SYSTEM +# 立即测试(杀掉当前实例 → 手动触发 → 验证新进程 + 外部访问) +taskkill /f /im node.exe & schtasks /run /tn RSSHub +tasklist | findstr /i node # 看到新 PID(Services 会话)即成功 +# 外部验证 +curl -s -o /dev/null -w "%{http_code}" http://192.168.123.11:1200/healthz # 200 +``` + +注意:`/ru SYSTEM` 让任务以系统身份运行(开机即起、无需登录);`/sc once /st 00:00` 是一次性占位任务(手动 /run 用),**持久部署要重建为 onstart**。实测 2026-08-03:杀旧 node PID → onstart 任务触发 → 新 node 起来、外部 200,全部通过。 + +### 5. 防火墙放行(外部访问必需) + +```bash +# 本机 127.0.0.1 能访问但外部 192.168.123.131 不行 → 防火墙拦截 +netsh advfirewall firewall add rule name=\"RSSHub 1200\" dir=in action=allow protocol=TCP localport=1200 +``` + +### 6. 验证 + +```bash +# 服务器本机验证(curl.exe Windows 自带) +curl.exe -s -o NUL -w \"LOCAL: %{http_code}\" http://127.0.0.1:1200/healthz +# 从本机验证外部访问 +curl -s -o /dev/null -w "external: %{http_code}" http://192.168.123.11:1200/healthz +``` + +## Pitfalls + +1. **SSH 断开杀子进程** — `start /b`、PowerShell `Start-Process` 都不行。必须 schtasks。 +2. **echo 重定向被 SSH 转义截断** — `echo node dist\index.mjs > log 2>&1` 里的 `>` 和 `&` 被吞。用 PowerShell `Set-Content -Value @('...','...')`。 +3. **Windows 没有 `tail`** — 用 `findstr /C:...` 过滤;不加过滤器先看原始输出更可靠。 +4. **中文乱码** — Windows cmd 输出 GBK,先 `chcp 65001`,或接受乱码只看 ASCII 关键词(OK/FAIL/Done)。 +5. **缺 VS 构建工具 → node-gyp 失败** — `bufferutil`/`ws` 等 native 模块报 `Could not find any Visual Studio installation`。可选依赖可忽略,服务照常跑。 +6. **防火墙拦外部** — 本机 200 外部 000 时,加 `netsh advfirewall` 规则(注意 sshpass 里引号转义 `\"`)。 +7. **schtasks 创建报 `/ST 超出当前时间` 警告** — 用 `/sc once /st 00:00` 占位 + `/run` 手动触发即可,警告无害。 +8. **RSSHub v1.0 路由已删** — `/github/release`、`/zhihu/hotlist`、`/github/trending` 返回 404 `The route does not exist or has been deleted`。测路由用现存路径:`/github/issue/DIYgod/RSSHub`、`/github/repos/DIYgod` 返回 200。RSSHub 需要 `npm run build` 后才有 `dist/index.mjs`(直接 `npm start` 报 MODULE_NOT_FOUND)。 + +## 参考 + +- `references/rsshub-windows-deploy-2026-08.md` — RSSHub 部署全程实录(命令、日志、验证) +- Gitea 镜像流程见 `gitea-repo-mirroring` skill diff --git a/skills/devops/windows-home-server-ops/references/rsshub-windows-deploy-2026-08.md b/skills/devops/windows-home-server-ops/references/rsshub-windows-deploy-2026-08.md new file mode 100644 index 00000000..02a312f9 --- /dev/null +++ b/skills/devops/windows-home-server-ops/references/rsshub-windows-deploy-2026-08.md @@ -0,0 +1,82 @@ +# RSSHub 部署 Windows 家庭服务器实录(2026-08-03) + +完整命令链与验证证据,从零到外部可访问。 + +## 环境 +- 服务器:192.168.123.11,Windows Server 2022,administrator / xue.2538 +- 无 Docker,Node v24.14.1,npm 11.11.0,git 2.53 +- 本机:192.168.123.131,Node v24.16.0,Docker 29.1.3(无 compose) + +## 1. 克隆(走本地 Gitea) + +```bash +sshpass -p 'xue.2538' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null administrator@192.168.123.11 \ + "cd C:\ && git clone http://xiaoxue_admin:TOKEN@192.168.123.11:3000/xiaoxue_admin/RSSHub.git rsshub" +# 结果:Cloning into 'rsshub'... Updating files: 100% (6655/6655) — CLONE_OK +``` + +## 2. 依赖安装(2m28s) + +```bash +"cd C:\rsshub && npm install -g pnpm@9 & pnpm install 2>&1 | findstr /C:Done /C:ERR /C:error" +# bufferutil/ws native 报 gyp ERR! Could not find any Visual Studio — 可选依赖,忽略 +# 结果:Done in 2m 28.7s using pnpm v9.15.9 +``` + +## 3. 构建(17.6s) + +```bash +"cd C:\rsshub && npm run build 2>&1 | findstr /C:\"Build complete\" /C:error" +# 结果:✔ Build complete in 17599ms +``` + +## 4. 启动脚本(PowerShell 写 bat,避免 SSH 转义截断) + +```bash +"powershell -Command \"Set-Content -Path 'C:\rsshub\start-rsshub.bat' -Value @('@echo off','cd /d C:\rsshub','set PORT=1200','set NODE_ENV=production','node dist\index.mjs > C:\rsshub\rsshub.log 2>&1') -Encoding Ascii\"" +``` + +## 5. schtasks 常驻 + +```bash +"schtasks /create /tn RSSHub /tr \"C:\rsshub\start-rsshub.bat\" /sc once /st 00:00 /f & schtasks /run /tn RSSHub" +# 结果:成功创建计划任务 "RSSHub" + 成功尝试运行 +# 验证:tasklist | findstr /i node → node.exe 11384 Services 0(Services 会话,SSH 断开不掉) +``` + +## 6. 防火墙 + +```bash +# 本机 127.0.0.1:1200 200 OK 但外部 000 → 加规则 +"netsh advfirewall firewall add rule name=\"RSSHub 1200\" dir=in action=allow protocol=TCP localport=1200" +# 结果:确定(OK) +``` + +## 7. 验证(外部访问) + +```bash +curl -s -o /dev/null -w "%{http_code}" http://192.168.123.11:1200/healthz # 200 +curl -s -o /dev/null -w "%{http_code}" http://192.168.123.11:1200/ # 200 (Welcome to RSSHub!) +curl -s -o /dev/null -w "%{http_code}" http://192.168.123.11:1200/github/issue/DIYgod/RSSHub # 200 +# RSS 内容真实:<rss> + <item> 含 DIYgod 仓库列表 +``` + +## 本机 Linux 对照(systemd) + +```bash +# ~/.config/systemd/user/rsshub.service +# ⚠️ 用户级 systemd 不要写 User=muc —— 会报 status=216/GROUP (Failed to determine supplementary groups) +# 用默认当前用户,WorkingDirectory + Environment 即可 +systemctl --user daemon-reload && systemctl --user enable --now rsshub.service +``` + +## 关键日志/错误锚点 + +| 症状 | 原因 | 解法 | +|------|------|------| +| `Cannot find module dist/index.mjs` | 没 build | `npm run build` | +| node 进程没起 | SSH 断开杀子进程 | schtasks | +| bat 最后一行 `2>&` 被截断 | SSH 转义吃 `&` | PowerShell Set-Content | +| `status=216/GROUP` | 用户级 systemd 写 User= | 删掉 User 行 | +| 外部 000 / 本机 200 | Windows 防火墙 | netsh advfirewall | +| `/github/release` 404 | RSSHub v1.0 删路由 | 用 `/github/issue` `/github/repos` | diff --git a/skills/email/himalaya/SKILL.md b/skills/email/himalaya/SKILL.md index dde9afa5..bc95449b 100644 --- a/skills/email/himalaya/SKILL.md +++ b/skills/email/himalaya/SKILL.md @@ -1,5 +1,6 @@ --- name: himalaya +version: 1.2.0 tags: [himalaya, email] description: "Himalaya CLI: 终端IMAP/SMTP邮件客户端 — 收件箱管理、邮件发送、搜索、附件下载。与Hermes Email Gateway互补:Gateway收邮件给Agent,Himalaya让Agent操作邮箱。安装: cargo install himalaya。" related_skills: diff --git a/skills/knowledge/cangjie-distill/SKILL.md b/skills/knowledge/cangjie-distill/SKILL.md index 73784094..a605e2a9 100644 --- a/skills/knowledge/cangjie-distill/SKILL.md +++ b/skills/knowledge/cangjie-distill/SKILL.md @@ -1,7 +1,7 @@ --- name: cangjie-distill -version: 1.6.0 -date: 2026-07-18 +version: 1.7.0 +date: 2026-08-02 description: | 把书籍/视频/播客/课程/长内容蒸馏成一组可执行 skills 的元 skill。 触发词:拆书/蒸馏/把XX做成skill/turn a book into skills/把视频/播客/课程蒸馏成skill @@ -184,17 +184,36 @@ Stage5 交付 → 输出为 skill/overview/digest/index 2. 书库有 → 下载 epub/pdf,启动蒸馏 3. 书库没有 + 是公版经典 → 找公版来源(《资本论》《共产党宣言》等均为公版) 4. 书库没有 + 非公版 → **停下来问用户提供文件** +5. **GitHub 开源书**(2026-08-02 实测新路径):git clone 常因国内网络超时(直连/ghfast.top 镜像都不稳),但 **`api.github.com` 可直连(~0.3s 响应)**。用 contents API 逐文件拉取正文: + +```bash +# 列目录 → 拿文件名和大小 +curl -s -H "User-Agent: Mozilla/5.0" "https://api.github.com/repos/{owner}/{repo}/contents/book" +# 逐文件拉取(返回 base64,需解码) +for f in chapter1.md chapter2.md; do + curl -s -H "User-Agent: Mozilla/5.0" "https://api.github.com/repos/{owner}/{repo}/contents/book/$f" \ + | python3 -c "import json,sys,base64; d=json.load(sys.stdin); open('$f','w').write(base64.b64decode(d['content']).decode('utf-8','ignore'))" +done +# 验证字符数:wc -c *.md | tail -1 +``` + +**实测**:ai-agent-book 12 个正文文件(introduction + chapter1-10 + afterword)共 1.1M 字符,用此方法约 1 分钟拉完。MCP GitHub 工具(mcp_github_get_file_contents)也可拉单文件,但大量文件用 curl 循环更快。README 走 `mcp_github_get_file_contents` 或 contents API 都行。 > ⚠️ 没有文本就不启动流水线。仓颉不凭记忆蒸馏。 -### 模型选择策略(2026-07-18 实测更新) +### 模型选择策略(2026-08-02 实测更新) + +> ⚠️ **2026-08-02 重要更新**:`qwen/qwen3.5-122b-a10b` 已于 **2026-07-20 EOL**、`qwen/qwen3-next-80b-a3b-instruct` 已于 **2026-07-27 EOL**,调用返回 410/end-of-life 错误。中文蒸馏首选改为 `openai/gpt-oss-120b`(实测 3 批蒸馏全部成功,输出质量高,probe=100 稳定)。 | 模型 | 响应速度 | 可用性 | 适用场景 | |------|---------|--------|---------| -| `qwen/qwen3.5-122b-a10b` | ~7-18s | ✅ **首选** | 中文深度推理、Stage0概览、skill构造(稳定,实测 5/5 成功) | +| `openai/gpt-oss-120b` | ~5-15s | ✅ **首选** | 中文深度推理、Stage0概览、skill构造(2026-08-02 实测 3/3 成功,ai-agent-book 17 skills) | +| `nvidia/nemotron-3-super-120b-a12b` | ~1s | ✅ 可用 | 1M ctx 大上下文、delegation | | `stepfun-ai/step-3.5-flash` | ~1s | ✅ 可用 | 快速问答、简单提炼(输出较短) | | `minimaxai/minimax-m2.7` | ~3-4s | ⚠️ 有风险 | 大段中文 content 有 60s 超时风险,**慎用长文本** | | `mistralai/mistral-large-3-675b` | ~1s | ❌ 常超时 | NewAPI 路径经常 `exit code 28`,不推荐通过 NewAPI 调用 | +| ~~`qwen/qwen3.5-122b-a10b`~~ | — | ❌ **已EOL 2026-07-20** | 历史首选,已不可用(410) | +| ~~`qwen/qwen3-next-80b-a3b-instruct`~~ | — | ❌ **已EOL 2026-07-27** | 已不可用(410) | **Token 限制**:单次 prompt + 系统 prompt + 输出 ≤ context window 的 80%,超长书分段。 @@ -207,18 +226,19 @@ Stage5 交付 → 输出为 skill/overview/digest/index ### 流水线实际执行顺序(2026-07-18 实测验证) -> 完整8阶段适合出版级蒸馏。日常使用:**Stage0 + 直接 skill 构造**,10分钟出可用结果。今天(2026-07-18)实测:5本书成功蒸馏,模型全部用 qwen3.5-122b-a10b。 +> 完整8阶段适合出版级蒸馏。日常使用:**Stage0 + 直接 skill 构造**,10分钟出可用结果。今天(2026-08-02)实测:ai-agent-book 成功蒸馏 17 skills,模型用 openai/gpt-oss-120b。 **实测推荐工作流**: ``` -1. Calibre OPDS 搜索书名 → 获取 id -2. /get/epub/<id>/<library> 下载 epub → ~/.hermes/cangjie-inputs/ -3. zipfile 提取 epub → 转 txt → 检查字符数(<5K 改 PDF,>50K 继续) -4. Stage0:用 qwen3.5-122b-a10b 跑一次 LLM,输出结构化 BOOK_OVERVIEW +1. 确认书源(Calibre OPDS 或 GitHub contents API,见上) +2. 下载/拉取正文 → 检查字符数(<5K 改 PDF,>50K 继续) +3. 按章分 3 批(每批 3-4 章,每章截 12-15K 字符)构造 skill +4. Stage0:用 openai/gpt-oss-120b 跑 LLM,输出结构化 BOOK_OVERVIEW 5. 直接构造 skill:基于 overview 让 LLM 输出 3-N 个完整 skill(R/I/A1/A2/E/B) -6. 写 INDEX.md -7. git add + commit + push 到 Gitea(每本书完成后单独 push) +6. 合并三批 → 拆分成独立 skill 目录(每个含 SKILL.md + test-prompts.json) +7. 写 INDEX.md / BOOK_OVERVIEW.md / PIPELINE_STATE.md +8. git add + commit + push 到 Gitea(每本书完成后单独 push) ``` **实测工具选择**: diff --git a/skills/media/tts-stt-tools/SKILL.md b/skills/media/tts-stt-tools/SKILL.md old mode 100755 new mode 100644 index d14d0c62..38d5a6d7 --- a/skills/media/tts-stt-tools/SKILL.md +++ b/skills/media/tts-stt-tools/SKILL.md @@ -1,13 +1,13 @@ --- name: tts-stt-tools description: "TTS 和 STT 工具封装 — edge-tts 语音合成 + 模力方舟 GLM-ASR 语音转文字,无需 HuggingFace 下载" -version: 1.3.0 +version: 1.4.0 author: 小唯 A06 -tags: [tts, stt, edge-tts, faster-whisper, voice, speech, GLM-ASR, 模力方舟] +tags: [tts, stt, edge-tts, faster-whisper, voice, speech, GLM-ASR, 模力方舟, cloudflare-edge-tts] trigger: "转语音 / 转文字 / text to speech / speech to text / 语音合成 / 语音转写 / 说出来 / 把我说的转成文字" trigger_fallback: true created: 2026-05-13 -updated: 2026-05-23 +updated: 2026-08-03 --- # TTS & STT 工具封装 @@ -40,6 +40,24 @@ edge-tts -t "低沉的声音" -v "zh-CN-YunxiNeural" --pitch=-50Hz --write-media | zh-CN-XiaoyiNeural | 女 | 活泼 | | zh-CN-YunyangNeural | 男 | 新闻播报 | +### Hermes 内置 TTS 通道(最省事,2026-08-03 验证) + +`~/.hermes/config.yaml` 已配置 `tts.provider: edge` + `voice: zh-CN-XiaoxiaoNeural`。 +直接用 `text_to_speech` 工具即可合成中文女声,输出真实 MP3(48kbps 24kHz)。 + +### cloudflare-edge-tts(Worker 版,可作独立 HTTP TTS API) + +DIYgod 的开源项目 `cloudflare-edge-tts`(本地路径 `~/projects/diygod/cloudflare-edge-tts/`): +- 端点:`GET /health`、`GET /voices`、`POST /tts`(body `{"text":"你好","voice":"可选"}` → audio/mpeg) +- **本地跑不需要 Cloudflare 认证**:`npx wrangler dev --local --port 8787` +- 测试:`npm test` 22/22 通过(2026-08-03) +- 用处:想要独立 TTS API 服务(非 Hermes 通道)时起这个 + +```bash +cd ~/projects/diygod/cloudflare-edge-tts && npx wrangler dev --local --port 8787 +curl -s -H 'Content-Type: application/json' -d '{"text":"你好"}' http://127.0.0.1:8787/tts -o out.mp3 +``` + ### Python 调用 > 参考:`references/edge-tts-venv-pattern.md` — 当系统 `pip` 无法直接安装时(externally-managed-environment),如何在项目 venv 中调用 edge-tts。 @@ -92,12 +110,10 @@ def transcribe(audio_path: str) -> str: ### 方案2:faster-whisper(本地,需模型) -> ⚠️ **服务器 HuggingFace 网络不通时无法下载模型**。优先用方案1。 - -服务器只有国内网络访问权(baidu.com、ai.gitee.com 可达),HuggingFace、jina.ai、firecrawl 等国际服务均不通。 +> ✅ **2026-08-03 实测:hf-mirror.com 镜像可下载成功**。直连 HuggingFace 超时(`ConnectTimeout: [Errno 110]`),但 `HF_ENDPOINT=https://hf-mirror.com` 后 base 模型 (~150MB) 正常下载并缓存到 `~/.cache/huggingface/hub/models--Systran--faster-whisper-base`(1-3 分钟)。该 env 已持久化到 `~/.hermes/.env`。 ```bash -# 方案A:配置 HF 镜像(如果 hf-mirror.com 可达) +# 方案A:配置 HF 镜像(✅ 已验证可下载,2026-08-03) HF_ENDPOINT=https://hf-mirror.com python3 -c "from faster_whisper import WhisperModel; model = WhisperModel('base', device='cpu', compute_type='int8')" # 方案B:回家后用家里网络下载,或用 Ollama whisper 替代 @@ -131,8 +147,8 @@ hermes-stt audio.wav |------|------|------| | edge-tts | ✅ 已安装 | 7.2.8 | | faster-whisper | ✅ 已安装 | 1.2.1 | -| ffmpeg | ✅ 已安装 | /usr/bin/ffmpeg | -| whisper 模型 | ✅ 已下载 | `~/.cache/huggingface/modules/faster_whisper_modules/` | +| ffmpeg | ⬜ **未安装**(2026-08-03 实测 `which ffmpeg` 无结果;faster-whisper 用 PyAV 直接解码 OGG/Opus,不需要 ffmpeg) | - | +| whisper 模型 | ✅ 已缓存 | `~/.cache/huggingface/hub/models--Systran--faster-whisper-base`(经 hf-mirror.com 下载) | | 模力方舟 GLM-ASR | ✅ STT 生产方案 | API 调用 | | espeak-ng | ⬜ 建议安装(NeuTTS 用) | - | diff --git a/skills/productivity/daily-recap/references/example-2026-08-02.md b/skills/productivity/daily-recap/references/example-2026-08-02.md new file mode 100644 index 00000000..ea6ebced --- /dev/null +++ b/skills/productivity/daily-recap/references/example-2026-08-02.md @@ -0,0 +1,14 @@ +## 示例报告(2026‑08‑02) +``` +今日完成: +- 织忆健康检查通过 ✅ +- Daemon 正常启动,无异常日志 + +明日待办: +- 继续监控 Daemon 与织忆组件 24 h 健康状态 +- 若有新任务,使用 `session_search` 捕获并记录 +- 如产生心迹,写入 `~/.hermes/soulful/heart-traces.jsonl` + +情绪状态: +- neutral(保持平稳) +``` diff --git a/skills/research/github-project-research/SKILL.md b/skills/research/github-project-research/SKILL.md index ad1411f2..19a0dfb2 100644 --- a/skills/research/github-project-research/SKILL.md +++ b/skills/research/github-project-research/SKILL.md @@ -11,6 +11,43 @@ trigger: 用户分享一个 GitHub 仓库名/产品名(如 "XX开源了"、" 牧尘会不定时丢项目名过来(Qwen Audio Agent、OmniRoute、各种开源工具)。**铁律:先查证再说话**——不凭印象编造 stars/功能,一切以 api.github.com 实时数据为准。 +## 工具链(2026-08-02 实测:MCP 优先) + +**首选:原生 GitHub MCP 工具**——本环境最可靠,免 curl/浏览器/网络代理: +- `mcp_github_search_repositories(query="repo:{owner}/{repo}")` → 元数据(full_name/desc/stars 可用性/created/updated/default_branch)——注意返回值里**没有 stargazers_count 字段**,要 stars 用 repo API 或接受缺失 +- `mcp_github_get_file_contents(owner, repo, path="README.md")` → 拿 README(base64 content 字段,需解码后读) +- `mcp_github_get_file_contents` 列目录:path 传目录名即可 + +**2026-08-02 实测降级顺序**:GitHub MCP 工具 → web_search(可能限流)→ web_extract(ddgs 后端只支持搜索,不支持提取,会报 "search-only backend")→ 浏览器(agent-browser 首次启动可能超时)→ terminal curl(可能被安全拦截 BLOCKED)。 +**经验**:不要一条路走到黑——`web_extract` 报 ddgs-only、browser 超时、execute_code/terminal 被 BLOCKED 时,**立即切 MCP 工具**,它没失败过。 + +## 源码/正文拉取(git clone 超时的正解,2026-08-02 实测) + +**场景**:要研究一个开源书的正文 / 代码文件,但 `git clone` 直连和 ghfast.top 等镜像都超时(本环境实测)。**`api.github.com` 可直连(~0.3s)**,用 contents API 逐文件拉: + +```bash +# 列目录 → 拿文件名和大小 +curl -s -H "User-Agent: Mozilla/5.0" "https://api.github.com/repos/{owner}/{repo}/contents/book" +# 逐文件拉取(返回 base64 content 字段,需解码) +for f in chapter1.md chapter2.md; do + curl -s -H "User-Agent: Mozilla/5.0" "https://api.github.com/repos/{owner}/{repo}/contents/book/$f" \ + | python3 -c "import json,sys,base64; d=json.load(sys.stdin); open('$f','w').write(base64.b64decode(d['content']).decode('utf-8','ignore'))" +done +# 验证:wc -c *.md | tail -1 +``` + +**实测**:ai-agent-book 12 个文件 1.1M 字符约 1 分钟拉完。README 也可走此 API(或 MCP)。**GitHub release 直链下载(releases/download/latest/xxx.pdf)本环境也超时**——要 PDF/二进制同样走 contents API 拿源码,或换代理。 + +## Go 工具安装(2026-08-02 实测) + +`go install` 直连 proxy.golang.org 超时(i/o timeout)。**先设 GOPROXY 再装**: + +```bash +export GOPROXY=https://goproxy.cn,direct && go install github.com/{owner}/{repo}/v10@latest +``` + +实测 croc v10.7.0 用此法装成功(goproxy.cn 国内可达)。 + ## 标准流程(3 步 + 收尾) ### ① 验证存在 + 元数据(API,免认证) @@ -68,7 +105,18 @@ content = base64.b64decode(d2['content']).decode('utf-8', 'ignore') 3. **给明确结论而非模糊建议**(例:"不替代,做第二网关"——新项目跑 :3001 专供 cron,现有 :3000 不动,核心生产链路付费模型绝不动 + 观察期 2-4 周) 4. **评估维度补充**:项目年龄(<6 个月太年轻)、open issues 数(数百 = 需谨慎)、最近提交时间(今天 = 活跃)。年轻但活跃 → 适合并行观察,不适合直接替换生产 -## 调研要点速查 +## 调研单个作者的仓库全景(2026-08-02 新增) + +用户说"研究 XX 作者/组织的项目"时(例:DIYgod),不是单项目调研,是**作者全景**: + +1. **用户信息 + profile README**:`api.github.com/users/{login}`(bio/company/blog/followers)→ profile README 常自报家门(DIYgod 写 "Founder of Folo, RSSHub, xLog and DPlayer"——**直接点名了四个项目,其中两个不在他名下**) +2. **仓库列表按 stars 排序**:`api.github.com/users/{login}/repos?per_page=100&sort=stars`——注意 100 条可能含 fork,按 `fork` 字段过滤 +3. **⚠️ 作者名下 ≠ 全部作品**:大项目常放组织(DIYgod 的 Folo→RSSNext、xLog→Crossbell-Box)。从 profile README 的 founder 声明里抓组织名,再用 `search/repositories?q={关键词}` 定位真实归属 +4. **文章/他人转述的归因要核实**:用户转发的文章说 "RSSHub + Reeder + DPlayer + Watermark + Social-Image 是 DIYgod 工具链"——实测 Watermark/Social-Image/Reeder **都不是他的**(在 DIYgod 名下搜不到,是泛指的独立开源工具)。**不核实归因,报告就会传播错误信息** +5. **区分活跃 vs 停更**:看 `pushed_at`(RSSHub 昨天推=活跃,GoodNight 2023 停更);README 里的 badge 有时比 description 信息量大(docker pulls / requests/month) +6. **给"对我们系统有什么用"的落地建议**,不只是罗列 star 数(DIYgod 案例 → RSSHub 可接入信息采集体系) + + - **同名项目很多时**:`api.github.com/search/repositories?q={query}&sort=stars&per_page=5` 按 stars 找主导者(OmniRoute 曾有多个同名小项目,主导者 36k stars) - **搜索会跑偏(2026-08-01 教训)**:搜 "grok-build" 按 stars 排序返回的是 `farion1231/cc-switch`(123k stars 的切换器,名字里含 grok-build 但根本不是 xAI 官方)——**搜索命中 ≠ 目标项目**。官方/大厂项目直接试 `api.github.com/repos/{org}/{repo}`,org 候选按记忆试(xai-org、x-ai、QwenAudio、HKUDS…),命中即真。搜索只能辅助定位,不能作为存在性证据 @@ -82,5 +130,7 @@ content = base64.b64decode(d2['content']).decode('utf-8', 'ignore') ## 已调研案例 +- `references/2026-08-02-research-diygod.md` — DIYgod 作者仓库全景(RSSHub/Folo/DPlayer/xLog star 表、组织归属、文章归因纠偏、RSSHub 落地建议) - `references/2026-08-01-research-cases.md` — Qwen Audio Agent(实时语音运行时)、OmniRoute(AI 网关)、system_prompts_leaks(大厂提示词库)完整调研记录 + 深度评估方法论 + 借鉴产出(5 个提示词改进点) - `references/2026-08-01-research-cases-batch2.md` — strix(AI 渗透)、grok-build(编码 Agent,含搜索跑偏案例 + 源码深读模式)、Vibe-Trading(量化交易) +- `references/2026-08-02-research-cases-batch3.md` — ai-agent-book(李博杰 Agent 书,ch3/ch8 对标织忆)、ui-skills(UI 质量技能集)、croc(安全文件传输)+ MCP 工具全流程方法论 diff --git a/skills/research/github-project-research/references/2026-08-02-research-cases-batch3.md b/skills/research/github-project-research/references/2026-08-02-research-cases-batch3.md new file mode 100644 index 00000000..9067502b --- /dev/null +++ b/skills/research/github-project-research/references/2026-08-02-research-cases-batch3.md @@ -0,0 +1,51 @@ +# 2026-08-02 调研案例(batch 3) + +牧尘一次性丢 3 个项目。全部用 GitHub MCP 工具查证(本环境实测最快路径)。 + +## 1. bojieli/ai-agent-book — 《深入理解 AI Agent》 + +| 项 | 值 | +|---|---| +| 作者 | 李博杰(前华为 AI 专家) | +| License | Apache-2.0 | +| 创建 | 2025-09-09(~11 个月,成熟持续更新,2026-08-02 仍有 push) | +| 形态 | 开源书:10 章正文 + 95 个配套实验 + PDF/EPUB 离线版 + 13 种语言 | +| 核心公式 | **Agent = LLM + 上下文 + 工具** | +| 章节亮点 | ch3 用户记忆和知识库(RAG/知识图谱)· ch4 工具/MCP · ch6 评估 · ch7 模型后训练 · ch8 持续进化 · ch10 多 Agent 协作 | +| 实验运行 | Python 3.10+,`uv sync --locked --extra ch1`(本机 uv 0.11.14 ✅) | +| 语言版本 | 中文原版在 `book/`,英文 `book-en/` 等社区翻译可能滞后 | + +**与织忆的契合**:ch3(记忆/知识库)直接对标织忆 MemoryWeave;ch8(持续进化)对标 learner/self-evolve。建议精读 ch3+ch8,可蒸馏成仓颉 skill。 + +## 2. ibelick/ui-skills — Design Engineers 技能集 + +| 项 | 值 | +|---|---| +| License | MIT | +| 创建 | 2026-01-07(~7 个月,活跃) | +| 定位 | Agent 的 UI 质量技能包:accessibility / motion / frontend craft / interface quality | +| 用法 | `npx ui-skills start` / `npx ui-skills list --category motion` / `npx ui-skills get baseline-ui` | +| 官网 | ui-skills.com(带 Agent 引导页) | +| 本地 | npx 已装(node v24)✅ | + +**契合**:与 creative 类技能(claude-design / popular-web-designs / p5js)互补——那些是"生成",这个是"打磨质量"。 + +## 3. schollz/croc — 安全文件传输 + +| 项 | 值 | +|---|---| +| License | MIT | +| 创建 | 2017-10-17(9 年,非常成熟,2026-08-01 仍有 push) | +| 定位 | 任意两台电脑安全传文件/文件夹,**唯一同时具备**:端到端加密(PAKE)+ 断点续传 + 跨平台 + 多文件 + 免端口转发 + IPv6-first + Tor 代理 | +| 用法 | 发:`croc send 文件` → 得到 code phrase;收:`croc 验证码` | +| 进阶 | `--store` 加密暂存 24h(CROC_STORE_TOKEN 防进程列表泄露)· `--qr` 手机收 · `--relay` 自建中继(默认 9009-9013)· `--socks5` 代理 | +| Linux 安全坑 | CVE-2023-43621:用 `CROC_SECRET=xxx croc` 而非明文参数(防 /proc 泄露);`croc --classic` 可永久开启单用户模式 | +| 本地 | 未装;Go 1.22.2 ✅(要求 1.22+,`go install github.com/schollz/croc/v10@latest`) | + +**契合**:与服务器(192.168.123.11)和云服务器传文件,比 rsync 更适合一次性安全传输(加密+断点续传);自建 relay 可内网直连。与现有 SMB/rsync 互补。 + +## 调研方法论沉淀 + +1. **MCP 工具全流程**:`mcp_github_search_repositories(query="repo:o/r")` 拿元数据 → `mcp_github_get_file_contents(path="README.md")` 拿 README → `terminal which/go version` 检查本地。三个项目 ~5 次调用完成。 +2. **search_repositories 的 stars 缺失**:返回 JSON 无 stargazers_count 字段,需要 stars 时用 repo API 或说明缺失——不要编造。 +3. **README 大小差异**:croc 13.5KB(全量读)、ai-agent-book 22.9KB(含超长附录,读关键段落)、ui-skills 466B(极简)。小 README 全读,大 README 分段。 diff --git a/skills/research/github-project-research/references/2026-08-02-research-diygod.md b/skills/research/github-project-research/references/2026-08-02-research-diygod.md new file mode 100644 index 00000000..e5a28b47 --- /dev/null +++ b/skills/research/github-project-research/references/2026-08-02-research-diygod.md @@ -0,0 +1,39 @@ +# DIYgod 开源项目全景调研(2026-08-02) + +调研触发:牧尘转来一篇文章("DIYgod 工具链:RSSHub+Reeder+DPlayer+Watermark+Social-Image"),要求研究 DIYgod 作者仓库。 + +## 作者档案 + +- login: DIYgod,新加坡 Web 开发者,15,911 followers,2014-07 加入 +- bio: "写代码是热爱,写到世界充满爱!" +- company: Natural Selection Labs +- profile README 自报:**Founder and Developer of Folo, RSSHub, xLog and DPlayer** + +## 核心项目(按 star 排序,2026-08-02 实测) + +| 项目 | Star | 归属 | 语言 | 状态 | 说明 | +|------|------|------|------|------|------| +| RSSHub | 45,525 | DIYgod | TS | 活跃(当日推) | 万物转 RSS,全球 5000+ 实例 | +| Folo | 38,749 | **RSSNext 组织** | TS | 活跃 | AI RSS Reader,跨平台 | +| DPlayer | 16,466 | DIYgod(现 MoePlayer org) | JS | 维护 | HTML5 弹幕视频播放器 | +| RSSHub-Radar | 7,286 | DIYgod | TS | 维护 | 浏览器扩展,一键发现 RSS | +| APlayer | 7,700 | DIYgod | JS | 维护 | HTML5 音乐播放器 | +| xLog | 2,672 | **Crossbell-Box 组织** | TS | 维护 | 链上(Crossbell 区块链)创作社区 | +| cloudflare-edge-tts | 199 | DIYgod | TS | 新(2026-04) | Cloudflare Worker TTS | +| GoodNight | 167 | DIYgod | JS | 停更(2023) | 自动给女朋友说晚安 | +| hexo-theme-sagiri | 488 | DIYgod | HTML | 停更 | Hexo 主题 | + +2RSS 系列前身(2016-2018):Weibo2RSS / bilibili2RSS / NetEaseCloudMusic2RSS / Juejin2RSS / Ziroom2RSS——**RSSHub 正是从这些单站转 RSS 工具合并长出来的**("一行代码起步"的实证)。 + +## 文章归因纠偏 + +文章称 "RSSHub + Reeder + DPlayer + Watermark + Social-Image 是 DIYgod 工具链": +- ✅ 真正 DIYgod:RSSHub、DPlayer/APlayer +- ❌ **Reeder / Watermark / Social-Image 不是他的项目**——在 DIYgod 名下搜不到(`search/repositories?q=user:DIYgod+watermark` 空结果),是泛指独立开源工具 +- 文章核心观点("别一开始做平台,从小工具开始,60K 星起点是一行代码")成立,但归因有误 + +## 对我们的落地价值 + +- RSSHub 可接入信息采集:`product-research` / `community-ops` 现在只监控博客 RSS,接 RSSHub 能覆盖 B站/小红书/微博等平台源 +- 路径验证:RSSHub 从"自己需要订阅微博"起步(Weibo2RSS → RSSHub)与织忆从"记不住东西"起步同构 +- 社区驱动:5000 实例靠社区贡献路由——开源项目杠杆在"让用户帮你建生态" diff --git a/skills/software-development/cbm-code-analysis/SKILL.md b/skills/software-development/cbm-code-analysis/SKILL.md index 31490316..a7b0bc7d 100644 --- a/skills/software-development/cbm-code-analysis/SKILL.md +++ b/skills/software-development/cbm-code-analysis/SKILL.md @@ -75,6 +75,8 @@ detect_changes(project="project-name") - `trace_path` 对跨包/跨语言的调用链可能返回 0 结果(索引深度不够,重试有时能解决) - `search_graph` 的 `total_results` 字段可能显示为 `?`,看 `results[]` 数组长度更可靠 - 项目名是路径自动生成的(如 `/tmp/memoryweave` → `tmp-memoryweave`),用 `list_projects` 确认 +- **MCP unreachable 先查进程数再怀疑坏了(2026-08-02)**:CBM 是 hermes gateway 的子进程(`ps -eo pid,ppid,etime,cmd | grep codebase-memory-mcp`,PPid 是 gateway 的 python 进程,不是 systemd)——gateway 可能短暂拉起第二个实例,两个进程抢同一个 `~/.cache/codebase-memory-mcp/home-muc-.hermes.db` sqlite 锁导致 MCP 瞬时 unreachable;新进程退出后单进程即恢复,**不需要任何修复**。诊断顺序:① ps 看进程数 ② 直接调一个 CBM 工具(如 `get_graph_schema`)重试 ③ 全挂再查 db 文件锁 +- **`home-muc-.hermes.db.corrupt` 是正常备份**:CBM 索引 db 目录里 `.corrupt` 后缀文件是旧备份机制(非故障),主库 `home-muc-.hermes.db` 一直在更新就是健康 ## 边界 - ❌ 不做:运行时诊断、日志分析、数据库查询 diff --git a/skills/soulful/soulful-framework/SKILL.md b/skills/soulful/soulful-framework/SKILL.md index 621ce66d..5db991fa 100644 --- a/skills/soulful/soulful-framework/SKILL.md +++ b/skills/soulful/soulful-framework/SKILL.md @@ -212,6 +212,28 @@ snippets = [f"{prefix}{behavior_rules[key]}" for key, prefix in snippet_prefixes 让模型"更聪明"的最快路径:不改模型,只改上下文注入方式。 把行为规范变成可直接执行的文本片段,模型无需自己从元数据推导。 +## 2026-08-02 牵挂 stale 生命周期 bug 修复 + +**症状**:cares-queue.json 里 3 条 `status=stale` 的牵挂长期残留,`_cleanup_expired_cares()` 只标记 stale 从不删除。 + +**根因**(daemon.py `_cleanup_expired_cares`): +- 原逻辑:`follow_up < today-7天` → 删除;否则保留 +- stale 的 3 条 follow_up=07-31,today=08-02 → `07-31 > 07-26` 不满足删除条件 → 永远残留 +- 且代码只对 `pending` 做"超14天标记 stale",**stale 状态本身没有任何删除规则** + +**修复**:stale 状态直接物理删除(stale 不再需要保留记录): +```python +# stale 状态 → 物理删除(stale 不再需要保留记录) +if c.get("status") == "stale": + continue +``` + +**教训**:标记 stale 只是"软删除"第一步,必须有配套的**物理清理规则**,否则 stale 堆积。生命周期必须是完整的:pending →(超14天)→ stale →(下轮清理)→ 删除。 + +**验证**:`python3 -c "import json; d=json.load(open('~/.hermes/soulful/cares-queue.json')); print(len(d.get('cares',[])))"` → 应输出 0(清理后)。 + +--- + ## 脏数据检查项 - `done` 状态残留(应删除) - 已过期 `follow_up_date` 的 pending 项(2026-07-10 已有3条) diff --git a/skills/whisper-stt/SKILL.md b/skills/whisper-stt/SKILL.md index 5b14d18c..e2c4f013 100644 --- a/skills/whisper-stt/SKILL.md +++ b/skills/whisper-stt/SKILL.md @@ -1,12 +1,12 @@ --- name: whisper-stt -description: "语音转文字 — 基于 faster-whisper,离线本地运行。base模型(~150MB),CPU推理,中文/英文识别。" -version: 1.0.0 +description: "语音转文字 — 基于 faster-whisper,离线本地运行。base模型(~150MB),CPU推理,中文/英文识别。含首次使用预检、HF镜像、模型缓存路径。" +version: 1.1.0 category: media -last_reviewed: 2026-07-09 +last_reviewed: 2026-08-03 tags: [stt, whisper, voice, speech-recognition] related_skills: - - hermes-tts: "文字转语音 — whisper的互补技能" + - tts-stt-tools: "TTS + 模力方舟 GLM-ASR 的封装(无需本地模型下载)" required_commands: - python3 readiness_status: available @@ -14,27 +14,46 @@ readiness_status: available # Whisper STT — 离线语音转文字 -## 使用条件 +当需要把用户语音/音频文件转成文字时使用(飞书语音消息、录音文件等)。本机已装 faster-whisper 1.2.1。 -当需要语音输入转文字时使用。本机已安装 faster-whisper 1.2.1,base 模型已缓存。 +## ⚠️ 首次使用必读(2026-08-03 教训) + +**用户视角:语音对话第一次特别费劲 = 模型没缓存 + HuggingFace 直连超时,等了 5 分钟才失败。** + +1. **先查模型缓存**(秒级判断,别直接跑转录): + ```bash + ls ~/.cache/huggingface/hub/ | grep -i whisper + # 看到 models--Systran--faster-whisper-base 才是已缓存 + ``` +2. **没缓存必须先设镜像**(HuggingFace 直连在本网络环境必超时 `ConnectTimeout: [Errno 110]`): + ```bash + export HF_ENDPOINT=https://hf-mirror.com # 已写入 ~/.hermes/.env,新 shell 也生效 + ``` +3. **首次下载 ~150MB 需要 1-3 分钟**:用 `background=true` + `notify_on_complete=true` 跑,别前台干等。 ## 环境 -- 模型: `faster_whisper` with `base` (150MB, CPU int8) -- 缓存路径: `/tmp/whisper-models/` -- HF 镜像: `HF_ENDPOINT=https://hf-mirror.com` -- 支持的音频格式: WAV (16kHz, mono, 16-bit) +- 模型: `faster_whisper` `base` (150MB, CPU int8) +- **真实缓存路径**: `~/.cache/huggingface/hub/models--Systran--faster-whisper-base`(❌ 不是 `/tmp/whisper-models/`,旧文档写错了) +- HF 镜像: `HF_ENDPOINT=https://hf-mirror.com`(已持久化到 `~/.hermes/.env`) +- 支持格式: **OGG/Opus 直接转(faster-whisper 用 PyAV 解码,无需 ffmpeg)**、WAV 16kHz mono +- 音频太长/格式怪异才需要 ffmpeg 转 WAV(本机未装 ffmpeg,用 PyAV 兜底) ## 使用方式 -### 转写音频文件 +### 转写音频文件(含预检,推荐直接跑这段) -```python +```bash +# 预检缓存 + 转写一步到位(缓存没命中会自动走镜像下载) +export HF_ENDPOINT=https://hf-mirror.com +python3 -c " from faster_whisper import WhisperModel -model = WhisperModel('base', device='cpu', compute_type='int8', - download_root='/tmp/whisper-models') -segments, info = model.transcribe('input.wav', language='zh') -text = ' '.join(seg.text for seg in segments) +model = WhisperModel('base', device='cpu', compute_type='int8') +segments, info = model.transcribe('INPUT.ogg', language='zh') +print(f'LANG: {info.language} prob={info.language_probability:.2f} dur={info.duration:.1f}s') +for seg in segments: + print(f'[{seg.start:.1f}-{seg.end:.1f}] {seg.text}') +" ``` ### 中文优化 @@ -49,14 +68,8 @@ segments, info = model.transcribe('input.wav', language='zh', ```bash # 先用 arecord 录一段 arecord -d 5 -f S16_LE -r 16000 -c 1 /tmp/recording.wav -# 再转写 -python3 -c " -from faster_whisper import WhisperModel -model = WhisperModel('base', device='cpu', compute_type='int8', download_root='/tmp/whisper-models') -segments, info = model.transcribe('/tmp/recording.wav', language='zh') -for seg in segments: - print(seg.text) -" +# 再转写(同上代码,路径换成 wav) +python3 -c "from faster_whisper import WhisperModel; ..." ``` ## 模型选项 @@ -69,13 +82,16 @@ for seg in segments: ## 注意事项 -- 首次使用会自动从 HuggingFace 下载模型(已设 HF_ENDPOINT 国内镜像加速) -- 模型缓存到 `/tmp/whisper-models/`,重启用没了需要重下 -- 建议用 `language='zh'` 指定中文以提升精度 +- ✅ **首次使用自动从 HuggingFace 下载模型**:直连会超时,必须 `HF_ENDPOINT=https://hf-mirror.com`(已写 `~/.hermes/.env`) +- ✅ **模型缓存** `~/.cache/huggingface/hub/`(持久,不随重启丢失) +- ✅ **OGG/Opus 直接转**,不需要 ffmpeg +- 建议 `language='zh'` 提升中文精度 - 背景噪声大的环境效果下降 +- 本机 hermes 内置 STT provider=local(base) 走同一套缓存;TTS 语音合成见 `tts-stt-tools` ## 文件 | 文件 | 说明 | |------|------| -| `/tmp/whisper-models/` | 模型缓存目录 | +| `~/.cache/huggingface/hub/models--Systran--faster-whisper-base` | 模型缓存(真实位置) | +| `~/.hermes/.env` | `HF_ENDPOINT=https://hf-mirror.com` 持久配置 | diff --git a/skills/zhiyi/zhiyi/SKILL.md b/skills/zhiyi/zhiyi/SKILL.md index 5c0cb7dc..305b5ab6 100644 --- a/skills/zhiyi/zhiyi/SKILL.md +++ b/skills/zhiyi/zhiyi/SKILL.md @@ -148,7 +148,7 @@ json.dump(d, open('cares-queue.json','w'), ensure_ascii=False, indent=2) > 🛑 **新会话必读**:本 skill 顶部「快速状态」表是**当前真实部署状态**(2026-06-25 全链路验证通过)。任何关于织忆的判断,先看此表 + 跑下方「系统全面检查步骤」(10 秒内拿真实状态)。**绝对不要从 AGENTS.md / MEMORY.md 里过去 1 个月以上的描述直接判断织忆状态**。 -**最后一次实地拉状态:2026-07-20(记忆系统统一合并后)** +**最后一次实地拉状态:2026-08-02(四系统体检 + episodes 持久化修复后)** | 项目 | 状态 | 路径/值 | |------|------|---------| @@ -157,7 +157,7 @@ json.dump(d, open('cares-queue.json','w'), ensure_ascii=False, indent=2) | bge-embed | ✅ active | 端口 8000 | | 织忆 API | ✅ health=ok | `http://localhost:7821` | | 后端 | ✅ lancedb (Rust IPC) | `STORAGE_BACKEND=lancedb` 环境变量 | -| 数据规模 | **4285 memories / 243 episodes** | LanceDB | +| 数据规模 | **5063 memories / episodes 已持久化**(2026-08-02 修复后重启不丢) | LanceDB | | Graph 图谱 | **8397 节点 / 53081 边** | `~/.hermes/graph.db`(pattern 节点=20,新增 daemon-distill namespace) | | Phase A (Go骨架+认证) | ✅ 完成 | `go/cmd/zhiyid/` | | Phase B (Rust sidecar+LanceDB) | ✅ 完成 | `rust/src/` | @@ -209,6 +209,39 @@ API key: `zhiyi-dev-key-2026` **下次任何 cron/任务引用"实施计划第 X 章"前,`search_files` 路径先验证再用结论,禁止沿用过期的版本文件名。** +## ⚠️ 记忆系统全景:不是一套,是四套(2026-08-02 牧尘纠正) + +> **牧尘原话**:"记忆系统可不止织忆,还有其他系统"、"你还少了cbm"。评估/汇报"记忆系统"时必须**四套一起看**,缺一不可: + +| 系统 | 职责 | 端口/位置 | 数据量(2026-08-02 实测) | 健康判定 | +|------|------|----------|------------------------|---------| +| **织忆 ZhiYi** | 语义记忆(项目/技术/对话) | :7821 | 5054 memories / 9075 图谱节点 | commit→distill→recall 链路通 | +| **Soulful** | 关系记忆(心迹/牵挂/画像) | daemon, ~/.hermes/soulful/ | 心迹13 / 牵挂 / 画像完整 | 牵挂 stale 自动清理 | +| **TencentDB TDAI** | 人格蒸馏(L0对话→L1 persona) | :8420 | L0 85K / L1 22 | Gateway 活 + L1 提取在跑 | +| **CBM** | 代码知识图谱 | MCP + ~/.cache/codebase-memory-mcp/ | 5 项目(.hermes 389M) | MCP 可达 + 索引完整 | + +**四套独立进程,默认互不影响**——诊断"记忆系统"问题先确认是哪一套,再独立排查(同织忆 4 组件铁律:不假设"a 挂了是 b 升级造成的")。 + +**TencentDB 特殊性**:L0 是 raw 日志(什么都收,85K 里大部分是 zhiyi-sync 心迹自动同步 52K + soulful-profile-sync 17K + l3-distill 15K),L1 按 everyN=5 或 idle 600s 触发、每次只处理 10 条新消息 → **L0/L1 比例 3876:1 是设计如此**,不是故障。判断"蒸馏是否工作"看日志 `L1-search DONE` 出现,不是看 L1 条数暴涨。 + +## ⚠️ 端到端链路验证法(2026-08-02 核心教训) + +> 牧尘反问"织忆很成熟么?"之后深挖发现:**组件都在跑 ≠ 链路在工作**。当时 zhiyid/sidecar/bge-embed 全 active,但 commit 写入的内容 20 分钟 recall 查不到——因为 distill 管道一直走 fallback(LLM 配置缺失),产出低质记忆根本排不上检索。 + +**判断记忆系统"健康/成熟"必须验证端到端链路,不是只看进程/端口**: + +``` +1. 写:POST /api/v1/commit → 返回 episode_id(201)≠ 已入库可用 +2. 等:distill 是异步队列,batch<10 或 <5min 不 flush;等 5-10s 或查日志 flush START +3. 验:日志出现 "endpoint=... model=..."(真 LLM)而非 "LLMEndpoint empty, fallback" +4. 查:recall 同主题能命中新写入内容 +5. 量:total_memories 增长(memories 持久化);total_episodes 重启会归零(Rust sidecar 内存,非权威) +``` + +**警惕 fallback 假象**:日志里 `LLMEndpoint empty, fallback` + `facts=1 entities=0` 就是"写入成功了但蒸馏质量=关键词提取",recall 永远排不上。真 LLM 蒸馏特征:`LLM entities: N` + `score=0.8x` + `decisions/conclusions` 结构化字段。 + +**systemd 路径漂移陷阱(2026-08-02 TencentDB 实测)**:`tdai-gateway.service` 的 ExecStart 被写坏成 `/src/gateway/server.ts`(不存在),systemd 崩溃循环 2534 次,但**手动进程撑在 8420 端口让服务"看起来活着"**。修复:ExecStart 改回 `--require .../tsx/dist/preflight.cjs --import .../loader.mjs src/gateway/server.ts`,杀手动进程,systemd 接管。教训:**端口在听 ≠ systemd 服务正常**——查 `systemctl --user show <svc> -p NRestarts` 看重启计数。 + ## 系统全面检查步骤 当牧尘说"全面检查织忆系统"时,按以下步骤执行。核心原则:从外到内,从进程到API。**先拉现状再判因** — 子系统互相独立时不要假设"是 X 升级造成的"。完整触发清单见 `references/diagnostic-trigger.md`。 @@ -361,8 +394,8 @@ echo "=== consolidate ===" && grep 'consolidation.*完成' /tmp/zhiyi-sidecar.lo | `memory.provider: zhiyi` 不生效 | 插件代码不存在于 `plugins/memory/` 目录 | 复制源码并补装依赖 | | **commit 报 `agent_id and content required`** | API 必传字段,硬性拒绝 | body 加 `"agent_id": "a06"`(或任意非空字符串)| | **commit 返回判断写成 `resp.get("id")` 恒为 False**(2026-08-02 踩坑) | commit 成功返回 `{"episode_id": "ep_...", "status": "ok", "memory_id": ""}`,**没有 `id` 字段** | 判断成功应检查 `resp.get("episode_id")` 或 `resp.get("status") == "ok"`;且 distill 是**异步队列**,写入后立即 recall 可能查不到,等 5-10s 或用 stats 验证 total_episodes/total_memories 增长 | -| **蒸馏一直 fallback、记忆质量低(facts=1 entities=0)**(2026-08-02 修复) | 实际运行的 `~/.config/systemd/user/zhiyid.service` **缺少 `LLM_ENDPOINT` / `LLM_MODEL` / `LLM_API_KEY` 环境变量** → 日志 `LLMEndpoint empty, fallback` → 每次蒸馏走关键词提取,产出低质记忆 | systemd unit 补上:`Environment=LLM_ENDPOINT=http://127.0.0.1:3000/v1/chat/completions` + `Environment=LLM_MODEL=openai/gpt-oss-120b` + `Environment=LLM_API_KEY=<NewAPI key>`;`systemctl --user daemon-reload && restart zhiyid`;验证日志出现 `endpoint=... model=...` + `LLM entities: N`(真 LLM)而非 fallback | -| **重启后 total_episodes 归零**(2026-08-02 发现) | episodes 存在 Rust sidecar **内存**中(lancedb_ipc.go `_local.episodes`),zhiyid 重启即清零;memories 持久化不受影响 | 已知弱点,memories 才是权威数据源;如需 episodes 持久化需改 Rust sidecar 落盘 | +| **蒸馏一直 fallback、记忆质量低(facts=1 entities=0)**(2026-08-02 修复,两次根因) | ① 实际运行的 `~/.config/systemd/user/zhiyid.service` **缺少 `LLM_ENDPOINT` / `LLM_MODEL` / `LLM_API_KEY` 环境变量** → 日志 `LLMEndpoint empty, fallback` → 关键词提取;② **模型选错**:`openai/gpt-oss-120b` 是 reasoning 模型(`content=null`,答案在 reasoning 字段),即使配了 LLM 也永远 `LLM JSON parse error` → `facts=1 entities=0` | systemd unit 补上三个 `Environment=` 且 **LLM_MODEL 用 `google/gemma-4-31b-it`**(2026-08-02 实测唯一蒸馏可用,勿用 gpt-oss 系);`systemctl --user daemon-reload && restart zhiyid`;验证日志出现 `endpoint=... model=...` + `LLM entities: N`(真 LLM)而非 fallback/parse error。若再遇模型挂,看门狗 `distill-model-watchdog.py` 会自动切换,或手动 `curl` 验证候选池(见模型白名单节) | +| **重启后 total_episodes 归零**(2026-08-02 发现 → **已修复 2026-08-02**) | episodes 存在 Go 进程**内存**中(lancedb_ipc.go `_local.episodes`),zhiyid 重启即清零;memories 持久化不受影响。修复后:`InsertEpisode` 增加 IPC 写入 LanceDB episodes 表 + `Stats()` 改从 Rust 读真实计数 | ✅ 已修复(commit `21bc777`):验证=提交测试 episode → stats episodes=1 → `systemctl --user restart zhiyid` → 仍=1。详见 `references/zhiyi-episodes-persistence-20260802.md`。注意:`lancedb_insert` 的 Rust IPC 已支持任意表(table="episodes"),Go 侧缺的只是调用它 | | `/search/memories` 输出逐字 `[F][o][u][n][d]` | `results` 是 markdown 字符串,代码按 `\n` 拆分逐字遍历 | `isinstance(results, str)` 判断后整段输出或解析 markdown 格式 | | 牵挂 due 字段为空 | 字段名是 `follow_up_date` 不是 `due` | `item.get("follow_up_date") or item.get("due") or "null"` | | **bge-embed systemd restart counter 刷到几千次** | `/tmp/memoryweave/deploy/` 脚本丢失 | 从 Gitea 重建:`git clone http://192.168.123.11:3000/xiaoxue_admin/memoryweave.git /tmp/memoryweave` 然后 `systemctl --user restart bge-embed` | @@ -818,7 +851,61 @@ python3 -c "from plugins.memory.zhiyi import HermesZhiYiMemoryProvider; \ --- -> ⚠️ **NewAPI 可用模型白名单(2026-07-13 逐一测试)**:绝大多数模型返回 400 或空响应。**唯一确认可用的 LLM 是 `minimaxai/minimax-m3`**,它能结构化 JSON 输出,是 TencentDB L1 提取的唯一选择。`minimax-m2.7` 可对话但 choices 有时为空。`yi-large` / `deepseek-v3.1-terminus` / `glm4.7` / `qwen2.5-coder-32b` 全部返回 400。**任何新模型上线前必须先手动 curl 验证**。 +**蒸馏模型看门狗(2026-08-02 上线,解决"免费模型挂了没人换")**: +- **30min 轻量探针**:`~/.hermes/scripts/distill-model-watchdog.py`(cron `89de35dc35a7`)——只测当前蒸馏模型的 JSON 输出能力(剥离 code fence 后可解析才算通过),挂了立即按候选池切换 + 更新 zhiyid.service + tdai-gateway.yaml + 重启 + 飞书报警 +- **6h 深度巡检**:model-health.py 新增 `_heal_distill_models()`——同步守护蒸馏配置,识别 reasoning 模型(content=null)不适合蒸馏 +- **候选池(2026-08-02 实测 JSON 可用,优先级降序)**:`google/gemma-4-31b-it` > `mistralai/mistral-nemotron` > `nvidia/llama-3.3-nemotron-super-49b-v1.5` > `meta/llama-3.1-8b-instruct` > `nvidia/nemotron-mini-4b-instruct` +- **蒸馏模型关键判定**:能对话 ≠ 能蒸馏。蒸馏必须 JSON 输出(content 非空且可解析),reasoning 模型(gpt-oss 系 content=null)直接排除 +- **手动验证**:`python3 ~/.hermes/scripts/distill-model-watchdog.py`(健康静默,异常自动切换) + +## ⚠️ 机制建设铁律(2026-08-02 牧尘两次纠正 + 一次追问) + +### 1. 建任何监控/自动化机制前,先摸清现状,别重复造轮子 +牧尘原话:"**先摸清现状,看看与之相关的定时任务等,别重复工作**"。本次差点重复建了 tdai-gateway 看门狗——**memory-system-check.sh(每小时)早就覆盖 4 系统全检 + health-watchdog.sh(30min)早就做进程自愈**。已有机制清单: +- `memory-system-check.sh`(每小时 cron)— 统一层+织忆+Soulful+TencentDB+CBM 全查 +- `health-watchdog.sh`(30min)— 进程自愈+磁盘/内存/CPU/GPU+config-protector 联动+防自杀 +- `memory-system-self-upgrade.py`(每日4点)— 牵挂清理+画像+心迹去重+报告 +- `config-protector.sh` / `anti-suicide-check.sh` / `dual-backup.sh` / `startup.sh` + +动作:先 `cronjob list` + `ls ~/.hermes/scripts/` 盘点 → 已有则只补缺口(改检查对象/加检查深度),没有才新建。新建后如与已有 cron 重复,删掉自己的,把逻辑并入已有脚本。 + +### 2. 自愈/自动化机制必须实测"失败路径",不只编译通过 +牧尘问"**都测试过了吧?**"——暴露我只 py_compile 了 `_heal_distill_models`,没跑真实路径。实测后**立刻抓到一个真 bug**:gemma 不在 ALL_MODELS 测试列表 → found=None → 被判"需替换" → 每 6h 会把健康模型换掉。 +铁律:任何会主动改系统的机制,交付前必须: +- 手动 `cronjob run <id>` 触发一次(确认 last_status=ok / execution_success=true) +- **模拟失败场景**(把配置改成已知坏模型)→ 跑机制 → 确认"切换+配置更新+服务重启+通知"全链路 +- 判断逻辑做 dry-run 单测(当前好模型应判健康、坏模型应判需替换、原文件未动) +- 陷阱:**模型不在测试列表 ≠ 模型挂了**。探针主判(content 非空+JSON 可解析),巡检结果仅作辅助覆盖(明确 dead 才覆盖探针)。 + +### 3. systemd is-active 会被 auto-restart 循环骗过 +tencentdb.service 与 tdai-gateway.service 同源(同一个 server.ts),端口被占后**崩溃循环 278 次**,`systemctl --user is-active` 在重启间隙返回 active → memory-system-check 一直以为它健康。真相靠 `systemctl --user status <svc>` 看 `Active: activating (auto-restart)` + `restart counter is at N`。 +教训:查服务健康用 `systemctl --user show <svc> -p NRestarts` 或 status 看 restart counter,别只信 is-active;发现两个服务同源时先确认哪个真在听端口(`ss -tlnp`),停用另一个(`systemctl --user disable --now`)。 + +### 4. 免费模型池会整体过期(skill 记录会 stale) +2026-07-27 模型池大换血:m2.7/step-flash/qwen3.5 全部 EOL,m3 空响应,gpt-oss 是 reasoning 模型(content=null)。**skill 里的模型白名单记录会过期,任何"可用模型"判断都必须实测**(新模型先 curl 验证 JSON 输出,见下方蒸馏模型看门狗节的验证命令)。 + +> ⚠️ **NewAPI 可用模型白名单(2026-08-02 实测更新,旧记录 7-27 已全部失效)**: +> **模型池 2026-07-27 大换血,以下旧记录全部 EOL/失效**: +> - ~~`minimaxai/minimax-m3`~~ / ~~`minimax-m2.7`~~ → **m2.7 EOL 2026-07-27**,m3 用户反馈不可用 +> - ~~`mistral-large-3-675b`~~ → 无渠道;~~`mistral-large-3-675b-instruct-2512`~~ → EOL +> - ~~`step-3.5-flash`~~ → EOL 2026-07-27;~~`qwen3.5-122b`~~ → EOL 2026-07-20 +> - ~~`gpt-oss-120b/20b`~~ → reasoning 模型,content=null(答案在 reasoning 字段),**不能用于 distill**(除非代码支持 reasoning 字段——engine.go 2026-08-02 已加) +> +> **✅ 蒸馏唯一可用模型(2026-08-02 实测):`google/gemma-4-31b-it`** +> - content 直接是纯 JSON(带 ```json code fence,engine.go 已支持剥离) +> - 5D 评分正确:`{"is": 8, "su": 9, ...}` 0-10 整数 → prompt 已改为明确要求 0-1 浮点 +> - 实测 distill 全链路通过:entities=2, overall=1.000, recall 命中 0.765 +> - **任何新模型上线前必须先手动 curl 验证 JSON 输出能力**(见下方测试命令) +> +> **蒸馏模型验证命令**: +> ```bash +> KEY=$(grep -oP 'LLM_API_KEY=\K.*' ~/.config/systemd/user/zhiyid.service) +> curl -s -m 30 http://127.0.0.1:3000/v1/chat/completions -H "Content-Type: application/json" \ +> -H "Authorization: Bearer $KEY" -d '{"model":"<候选模型>","messages":[{"role":"user","content":"输出严格JSON {\"entities\":[]}"}],"max_tokens":150}' +> # 期望: choices[0].message.content 是纯 JSON(或可剥离的 code fence),且非空 +> # 失败特征: content=null(reasoning 模型)/ 400 EOL / No available channel / system_cpu_overloaded +> ``` +> **完整模型池列表**:`curl -s http://127.0.0.1:3000/v1/models -H "Authorization: Bearer $KEY"`(136 个,2026-08-02) > > 更新:2026-07-12:**TencentDB Agent Memory 安装研究 + 三层记忆架构梳理** > - TencentDB(8603 stars,4层渐进管道)补的是 Soulful 的「自动人格蒸馏」那块,不是织忆的语义检索 @@ -850,17 +937,17 @@ TencentDB(补) 自动从对话蒸馏 → Persona(人格文件) 效果:我说"牧尘不喜欢废话"不需要每次解释 ``` -**TencentDB Agent Memory 集成状态(2026-07-13 — L0/L1 全通)**: +**TencentDB Agent Memory 集成状态(2026-08-02 更新 — L0/L1 全通,模型已切 gemma)**: - npm 安装:✅(npmmirror 镜像,16s) -- Gateway 进程:✅(:8420,独立 Node.js) +- Gateway 进程:✅(:8420,独立 Node.js,systemd `tdai-gateway.service`) - embedding:✅(走 bge-m3 8000 端口,`sendDimensions: false`) -- LLM:✅(**`minimaxai/minimax-m3`** via NewAPI 3000,唯一可用模型) -- **L1 提取:✅(minimax-m3 结构化输出正常,已验证 persona/instruction 两种记忆)** +- LLM:✅(**`google/gemma-4-31b-it`** via NewAPI 3000,2026-08-02 从 minimax-m3 切换——m3 实测连续空响应/非 JSON,不可用) +- **L1 提取:✅(gemma-4-31b-it 结构化输出正常,extracted=1 stored=1,已验证 persona/instruction 两种记忆)** - BM25 搜索:✅(能搜到对话,`/search/conversations`) - **注意**:TencentDB `/search/memories` 和 `/search/conversations` 均可用(返回 markdown 字符串,需 `isinstance(results, str)` 判断);只有 `/scenes` 返回 404,详见 `references/tencentdb-api-endpoints-20260720.md` - recall API:✅(495 chars 上下文注入) - systemd 服务:✅(开机自启,`~/.config/systemd/user/tdai-gateway.service`) -- config 文件:`~/.memory-tencentdb/memory-tdai/tdai-gateway.yaml` +- config 文件:`~/.memory-tencentdb/memory-tdai/tdai-gateway.yaml`(llm.model 字段;备份 `.bak-watchdog` / `.bak-health`) **关键修复记录(2026-07-13,逐一踩坑,最终全部通过)**: 1. ❌→✅ `apiKey: not-needed` → **必须填真实 NewAPI token**(`0ExNiLblJvIWBDpkS50fwOBw4MmqLyKdHJK5iQtlw9dOMWBP`)否则 `Invalid token` @@ -1346,12 +1433,15 @@ python3 ~/.hermes/scripts/wiki_curator.py --dir ~/mc/小唯/ --llm --dry-run - **⭐ 竞品架构对比(2026-07-01)**:`references/memory-os-7-layer-comparison.md` — Memory-OS 7 层记忆架构 vs 织忆完整对照。含信任评分、4 级降级、自动注入钩子、CREATIVE.md 隔离、强制注入 prompt 共 5 个可直接借鉴的设计点。 - **⭐ 记忆系统对比分析(2026-07-13)**:`references/memory-system-comparison.md` — 克隆分析 yantrikdb/memos/honcho/agent-memory-skill 等 9 个参考项目,输出 P0-P2 优先级建议(Ebbinghaus遗忘/冲突检测/多信号评分/think Consolidation/主动触发器)用于织忆迭代时对标参考。 - **⭐ 织忆提升:轨迹学习门禁+程序记忆分类(2026-08-02)**:`references/zhiyi-enhancement-trajectory-learning-20260802.md` — 从《深入理解 AI Agent》蒸馏方法论落地的 learner.py 门禁 + daemon.py 分类改动,含 commit API 返回字段陷阱(episode_id 非 id)和异步 distill 延迟验证法。 +- **⭐ episodes 持久化修复 + 四系统体检(2026-08-02)**:`references/zhiyi-episodes-persistence-20260802.md` — episodes 重启清零的根因(Go 内存 + Stats 覆盖)与修复(IPC 写 LanceDB episodes 表),含 Rust IPC 手动调试协议(4字节大端长度前缀)、L1 蒸馏率误读教训(真数据在 records/*.jsonl 不在 DB 表)、端口在听≠systemd 正常、tdai-gateway 看门狗。 +- **⭐ 模型池轮换 + 蒸馏双层守护(2026-08-02)**:`references/model-pool-rotation-20260802.md` — 2026-07-27 模型池大换血 EOL 对照表、蒸馏 vs 对话判定标准、30min 看门狗 + 6h 巡检双层架构、候选池、验证命令、失败特征速查。 - **⭐ 自启动架构(2026-07-02)**:`references/systemd-auto-start.md` — 4 组件启动串行、binary 持久化位置、service 文件配置、ExecStartPre 自愈、重启后验证方法 - **⭐ /tmp/memoryweave 丢失恢复指南(2026-06-25)**:`references/tmp-memoryweave-recovery.md` - **⭐ 织忆代码健康度审计 2026-06-20**:`references/code-health-audit-20260620.md` — Go daemon 6 个问题 + Python 插件 4 个 bug,修复详情、编译部署、Gitea push - **⭐ Gitea push 完整流程**:`references/zhiyi-gitea-push.md`(含标准开发 + 多源同步 + 批量全量 三种模式,token 查找路径、编译错误修复、常见坑) +- **⭐ GitHub → Gitea 镜像踩坑(2026-08-02)**:`references/gitea-mirroring-20260802.md`(浅克隆 `--depth 1` 不能推(shallow update not allowed)/ github.com 被限时 codeload 快照方案 / Gitea API 建仓库 description 特殊字符破坏 JSON / 批量镜像 15 仓库流程) - 设计文档:`~/mc/小唯/07-Wiki/concepts/织忆(MemoryWeave)-v3.8-完整定稿.md`(v2.6/v3.8-实施计划等历史文件已删除) - 实施进度:`~/mc/小唯/记忆/织忆/进度-*.md` - **⭐ systemd 部署流程**:`references/systemd-zhiyi-binary-update.md` diff --git a/skills/zhiyi/zhiyi/references/gitea-mirroring-20260802.md b/skills/zhiyi/zhiyi/references/gitea-mirroring-20260802.md new file mode 100644 index 00000000..eb181649 --- /dev/null +++ b/skills/zhiyi/zhiyi/references/gitea-mirroring-20260802.md @@ -0,0 +1,65 @@ +# GitHub → Gitea 镜像踩坑(2026-08-02 实测) + +镜像 DIYgod 等 GitHub 仓库到自建 Gitea(192.168.123.11:3000)时实测的三个坑。 +Gitea 基础 push 流程见 `zhiyi-gitea-push.md`;本文件只记镜像特有坑。 + +## 坑 1:浅克隆不能推(shallow update not allowed) + +```bash +git clone --depth 1 https://github.com/owner/repo.git # ❌ 快但推不了 +git push -f gitea HEAD:master +# ! [remote rejected] HEAD -> master (shallow update not allowed) +``` + +- `git fetch --unshallow` **不一定修好**——只拉默认分支时 `.git/shallow` 残留标记; + 删掉 `.git/shallow` 再推可能触发 `remote end hung up`(历史仍不完整) +- 干净解法:**全量 clone**(保留完整历史)或**快照方案**(见坑 2,镜像存档无需历史) + +## 坑 2:github.com git 协议被限时,codeload 常可用 + +GitHub 主站 `github.com` 的 git 协议可能超时/连不上,但 **`codeload.github.com`(HTTP 下载)经常通**: + +```bash +# 诊断:主站挂起但 codeload 200 → 用快照方案 +curl -sI https://github.com # 可能超时 +curl -sI https://codeload.github.com/owner/repo/tar.gz/refs/heads/main # 200 + +# 快照方案:下载 tar.gz → 解压 → 推 Gitea(适合镜像,无历史) +curl -sL -o /tmp/repo.tar.gz "https://codeload.github.com/owner/repo/tar.gz/refs/heads/main" +tar xzf /tmp/repo.tar.gz -C ~/projects/ +cd ~/projects/repo-main && git init && git add . && git commit -m "snapshot" +git remote add gitea "http://USERNAME:TOKEN@host:3000/owner/repo.git" +git push -f gitea HEAD:master +``` + +## 坑 3:Gitea API 建仓库,description 别放特殊字符 + +```bash +# ❌ README 首行有 emoji/引号会破坏 JSON → "expected comma after object element" +curl -X POST http://host:3000/api/v1/user/repos \ + -H "Authorization: token $TOKEN" -H "Content-Type: application/json" \ + -d "{\"name\":\"$name\",\"description\":\"$(head -1 README.md)\"}" +# ✅ description 用固定值 +curl -X POST http://host:3000/api/v1/user/repos \ + -H "Authorization: token $TOKEN" -H "Content-Type: application/json" \ + -d "{\"name\":\"$name\",\"description\":\"mirror\",\"private\":false}" +``` + +- 认证:`Authorization: token $TOKEN` 建仓库;git push 用 `http://用户名:token@host/...` + (token 当密码,不能只有 token 当用户名——会提示输密码) +- Gitea token 位置:`~/mc/牧尘/claw/key.md` → `gitea令牌:<40位hex>` + +## Gitea API 端点速查 + +- 建仓库:`POST /api/v1/user/repos`(body: name/description/private) +- 搜索/验证:`GET /api/v1/repos/search?limit=N`(返回 data[] 的 name) +- 服务端迁移(Gitea 自己从 GitHub 拉,绕开本地网络):`POST /api/v1/repos/migrate` + (body: clone_addr/repo_name/repo_owner/service)——⚠️ 有些版本返回非 JSON,先小仓库试 + +## 批量镜像流程(15 仓库实测) + +1. `GET /users/DIYgod/repos?per_page=100&sort=stars` 拉全量 → 按 star/活跃度分类 +2. 分类:Tier1 核心(下载+测试)/ Tier2 生态(存档)/ Tier3 趣味(可选) +3. 批量 `curl codeload` 下载 tar.gz → 解压 → `git init + commit` +4. 批量 `POST /api/v1/user/repos` 建空仓库(description 固定值) +5. 逐个 `git push -f gitea HEAD:master` diff --git a/skills/zhiyi/zhiyi/references/model-pool-rotation-20260802.md b/skills/zhiyi/zhiyi/references/model-pool-rotation-20260802.md new file mode 100644 index 00000000..126689d9 --- /dev/null +++ b/skills/zhiyi/zhiyi/references/model-pool-rotation-20260802.md @@ -0,0 +1,83 @@ +# 模型池轮换 + 蒸馏模型双层守护(2026-08-02) + +## 背景:免费模型经常挂,且模型池会整体 EOL + +2026-07-27 NewAPI 模型池大换血,旧 skill 记录全部失效: + +| 旧记录(2026-07-13 skill 白名单) | 2026-08-02 实测状态 | +|----------------------------------|--------------------| +| `minimaxai/minimax-m3`("唯一可用") | 连续 3 次空响应 / 超时,用户早已发现不可用 | +| `minimaxai/minimax-m2.7` | **EOL 2026-07-27** | +| `stepfun-ai/step-3.5-flash` | **EOL 2026-07-27** | +| `qwen/qwen3.5-122b-a10b` | **EOL 2026-07-20** | +| `mistral-large-3-675b` / `-instruct-2512` | 无渠道 / EOL | +| `openai/gpt-oss-120b` / `gpt-oss-20b` | reasoning 模型,`content=null`(答案在 `reasoning` 字段),**不能用于 distill** | +| `nvidia/nemotron-3-super-120b-a12b` | reasoning 回显,content 是思考过程 | +| `mistralai/mistral-medium-3.5-128b` | 非 JSON 输出 | +| `moonshotai/kimi-k2-instruct` / `mistral-small-4-119b-2603` / `qwen3-next-80b` | EOL | +| **`google/gemma-4-31b-it`** | ✅ **蒸馏唯一可用**:content 纯 JSON + 5D 评分 | + +## 蒸馏 vs 对话:判定标准不同 + +**能对话 ≠ 能蒸馏**。model-health.py 的 `_verify_model_usable` 只测"有内容返回",但蒸馏需要: +1. `choices[0].message.content` 非空(reasoning 模型 content=null 直接排除) +2. 剥离 ```json code fence 后可 `json.loads` 成功 +3. 能输出 5D 评分字段(is/su/pa/vd/ru 0-1 浮点) + +## 双层守护架构 + +### 第一层:30min 轻量看门狗 `distill-model-watchdog.py`(cron `89de35dc35a7`) +- 只测当前蒸馏模型的 JSON 输出能力(content 非空 + code fence 剥离后可解析) +- 挂了 → 按候选池优先级逐个测 → 第一个可用顶上 +- 自动更新两处配置 + 重启 + 飞书报警: + - `~/.config/systemd/user/zhiyid.service` 的 `LLM_MODEL=` + - `~/.memory-tencentdb/memory-tdai/tdai-gateway.yaml` 的 `model:` +- 全部候选失败 → 飞书报警人工介入 +- 健康时静默(no-agent cron 空输出 = 不发送) + +### 第二层:6h 深度巡检 `model-health.py` 新增 `_heal_distill_models()` +- 与第一层相同的候选池,补充 reasoning 模型识别 +- **关键陷阱(测试中抓到的真 bug)**:当前模型不在 ALL_MODELS 测试列表时(如 gemma 是后加的),`found=None` 会被误判"需替换"→ 每 6h 把健康模型换掉。 + - 修复:判断改为 **JSON 探针为主**(content 非空+可解析 → 健康),巡检结果仅作辅助覆盖(明确 dead 才覆盖探针)。 + - 教训:**模型不在测试列表 ≠ 模型挂了**。 + +### 候选池(2026-08-02 实测 JSON 可用,优先级降序) +``` +google/gemma-4-31b-it(主用)> mistralai/mistral-nemotron +> nvidia/llama-3.3-nemotron-super-49b-v1.5 +> meta/llama-3.1-8b-instruct > nvidia/nemotron-mini-4b-instruct +``` + +## 验证命令 + +```bash +# 单模型 JSON 能力测试(新模型上线前必跑) +KEY=$(grep -oP 'LLM_API_KEY=\K.*' ~/.config/systemd/user/zhiyid.service) +curl -s -m 30 http://127.0.0.1:3000/v1/chat/completions -H "Content-Type: application/json" \ + -H "Authorization: Bearer $KEY" \ + -d '{"model":"<候选>","messages":[{"role":"system","content":"输出严格JSON"},{"role":"user","content":"提取实体:牧尘喜欢简洁。输出 {\"entities\":[],\"decisions\":[],\"conclusions\":[]} 格式"}],"max_tokens":150}' + +# 完整模型池 +curl -s http://127.0.0.1:3000/v1/models -H "Authorization: Bearer $KEY" + +# 看门狗手动跑(健康静默,异常自动切换+飞书) +python3 ~/.hermes/scripts/distill-model-watchdog.py + +# 看门狗 cron 手动触发 +hermes cron run 89de35dc35a7 # 或 cronjob action=run + +# 验证当前蒸馏模型确实生效 +grep LLM_MODEL ~/.config/systemd/user/zhiyid.service +grep "^ model:" ~/.memory-tencentdb/memory-tdai/tdai-gateway.yaml +journalctl --user -u zhiyid --no-pager -n 20 | grep "\[distill\]" | tail # 期望 model=google/gemma-4-31b-it + LLM entities: N +``` + +## 失败特征速查 +| 现象 | 含义 | 处理 | +|------|------|------| +| `content=null` | reasoning 模型(gpt-oss 系) | 排除,换 gemma 系 | +| `content` 带 ```json 包裹 | 正常但需 code fence 剥离 | engine.go 已支持(2026-08-02) | +| `The model ... reached its end of life` | EOL | 从候选池换 | +| `No available channel` | 渠道失效 | 从候选池换 | +| `system_cpu_overloaded` | NewAPI 过载 | 等几秒重试 | +| `LLMEndpoint empty, fallback` + `facts=1 entities=0` | distill 走关键词降级 | 查 zhiyid.service 的 LLM 三件套 env | diff --git a/skills/zhiyi/zhiyi/references/zhiyi-enhancement-trajectory-learning-20260802.md b/skills/zhiyi/zhiyi/references/zhiyi-enhancement-trajectory-learning-20260802.md new file mode 100644 index 00000000..b804ea4b --- /dev/null +++ b/skills/zhiyi/zhiyi/references/zhiyi-enhancement-trajectory-learning-20260802.md @@ -0,0 +1,51 @@ +# 织忆提升:轨迹学习门禁 + 程序记忆分类(2026-08-02) + +> 来源:《深入理解 AI Agent》仓颉蒸馏方法论(skill-14 轨迹学习四类更新 + skill-05 记忆分层) +> 仓库:`/tmp/memoryweave/织忆提升实施计划-v2.md` + +## 背景校准(重要教训) + +审计时**先假设"冲突检测缺失"**,实测织忆**早已实现**: +- ✅ `governance.ConflictDetector`(governance.go:32) +- ✅ 写入路径已调用 `DetectContradiction`(core.go:130) +- ✅ API: GET /api/v1/conflicts + POST /api/v1/conflicts/resolve + +**教训**:做记忆系统改进前先 `memory_graph_stats` + 拉真实状态,不要凭蒸馏出的"最佳实践"假设现状。织忆已相当成熟。 + +## 实际落地的提升点 + +### 提升点 1:learner.py 轨迹学习门禁(~/.hermes/scripts/learner.py) + +书中第8章方法论:只有支持度≥2 且无冲突的结论才升为正式知识。 + +改动: +1. `extract_patterns()` 加通用归纳门禁: + - 每个 pattern 带 `support_count` + - 末尾统一过滤:`support >= 2` 才保留,否则 `log("门禁拦截")` +2. `cmd_learn()` 中把达标 patterns 写入织忆: + - `write_pattern_to_zhiyi(pattern)` → POST /api/v1/commit + - content 格式:`[learner模式] {desc} | 建议: {action} | 支持度: {n}` + - category=distilled, agent_id=learner + +验证:单例观察 → patterns=0;三次观察 → patterns=1 (support=3)。 + +### 提升点 2:daemon.py 程序记忆分类(~/.hermes/scripts/daemon.py) + +书中第3章方法论:记忆分情景/语义/程序三类,程序记忆存"如何做"。 + +改动:`_distill_l1_to_l2()` 的 session 消息 topic 提取处(约 line 927): +- 检测 topic 是否含流程性词(步骤/流程/方法/操作/命令/脚本/配置/工作流/pipeline/workflow/script/command/steps) +- 命中 → props["category"] = "procedural",否则 "pattern" + +## 织忆 commit API 实测要点 + +- 必传:`agent_id` + `content`(缺 agent_id 400) +- 成功返回:`{"episode_id": "ep_...", "status": "ok", "memory_id": ""}` — **没有 id 字段** +- 判断成功:检查 `episode_id` 或 `status == "ok"`,不是 `resp.get("id")` +- distill 是**异步队列**:写入后立即 recall 查不到,等 5-10s 或查 stats(total_episodes/total_memories 增长) + +## 验证结果 + +- episodes 52→70(+18),memories 5040→5046(+6) +- daemon 重启 active,graph.db 9083 节点就绪 +- Gitea push: `0d607c8`(2 files, +62/-2) diff --git a/skills/zhiyi/zhiyi/references/zhiyi-episodes-persistence-20260802.md b/skills/zhiyi/zhiyi/references/zhiyi-episodes-persistence-20260802.md new file mode 100644 index 00000000..965ac21f --- /dev/null +++ b/skills/zhiyi/zhiyi/references/zhiyi-episodes-persistence-20260802.md @@ -0,0 +1,125 @@ +# 织忆 episodes 持久化修复 + 四系统体检(2026-08-02) + +## 背景 + +牧尘要求"全面检查记忆系统",指出"记忆系统可不止织忆,还有其他系统"、"你还少了cbm"。 +结论:记忆系统是**四套**(织忆 / Soulful / TencentDB / CBM),各自独立进程,默认互不影响。 + +## 核心修复:episodes 重启清零(commit 21bc777) + +### 根因(两层问题叠加) + +1. **`RustLanceDBClient.InsertEpisode` 只写 Go 进程内存**(`lancedb_ipc.go` 的 `_local.episodes`), + 从不通过 IPC 持久化。Rust LanceDB 的 episodes 表是空表(Rust stats 返回 `total_episodes: 0`)。 +2. **`Stats()` 用内存值覆盖 Rust 真实计数**: + ```go + s["total_episodes"] = len(_local.episodes) // 覆盖了 Rust 返回的真实值 + ``` + 所以 stats 显示 45 条但 LanceDB 里 0 条,重启 zhiyid 后内存清空 → 归零(曾观察到 70→3)。 + +### 修复内容 + +```go +// 1. InsertEpisode 增加 IPC 持久化(照 InsertMemory 模式) +record := map[string]interface{}{ + "id": id, "agent_id": agentID, "namespace": namespace, + "content": content, "category": category, + "tier": "episode", "importance": 1.0, "quality_score": 0.0, + "recall_count": 0, "useful_count": 0, "not_useful_count": 0, + "freshness": "fresh", "version": 1, "version_history": "[]", + "source": "episode", "volatile_flag": false, "is_deleted": false, + "depends_on": "[]", "derived_from": "", "last_recalled_at": "", + "created_at": now.Format(time.RFC3339), + "updated_at": now.Format(time.RFC3339), +} +recJSON, _ := json.Marshal([]interface{}{record}) +if _, err := rc.rpc(ipcReq{Type: "lancedb_insert", Table: "episodes", Records: string(recJSON)}); err != nil { + log.Printf("[ipc] InsertEpisode persist to LanceDB failed (id=%s): %v", id, err) // 只记日志不阻断 +} + +// 2. Stats() 优先 Rust 真实计数,缺失才回退内存 +if _, ok := s["total_episodes"]; !ok { + _local.mu.RLock() + s["total_episodes"] = len(_local.episodes) + _local.mu.RUnlock() +} +``` + +### 关键知识:Rust IPC 协议(手动调试用) + +IPC socket:`/tmp/zhiyi-ipc.sock`,协议是 **4 字节大端长度前缀 + JSON body**(不是纯 JSON 行流): + +```python +import socket, json, struct +s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) +s.connect('/tmp/zhiyi-ipc.sock') +req = json.dumps({'type':'lancedb_stats'}).encode() +s.sendall(struct.pack('>I', len(req)) + req) +lenbuf = b'' +while len(lenbuf) < 4: + lenbuf += s.recv(4 - len(lenbuf)) +msg_len = struct.unpack('>I', lenbuf)[0] +resp = b'' +while len(resp) < msg_len: + chunk = s.recv(msg_len - len(resp)) + if not chunk: break + resp += chunk +print(resp.decode()) +``` + +Rust IPC 已支持的类型:`encode` / `lancedb_search` / `lancedb_insert`(**任意表**,含 episodes)/ +`lancedb_stats` / `lancedb_update` / `lancedb_query`(只查 memories 表)。Go 侧 `rpc()` 实现同协议。 + +### 验证方法(改完必跑) + +```bash +# 1. 提交测试 episode → stats episodes=1 +curl -s -X POST -H "X-API-Key: zhiyi-dev-key-2026" -H "Content-Type: application/json" \ + -d '{"agent_id":"hermes-main","namespace":"test-persist","content":"持久化验证","category":"test"}' \ + http://localhost:7821/api/v1/commit +curl -s -H "X-API-Key: zhiyi-dev-key-2026" http://localhost:7821/api/v1/stats # episodes: 1 +# 2. 重启 → 仍=1(修复前会归零) +systemctl --user restart zhiyid && sleep 3 +curl -s -H "X-API-Key: zhiyi-dev-key-2026" http://localhost:7821/api/v1/stats # episodes: 1 ✅ +``` + +编译部署(注意 Text file busy):`cd /tmp/memoryweave/go && go build -o /home/muc/bin/zhiyid-new ./cmd/zhiyid/`, +先 `systemctl --user stop zhiyid` 再 cp 再 start。旧 binary 备份为 `zhiyid-new.bak-0802`。 + +## 教训 1:L1 蒸馏率"22 条"是误读 + +判断 TencentDB L1 蒸馏是否工作,**不要看 DB 表条数**: +- `vectors.db` 的 `l1_records` 表只有 19 条——那是同步缓存 +- **真正的 L1 数据在 `records/*.jsonl`**:全量 2245 条(persona 459 / instruction 543 / episodic 1243),每天更新 +- "85K L0 只蒸馏 22 条"(0.03%)是错误结论,实际提取器工作正常 + +正确判断:`ls -la ~/.memory-tencentdb/memory-tdai/records/ | tail`(看每天 jsonl 更新)+ 日志 `L1-search DONE`。 +锁冲突 11:5(pipeline-worker 的 lock conflicts)是瞬时竞争,**无积压就不算故障**——看 records 是否每天增长。 + +## 教训 2:端口在听 ≠ systemd 服务正常 + +`tdai-gateway.service` ExecStart 被写坏成 `/src/gateway/server.ts`(不存在),systemd 崩溃循环 +2534 次,但**手动进程撑在 8420 端口让服务"看起来活着"**。 +检查:`systemctl --user show tdai-gateway -p NRestarts`(重启计数)> 100 就是循环。 +修复:ExecStart 改回 `--require .../tsx/dist/preflight.cjs --import .../loader.mjs src/gateway/server.ts`, +杀手动进程(`pkill -f "server.ts"` 会误杀 shell,用精确 PID 或 `pgrep -f` 先查),systemd 接管。 + +## 教训 3:Soulful 牵挂 stale 清理逻辑缺陷 + +`_cleanup_expired_cares` 原来只把 pending 标记 stale,**从不删除 stale** → stale 堆积。 +修复:stale 即删(staled_at 超过阈值就物理删除)。3 条 stale 牵挂手动清理(cares: 3→0)。 + +## 看门狗新增 + +- `~/.hermes/scripts/tdai-gateway-watchdog.sh`:检查 `systemctl --user is-active tdai-gateway` + 8420 端口监听, + 正常静默(空输出)、异常输出报警(no-agent cron 空输出=静默,非空=发送) +- cron `fd14dc936e31`(every 30m,no_agent=true) + +## 四系统体检结果(2026-08-02 终态) + +| 系统 | 状态 | 动作 | +|------|------|------| +| 织忆 | ✅ | distill LLM 修复 + episodes 持久化修复(本次) | +| Soulful | ✅ | 3 条 stale 牵挂清理 + 清理逻辑修复 | +| TencentDB | ✅ | systemd ExecStart 修复 + 30min 看门狗 | +| CBM | ✅ | 瞬态故障自愈(双进程抢锁,新进程已退出),图谱完好 140万+ 边 |