| name | build-loop:sync-skills |
| description | Use when the user asks to "check skill drift", "sync skills", or "update architecture skills", or when Phase 1 Assess detects stale source_hash values. Walks skills/architecture/, recomputes source_hash, reports drift. Read-only. |
| version | 0.1.0 |
| user-invocable | false |
Sync-Skills — Drift Detection for Native Copies
Build-loop's skills/architecture/ skills are copied from the canonical upstream repo (NavGator). Each carries a source: path and source_hash: SHA-256 in its frontmatter. This skill recomputes the hash from the canonical source file and reports any drift. (The former skills/debugging/ skills were folded into the debugging-memory skill on 2026-07 and are no longer drift-checked — native/adapted, no canonical upstream.)
Read-only. Never auto-updates a skill — surfaces a list of skills that need refresh and a one-line refresh command.
When to Activate
- User asks "check skill drift", "sync skills", "are native skills stale"
- After updating NavGator or claude-code-debugger locally and you want to know which build-loop skills inherit the change
- Periodic maintenance (run quarterly, or before any release that touches the architecture/debugging surfaces)
Workflow
Run the drift-check script:
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/sync_skills.py
Or inline (no script dependency):
python3 - <<'PY'
import hashlib, os, pathlib, re, sys
ROOT = pathlib.Path(os.environ.get("CLAUDE_PLUGIN_ROOT") or pathlib.Path(__file__).resolve().parents[2])
HOME = pathlib.Path.home()
def read_frontmatter(path):
text = path.read_text()
m = re.match(r'^---\n(.*?)\n---\n', text, re.DOTALL)
if not m:
return {}
fm = {}
for line in m.group(1).splitlines():
if ':' in line:
k, v = line.split(':', 1)
fm[k.strip()] = v.strip().strip('"').strip("'")
return fm
def find_canonical(rel_path):
for parent in [HOME / "dev" / "git-folder", ROOT.parent, pathlib.Path.cwd()]:
candidate = parent / rel_path
if candidate.exists():
return candidate
return None
drift = []
checked = 0
for tree in ["skills/architecture"]:
for skill_md in (ROOT / tree).rglob("SKILL.md"):
fm = read_frontmatter(skill_md)
src = fm.get("source")
expected_hash = fm.get("source_hash")
if not src or not expected_hash:
continue
canonical = find_canonical(src)
rel = skill_md.relative_to(ROOT)
checked += 1
if not canonical:
drift.append((str(rel), "MISSING", "canonical source not found: " + src))
continue
actual = hashlib.sha256(canonical.read_bytes()).hexdigest()
if actual != expected_hash:
drift.append((str(rel), "DRIFT", f"expected {expected_hash[:12]} got {actual[:12]}"))
print(f"Checked: {checked} skills")
if not drift:
print("Status: clean — no drift")
sys.exit(0)
print(f"Status: {len(drift)} drift(s)")
for rel, kind, detail in drift:
print(f" [{kind}] {rel}")
print(f" {detail}")
print()
print("Refresh: rerun build-loop:sync-skills with --refresh after reviewing the canonical diff,")
print("or invoke the orchestrator to re-import the affected skill(s).")
sys.exit(1 if drift else 0)
PY
Output
- Clean:
Checked: 10 skills. Status: clean — no drift.
- Drift detected: list of
<skill path> | DRIFT | expected <hash-prefix> got <hash-prefix> plus one-line refresh hint
- Missing canonical: list of
<skill path> | MISSING | canonical source not found: <path> — means upstream repo moved or was deleted
What This Skill Does NOT Do
- Does not auto-update SKILL.md files (refresh is a deliberate, reviewed action)
- Does not modify the canonical source repos
- Does not re-import — the user (or build-orchestrator on user request) re-runs the import flow
How to Refresh a Drifted Skill
- Read the canonical source file at the path in
source:
- Diff against the local SKILL.md (skipping the rewritten frontmatter and any build-loop-specific sibling-skill references)
- Decide: pull the upstream change, keep local fork, or escalate to user
- If pulling: re-author the local SKILL.md preserving the build-loop-specific framing (skill name, sibling references), recompute
source_hash, update frontmatter
- Re-run
build-loop:sync-skills to confirm drift cleared
Locations Walked
skills/architecture/scan/SKILL.md
skills/architecture/impact/SKILL.md
skills/architecture/trace/SKILL.md
skills/architecture/rules/SKILL.md
skills/architecture/dead/SKILL.md
skills/architecture/review/SKILL.md
(The former skills/debugging/{memory,store,assess} skills were folded into the
debugging-memory skill's op reference files on 2026-07, pool-consolidation Inc 5;
they are native/adapted with no canonical upstream, so drift-detection for them is
retired. debug-loop lives at skills/debug-loop/ and was never drift-checked.)
Sibling Skills
- All skills under
build-loop:architecture-* — drift-checked by this skill
- All skills under
build-loop:debugging-* — drift-checked by this skill
Native to build-loop. Not copied from any upstream — this is the drift-detector itself.