mirror of
https://github.com/dtzp555-max/memory-continuity.git
synced 2026-07-19 09:42:42 +00:00
feat: add post-install script and troubleshooting guide
Add scripts/post-install.sh to clear stale skillsSnapshot cache from existing sessions, ensuring the skill loads immediately after install. Update README with corrected install path and post-install instructions. Include detailed troubleshooting report documenting the snapshot cache root cause analysis. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -55,12 +55,21 @@ v1 direction.
|
||||
### Install
|
||||
|
||||
```bash
|
||||
cd ~/.openclaw/workspace/skills/
|
||||
cd ~/.openclaw/workspace/main/skills/
|
||||
git clone https://github.com/dtzp555-max/memory-continuity.git
|
||||
cd memory-continuity
|
||||
bash scripts/post-install.sh
|
||||
```
|
||||
|
||||
No npm install, no API keys, no external database.
|
||||
|
||||
> **Why `post-install.sh`?**
|
||||
> OpenClaw caches each session's skill list in a `skillsSnapshot`. If you
|
||||
> install this skill while the gateway is stopped (or restart the gateway
|
||||
> after cloning), existing sessions won't detect the new skill until their
|
||||
> snapshot is cleared. The post-install script handles this automatically.
|
||||
> New sessions created after install are unaffected.
|
||||
|
||||
### Test the current skill version
|
||||
|
||||
1. Start a multi-step task with your agent
|
||||
@@ -158,7 +167,9 @@ Memory continuity is for:
|
||||
|
||||
```text
|
||||
memory-continuity/
|
||||
├── SKILL.md
|
||||
├── SKILL.md # Behavior contract / skill definition
|
||||
├── skill.json # Skill metadata for OpenClaw loader
|
||||
├── _meta.json # Workspace skill registry metadata
|
||||
├── README.md
|
||||
├── LICENSE
|
||||
├── plugin/
|
||||
@@ -168,6 +179,7 @@ memory-continuity/
|
||||
│ ├── doctor-spec.md
|
||||
│ └── phase2-hook-validation.md
|
||||
└── scripts/
|
||||
├── post-install.sh # Clears stale skill snapshots
|
||||
└── continuity_doctor.py
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
# memory-continuity Skill 排错报告
|
||||
|
||||
> 日期: 2026-03-14
|
||||
> 排错人: Claude Opus 4.6 (via Claude Code)
|
||||
> 环境: OpenClaw 2026.3.12 (6472949) / macOS / Node 25.8.0
|
||||
|
||||
---
|
||||
|
||||
## 问题描述
|
||||
|
||||
memory-continuity skill 安装后无法正常工作。具体表现:
|
||||
|
||||
1. `/new` 重置会话后,agent 不按照 skill 定义的恢复优先级协议行事
|
||||
2. Agent 说"我不记得",然后才提到 `CURRENT_STATE.md` 中的"残留记录"
|
||||
3. `openclaw skills check` 显示 skill 状态为 `✓ ready`,但 agent 的 system prompt 中没有加载它
|
||||
|
||||
---
|
||||
|
||||
## 排错过程
|
||||
|
||||
### 第一阶段:确认 skill 文件完整性
|
||||
|
||||
- 检查 `~/.openclaw/workspace/main/skills/memory-continuity/SKILL.md` — 存在且 frontmatter 格式正确
|
||||
- 检查 `openclaw.json` — 5 个 agent 的 `skills` 数组中均已包含 `"memory-continuity"`
|
||||
- 检查 `openclaw skills check` — 显示 ready,source 为 `openclaw-workspace`
|
||||
- **结论:安装和配置层面无问题**
|
||||
|
||||
### 第二阶段:验证 skill 是否进入 agent prompt
|
||||
|
||||
通过 `openclaw agent --agent main -m "ping" --json` 获取 `systemPromptReport`,发现:
|
||||
|
||||
- 加载了 20 个 skills,**memory-continuity 不在其中**
|
||||
- 对比发现 `secureclaw`(同为 workspace skill)成功加载
|
||||
|
||||
对比两者差异:
|
||||
| 项目 | secureclaw | memory-continuity |
|
||||
|---|---|---|
|
||||
| SKILL.md | ✓ | ✓ |
|
||||
| skill.json | ✓ | ✗ |
|
||||
| _meta.json | ✓ | ✗ |
|
||||
|
||||
尝试为 memory-continuity 补充 `skill.json` 和 `_meta.json` 后重启 gateway,**问题未解决**。
|
||||
|
||||
### 第三阶段:逆向分析 skill loader 源码
|
||||
|
||||
反编译分析 OpenClaw 的 skill 加载链路:
|
||||
|
||||
```
|
||||
resolveSkillsPromptForRun()
|
||||
→ 优先使用 skillsSnapshot(session 缓存)
|
||||
→ 否则调用 buildWorkspaceSkillSnapshot()
|
||||
→ resolveWorkspaceSkillPromptState()
|
||||
→ filterSkillEntries()
|
||||
→ shouldIncludeSkill() // 过滤
|
||||
→ skillFilter // allowlist
|
||||
```
|
||||
|
||||
关键发现:
|
||||
|
||||
1. **skill 发现机制**(`loadSkillEntries`)基于文件系统扫描 `workspace/skills/*/SKILL.md`,与 `_meta.json` 和 `skill.json` 无关
|
||||
2. **skill 过滤机制**(`filterSkillEntries`)使用 agent 配置中的 `skills` 数组作为 allowlist
|
||||
3. **skill snapshot 缓存**(`skillsSnapshot`)存储在 session store 中,只在以下条件刷新:
|
||||
- `isFirstTurnInSession`(首轮对话)
|
||||
- `snapshotVersion > 0` 且版本号增加
|
||||
|
||||
### 第四阶段:定位根因
|
||||
|
||||
检查 session store 中的 skills snapshot:
|
||||
|
||||
```json
|
||||
// ~/.openclaw/agents/main/sessions/sessions.json
|
||||
// session "agent:main:main"
|
||||
{
|
||||
"skillsSnapshot": {
|
||||
"version": 0,
|
||||
"skills": [/* 20 个 skill,不含 memory-continuity */]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**根因确认:**
|
||||
|
||||
- 所有 239 个 session 在 memory-continuity 安装前就已缓存了 skills snapshot
|
||||
- snapshot `version: 0`,而刷新条件是 `snapshotVersion > 0`,导致永远不会自动刷新
|
||||
- 后续对话复用已有 session(非 firstTurn),跳过重建
|
||||
- 结果:无论怎么重启 gateway 或重装 skill,缓存的旧 snapshot 始终被使用
|
||||
|
||||
---
|
||||
|
||||
## 修复措施
|
||||
|
||||
### 1. 清除所有 session 的过期 skillsSnapshot(关键修复)
|
||||
|
||||
```python
|
||||
# 遍历 sessions.json,删除所有 session 的 skillsSnapshot 字段
|
||||
for key in data:
|
||||
if 'skillsSnapshot' in data[key]:
|
||||
del data[key]['skillsSnapshot']
|
||||
# 共清除 239 个 session 的缓存
|
||||
```
|
||||
|
||||
下次 agent 响应时,检测到 `!current.skillsSnapshot`,触发 `buildWorkspaceSkillSnapshot()` 重建,新 snapshot 包含 memory-continuity。
|
||||
|
||||
### 2. 补充 skill.json(规范性改进)
|
||||
|
||||
创建 `workspace/main/skills/memory-continuity/skill.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "memory-continuity",
|
||||
"version": "1.0.0",
|
||||
"description": "Short-term working continuity for OpenClaw agents...",
|
||||
"author": "dtzp555-max",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/dtzp555-max/memory-continuity"
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 补充 _meta.json(规范性改进)
|
||||
|
||||
创建 `workspace/main/skills/memory-continuity/_meta.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"ownerId": "github:dtzp555-max",
|
||||
"slug": "memory-continuity",
|
||||
"version": "1.0.0",
|
||||
"publishedAt": 1710388800000
|
||||
}
|
||||
```
|
||||
|
||||
> 注:措施 2 和 3 对 skill 加载无实际影响,但与其他 workspace skill(如 secureclaw)保持一致。
|
||||
|
||||
---
|
||||
|
||||
## 验证结果
|
||||
|
||||
### Skill 加载验证
|
||||
|
||||
```
|
||||
修复前: Total: 20, memory-continuity: False
|
||||
修复后: Total: 11, memory-continuity: True (620 chars)
|
||||
```
|
||||
|
||||
加载的 11 个 skills 与 main agent 配置的 `skills` 数组完全匹配。
|
||||
|
||||
### 功能黑盒测试
|
||||
|
||||
| 步骤 | 操作 | 结果 |
|
||||
|---|---|---|
|
||||
| 1 | 告诉 agent 秘密信息 | agent 确认记录 |
|
||||
| 2 | 检查 CURRENT_STATE.md | 秘密已写入 `## In Flight` |
|
||||
| 3 | 删除 session 模拟 `/new` | 新 session 创建 |
|
||||
| 4 | 在新 session 中问秘密 | agent 从 CURRENT_STATE.md 恢复,正确回答 |
|
||||
|
||||
---
|
||||
|
||||
## 经验总结
|
||||
|
||||
1. **OpenClaw 的 skill 加载不是实时的** — session store 中的 `skillsSnapshot` 会缓存 skill 列表,新安装的 skill 不会自动出现在已有 session 中
|
||||
2. **`openclaw skills check` 显示 ready 不代表已加载** — ready 只表示文件系统发现成功,实际加载还受 session snapshot 缓存影响
|
||||
3. **snapshot version = 0 是一个 edge case** — 在这个版本下,自动刷新逻辑永远不会触发(`snapshotVersion > 0` 为 false)
|
||||
4. **重启 gateway 不会清除 session snapshot** — snapshot 持久化在 sessions.json 中,只有清除缓存或触发 firstTurn 才能刷新
|
||||
|
||||
---
|
||||
|
||||
## 涉及文件
|
||||
|
||||
| 文件 | 操作 |
|
||||
|---|---|
|
||||
| `~/.openclaw/agents/main/sessions/sessions.json` | 清除 239 个 session 的 skillsSnapshot |
|
||||
| `~/.openclaw/workspace/main/skills/memory-continuity/skill.json` | 新建 |
|
||||
| `~/.openclaw/workspace/main/skills/memory-continuity/_meta.json` | 新建 |
|
||||
Executable
+71
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env bash
|
||||
# post-install.sh — Flush stale skill snapshots after installing memory-continuity
|
||||
#
|
||||
# OpenClaw caches a "skillsSnapshot" per session. If this skill was installed
|
||||
# while the gateway was stopped (or after a gateway restart), the file watcher
|
||||
# won't detect the new SKILL.md and existing sessions will never refresh.
|
||||
#
|
||||
# This script clears stale snapshots so every session rebuilds on next turn.
|
||||
#
|
||||
# Usage:
|
||||
# bash scripts/post-install.sh [--agent-id <id>]
|
||||
#
|
||||
# Options:
|
||||
# --agent-id <id> Agent ID (default: main)
|
||||
#
|
||||
# Safe to run multiple times (idempotent).
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
AGENT_ID="main"
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--agent-id) AGENT_ID="$2"; shift 2 ;;
|
||||
*) echo "Unknown option: $1" >&2; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
OPENCLAW_DIR="${OPENCLAW_STATE_DIR:-$HOME/.openclaw}"
|
||||
SESSIONS_FILE="$OPENCLAW_DIR/agents/$AGENT_ID/sessions/sessions.json"
|
||||
|
||||
if [[ ! -f "$SESSIONS_FILE" ]]; then
|
||||
echo "No sessions file found at $SESSIONS_FILE — nothing to do."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Count and clear stale skillsSnapshot entries
|
||||
BEFORE=$(python3 -c "
|
||||
import json, sys
|
||||
with open('$SESSIONS_FILE') as f:
|
||||
data = json.load(f)
|
||||
count = sum(1 for v in data.values() if isinstance(v, dict) and 'skillsSnapshot' in v)
|
||||
print(count)
|
||||
" 2>/dev/null || echo "0")
|
||||
|
||||
if [[ "$BEFORE" == "0" ]]; then
|
||||
echo "No stale skill snapshots found — all sessions will discover skills normally."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
python3 -c "
|
||||
import json
|
||||
path = '$SESSIONS_FILE'
|
||||
with open(path) as f:
|
||||
data = json.load(f)
|
||||
for key in data:
|
||||
if isinstance(data[key], dict) and 'skillsSnapshot' in data[key]:
|
||||
del data[key]['skillsSnapshot']
|
||||
with open(path, 'w') as f:
|
||||
json.dump(data, f, indent=2)
|
||||
"
|
||||
|
||||
echo "Cleared skillsSnapshot from $BEFORE session(s) in $SESSIONS_FILE"
|
||||
echo "All sessions will rebuild their skill list on next turn."
|
||||
|
||||
# Restart gateway if running, so file watcher picks up the new SKILL.md
|
||||
if command -v openclaw &>/dev/null; then
|
||||
if openclaw gateway status 2>&1 | grep -q "running"; then
|
||||
echo "Restarting gateway to activate file watcher..."
|
||||
openclaw gateway restart 2>/dev/null && echo "Gateway restarted." || echo "Gateway restart failed — try manually: openclaw gateway restart"
|
||||
fi
|
||||
fi
|
||||
Reference in New Issue
Block a user