harness-sync · git:20261010.b5821aa · 2026-10-10 · sha256 13d522bca21e81fa
harness-sync git:20261010.b5821aaA
Immutable. This exact content never changes and is served at /api/v1/blob/13d522bca21e81fa.
--- name: harness-sync description: "One-way sync of origin-filtered components from ~/.claude to the public repos (claude-harness and the single-skill repos). Use when publishing or updating harness skills in the public repos (公開 repo に同期)." user-invocable: true origin: shimo4228 --- # /harness-sync — 公開 repo への一方向エクスポート ローカルの生きた harness (~/.claude) と公開 artifact repo は**目的の違う別 repo** として保ち、 remote 直結ではなく **filter 付き一方向コピー**で同期する。公開境界は script の origin filter 1 箇所で宣言的に管理される。 ## なぜ remote 直結にしないか - ~/.claude は実行時状態 (settings, metrics, session 情報) を含む生きたディレクトリで、 gitignore の永久警戒を前提にした公開はミス耐性がゼロ - origin filter は出自の記録であって再配布権の整理ではない (外部 origin はライセンス 整備が別途必要) - 目的の違う repo 間は丸コピが調整コスト最小 (duplicate over coordination) ## Workflow ### 1. Dry-run で差分を確認 ```bash bash <公開repo>/scripts/sync-from-local.sh --dry-run ``` 差分の要約 (新規 / 変更 / 削除されるコンポーネント) をユーザーに提示する。 ### 2. 公開スコープ確認 task request / approved plan に列挙された repo と component は追加確認なしで進める。 列挙外の repo・新規公開 component が見つかった場合だけ scope change として停止する。 ### 3. 適用 ```bash bash <公開repo>/scripts/sync-from-local.sh ``` script は staging 収集 → runtime artifact と保守用 file の除去 (results.json, __pycache__, MAINTENANCE.md 等) → frontmatter YAML 検証 (GitHub 等の厳密パーサ基準。invalid なら abort) → secret scan (検出時 abort) → skills/ agents/ rules/ docs/adr/ docs/plans/ rfcs/ hooks/ scripts/hooks/ tests/ subtree の置換、まで行う。origin filter が効くのは skills/ agents/ rules/ だけで、 残りは別の規則で決まる (いずれも集約 repo のみ): - `docs/adr/` — ADR はハーネス自身の設計判断の記録で定義上すべて自作のため、origin filter を 掛けずディレクトリ丸ごとが対象。以後の ADR は公開される前提で書く。 - `rfcs/` — 台帳エントリも自作の判断記録なので ADR と同じく丸ごと (ADR-0049)。起票は公開可能な書き方が既定 — 機微はリンク先へ (task-stocktake の公開規約)。 - `docs/plans/` — 承認して commit した plan。ADR / RFC から相対リンクされる原本 (ADR-0085)。集めるのは git が追跡している plan だけで、untracked・未 commit の変更があれば abort する。公開可能な書き方が既定で、`$HOME` の実値を含む行があると script の home-directory path scan が abort する — `~/` に書き直す。 - `hooks/` `scripts/hooks/` `tests/` — script 内の `HOOK_ALLOWLIST` に列挙したファイルだけ。 公開は provenance でなく curation の判断 (ADR-0038)。公開対象の hook を追加・rename したら allowlist を更新する — source に無い entry があると sync は abort する。`scripts/claims.py` (台帳 CLI、rfcs/ の消費側) も allowlist 経由 — subtree 外に置かれるため削除は伝播しない (delist したら公開 repo 側で手動削除)。install 手順の正本は 公開 repo の `docs/hooks.md` で、これは subtree の**外**にある (中に置くと sync で消える)。 script は commit しない。LLM 側で diff と secret scan の結果を確認してから次へ進む。 ### 4. ドキュメント整合 (LLM 側の責務) 構成が変わったら、公開 repo の以下を確認する: - `docs/components.md` / `docs/components.ja.md` の skill/agent/rule テーブルは **GENERATED マーカー間で apply 時に script 自動再生成**される(README は表を持たず、このページを指すだけ。表が README の約 16k 字を 占め、LLM の取得が初回で切れたため — ADR-0091)(`skills-table` / `agents-table` / `rules-table`。 membership は origin filter が正、Purpose 列は既存キュレーションを保持し新規のみ seed)。 手で直すのは **Purpose 文面と周辺 prose のみ**。**集約カウント("N skills" 等)はどこにも 書かない**(No-volatile-state。churning count は焼き込むと drift する) - **repo の About(description)も同様に volatile-free に保つ** — 数字を入れず、 価値提案(何を pick できるか)で記述する。`gh repo edit --description` で編集 - `docs/hooks.md` — **script 生成ではない手書き doc**。hook の発火条件・bypass 変数・ `settings.json` 断片・bats 被覆を持つので、公開 hook を足す / 挙動を変えたら手で追随する - `llms.txt` / `llms-full.txt` — **退役した component の行を消すのは機械検査で確認する** (下の 4b)。文面の質は `llms-txt-writer` に defer - 集約 repo の `docs/components.md` の「Upstream components」節も **script 生成**(marker 間を apply 時に 自動再生成、外部 origin の名前のみ・ECC トップリンクのみ)— 手で編集しない ### 4b. 公開前リンク検査(機械、blocking、全モード) apply の後・commit の**前**に、対象の公開 repo ごとに走らせる。集約・skill repo・rule repo・ plugin variant のどのモードでも同じ。どれかが非 0 なら直すまで commit しない: ```bash python3 ~/.claude/skills/context-sync/scripts/context_evidence.py --root <公開repo> --gate --gate-readme python3 ~/.claude/skills/harness-sync/scripts/public_links.py --root <公開repo> --owner shimo4228 --clones ~/MyAI_Lab [ -f <公開repo>/.claude-plugin/marketplace.json ] && claude plugin validate <公開repo> ``` | 検査 | 見るもの | |---|---| | `context_evidence.py --gate` | `adr_index` / `graph_jsonld` / `llms_txt`(llms.txt と llms-full.txt の repo 内相対リンク)。集約 repo は `docs/adr/` を丸ごと持つので ADR index drift でも鳴る | | `--gate-readme` | README.md・README.*.md・CHANGELOG.md の repo 内相対リンク(suffix でなく root からの完全一致) | | `public_links.py` | root docs の `github.com/shimo4228/<repo>[/(blob\|tree)/<ref>/<path>]` と raw リンク: repo が public の現名か、path がその ref に在るか(clone が無い・古いときは `gh api`。確かめられなかった path も違反) | | `claude plugin validate` | marketplace manifest の形(`name`・`owner`・`plugins` 必須) | exit 3 = 違反(2 = 実行不能)。出力行がどの検査かを名指しするので、そこを読む。 **この検査が要る理由は削除と変更の非対称にある。** subtree の丸ごと置換は退役した skill を 公開側から消すが、README・llms.txt・CHANGELOG は root files として不可侵で、手で保守する 文書のまま残る。repo 間リンクは相手の repo の変更で切れる。どちらも sync 自身は気づかない。 **agent を経由しない sync はこの検査を通らない。** sync 自身が作る壊れ方(root files が payload に無い `skills/` パスを指す)は vendored の `scripts/sync-from-local.sh` が apply 前に abort する。repo 間リンクは相手側の変更でも切れるので、`public_links.py` を全公開 repo に ときどき走らせる(repo-asset-stocktake の棚卸しのついでなど)。凍結済みで sync が abort する repo はこの経路を通らないので、その棚卸しが唯一の検査になる。 ### 5. コミット commit の前に `find <公開repo> -name MAINTENANCE.md` が空であることを確かめる — skill の `MAINTENANCE.md` は 保守者向けで公開しない(script の除去が漏れたら commit せず script を直す)。 ```bash git -C <公開repo> add -A git -C <公開repo> commit ``` メッセージ例: `chore: sync from local harness (origin: shimo4228)` + 主な増減を body に。 default branch へ直接 commit するのは意図的(sync = mirror 更新であり branch-first 規約の対象外)。 task request が push まで含む場合は追加確認せず push する。 ## 削除の伝播 claude-harness の script は subtree を丸ごと置換するため、ローカルで退役した skill や origin が変わったファイルは公開側からも消える。退役理由は ~/.claude 側の ADR にあるので、 公開側 commit message から参照する。 skill repo の script は逆に**削除を伝播しない**: 対象 skill を repo 自身の `skills/` 配下から導出するため、harness 側に skill が無い・origin が一致しない場合は skip ではなく **abort** する(公開済み skill が静かに消えるのを防ぐ)。skill を退役させる場合は repo 側で明示的に削除する。 ## Skill repo sync モード 単独 skill repo (1 repo = 1 skill) も同じ workflow (dry-run → scope 確認 → apply → docs 整合 → 4b → commit) で同期する。違いは script だけ: - 対象 skill は **repo 自身の `skills/` 配下ディレクトリ名から導出**(これにより script は 全 skill repo で byte-identical に vendor できる) - script の正本は `templates/skill-repo-sync-from-local.sh`(この skill の中)。直すときはそこを直し、 全 skill repo の `scripts/sync-from-local.sh` へ copy する。正本は apply 前に、root files が payload に 無い `skills/` パスを指していないかを検査して abort する(4b の「sync 自身が作る壊れ方」) - 置換対象は `skills/<name>/` のみ。agents/ rules/ は扱わない - root files (README / llms.txt / CHANGELOG / LICENSE) 不可侵、commit しない、は共通 **対象は harness が正本の skill のみ**。CA 等 project 運用版から汎用化 fork した curated skill repo (code-and-llm-collaboration, llm-agent-security-principles) には script を置かない — 丸ごと置換が汎用化リライトを上書きしてしまうため、手動 curation で 更新する。 ### Rule repo variant 単独 **rule** repo (1 repo = 1 rule file) も同じ workflow だが script が違う: 対象は `skills/<name>/` ではなく固定の単一ファイル `rules/common/<name>.md` を publish する (source = `~/.claude/rules/common/<name>.md`)。origin marker は rule ファイルの HTML コメント (`<!-- origin: shimo4228 -->`) を `head -15 | grep` で検出する。secret scan・ root files 不可侵・commit しない、は共通。 ### Rule + plugin repo variant (akc-cycle) `akc-cycle` は **rule + Claude Code plugin** repo。**rule は sync 対象外**: repo が自己完結版 (self-contained edition) を所有し、harness 側はポインター版 — 別内容が意図 (ADR-0018 / ADR-0035 「圧縮版を配布 repo へ同期しない」)。script は固定 allowlist 方式: 対象 skills の正本は script の `SKILLS=` 配列(AKC cycle phase binding の skill 群。payload は skills のみで agent を持たない)。allowlist に harness 側で退役した component が残っていると sync は abort する — その場合は repo 側で allowlist から外し、payload の 増減として plugin.json の version と CHANGELOG を更新する。 staging → prune → YAML frontmatter 検証 → secret scan → subtree 置換 (skills/)。 allowlist の component が harness に無い / origin marker が無いと abort (silently drop しない)。**`.claude-plugin/plugin.json` / `marketplace.json` と `rules/common/akc-cycle.md` は repo 側 root 資産** (README / LICENSE と同格) — sync は触らない。version 更新は plugin.json を repo 側で手動 bump する。plugin は rules を運べない (Claude Code plugin 仕様) ため、rule file は plugin payload 外の copy-install 経路のまま。 `herdr-toolkit` は同型の **skills-only plugin variant**: 固定 allowlist は 2 skills (spawn-session, agent-send) で rule / agent 収集ブロックを持たない。spawn.sh は兄弟 skill の agent-send を呼ぶので、2 つは一緒に publish する。 外部 origin の `herdr` skill 本体は Herdr 自身の integration が配るため対象外 (ADR-0036)。 ## Skill repo packaging(命名と subagent 同梱) skill repo を GitHub 公開する際の規約(正本): - **subagent 同梱**: skill が呼ぶ subagent は repo に同梱する。同梱しないと installer が agent を別途探す羽目になり、canonical rules を agent が SKILL.md から参照する orchestrator skill は両方入れるまで壊れる。 - **命名の非対称**: skill(SKILL.md)はオープンな cross-tool 標準(Agent Skills / agentskills.io — Codex / Gemini CLI / Cursor 等でも動く)、subagent(`agents/*.md`)は Claude Code 固有。→ **agent を同梱する repo は `claude-skill-` prefix を維持**し `compatibility` frontmatter に Claude Code 向けと明記。**pure-skill repo は prefix を 外す**(`<owner>/<skill-name>`)。awesome-list 掲載は `owner/skill-name` で並び repo prefix を見ないので、命名は意味の正確さで決める。 - **レイアウト**: `install.sh`(skills/* → ~/.claude/skills/、agents/*.md → ~/.claude/agents/)+ `skills/<name>/SKILL.md` + `agents/<agent>.md`(top-level フラット。 nest しない)。pure-skill repo は install.sh 省略可(citation-sync 等の先例)。 - **install.sh は冪等**: 同一なら skip(`.venv` とキャッシュは比較しない)、異なれば `~/.claude/backups/install-<ts>/` に退避してから上書き(skills/ の中に残すと旧版が同名の 2 つ目の skill として読まれる) (`--force` / `--dry-run`)。全 repo で byte-identical に保つ。README install 節は Option A(`./install.sh`)/ Option B(手動 `cp`)/ SkillsMP の 3 つを書く。 - **SkillsMP caveat**: `/skills add <owner/repo>` は `skills/` のみ install し `agents/` は入れない。agent 同梱 repo の README に必ず注記する(`cp agents/*.md ~/.claude/agents/` または `install.sh` を実行)。 - **自分のファイルは skill ディレクトリの変数で指す**: `~/.claude/skills/<name>` を SKILL.md に書かない (install 先が違うと壊れる)。変数名・兄弟と他 skill の書き方・その場で読み替えを書く 1 行は skill-creator の `references/portability.md` が正本(SKILL.md 本文に変数名を書くと読み込み時に置換されるので、ここには書かない)。 dangling 検査は skill-health の `scan_refs.py` が変数を展開して行う。 - **単独 skill repo は `.claude-plugin/` を持たない**: plugin の経路は plugin repo(akc-cycle など)に寄せる。 単独 repo にも置くと同じ skill を別の名前空間で二重に配り、version を保守するファイルも増える。 置くなら `claude plugin validate` が通ること(4b) - **公開用 packaging metadata は local 正本に持たせる**: `compatibility:` 等の公開向け frontmatter を repo 側で足すと、丸ごと置換のたびに消える(= 恒常的な偽 drift 源)。 local SKILL.md の frontmatter に持たせる — Claude Code は未知キーを無視するので無害。 ## Repo mapping (project-specific) | target | 種別 | script | 正本 | |---|---|---|---| | `~/MyAI_Lab/claude-harness` ([repo](https://github.com/shimo4228/claude-harness)) | 集約 (skills + agents + rules + ADRs) | `scripts/sync-from-local.sh` (集約版) | `~/.claude` | | `~/MyAI_Lab/signal-first-research` ([repo](https://github.com/shimo4228/signal-first-research)) | 単独 skill | script sync 停止 (local 正本を retire 済み — abort する) | なし (repo 凍結 — AKC の citable design-pattern artifact として存続。原則の正本は `search-first` 等の消費 skill、ADR-0026) | | `~/MyAI_Lab/citation-sync` ([repo](https://github.com/shimo4228/citation-sync)) | 単独 skill | `scripts/sync-from-local.sh` (skill repo 版) | `~/MyAI_Lab/paper-lab/.claude/skills/citation-sync`(RFC-0019) | | `~/MyAI_Lab/generation-audit` ([repo](https://github.com/shimo4228/generation-audit)) | 単独 skill | `scripts/sync-from-local.sh` (skill repo 版) | `~/.claude/skills/generation-audit` | | `~/MyAI_Lab/agent-stocktake` ([repo](https://github.com/shimo4228/agent-stocktake)) | 単独 skill | `scripts/sync-from-local.sh` (skill repo 版) | `~/.claude/skills/agent-stocktake` | | `~/MyAI_Lab/human-gate` ([repo](https://github.com/shimo4228/human-gate)) | retired rule artifact | sync abort(local scaffold は退役済み) | なし(公開記録として凍結) | | `~/MyAI_Lab/rules-stocktake` ([repo](https://github.com/shimo4228/rules-stocktake)) | 単独 skill | `scripts/sync-from-local.sh` (skill repo 版) | `~/.claude/skills/rules-stocktake` | | `~/MyAI_Lab/learn-eval` ([repo](https://github.com/shimo4228/learn-eval)) | 単独 skill | `scripts/sync-from-local.sh` (skill repo 版) | `~/.claude/skills/learn-eval` | | `~/MyAI_Lab/rules-distill` ([repo](https://github.com/shimo4228/rules-distill)) | 単独 skill | `scripts/sync-from-local.sh` (skill repo 版) | `~/.claude/skills/rules-distill` | | `~/MyAI_Lab/skill-stocktake` ([repo](https://github.com/shimo4228/skill-stocktake)) | 単独 skill | `scripts/sync-from-local.sh` (skill repo 版) | `~/.claude/skills/skill-stocktake` | | `~/MyAI_Lab/skill-health` ([repo](https://github.com/shimo4228/skill-health)) | 単独 skill | `scripts/sync-from-local.sh` (skill repo 版) | `~/.claude/skills/skill-health` | | `~/MyAI_Lab/akc-cycle` ([repo](https://github.com/shimo4228/akc-cycle)) | plugin (固定 allowlist) + repo 所有 rule (自己完結版、sync 対象外) | `scripts/sync-from-local.sh` (plugin 版、固定 allowlist、agents なし) | 対象 skills のみ (rule の正本は repo 側。harness の `rules/common/akc-cycle.md` はポインター版で別内容) | | `~/MyAI_Lab/herdr-toolkit` ([repo](https://github.com/shimo4228/herdr-toolkit)) | plugin (2 skills) | `scripts/sync-from-local.sh` (plugin 版、固定 allowlist、rules/agents なし) | `~/.claude/skills/spawn-session`, `~/.claude/skills/agent-send` | | `~/MyAI_Lab/jev-skill-router` ([repo](https://github.com/shimo4228/jev-skill-router)) | plugin (hook + skill) | `tools/sync-from-local.sh` (plugin 版、固定 allowlist。`.claude-plugin/`・`hooks/`・README は repo root 資産) | `~/.claude/skills/jev-skill-router` | | `~/MyAI_Lab/codex-review` ([repo](https://github.com/shimo4228/codex-review)) | 単独 skill | sync abort(local 正本を退役済み) | なし(公開記録として凍結) | | `~/MyAI_Lab/when-code-when-llm` ([repo](https://github.com/shimo4228/when-code-when-llm)) | 単独 skill | sync abort(local 正本を退役済み) | なし(公開記録として凍結) | | `~/MyAI_Lab/wikidata-federation`(GitHub 上の repo は無い) | 単独 skill(local のみ) | sync abort(local 正本を退役済み) | なし(push 先が無いので同期しない) | | `~/MyAI_Lab/authorship-strategy-rules` ([repo](https://github.com/shimo4228/authorship-strategy-rules)) | rule | sync abort(local の `rules/common/authorship-strategy.md` を退役済み) | なし(公開記録として凍結) | | `~/MyAI_Lab/skill-comply` ([repo](https://github.com/shimo4228/skill-comply)) | 単独 skill | `scripts/sync-from-local.sh` (skill repo 版) | `~/.claude/skills/skill-comply` | | `~/MyAI_Lab/context-sync` ([repo](https://github.com/shimo4228/context-sync)) | 単独 skill | `scripts/sync-from-local.sh` (skill repo 版) | `~/.claude/skills/context-sync` | | `~/MyAI_Lab/llms-txt-writer` ([repo](https://github.com/shimo4228/llms-txt-writer)) | 単独 skill | `scripts/sync-from-local.sh` (skill repo 版) | `~/.claude/skills/llms-txt-writer` | | `~/MyAI_Lab/readme-writer` ([repo](https://github.com/shimo4228/readme-writer)) | skill + agent 同梱 | `scripts/sync-from-local.sh` (skill repo 版) | `~/.claude/skills/readme-writer`(同梱 agent `agents/readme-judge.md` の正本は `~/.claude/agents/readme-judge.md`、script の対象外で手動 diff) | | `~/MyAI_Lab/release-doi` ([repo](https://github.com/shimo4228/release-doi)) | 単独 skill | `scripts/sync-from-local.sh` (skill repo 版) | `~/.claude/skills/release-doi` | | `~/MyAI_Lab/search-first` ([repo](https://github.com/shimo4228/search-first)) | 単独 skill | `scripts/sync-from-local.sh` (skill repo 版) | `~/.claude/skills/search-first` | | `~/MyAI_Lab/jsonld-knowledge-graph` ([repo](https://github.com/shimo4228/jsonld-knowledge-graph)) | 単独 skill | `scripts/sync-from-local.sh` (skill repo 版) | `~/.claude/skills/jsonld-knowledge-graph` | | `~/MyAI_Lab/authorship-strategy-skill` ([repo](https://github.com/shimo4228/authorship-strategy-skill)) | 単独 skill | `scripts/sync-from-local.sh` (skill repo 版) | `~/.claude/skills/authorship-strategy` | | `~/MyAI_Lab/repo-asset-stocktake` ([repo](https://github.com/shimo4228/repo-asset-stocktake)) | 単独 skill | `scripts/sync-from-local.sh` (skill repo 版) | `~/.claude/skills/repo-asset-stocktake` | | `~/MyAI_Lab/llm-as-judge` ([repo](https://github.com/shimo4228/llm-as-judge)) | 単独 skill | `scripts/sync-from-local.sh` (skill repo 版) | `~/.claude/skills/llm-as-judge` | | `~/MyAI_Lab/claude-skill-paper-ecosystem` ([repo](https://github.com/shimo4228/claude-skill-paper-ecosystem)) | skill ×2 + agents 同梱 | `scripts/sync-from-local.sh` (skill repo 版) | `~/MyAI_Lab/paper-lab/.claude/skills/paper-ecosystem` + 同 `paper-writing`(RFC-0019。同梱 agents の正本は `~/MyAI_Lab/paper-lab/.claude/agents/`、script の対象外で手動 diff) | | `~/MyAI_Lab/claude-skill-writing-ecosystem` ([repo](https://github.com/shimo4228/claude-skill-writing-ecosystem)) | skill + agents 同梱 | `scripts/sync-from-local.sh` (skill repo 版) | `~/MyAI_Lab/zenn-content/.claude/skills/writing-ecosystem`(RFC-0019。同梱 agents の正本は `~/MyAI_Lab/zenn-content/.claude/agents/`、同梱 rule `rules/writing-principles.md` の正本は `~/MyAI_Lab/zenn-content/.claude/rules/writing-principles.md`(zenn-content ADR-0014)、いずれも script の対象外で手動 diff) | 共通 env: origin filter `shimo4228` (`HARNESS_SYNC_ORIGIN`)、source (`HARNESS_SYNC_SOURCE`)。source の既定は `~/.claude` だが、正本を移設した 3 repo(citation-sync / paper-ecosystem / writing-ecosystem)だけは script 側の既定が移設先を指す(RFC-0019 手段 A)。既定以外を使うときは env で上書きする。 ### 手動 diff 確認が残る対象(script が置換しないもの) skill 本体の drift は script が拾う。手動 diff の対象は **script が置換しない同梱物だけ**: - **agents/*.md**(`claude-skill-paper-ecosystem` / `claude-skill-writing-ecosystem` / `readme-writer` の 同梱 subagent。正本は writing 系が `~/MyAI_Lab/zenn-content/.claude/agents/`、 paper 系が `~/MyAI_Lab/paper-lab/.claude/agents/`、readme-writer が `~/.claude/agents/readme-judge.md`) - **rules/writing-principles.md**(`claude-skill-writing-ecosystem` の同梱 rule。writing-ecosystem の 背骨で、同梱しないと公開版 skill は原理を失う。正本 `~/MyAI_Lab/zenn-content/.claude/rules/writing-principles.md`) - **hook script**(例: skill-stocktake の `hooks/log-skill-usage.sh`。正本 `~/.claude/hooks/`) - **repo root の `inspiration.md`**(repo 固有文書。harness に正本なし — diff 対象外だが、 `skills/<name>/` 配下に置くと置換で消えるため root に置く) **script を置かない repo**: 汎用化 fork の curated repo(`code-and-llm-collaboration`, `llm-agent-security-principles` — 意図的に乖離、diff 同期しない)と、harness に正本を 持たない repo 単独 skill(`agent-adoption-triage` 等)。新しい単独 skill repo を作ったら **script を vendor するのが default** — 例外にする場合はここに理由ごと追記する。