agentleFS
TbusOSTbusOS/sky-skills/skills/gated-dual-clone/SKILL.md

gated-dual-clone

Skill3 starsChanged 33 days agoMITView on GitHub

Dual-repo git workflow bootstrapper for projects where upstream branches are protected (MR/PR required) and builds are heavy. Creates a gateway repo (push source) and a satellite repo (fetch-only build tree), with three safety gates verified post-setup and a daily-workflow cheatsheet. 双仓库 MR/PR 流 git 工作流搭建器。适用于上游分支受保护 + 编译重 + 需物理隔离防 误推的项目。 TRIGGER: "dual clone workflow", "gateway repo", "verify repo", "compile sandbox", "protected branch workflow", "双仓库工作流", "编译仓库", "gateway 仓库", "set up dual clone". DO NOT TRIGGER: single-repo direct-push flow, pure worktree setup, monorepo package management, small projects where one clone is enough.

  • Deletes or force-pushes
  • Commits and pushes

The file

We split this skill into the rules it gives an agent

2 rules. About 0 are common, 1 is distinctive, and 1 is very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    All 7 flags are required. --dry-run prints the command sequence without executing.

    line 53
  2. Distinctive:

    When ready to push, run:

    line 188

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Gated Dual-Clone Workflow

One-liner · 一句话

EN — Clone the upstream twice: a gateway repo that pushes, and a satellite repo that builds. The satellite's origin points at the local gateway path — so a stray git push from the compile tree is physically unable to reach the remote.

ZH — 把上游仓库 clone 两份:一个 gateway 仓库负责 push,一个 satellite 仓库只读编译。satellite 的 origin 指向本地 gateway 路径, 编译树里误跑一条 git push 在物理上也够不到远程。

Should I use this? · 该不该用

→ See references/decision-checklist.md

Four yes/no questions. Three or more "yes" → use this skill. Otherwise fall back to a single repo or git worktree.

四道是非题:≥ 3 个 yes 用本 skill,否则单仓库或 git worktree 更合适。

Minimal bootstrap · 最小搭建

scripts/bootstrap.sh \
  --remote          git@gitlab.example.com:team/project.git \
  --upstream-branch release \
  --push-branch     feature/alice-auth \
  --gateway-dir     ~/projects/foo-work \
  --satellite-dir   ~/projects/foo-verify \
  --user-email      alice@example.com \
  --user-name       alice

All 7 flags are required. --dry-run prints the command sequence without executing. --force is only valid for empty target dirs (non-empty is always rejected; clean up by hand first). See scripts/bootstrap.sh --help for detail.

Post-setup · 搭建完成后(3 道检查)

bootstrap.sh verifies three safety layers before exiting 0:

  • Gate A · Protocol wall — cd satellite && git push rejected ("DISABLED" in error). Satellite's origin is a local path; no network route to upstream exists.
  • Gate B · Explicit disable — Satellite's push URL is literally set to DISABLED, so even malformed config still errors fast instead of silently trying.
  • Gate C · Pre-push hook — Gateway's pre-push hook rejects any push to a protected-branch regex (default: the upstream branch passed in).

Gate failures halt bootstrap with a clear reason — nothing is left in a partial state that the user has to hand-clean.

三道检查都过才算 bootstrap 成功。任一失败会明确说明原因,不留一半成品。

Daily operations · 日常操作

→ See references/daily-workflow.md

The core loop: edit in gateway, sync satellite with scripts/sync-satellite.sh, build in satellite, push from gateway, open MR/PR. Four commands, copy-paste ready.

日常 4 步:在 gateway 里改 → sync-satellite.sh 同步到 satellite → satellite 里编译 → gateway 里 git push → GitLab / GitHub 上发 MR/PR。 cheatsheet 里每步都是现成命令。

Safety model · 安全模型

Three layers, each independent. Any one holds; all three together is belt, braces, and shoulder strap.

  1. Protocol layer — satellite's origin is a file path; no TCP/SSH route to upstream exists from the compile tree.
  2. Config layer — satellite's push URL = literal DISABLED. Explicit failure mode.
  3. Hook layer — gateway's pre-push hook rejects protected-branch refs.

