一键导入
sync-progress
扫描所有 "In Progress" 任务关联的 GitHub 仓库,通过本地 git commit 历史和 CHANGELOG 分析开发进度,再将结果同步写回任务文件并部署。当用户想了解项目进展、更新任务进度时使用。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
扫描所有 "In Progress" 任务关联的 GitHub 仓库,通过本地 git commit 历史和 CHANGELOG 分析开发进度,再将结果同步写回任务文件并部署。当用户想了解项目进展、更新任务进度时使用。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
扫描所有活跃 repo 的 License 合规状态,确保每个 repo 包含完整的七件套文件(LICENSE 五件套 + CONTRIBUTING.md + CLA Action),同步模板变更,创建 PR 到 main。当用户想检查 license 合规、初始化新 repo 的 license、或批量更新 TRADEMARK/CLA 政策时使用。
反向同步:扫描所有生态 repo,将接口/版本/状态/依赖变更回流到 Brood 的 INTERFACES.md、PROFILE.md 和 ECOSYSTEM_MAP.md。当用户想检查上下文健康度、同步接口变更、或验证所有 repo 的 @-include 完整性时使用。
扫描所有 "In Progress" 任务关联的 GitHub 仓库,通过本地 git commit 历史和 CHANGELOG 文件分析开发进度,估算完成百分比并更新任务文件。当用户想了解项目进展、更新任务进度时使用。
| name | sync-progress |
| description | 扫描所有 "In Progress" 任务关联的 GitHub 仓库,通过本地 git commit 历史和 CHANGELOG 分析开发进度,再将结果同步写回任务文件并部署。当用户想了解项目进展、更新任务进度时使用。 |
| allowed-tools | Bash(git *), Bash(find *), Bash(mkdir *), Bash(cd * && pnpm run build *), Bash(bash *update-task*), Bash(echo *), Bash(python3 *), Read, Glob, Grep, Edit, Write |
你是一个项目进度分析师。本 skill 分两个阶段:
扫描阶段(Phase 0 ~ 第五步):读取生态地图 → 找本地仓库 → 拉取最新 commit → 对照 AC 评估进度百分比。这一阶段只读不写。
同步阶段(第六步 ~ 第八步):将扫描结果用 Edit 工具写入每个任务文件 → 强制验证所有任务的扫描日期已更新为今天 → 更新 doc-7 → build + commit + deploy。
⚠️ "扫描"≠"完成"。扫描阶段结束只是有了数据,必须完成同步阶段才算一次完整的 sync-progress。没有写入 + 验证的扫描没有任何意义。
这是整个生态的约定:所有仓库按所属组织存放在固定的本地目录下:
| 本地目录 | GitHub 组织 | 说明 |
|---|---|---|
~/Dev/aastar/ | AAStarCommunity | 区块链基础设施(SuperPaymaster、AirAccount、SuperRelay 等) |
~/Dev/auraai/ | AuraAIHQ | AI 基础设施(iDoris、Agent24、agent-speaker 等) |
~/Dev/mycelium/ | MushroomDAO | 社区/个人/城市 OS(Sin90、Cos72、CometENS、Expresser 等) |
当用户在 GitHub 新建仓库并 clone 到本地时,必须放在对应组织的目录下。例如:
git clone git@github.com:AAStarCommunity/NewRepo.git ~/Dev/aastar/NewRepogit clone git@github.com:AuraAIHQ/NewRepo.git ~/Dev/auraai/NewRepogit clone git@github.com:MushroomDAO/NewRepo.git ~/Dev/mycelium/NewRepoClone 备用目录(未找到本地仓库时临时 clone):~/Dev/tmp/
# 1. 项目根目录(Brood 所在位置)
REPO_ROOT=$(git rev-parse --show-toplevel)
# 2. 三大组织固定本地目录
DIR_AASTAR="$HOME/Dev/aastar"
DIR_AURAAI="$HOME/Dev/auraai"
DIR_MYCELIUM="$HOME/Dev/mycelium"
# 3. Clone 备用目录
CLONE_DIR="$HOME/Dev/tmp"
运行时:先执行上述命令,打印确认:
📍 项目根目录: /Users/xxx/Dev/Brood
🗂️ AAStarCommunity: ~/Dev/aastar/
🗂️ AuraAIHQ: ~/Dev/auraai/
🗂️ MushroomDAO: ~/Dev/mycelium/
📦 Clone 备用: ~/Dev/tmp/
严格按以下步骤执行。扫描阶段和同步阶段都必须完成,缺一不可。
目标:收集所有 In Progress 任务的关联仓库数据,评估每个任务的完成进度百分比。 本阶段只读不写,结果保留在内存中供同步阶段使用。
在分析进度之前,先同步生态仓库全景图(docs/ECOSYSTEM_MAP.md)。目的:
references: 字段执行步骤:
使用以下 Python 脚本扫描三个固定目录,构建 remote→本地路径映射表:
import os, subprocess
# 固定目录 → 组织映射
ORG_DIRS = {
os.path.expanduser("~/Dev/aastar"): "AAStarCommunity",
os.path.expanduser("~/Dev/auraai"): "AuraAIHQ",
os.path.expanduser("~/Dev/mycelium"): "MushroomDAO",
}
found_repos = [] # [(local_path, remote_url, org, last_commit)]
for base_dir, org in ORG_DIRS.items():
if not os.path.isdir(base_dir):
print(f"⚠️ 目录不存在: {base_dir}")
continue
for name in sorted(os.listdir(base_dir)):
path = os.path.join(base_dir, name)
git_dir = os.path.join(path, ".git")
if not os.path.isdir(git_dir):
continue
# 获取 remote URL
r = subprocess.run(["git", "-C", path, "remote", "get-url", "origin"],
capture_output=True, text=True)
if r.returncode != 0:
continue
remote = r.stdout.strip()
# 标准化 URL
remote = remote.removesuffix(".git")
remote = remote.replace("git@github.com:", "https://github.com/")
# 仅保留三大 org 的仓库
if not any(f"github.com/{o}/" in remote for o in ORG_DIRS.values()):
continue
# 最近提交日期
r2 = subprocess.run(["git", "-C", path, "log", "-1", "--format=%ad", "--date=short"],
capture_output=True, text=True)
last_commit = r2.stdout.strip() or "unknown"
found_repos.append((path, remote, org, last_commit))
print(f" ✓ {org}/{name} | {last_commit}")
print(f"\n✅ 三大目录共发现 {len(found_repos)} 个仓库")
将 found_repos 列表保留在内存中,后续步骤复用,避免重复扫描。
读取 $REPO_ROOT/docs/ECOSYSTEM_MAP.md,提取其中已有的所有 GitHub URL(github.com/ORG/REPO 格式)。
对每个在 found_repos 中但不在地图里的仓库:
🆕 新发现: {path} → {remote}new_repos 列表,进入步骤 0-3 处理对地图中存在但本地目录不存在的仓库:
❓ 本地缺失: {repo}(尚未 clone)对每个新发现仓库,用 Edit 工具将其追加到 ECOSYSTEM_MAP.md 对应 org 区块的核心产品表格末尾:
| **{RepoName}** | (待补充定位描述) | `../aastar/{RepoName}` 或 `../auraai/...` 或 `../mycelium/...` | [{Org}/{RepoName}]({remote_url}) | ✓ 已克隆 |
同时更新文件顶部"最后更新"日期为今天。
对每个新发现的仓库,在 backlog 任务中搜索可能关联的任务:
import glob, re
tasks_dir = os.path.join(REPO_ROOT, "backlog/tasks")
repo_name = os.path.basename(new_repo_path).lower()
for task_file in sorted(glob.glob(tasks_dir + "/*.md")):
content = open(task_file).read()
# 检查任务是否已有 references 指向该 repo
if new_repo_remote in content:
continue # 已存在,跳过
# 在任务标题、描述中搜索仓库名关键词(不区分大小写)
if repo_name in content.lower() or repo_name.replace("-", "") in content.lower():
# 提取 task ID 用于日志
tid = re.search(r'^id:\s*(.+)', content, re.M)
tid = tid.group(1).strip().strip("'\"") if tid else task_file
print(f" 🤖 任务匹配: {tid} ↔ {repo_name}(名称关键词匹配)")
# 检查 frontmatter references 字段
# 如果 references: [] 或不存在,追加新 URL
# (具体 Edit 操作见第一步·五的写入规则)
如果有匹配,用 Edit 工具按第一步·五的规则将新仓库 URL 写入任务 frontmatter 的 references: 字段。
打印操作日志:
🤖 references 补全: TASK-XX ← https://github.com/MushroomDAO/NewRepo(仓库名关键词匹配)
📡 生态地图扫描完成
三大目录已有仓库: {N} 个
~/Dev/aastar/: {N} 个(AAStarCommunity)
~/Dev/auraai/: {N} 个(AuraAIHQ)
~/Dev/mycelium/: {N} 个(MushroomDAO)
🆕 新发现: {N} 个(已加入地图 + 搜索任务匹配)
❓ 本地缺失: {N} 个(未 clone)
地图已更新: docs/ECOSYSTEM_MAP.md
注意:Phase 0 的 found_repos 列表在内存中保留,供**第三步(定位本地仓库)**直接使用,避免重复扫描。
跑 scripts/scan-repo-status.py 生成 docs/REPO_STATUS.md,这张表与 task 视角的 doc-7 互补,覆盖所有 65 个仓库(含 dormant / 候选启动 / 边缘仓库):
python3 ${REPO_ROOT}/scripts/scan-repo-status.py
输出:
这一步让 orchestrator 拥有 repo-centric 视野:不仅看到 In Progress 任务关联的仓库,还能识别长期静默 / 待激活 / 漂移的仓库,是 Brood 作为生态大脑的关键摘要数据源。
⚠️ 事故教训(2026-06-21):sync-progress 2026-06-21 漏扫了
aastar-sdk(217 commits/9d)+YetAnotherAA-Validator(116 commits/9d)+aastar-docs(15 commits/9d),原因是这些仓库不在任何 task 的references:字段里。 用户发现并反馈:"为何这几个仓库都没有进度展示变化?更新了很多"。 根因:sync-progress 完全依赖 task references 做扫描入口,有大量提交但无 task 绑定的仓库会被默默跳过。
目标:在进入第一步之前,主动报警所有"高活跃但未绑定 task"的仓库,让 orchestrator 决定归属,杜绝漏扫。
执行步骤:
references: URL 标准化后存入 referenced_set,对 found_repos 中每个三大 org 仓库,统计 9 天 commit 数 + 检查是否被任一 task 引用:import subprocess, re, glob
# Collect all referenced URLs from In Progress tasks
referenced = set()
for f in sorted(glob.glob(f'{REPO_ROOT}/backlog/tasks/*.md')):
content = open(f).read()
fm = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
if not fm: continue
if 'In Progress' not in (re.search(r'^status:\s*(.+)', fm.group(1), re.M) or type('',(),{'group':lambda*_:''})).group(1):
continue
for u in re.findall(r'https://github\.com/[A-Za-z0-9._-]+/[A-Za-z0-9._-]+', content):
owner, repo = u.replace("https://github.com/","").rstrip("/").split("/")[:2]
referenced.add(f"{owner.lower()}/{repo.lower()}")
# Find high-activity orphans
THRESHOLD = 30 # 9 天内提交数门槛
orphans = []
for (path, remote, org, last) in found_repos:
owner, repo = remote.replace("https://github.com/","").rstrip("/").split("/")[-2:]
key = f"{owner.lower()}/{repo.lower()}"
if key in referenced:
continue
# Skip Brood self
if "brood" in repo.lower():
continue
r = subprocess.run(["git","-C",path,"log","--all","--oneline","--since","9 days ago"],
capture_output=True, text=True, timeout=10)
count = len([l for l in r.stdout.split("\n") if l.strip()])
if count >= THRESHOLD:
orphans.append((count, key, path, remote))
if orphans:
orphans.sort(reverse=True)
print(f"\n⚠️ 检测到 {len(orphans)} 个高活跃但未绑定 task 的孤儿仓库(9 天 commits ≥ {THRESHOLD}):\n")
for count, key, path, remote in orphans:
print(f" 🔴 {key} — {count} commits/9d ({remote})")
print("\n⛔ 必须先决定每个孤儿仓库的归属:")
print(" 选项 A: 加到现有最相关 task 的 references 字段")
print(" 选项 B: 新建独立 task 跟踪")
print(" 选项 C: 显式跳过(在本 skill 的 IGNORE_LIST 里记一笔)")
print("\n建议主动询问用户:「检测到 X 个孤儿活跃仓库,每个归到哪个 task?」\n")
else:
print(f"\n✅ 无孤儿活跃仓库(所有 ≥{THRESHOLD} commits/9d 的仓库都被 task 引用)")
强制要求:检测到孤儿仓库时,必须在第一步开始前用 AskUserQuestion 或文本明确列出,等待用户决定归属后再继续。不可静默跳过,否则会重演 2026-06-21 事故。
用户决定归属后:
references: 字段(参考第一步·五的写入规则)npx backlog task create ...)并加 referencesIGNORE_LIST(如 fork-only / archived 仓库)— 当前默认 IGNORE_LIST 为空完成归属后继续 Phase 0-5 摘要 + 第一步。
门槛 30 的选择依据:30 commits/9d ≈ 3-4 commits/day,是有意义工程化活动的下限。低于此可能只是 license/chore 治理提交。可根据 IGNORE_LIST 适度调整。
backlog/tasks/*.md 下所有任务文件status: "In Progress" 或 status: In Progress 的任务references: 字段是否包含 github.com URL对 frontmatter 中没有 github.com references 的 In Progress 任务,扫描全文提取 GitHub URL 并自动写入 frontmatter,扩大扫描覆盖范围。
执行步骤:
用 Bash 从整个任务文件中提取所有 GitHub URL:
grep -oE 'https://github\.com/[A-Za-z0-9._-]+/[A-Za-z0-9._-]+(/[^[:space:]"'"'"'>)]*)?' "<task_file>"
标准化每个 URL,提取 repo 根地址或保留有价值的分支信息:
https://github.com/owner/repo/blob/branch/file.md → https://github.com/owner/repo(去掉 blob 路径)https://github.com/owner/repo/tree/branch → 保留完整(含分支信息)https://github.com/owner/repo/issues/... → https://github.com/owner/repo(只保留 repo)https://github.com/owner/repo → 保留去重,过滤掉 Brood 仓库自身的 URL(即 Brood repo)
如果提取到有效 URL,用 Edit 工具将其写入 frontmatter references: 字段:
references: 行但内容为 [] 或空,替换为列表格式references: 行,在 priority: 或 --- 结束行前插入打印操作日志(带 🤖 标记区分自动行为):
🤖 智能匹配: TASK-32 ← https://github.com/jhfnetboy/DSR-Research-Flow(从 description body 提取)
🤖 智能匹配: TASK-34 ← https://github.com/jhfnetboy/AuraAI(从 description body 提取)
对自动补全了 references 的任务,继续后续第二步~第六步的完整分析流程
注意事项:
从 references: 中提取 GitHub URL,解析出关键信息:
https://github.com/{owner}/{repo} 部分https://github.com/{owner}/{repo}/tree/{branch},提取分支名一个任务可能有多个 GitHub references,全部处理。
优先复用 Phase 0 已建立的 found_repos 映射表(remote_url → local_path),无需重复扫描。
匹配规则:
.git 后缀,统一 git@github.com: 和 https://github.com/ 格式)owner/repo 去匹配 found_repos 中的条目# 从 Phase 0 的 found_repos 构建查找表
url_to_path = {}
for (path, remote, org, last_commit) in found_repos:
# 提取 owner/repo 作为 key
key = "/".join(remote.rstrip("/").split("/")[-2:]).lower()
url_to_path[key] = path
# 匹配任务 reference
def find_local_repo(github_url):
key = "/".join(github_url.rstrip("/").split("/")[-2:]).lower()
return url_to_path.get(key)
如果本地未找到仓库(Phase 0 三大目录都没有):
mkdir -p "$HOME/Dev/tmp"
git clone <github_url> "$HOME/Dev/tmp/<repo_name>"
注意:三大固定目录 ~/Dev/aastar、~/Dev/auraai、~/Dev/mycelium 覆盖了绝大多数情况;tmp/ 仅用于不属于三大 org 的 jhfnetboy 个人仓库或外部仓库。
对每个定位到的本地仓库:
git -C <repo_path> pull --rebase 2>/dev/null || git -C <repo_path> fetch --all
git -C <repo_path> log --all --oneline --since="30 days ago" -50
如果 references URL 指定了分支,确保该分支在本地存在后:
git -C <repo_path> log <branch> -- --oneline --since="30 days ago" -50
读取 CHANGELOG: 先在根目录查找,再搜索子目录:
# 根目录优先
for f in CHANGELOG.md changelog.md CHANGES.md HISTORY.md; do
[ -f "<repo_path>/$f" ] && echo "ROOT:$f" && break
done
# 子目录搜索(深度 2)
find <repo_path> -maxdepth 2 -name "CHANGELOG.md" -o -name "changelog.md" -o -name "CHANGES.md" 2>/dev/null
用 Read 工具读取找到的所有 CHANGELOG 文件。
辅助信息 (可选): 如果 CHANGELOG 内容不够丰富,尝试读取 <repo_path>/README.md 中的 roadmap 或进度相关内容。
核心方法: 将 CHANGELOG + commits 的内容与任务的 Acceptance Criteria 做语义匹配。
评估步骤:
## Acceptance Criteria(AC)和 ## Definition of Done(DoD)列表[x] 已完成 — changelog 或 commits 中有明确对应的完成记录[~] 进行中 — 有相关的 WIP commit 或部分完成的记录[ ] 未开始 — 没有找到相关记录(已完成数 + 进行中数×0.5) / 总AC数 × 100%如果 AC 条目很少或很笼统(比如只有一条),则主要依据 changelog 和 commits 的内容量来估算:
目标:将扫描阶段的评估结果写入任务文件,验证写入成功,更新报告,构建并部署上线。 本阶段是 sync-progress 的核心输出。没有同步阶段,扫描阶段的数据毫无意义。
⚠️ "同步"的定义:用 Edit 工具写入文件 + 跑验证脚本确认每个文件的扫描日期已更新为今天。 只生成了分析文字而没有调用 Edit 工具 = 没有同步。 已发生事故(2026-05-02):运行产生了终端输出,汇报"12 个任务已写入", 但 Edit 工具从未被调用,文件内容未变,任务扫描日期停留在 4-27。 根因:把"生成了分析文字"误当成"完成了写入",且没有跑验证脚本。
必须用 Edit 工具(不是 sed,rtk hook 会拦截)将评估得到的进度百分比回写到任务文件中的 预估进度: N% 标记。这是 build 脚本 computeMilestoneProgress() 计算首页进度条的数据源。
如果任务文件中没有 预估进度: 标记,在进度报告区块的第一行添加。
如果不执行此步骤,首页和看板的进度条不会更新!
将进度信息写入任务的 Description section(<!-- SECTION:DESCRIPTION:BEGIN/END --> 标记内),因为 backlog web UI 只渲染已知 section,自定义 section 不会在页面上显示。
写入规则:
### 进度报告 子标题和进度数据### 进度报告,替换该子标题及其后面的全部内容(直到 <!-- SECTION:DESCRIPTION:END -->)格式模板 (追加在 Description 原有内容之后,<!-- SECTION:DESCRIPTION:END --> 之前):
### 📊 进度报告 ({YYYY-MM-DD} 扫描)
**🚀 预估进度: {N}%** | 近 30 天 {N} 次提交,最近一次 {日期}
**✅ AC 完成情况**:
- ✅ {AC条目1} — {依据简述}
- 🔧 {AC条目2} — {进行中,相关 commit}
- ⬜ {AC条目3} — 未开始
**📝 近期动态** ({changelog来源}):
- {MM-DD}: {版本/动态1}
- {MM-DD}: {版本/动态2}
- {MM-DD}: {版本/动态3}
💡 {一句话总结当前阶段和剩余工作}
在终端用表格格式打印所有扫描结果的概览:
=== BroodBrain 进度扫描报告 ===
扫描时间: {YYYY-MM-DD HH:MM}
| 任务 | 进度 | 仓库 | 最近提交 | 摘要 |
|------|------|------|----------|------|
| TASK-18 KMS/TEE | 75% | AirAccount (KMS) | 今天 | v0.16.4 stable beta |
| TASK-8 Paymaster V4 | 60% | SuperPaymaster | 今天 | V4.3 稳定币已合并 |
| TASK-9 Comet ENS | — | 无关联仓库 | — | 跳过 |
在输出第七步汇总表之前,必须先跑以下验证脚本,确认每个 In Progress 任务的扫描日期已变为今天。如果有任务日期未更新,说明第六步的 Edit 工具调用失败或被跳过,必须重新执行写入,直到全部日期为今天。
import os, re, glob
from datetime import date
TODAY = str(date.today())
tasks_dir = f'{REPO_ROOT}/backlog/tasks'
fail = []
for f in sorted(glob.glob(tasks_dir + '/*.md')):
content = open(f).read()
fm = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
if not fm: continue
status = re.search(r'^status:\s*(.+)', fm.group(1), re.M)
if not status or 'In Progress' not in status.group(1): continue
tid = re.search(r'^id:\s*(.+)', fm.group(1), re.M).group(1).strip().strip("'\"")
scan = re.search(r'进度报告\s*\((\d{4}-\d{2}-\d{2})\s*扫描\)', content)
date_in_file = scan.group(1) if scan else "无"
if date_in_file != TODAY:
fail.append(f'{tid}: {date_in_file}(应为 {TODAY})')
print(f'❌ {tid}: 扫描日期未更新 ({date_in_file})')
else:
print(f'✅ {tid}: {date_in_file}')
if fail:
print(f'\n⛔ {len(fail)} 个任务写入失败,必须重新执行第六步再继续:')
for f in fail: print(f' {f}')
raise SystemExit('写入验证失败,禁止继续!')
else:
print(f'\n✅ 所有 In Progress 任务扫描日期已更新为 {TODAY},可继续第七步')
只有验证全部通过(无 ❌)才能继续后续步骤。
在更新 doc-7 之前,先计算 Phase 1/2/3 的真实进度。核心思想:Phase 进度 = 该 Phase 所有任务的完成度加权平均,而非简单的「已完成任务数 / 总任务数」。
进度取值规则(按优先级):
status: Done → 100%(已完成,不论进度报告里写多少)status: In Progress + 有「预估进度: N%」→ 取 N%status: In Progress + 无进度估算 → 保守取 10%(有开始但无数据)status: To Do → 0%(未开始)Milestone → Phase 映射规则:
m-1 / Phase 1: Genesis Launch / 'Phase 1: Genesis Launch' → Phase 1m-2 / Phase 2: Community Expansion → Phase 2m-3 / Phase 3: Ecosystem Maturity → Phase 3m-r / 其他 → Research/Other(不计入 Phase)计算方法:用以下 Python 脚本(在 Bash 工具中运行):
import os, re, glob
tasks_dir = f'{REPO_ROOT}/backlog/tasks'
files = glob.glob(tasks_dir + '/*.md')
tasks = []
for f in sorted(files):
content = open(f).read()
fm_match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
if not fm_match: continue
fm = fm_match.group(1)
tid = re.search(r'^id:\s*(.+)', fm, re.M)
status = re.search(r'^status:\s*(.+)', fm, re.M)
milestone = re.search(r'^milestone:\s*(.+)', fm, re.M)
if not tid or not status or not milestone: continue
tid = tid.group(1).strip().strip("'\"")
status_raw = status.group(1).strip().strip("'\"")
milestone = milestone.group(1).strip().strip("'\"")
# Determine progress
prog_match = re.search(r'预估进度:\s*(\d+)%', content)
if 'done' in status_raw.lower():
progress = 100
elif 'in progress' in status_raw.lower():
progress = int(prog_match.group(1)) if prog_match else 10
else: # To Do
progress = 0
# Map to phase
m = milestone.lower()
if 'm-1' in m or 'phase 1' in m or 'genesis' in m:
phase = 'Phase 1'
elif 'm-2' in m or 'phase 2' in m or 'community' in m:
phase = 'Phase 2'
elif 'm-3' in m or 'phase 3' in m or 'ecosystem' in m:
phase = 'Phase 3'
else:
phase = 'Research'
tasks.append({'id': tid, 'status': status_raw, 'phase': phase, 'progress': progress})
# Calculate phase averages
for phase in ['Phase 1', 'Phase 2', 'Phase 3']:
ptasks = [t for t in tasks if t['phase'] == phase]
if ptasks:
avg = sum(t['progress'] for t in ptasks) / len(ptasks)
print(f"{phase}: {avg:.1f}% ({len(ptasks)} tasks)")
将计算结果保存为变量,在下一步写入 doc-7。
将本次扫描结果写入 $REPO_ROOT/backlog/docs/doc-7 - 📊-Progress-Report.md,使进度数据在 backlog 左侧文档栏中可见。
写入规则:
updated_date 为今天的日期## Phase 进度 / Phase Progress 区块(如不存在则在总览表之前新增),写入三个 Phase 的加权进度## 总览 / Overview 表格中所有行,使用本次扫描的最新数据## 详细报告 / Detailed Reports 各任务段落,使用本次各任务的进度报告摘要## 历史扫描记录 / Scan History 表格顶部追加一行新记录(格式:| YYYY-MM-DD | N | 本次关键变化摘要 |)doc-7 文件路径:$REPO_ROOT/backlog/docs/doc-7 - 📊-Progress-Report.md
Phase 进度区块格式模板(每次全量替换该区块内容):
## Phase 进度 / Phase Progress
| Phase | 加权进度 | 任务数 | 说明 |
|:---|:---:|:---:|:---|
| **Phase 1**: Genesis Launch | **{N}%** | {n}个任务 | Done={d}, In Progress={ip}, To Do={td} |
| **Phase 2**: Community Expansion | **{N}%** | {n}个任务 | Done={d}, In Progress={ip}, To Do={td} |
| **Phase 3**: Ecosystem Maturity | **{N}%** | {n}个任务 | Done={d}, In Progress={ip}, To Do={td} |
> 进度算法:Done=100%,In Progress=取进度报告实际估算值,To Do=0%;对该 Phase 所有任务取算术平均。
总览表格式模板(每次全量替换):
| 任务 | 标题 | 进度 | 仓库 | 最近提交 | 状态摘要 |
|:---|:---|:---:|:---|:---:|:---|
| TASK-XX | {标题} | **{N}%** | {仓库} | {日期} | {一句话} |
| TASK-YY | {标题} | **—** | 无关联仓库 | — | {说明} |
⚠️ 绝对不能跳过此步骤。 任务文件写入进度后,
dist/不会自动更新,线上看板显示的仍是上一次 build 的旧数据。 已发生事故(2026-05-02):sync-progress 运行后漏掉第八步,导致线上任务仍显示"2026-04-27 扫描"的旧进度报告,用户反馈才发现。根因:把"写入任务文件"误当做"完成",忘记 build + deploy 才让内容上线。
先重新构建静态站点,提交推送,再部署到 Cloudflare Pages:
# Step 8-1: 构建(timeout 120s)
cd "$REPO_ROOT" && pnpm run build
# Step 8-2: 提交推送
bash "$REPO_ROOT/update-task.sh"
# Step 8-3: 部署 Cloudflare Pages(带一次 retry)
cd "$REPO_ROOT" && pnpm run deploy:cf || (sleep 5 && pnpm run deploy:cf)
注意事项:
pnpm run build 需要约 30-60 秒(启动本地 backlog server → 抓取 → 生成 dist/),Bash 工具设置 timeout: 120000Patched Kanban column progress formula 和 Patched right-panel milestone progress formula。任一缺失说明 backlog.md 升级后 JS minified 名变了,build 脚本应已自动抛错;如果 build 通过但缺少 patch 日志,说明脚本被绕过,禁止继续部署。pnpm run deploy:cf 可能因 proxy 卡住或网络问题失败:先尝试 unset http_proxy https_proxy all_proxy && pnpm run deploy:cf;超过 3 分钟无输出视为挂死,kill 掉 wrangler 进程后重试一次pnpm run deploy:cf⚠️ 事故教训(2026-05-12):build 脚本里的 JS patch 字符串被 backlog.md v1.45 minified 变量名变更破坏,patch 静默失败但 build 仍成功输出 dist/。CF 部署也成功,但页面 Phase 进度回退到
doneCount/total简单计数(46/0/0 而不是 67/7/9)。用户访问 kanban 才发现错误。 教训:commit + deploy 成功 ≠ 上线数据正确。必须 fetch 部署 URL 并断言关键数据正确。
完成第八步部署后,立刻 fetch 线上 URL 验证三件事:
# 拿到部署 URL(从 deploy:cf 输出中提取)— 也可以直接用主域 https://kanban.mushroom.cv/
DEPLOY_URL="https://kanban.mushroom.cv/"
# 验证 1:__milestoneProgress 数据存在且与本地计算的 Phase 进度一致
curl -sf "$DEPLOY_URL" | grep -oE "__milestoneProgress[^;]{0,300}"
# 预期输出:__milestoneProgress = {"m-1":N,"lane:milestone:m-1":N,"m-2":N,...}
# 如果没有输出或值是 {},说明 index.html 没有注入 milestone 数据 → build 失败或部署未刷新
# 验证 2:JS bundle 中存在 patch 后的 milestoneProgress 引用
JS_URL=$(curl -sf "$DEPLOY_URL" | grep -oE "chunk-[a-z0-9]+\.js" | head -1)
curl -sf "${DEPLOY_URL}${JS_URL}" | grep -c "__milestoneProgress"
# 预期 >= 2(kanban patch + right-panel patch 各引用一次)
# 如果是 0,说明 JS bundle patch 没生效,UI 会回退到错误的简单计数
# 验证 3:抽查一个 In Progress 任务的进度报告扫描日期是今天
TODAY=$(date +%Y-%m-%d)
curl -sf "${DEPLOY_URL}api/tasks.json" | python3 -c "
import json, sys
data = json.load(sys.stdin)
tasks = data.get('tasks', data) if isinstance(data, dict) else data
ip = [t for t in tasks if t.get('status') == 'In Progress']
print(f'In Progress tasks online: {len(ip)}')
if ip:
print(f'Sample task: {ip[0].get(\"id\")}: {ip[0].get(\"title\", \"\")[:40]}')
"
强制断言:
__milestoneProgress 在 index.html 中存在且至少包含 m-1 / m-2 / m-3 三个键__milestoneProgress 引用 >= 2任一断言失败时:必须在终端用红色文字明确告警,列出失败项,并提示「请检查 build 输出 / 重新 deploy / 等待 CF 缓存刷新(最多 30 秒)」。不要假装成功。
验证清单(完成后逐项确认,必须全部打勾才算完成):
backlog/tasks/ 中的任务文件已更新(包含 ### 📊 进度报告 和 预估进度: N%)backlog/docs/doc-7 - 📊-Progress-Report.md 的 Phase 进度表和总览表已更新docs/ECOSYSTEM_MAP.md 的状态和日期已更新dist/ 重新生成,含最新内容(pnpm run build 成功,包含两个 ✅ Patched 日志)update-task.sh commit + push 成功__milestoneProgress 存在 + JS bundle 含 patch + tasks.json 数据对齐pnpm run build → update-task.sh → pnpm run deploy:cf 三步全部完成,内容才会在线上可见。漏掉任意一步,用户看到的仍是上次 build 的旧数据。(2026-05-02 事故教训)__milestoneProgress 存在 + JS bundle 含 patch 引用。(2026-05-12 事故教训)git pull/git fetch 将远程同步到本地,之后所有分析(git log、读文件等)只使用本地分支和本地文件,禁止使用 origin/ 前缀的远程引用。不调用 GitHub API。git pull 失败不要中断流程,改用 git fetch 然后继续分析本地已有数据git log 使用本地分支名(不加 origin/ 前缀),用 --all 参数确保覆盖所有本地分支详见 skills/sync-progress/README.md。快速安装:
# 在你自己的 backlog 项目中安装此 skill
mkdir -p .claude/skills/sync-progress
curl -o .claude/skills/sync-progress/SKILL.md \
https://raw.githubusercontent.com/AAStarCommunity/Brood/main/skills/sync-progress/SKILL.md
可选配置:export SYNC_SCAN_ROOT="$HOME/projects" 指定仓库扫描范围。