/athena-migrate — v9.5.5 → v9.6 迁移

SkillDev tools

把 v9.5.5 项目的 .ai_state/ 升级到 v9.6 schema (INDEX + details/ 重构)。

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the /athena-migrate — v9.5.5 → v9.6 迁移 skill

What this skill tells your AI

The instructions your AI receives, as published by m-xlsea/ruoyi-plus-soybean in .claude/skills/athena-migrate/SKILL.md and read by ahel’s review.

参考: https://code.claude.com/docs/en/skills

前置检查

test -d .ai_state || { echo "[migrate] 无 .ai_state, 请先 /athena-init"; exit 1; }
test -f .ai_state/_index.md && grep -q 'schema_version: "9.6"' .ai_state/_index.md && {
  echo "[migrate] 已是 v9.6 schema, 无需迁移"; exit 0;
}

迁移算法

Step 1: 备份

mkdir -p .ai_state/.legacy-v9.5
cp -r .ai_state/{tasks.md,design.md,progress.md,lessons.md,handoff.md,project.json,reviews,hook-trace.jsonl,compact-snapshot.json} .ai_state/.legacy-v9.5/ 2>/dev/null || true
echo "[migrate] 旧文件已备份到 .ai_state/.legacy-v9.5/"

Step 2: 创建 details/ 目录

mkdir -p .ai_state/details/reviews
mkdir -p .ai_state/details/tasks-archive

Step 3: 迁移文件

v9.5.5 路径v9.6 路径备注
.ai_state/tasks.md.ai_state/details/tasks-current.md改名
.ai_state/design.md.ai_state/details/design.md平移
.ai_state/progress.md.ai_state/details/progress.md平移
.ai_state/lessons.md.ai_state/details/lessons.md平移
.ai_state/handoff.md.ai_state/details/handoff.md平移
.ai_state/reviews/sprint-N.md.ai_state/details/reviews/sprint-N.md平移
.ai_state/project.json(merge 到 _index.md frontmatter)转 markdown frontmatter
.ai_state/hook-trace.jsonl.ai_state/hook-trace.jsonl保持原位置
.ai_state/compact-snapshot.json(删, v9.6 改写到 _index.md.snapshots)删除
# 平移
[ -f .ai_state/tasks.md ] && mv .ai_state/tasks.md .ai_state/details/tasks-current.md
for f in design.md progress.md lessons.md handoff.md; do
  [ -f .ai_state/$f ] && mv .ai_state/$f .ai_state/details/$f
done
[ -d .ai_state/reviews ] && mv .ai_state/reviews .ai_state/details/reviews
[ -f .ai_state/compact-snapshot.json ] && rm .ai_state/compact-snapshot.json

Step 4: 生成 _index.md

.ai_state/project.json 读 path/stage/sprint/tech_stack/test_cmd/build_cmd/lint_cmd/dev_cmd/conventions/gotchas, 写入新 _index.md frontmatter。

# 用 node 脚本生成 _index.md (避免手写 yaml escape 出错)
node -e '
const fs = require("fs");
const path = require("path");

let proj = {};
try { proj = JSON.parse(fs.readFileSync(".ai_state/.legacy-v9.5/project.json","utf8")); } catch(e) {}

const sprint = proj.sprint || 0;

// 计算 counts
let tasks_pending = 0, tasks_done = 0, tasks_blocked = 0;
try {
  const t = fs.readFileSync(".ai_state/details/tasks-current.md","utf8");
  tasks_pending = (t.match(/^- \[ \]/gm) || []).length;
  tasks_done    = (t.match(/^- \[x\]/gm) || []).length;
} catch(e) {}

let progress_entries = 0, latest_progress = "";
try {
  const lines = fs.readFileSync(".ai_state/details/progress.md","utf8").split("\n").filter(l => l.trim().length > 0 && !l.startsWith("<!--") && !l.startsWith("#"));
  progress_entries = lines.length;
  if (lines.length > 0) latest_progress = `details/progress.md#L${lines.length}`;
} catch(e) {}

let lessons_lines = 0, latest_lesson = "";
try {
  const lines = fs.readFileSync(".ai_state/details/lessons.md","utf8").split("\n");
  lessons_lines = lines.filter(l => l.startsWith("##")).length;
  for (let i = lines.length - 1; i >= 0; i--) {
    if (lines[i].startsWith("## ")) { latest_lesson = `details/lessons.md#L${i+1}`; break; }
  }
} catch(e) {}

let reviews_count = 0, latest_review = "";
try {
  const files = fs.readdirSync(".ai_state/details/reviews").filter(f => f.startsWith("sprint-") && f.endsWith(".md"));
  reviews_count = files.length;
  if (files.length > 0) {
    const sorted = files.sort();
    latest_review = `details/reviews/${sorted[sorted.length-1]}`;
  }
} catch(e) {}

const idx = `---
schema_version: "9.6"
athena_version: "9.6.0"
project:
  path: "${proj.path || ""}"
  stage: "${proj.stage || ""}"
  sprint: ${sprint}
  active_goal: ""
counts:
  tasks_pending: ${tasks_pending}
  tasks_done: ${tasks_done}
  tasks_blocked: ${tasks_blocked}
  lessons_lines: ${lessons_lines}
  progress_entries: ${progress_entries}
  reviews_count: ${reviews_count}
pointers:
  latest_progress: "${latest_progress}"
  latest_review: "${latest_review}"
  latest_lesson: "${latest_lesson}"
  latest_proposal: ""
fingerprints:
  tasks_mtime: 0
  design_mtime: 0
  progress_mtime: 0
  lessons_mtime: 0
platform_features:
  cc_version: ""
  cx_version: ""
  goal_supported: false
  batch_supported: false
  background_supported: false
  session_memory_active: false
  cross_session_memory: "none"
gotchas: ${JSON.stringify(proj.gotchas || [])}
conventions: ${JSON.stringify(proj.conventions || [])}
tech_stack: "${proj.tech_stack || ""}"
test_cmd: "${proj.test_cmd || ""}"
build_cmd: "${proj.build_cmd || ""}"
lint_cmd: "${proj.lint_cmd || ""}"
dev_cmd: "${proj.dev_cmd || ""}"
---

# 项目状态索引 (v9.6 migrated from v9.5.5)

## 最近活动

## 当前阻塞

## 下一动作 (PACE 建议)

## 反思建议 (Hook 沉淀)
`;

fs.writeFileSync(".ai_state/_index.md", idx);
console.log("[migrate] _index.md generated");
'

Step 5: 创建空 next.md 和 proposals.md

touch .ai_state/details/next.md
touch .ai_state/details/proposals.md

Step 6: 平台版本检测填入 _index.md

调用 /athena-setup --detect-only, 它会原地更新 _index.md.platform_features

Step 7: 提示用户

✓ 迁移完成。备份在 .ai_state/.legacy-v9.5/, 确认无问题可删除。
新增的文件: .ai_state/details/next.md, .ai_state/details/proposals.md
删除的文件: .ai_state/project.json (合并到 _index.md frontmatter)
                .ai_state/compact-snapshot.json (改写到 _index.md.snapshots 数组)
下一步: /athena-status 查看新状态面板

Step 8: Git commit

git add .ai_state/
git commit -m "athena: migrate state to v9.6 schema"

回滚 (如果出问题)

rm -rf .ai_state/details .ai_state/_index.md
cp -r .ai_state/.legacy-v9.5/* .ai_state/

Signals

GitHub stars
325
Forks
74
Last commit
Jun 2026
Advanced
Catalog kind
skill
Gateway key
athena-migrate
Source
github.com/m-xlsea/ruoyi-plus-soybean