Critical caveat · 关键注意: Client-side git hooks are advisory, not enforcement. --no-verify bypasses them. Real protection = server-side protected-branch rules in GitLab / GitHub / Gerrit. This skill's hook is a second layer — catches finger-slips, not determined bypass. Enable server-side branch protection alongside.

客户端 hook 只是提醒,不是强制边界。--no-verify 可以绕过。真正的保护 在托管平台的 protected-branch 规则上。本 skill 的 hook 是第二层,接手滑, 不防恶意。服务端保护一起开。

Variants · 变体

  • 1 gateway + N satellites — run bootstrap.sh again with --skip-gateway + a new --satellite-dir. Useful for verify / debug / test trees.
  • 3-clone with reproducibility gate (see below) — add a clean-verify clone on separate disk/machine, with a pre-push hook that refuses to push anything clean-verify hasn't stamped. Trade extra disk + extra build time for catching "works on SSD, fails on HDD / CI" bugs before they reach upstream.
  • Worktree fallback — if disk is tight (< 2× source size) and single developer, single machine: git worktree trades isolation for disk. See decision-checklist.md for when worktree beats this skill.
  • Hosting differences — GitLab MR, GitHub PR, Gerrit push-to-refs/for/*. The skill is host-neutral; protected-branch regex is a per-project flag.

Optional 3rd clone · reproducibility gate · 可选 第 3 仓 · reproducibility 关卡

For projects where a failed build on CI (different filesystem, different disk speed, different filesystem cache state) has a real cost — add a clean-verify clone on a separate disk (or separate machine) and gate every push on a from-scratch full-build in it.

When to use (all four should be true):

  1. Daily dev happens on SSD; CI / shipping happens on HDD or remote machine.
  2. The project has reproducibility bugs that only surface from a cold, clean tree (SSD cache / generated files / stale build artefacts hide them on the iteration clone).
  3. The push path is high-stakes (production branch, signed release, audit trail required).
  4. The team already has discipline to run a pre-push command.

Topology:

                 ┌──────────┐       ┌──────────┐       ┌───────────────────┐
   upstream ───► │ gateway  │ ────► │satellite │       │  clean-verify     │
   (push only    │ (dev +   │ sync  │ (build · │       │  (pre-push gate · │
   from gateway) │  push)   │ via   │  disabled│       │   HDD / diff disk)│
                 │   SSD    │ local │  push)   │       │                   │
                 └──▲───────┘ path  └──────────┘       └───▲───────────────┘
                    │                                       │
                    │ pre-push hook reads .git/last-clean-verify
                    │ and refuses to push a commit whose sha ≠ stamped
                    │                                       │
                    └─── clean-verify-run.sh stamps on success ─┘

Bootstrap it:

scripts/bootstrap.sh \
  --remote              git@gitlab.example.com:team/project.git \
  --upstream-branch     release \
  --push-branch         feature/alice-auth \
  --gateway-dir         ~/projects/foo-work \
  --satellite-dir       ~/projects/foo-verify \
  --clean-verify-dir    /mnt/hdd/foo-clean-verify \
  --user-email          alice@example.com \
  --user-name           alice

Same as the 2-clone bootstrap, plus --clean-verify-dir=<path>. The script adds:

  • Step 5b — git clone the clean-verify from gateway (same local-path trick as satellite · origin on a local path, never the real remote).
  • Step 6b — set pushurl = DISABLED on both origin and the diagnostic upstream remote. Check out <push-branch>.
  • Gate D — in Step 7 post-setup, verify clean-verify push is DISABLED.
  • Pre-push hook gets a 2nd gate — install-hooks.sh is invoked with --enforce-clean-verify, which adds a "stamp match" check alongside the protected-branch check.

Daily flow (5 steps instead of 4):

  1. Edit in gateway, commit.
  2. sync-satellite.sh → satellite → build + test there (fast iteration).
  3. When ready to push, run:
    scripts/clean-verify-run.sh \
      --gateway-dir=<gw> --clean-verify-dir=<cv> \
      --push-branch=<br> --build-cmd='<full-build command>' --yes
    This syncs clean-verify from gateway, runs git clean -fdx (drops every untracked/ignored file), runs your full build end-to-end, and on success writes gateway/.git/last-clean-verify.
  4. git push origin <push-branch> — the hook reads the stamp, refuses if commit doesn't match. Emergency bypass: git push --push-option=allow-unverified (use sparingly; the point of the gate is that it holds).
  5. Raise MR/PR.

What this catches that 2-clone doesn't:

  • SSD-only bugs: code depends on files that happen to be in OS filesystem cache on the dev SSD but not on a cold HDD.
  • Stale-artefact bugs: satellite has build products from an earlier commit that accidentally satisfy a missing #include / missing codegen that the current commit wouldn't produce fresh.
  • Dirty-tree bugs: satellite has hand-edits the author forgot about; they pass the build; clean-verify starts from git HEAD and fails.
  • Build-command drift: --build-cmd is sha256-hashed into the stamp; if team changes build command out from under you, next push asks for a re-verify.

Paired evaluator: gated-dual-clone-audit auto-detects 3-clone mode when you pass --clean-verify-dir, and runs 4 extra gates (S9-S11 + C9 + B4) to re-verify the topology on demand.

Files · 文件

  • scripts/bootstrap.sh — the main setup command, runs all 8 steps + 3 gates (4 gates in 3-clone mode) · accepts optional --clean-verify-dir
  • scripts/sync-satellite.sh — fetch / reset-hard / merge-ff modes for syncing satellite from gateway
  • scripts/clean-verify-run.sh — sync + clean + full-build + stamp · the pre-push reproducibility gate for 3-clone mode
  • scripts/install-hooks.sh — writes the pre-push hook on the gateway · --enforce-clean-verify adds the stamp-match gate
  • scripts/check_before_mr.sh — 5 checks to run right before opening the MR (clean tree · clean-verify repo exists · stamp present · stamp sha == branch head · remote == local). For push-early / MR-late projects — see below
  • references/decision-checklist.md — when to use / when not to use
  • references/daily-workflow.md — 4-step cheatsheet
  • references/patterns.md — N-satellite / worktree fallback / GitHub-GitLab-Gerrit shapes
  • references/guardrails.md — why the three gates work / when they break / how to verify
  • references/server-side-enforcement.md — GitLab / GitHub / Gerrit / pre-receive / Actions templates (real enforcement beyond advisory client-side hook)
  • references/troubleshooting.md — 10 common failures, symptom → diagnose → fix → prevent
  • references/comparison.md — dual-clone vs worktree vs single-repo, 11-dimension table

Push-early / MR-late · 先推分支,最后才开 MR

有些项目这样走:个人分支随时 push 到远端当备份,一整个主题做完才开 MR。 这时 install-hooks.sh --enforce-clean-verify 那道会碍事 —— 它不看分支名, 任何 push 都拦,于是每次备份性质的 push 都要 --push-option=allow-unverified。

绕过一旦变成肌肉记忆,哪天真该拦的那次也会顺手绕过 —— 比关掉更糟, 因为还以为有人看着。

而真正该卡的是开 MR 那一刻,那是托管平台上的动作,不是 git 事件,pre-push hook 根本接不到。所以这类项目应该:

# 1. 建仓时【不加】 --enforce-clean-verify(或事后把 hook 里 enforce_cv 改 0)
#    Gate 1(保护分支)照旧生效,个人分支随便推

# 2. 开 MR 之前跑这个,五项全过才去点开 MR
scripts/check_before_mr.sh \
  --gateway-dir=<gateway> \
  --clean-verify-dir=<clean-verify> \
  --branch=<待 MR 的分支>

五项:

查什么漏了会怎样
M1gateway 工作区干净要 MR 的不是手上这份
M2clean-verify 仓在位且是 git 仓空目录 = 那道关卡从来没建起来过
M3盖章文件存在压根没跑过 clean-verify-run.sh
M4盖章 sha == 待 MR 分支 HEAD跑过,但之后又提交了几笔 —— 最容易漏的一种
M5远端分支 == 本地 HEAD本地验过没推,MR 提的是远端那份旧的

怎么选:每次 push 都该验 → 用 --enforce-clean-verify; 先推后 MR → 关掉它,改用 check_before_mr.sh。两个都不用 = 那道关卡不存在。

Reference · 参考

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.