WHAT
Purpose and context
- Purpose: Sync structural/template improvements between project and
https://github.com/Rheinmir/setup.git. - Trigger (when to use):
- Upstream: Improved template locally → save to Master.
- Downstream: Master has newer fixes → bring into project.
- Non-goals: do not sync
.env, credentials, business docs; do not--strategy pullto shorten time; do notgit clonetemplate; do not self-trigger (disable-model-invocation: true); Antigravity cannot run this skill (sandbox blocks tool).
Mental model
Downstream by default: version.json + manifest remote → phân loại hash 3 mốc (disk ↔ R0 remote_synced ↔ remote hiện tại) → NEW/UPDATE tự PULL · KEPT giữ · CONFLICT giữ local + lưu bản remote → OKF backfill → fingerprint → cài skill 3 chỗ → verify 3 vị trí → log. Upstream / migrate / debug go through MANUAL STEPS 0–8 with a STOP point asking the user at Step 5.
Input and output contract
| Field | Required? | Meaning | |
|---|---|---|---|
| In | sync direction | yes | downstream (default, FAST PATH) or upstream (MANUAL) |
| In | .template-manifest.json + harness/version.json |
yes | inclusion list, remote URL, branch, remote_synced |
| In | --branch, --strategy pull, --dry-run, --json |
no | change branch, fetch remote for CONFLICT, preview, machine-readable output |
| In | user decision | on CONFLICT or Step 5 | fetch remote or keep local; which files to pull/push |
| Out | synced template files + OKF backfill | yes | old wiki files converted bold→YAML |
| Out | harness/version.json refresh |
yes | fingerprint after OKF + template_version + remote_synced |
| Out | skill installed at .claude/commands/, ~/.claude/skills/, ~/.claude/commands/ |
downstream | verify 3 locations |
| Out | report + exit code | yes | 0 clean, 1 download/OKF/verify error, 3 CONFLICT needs decision |
| Out | line wiki/log.md + draft output report |
yes | script auto-writes log when --full |
Rules and capabilities
- RULE-01 (MUST): NEVER sync
.env, credentials, business docs. - RULE-02 (MUST): ALWAYS audit remote branches — non-default may be newest.
- RULE-03 (MUST): ALWAYS show diff for
[CONFLICT]→ wait for instruction. - RULE-04 (MUST): NEVER
cp -R— file by file. - RULE-05 (MUST): Step 3 every sync — detect old
skills/, offer migrate. - RULE-06 (MUST): Step 7 every downstream sync — install all 3 Claude Code locations.
- RULE-07 (MUST):
[NEW]: add to manifest BEFORE upstream commit. - RULE-08 (MUST):
[MISSING]: add to manifest AFTER downstream copy. - RULE-09 (MUST): Frontmatter:
name:+description:for skills;description:only for slash commands. - RULE-10 (MUST): Skip
README.md,index.md,log.md, no-Purpose/Steps files. - Capabilities: read remote template (HTTP/GitHub API); write files in project + user-level skill/command directory; push to remote template when upstream (only after approval).
Failure boundaries
- CONFLICT (both changed) → keep local, save remote copy to
/tmp/sync-template-conflicts/, exit 3 → clarify with user. - Download / OKF / verify error → exit 1 → failed, fix
✗before finishing. - Remote branch unclear which is newest → clarify, ask user which branch.
- health-check
OK→ no sync needed, stop (succeeded no-op). - Old
skills/layout → propose migrate, confirm before deleting.
HOW
Main workflow
| Step | Type | Inputs | Action | Outputs/exit | Failure/next |
|---|---|---|---|---|---|
| W01 | judgment | request | Choose path: normal downstream → FAST PATH --full; upstream, migrate old structure, debug → MANUAL (B01) |
path | — |
| W02 | effect | manifest, remote | python3 harness/scripts/sync-template.py --full ONCE (sync + OKF + fingerprint + install 3 places + verify + log) |
report | exit 1 → failed; exit 3 → W03 |
| W03 | judgment | report | Read report; CONFLICT wanting remote → rerun --strategy pull; other branch → --branch |
decision | unclear → ask user |
| W04 | deterministic | report | Do not call additional okf-check, health-check, verify loop, do not self-edit log | report to user | — |
| W05 | effect | result | Output Report draft | draft + index + log | 0 artefacts → skip |
Step-by-step details (source of truth for W01–W05 and the MANUAL branch):
FAST PATH — downstream 1 command --full (< 30s, default)
Downstream sync is 1 self-contained non-interactive script. Call once with --full → all post-sync steps (Step 6a/6b/8 + log write) run in the SAME process. Agent reads 1 report then reports — do NOT repeat separate commands. Bench this repo: full steady-state 0.27s · full pull+install+verify 0.76s (harness/metrics/sync-template-bench.json).
python3 harness/scripts/sync-template.py --full # ⭐ MẶC ĐỊNH: sync + OKF backfill + fingerprint + verify ×3 + ghi log, 1 process
python3 harness/scripts/sync-template.py --full --json # như trên, output máy đọc (đọc okf_migrated / verify_bad)
python3 harness/scripts/sync-template.py --dry-run # xem trước, không ghi (kèm --full để xem OKF sẽ migrate gì)
python3 harness/scripts/sync-template.py --strategy pull # ghi đè cả CONFLICT bằng remote (backup .local-bak)
Run
--fullone pass and done — don't call againokf-check,health-check --update, the verify round, or self-Editlog.md (the script already did it all). That's how to keep the skill under 30s: the old bottleneck was the number of agent round-trips around the post-sync steps, not CPU. No flag--full= exact old behavior.
Classify by 3-point hash — disk ↔ R0 (remote at previous sync, stored in version.json:remote_synced) ↔ current remote:
NEW(missing local) +UPDATE(remote newer, local untouched) → auto PULL.KEPT(I've customized it, remote not newer) → leave as is, no asking.CONFLICT(both changed) → default keep local + save the remote version to/tmp/sync-template-conflicts/for diffing; exit code 3. Never auto--strategy pullto shorten the time.
Automated process in the script (--full): fetch remote version.json+manifest → classify → parallel download → OKF backfill in-process (migrate bold→YAML, idempotent) → refresh version.json (fingerprint AFTER OKF + template_version + remote_synced) → install skill to 3 places (.claude/commands/, ~/.claude/skills/, ~/.claude/commands/) → self-verify 3 locations → append wiki/log.md. Exit: 0 clean · 1 download/OKF/verify error · 3 CONFLICT needs a decision.
When you NEED to step in manually (run the script first, read the report):
- Report has
CONFLICTand you want to take the remote → rerun--strategy pull(1 decision, not 3). - Remote branch DIFFERENT from
version.json:branch→--branch <tên>(see Step 2 to audit branches). - Structure
skills/old and needs migration (Step 3), or you need upstream (push up) → use MANUAL STEPS below.
⚠ Bug already fixed:
health-check --updateset baseline = disk → sync COULDN'T tell "remote newer" from "I've customized" → nearly overwrote customized files. This script uses a separate baselineremote_synced(remote hash at previous sync) so it classifies correctly. Don't go back to usingpatterns(disk) as the classification baseline.
MANUAL STEPS (fallback — upstream, migrate old structure, or debug)
Step 0: Pre-flight — health-check (diagnose before syncing)
Run /health-check (python3 harness/scripts/health-check.py --root .) to know WHICH WAY to sync:
NEEDS-SYNC(behind/missing) → downstream (pull down).DRIFT(locally modified) → upstream (push up) or revert.OK→ no sync needed, stop.
Step 1: Load Manifest
Read .template-manifest.json — inclusion list + remote URL.
Step 2: Fetch & Branch Audit
- CRITICAL: List all remote branches:
gh api repos/<owner>/<repo>/branches. - Check commit date per branch — don't assume
master/mainis newest. - Unclear → ask user which branch.
- Fetch via
gh api+curl— nogit clone.
Step 3: Detect Old Structure Migration
Check for old skills/ layout needing migration to llmwiki/:
# Signs of old structure:
[ -d "skills/" ] && [ ! -d "llmwiki/skills/" ] # old only
[ -d "skills/" ] && [ -d "llmwiki/skills/" ] # both exist → migration in progress
Old skills/ + new llmwiki/skills/ coexist:
- List
skills/(flat .md + subdirs:dev-loop/,wiki-loop/, etc.) - Map old → new:
skills/dev-loop/*.md→llmwiki/skills/dev-loop/*.mdskills/wiki-loop/*.md→llmwiki/skills/wiki-loop/*.mdskills/orchestrate/*.md→llmwiki/skills/orchestrate/*.mdskills/utils/*.md→llmwiki/skills/utils/*.mdskills/*.md(flat) → already covered by subdirs, skip duplicates
- Content matches → old stale, safe to remove.
- Show migration table → confirm before delete.
Step 4: Compare Manifest Files
diff local vs remote for each file in includes:
BASE="https://raw.githubusercontent.com/<owner>/<repo>/<branch>"
for file in <includes>; do
http_code=$(curl -s -o /dev/null -w "%{http_code}" "$BASE/$file")
# SAME / DIFF / MISSING / NEW / ABSENT
done
Status:
SAME— skipDIFF— content differsMISSING— remote only → downstream candidateNEW— local only → upstream candidateABSENT— neither
Step 5: Sync Plan
Show table. STOP → ask user: pull all / push all / specific files / direction per DIFF.
Step 6: Execute
- Downstream:
mkdir -p→curl -sfL <url> -o <local_path>→ updatewiki/log.md - Upstream: commit + push via
gh/git - File by file — no
cp -R
Step 6a/6b/8 have been MERGED into
--full. If you run FAST PATH--fullthen SKIP 6a/6b/8 — the script has already OKF-backfilled + refreshed fingerprint + verified + written log in process. The steps below are only used when running MANUAL (debug / upstream / old-structure migration), not after--full.
Step 6a: OKF backfill (MANUAL — --full already done)
A new template/skill may upgrade the wiki format (e.g. OKF v0.1 standard). After pulling, convert all old content files still using bold pseudo-frontmatter **Type:** to YAML frontmatter to avoid tripping R9:
python3 harness/scripts/okf-check.py --check # exit 3 = có file chưa đạt OKF
python3 harness/scripts/okf-check.py --migrate # convert bold → YAML (chỉ THÊM frontmatter, giữ body/## Origin)
- Idempotent — files that already have
---frontmatter are skipped. Reserved (index/log/README/decisions/_template…) are exempt. - After migrating: re-run
--checkuntilDAT CHUAN OKF v0.1, then update index/log like any wiki change.
Step 6b: Refresh version fingerprint (MANUAL — --full already done)
The pattern content just changed → update harness/version.json so the health-check stops reporting false DRIFT:
python3 harness/scripts/health-check.py --update # KHÔNG --bump ở project con
--bump major|minor|patchONLY run in the template repoRheinmir/setupwhen RELEASING a new pattern version.- Upstream sync in the template repo: after pushing, run
--update --bump <part>then commitharness/version.json.
Step 7: Install as Native Skills (runs every downstream sync)
Collect skill files synced (under llmwiki/skills/ in manifest). Skip: README.md, index.md, log.md, no-## Purpose/## Steps files.
A. Project-level (.claude/commands/ — this repo):
mkdir -p .claude/commands/
# Add description: frontmatter if missing, then copy
printf -- "---\ndescription: %s\n---\n\n" "$desc" | cat - <src> > .claude/commands/<name>.md
B. Global user-level (~/.claude/skills/<name>/SKILL.md — all projects):
mkdir -p ~/.claude/skills/<name>/
# Requires name: + description: frontmatter
printf -- "---\nname: %s\ndescription: %s\n---\n\n" "$name" "$desc" | cat - <src> > ~/.claude/skills/<name>/SKILL.md
C. Global slash command (~/.claude/commands/<name>.md):
printf -- "---\ndescription: %s\n---\n\n" "$desc" | cat - <src> > ~/.claude/commands/<name>.md
Install all 3. Report:
| Skill | Project .claude/commands/ | ~/.claude/skills/ | ~/.claude/commands/ |
|----------------|---------------------------|-------------------|---------------------|
| propose | ✓ | ✓ | ✓ |
| ingest | ✓ | ✓ | ✓ |
| ... | ... | ... | ... |
Step 8: Verify & Finalize
for name in <skill-list>; do
[ -f ".claude/commands/$name.md" ] && echo "✓ proj $name" || echo "✗ proj $name"
[ -f "$HOME/.claude/skills/$name/SKILL.md" ] && echo "✓ global $name" || echo "✗ global $name"
done
Fix ✗ before done. No restart needed.
Branches
| ID | Kind | Guard | Behavior | Skip / failure | Rejoin |
|---|---|---|---|---|---|
| B01 | conditional_required | requires upstream, migrate old structure skills/ or debug |
run MANUAL STEPS 0–8, STOP and ask user at Step 5 | downstream usually → FAST PATH | W05 |
| B02 | recovery | exit 3 CONFLICT and user chooses to take remote | re-run --strategy pull (overwrite, backup .local-bak) |
user keeps local → do nothing | W04 |
| B03 | conditional_required | remote branch differs version.json:branch |
--branch <tên> after auditing branch (Step 2) |
— | W02 |
| B04 | user_optional | want to preview | --dry-run (with --full to see what OKF will migrate) |
— | W02 |
| B05 | conditional_required | detect old skills/ layout (Step 3) |
show migration table, confirm then delete | user refuses → keep | W05 |
Validation and stopping
Deterministic: script exit code (0/1/3), self-verify 3 install locations, okf-check.py --check to DAT CHUAN OKF v0.1 (MANUAL), loop [ -f … ] Step 8 no longer ✗. Stop after ONE --full when exit 0; exit 3 stops awaiting user decision; MANUAL stops at Step 5 awaiting approval.
Examples
- Positive: child project, Master has new fix →
python3 harness/scripts/sync-template.py --full→ 2 UPDATE auto PULL, 1 KEPT left unchanged, OKF migrates 3 files, verify 3 locations ✓, exit 0 in < 1s → report, run no further commands. - Boundary/failure: file
llmwiki/skills/dev-loop/ship.mdmodified both locally and remotely → CONFLICT, keep local, remote version at/tmp/sync-template-conflicts/, exit 3 → show diff, wait for user; do not auto--strategy pull.
Reference — Agent Compatibility
| Agent | Run? | Reason |
|---|---|---|
| Claude Code | Yes | Full tool access |
| OpenCode | Yes | Full tool access |
| Antigravity | No | Sandbox blocks file/command tools |
Delivery — Output Report
After all main skill tasks complete, write a propose draft to the wiki.
Steps
1. Build the filename:
- Format:
DDMMYY-<ten>.md DDMMYY= today (e.g.,020626for 2 June 2026)<ten>= 2–4 kebab-case words summarising what was done (e.g.,landing-page-coteccons,brand-kit-fintech,ingest-auth-spec)
2. Write llmwiki/wiki/sources/draft/DDMMYY-<ten>.md:
---
type: draft
title: "DDMMYY-<ten>"
status: proposed
tags: [<skill-name>, output-report]
timestamp: YYYY-MM-DD
---
# DDMMYY-<ten>
**Type:** draft
**Status:** proposed
**Tags:** <skill-name>, output-report
**Proposed:** YYYY-MM-DD
## What
<One sentence — what this skill invocation produced or decided>
## Output
<Key artefacts, files created/modified, or decisions made>
## Files
| File | Action |
|------|--------|
| `path/to/file` | created / modified |
## Notes
- Invoked via: `/<skill-name>` skill
## Origin
- **Draft:** `wiki/sources/draft/DDMMYY-<ten>.md`
- **Commit:** _(filled by verify-before-commit)_
- **Date promoted:** _(filled by verify-before-commit)_
3. Update wiki index & log:
llmwiki/wiki/index.md— append one row:| [DDMMYY-<ten>](sources/draft/DDMMYY-<ten>.md) | draft | YYYY-MM-DD |llmwiki/wiki/log.md— append:## YYYY-MM-DD — <skill-name> — <ten>
Skip only when the skill produces zero artefacts and zero decisions (e.g., a pure display mode like
/caveman-stats).