dshbase

插件目录 / Developer / dsh-checkout-guard

dsh-checkout-guard

已验证 · 实测可装 LeslieWylie

✓ 持续维护 基于 2 个官方 DSH 包

查看 GitHub ↗ ← 返回插件目录

0Stars
0Forks
0未关闭 issue
—语言
2026-08-18最近推送
跨平台平台

功能简介

Pre-flight guard for git working copies: is the checkout you are about to write to the one you think it is? Branch identity, drift from the remote and how stale that figure is, the identity your next commit will carry, work already in the index, and duplicate clones. Read-only, offline by default.

✅
我们的评价
可用 — 实测通过,早期项目

Pre-flight guard for git working copies: is the checkout you are about to write to the one you think it is? Branch identity, drift from the remote and how stale that figure is, the identity your next commit will carry, work already in the index, and duplicate clones. Read-only, offline by default. 实测能干净安装、正常启动。早期项目,但功能可用。

「已验证」表示我们的自动化 CI 在干净 profile 里实际执行了 dsh plugin add 并启动成功——仅此而已。功能描述与版本兼容性均为作者声明。这不是安全审计,也不代表对第三方代码的背书。

README

dsh-checkout-guard

Is the working copy you are about to write to the one you think it is?

A DSH plugin that answers that before you edit, commit, or push — not after. It
reads a git checkout and tells you where it sits relative to its remote, how
stale that answer is, who your next commit will be attributed to, what work is
already sitting in the index, and whether another clone of the same repository
on this machine has moved ahead of the one you are in.

Read-only. Offline unless you ask for a fetch. Never takes the index lock.


Why

Every check here exists because a specific mistake actually happened, usually to
an agent working across many repositories at once:

What goes wrong What you see afterwards
You edit a checkout that is 8 commits behind Your "fix" reverts work, or your push is rejected after the fact
Two clones of one repository, you are in the stale one Changes vanish; the repo on the forge never shows them
A concurrent process moved HEAD to another branch Your commit lands on a branch you have never heard of
Something was already staged before you ran git add Your commit packages somebody else's work in progress
No repository-local user.email A work address is permanently attached to a public commit
Detached HEAD The commits exist, then don't, and nothing warned you

None of these throw. Git does exactly what you asked; you asked in a state you
had misread. That is the entire problem space this plugin covers.

Install

npm install dsh-checkout-guard

Then append to your profile's cordis.yml:

- id: checkout-guard
  name: 'dsh-checkout-guard'

Node 22.19+ or 24+. The only runtime requirement is git on PATH.

Tools

checkout_guard — one working copy, in depth

{ "path": "/abs/path/to/repo", "expectBranch": "main" }
{
  "branch":  { "current": "main", "detached": false, "upstream": "origin/main", "linkedWorktree": false },
  "sync":    { "ahead": 1, "behind": 1, "fetchAgeSeconds": 255600, "fetchedNow": false },
  "remote":  { "normalized": "github.com/acme/widget", "host": "github.com", "publicForge": true },
  "identity":{ "email": "you@example.com", "source": "global", "repositoryOverride": false },
  "workingTree": { "staged": [], "unstaged": ["package.json"], "untracked": [], "clean": false },
  "duplicateCheckouts": [ { "path": "/elsewhere/widget", "branch": "main", "ahead": 3, "aheadOfThisOne": true } ],
  "blockers": [
    "diverged from origin/main by 1 commit(s) (and 1 ahead); you are reading code the remote has already moved past, and a push will be rejected",
    "another checkout of the same remote is ahead of this one: /elsewhere/widget (main, 3 ahead vs 1); you may be editing the stale copy"
  ],
  "warnings": [
    "remote refs were last updated 71h ago; ahead/behind is computed from that snapshot, not from the remote as it is now (re-run with fetch: true)"
  ],
  "verdict": "blocked",
  "safeToWrite": false
}

safeToWrite is the one field a caller needs. blockers are states where
proceeding loses or misplaces work; warnings are things worth knowing that
are not automatically wrong.

Parameter Effect
path (required) Absolute path to the working copy, or any directory inside it
fetch Contact the remote first so ahead/behind is current. The only networked option, default false
expectBranch The branch you believe you are on. A mismatch is a blocker
expectIdentity The email you expect to author with. A mismatch is a blocker
remote Remote to compare against (default origin)
staleAfterHours When remote refs count as stale (default 24)
findDuplicates / duplicateRoots / maxDepth / maxRepos Control the search for other clones

expectBranch and expectIdentity are how you turn a report into an assertion.
Without them the plugin describes; with them it refuses.

checkout_guard_scan — every working copy under a root

{ "roots": ["/abs/path/to/projects"], "maxDepth": 3 }

Returns one row per checkout — branch, upstream, ahead/behind, uncommitted
counts, fetch age — plus:

  • needsAttention: the ones that are behind, diverged, detached, or have no upstream
  • duplicateRemotes: paths grouped by remote, so two clones of one repository are visible at a glance

Run this first to find out which checkouts deserve a closer look, then hand
those paths to checkout_guard.

What it deliberately does not do

  • It does not tell you a remote is archived. That needs the forge's API, and
    this plugin does not make authenticated HTTP calls. remote.normalized gives
    you host/owner/repo to check yourself.
  • It does not fix anything. No pull, no rebase, no stash, no checkout. The
    recovery for "behind" and the recovery for "diverged" are different, and
    picking between them is not a decision a guard should make for you.
  • It does not judge your identity. It reports which config your author line
    comes from, and warns only when a public forge is involved and the repository
    has no local override. If you pass expectIdentity, it compares against
    exactly what you named — it never guesses what your address should be.

Safety properties

  • No writes to any repository. The only command that can modify anything is
    git fetch --dry-run, which runs only when fetch: true and touches nothing
    but FETCH_HEAD.
  • GIT_OPTIONAL_LOCKS=0 on every call. Ordinary git status refreshes and
    rewrites the index, taking .git/index.lock. A guard whose whole premise is
    "another agent may be in this checkout right now" must not be able to block
    that agent.
  • GIT_TERMINAL_PROMPT=0, empty GIT_ASKPASS. A fetch against a private
    remote fails fast instead of parking on a credential prompt nobody can see.
  • Credentials are stripped during URL normalization, before a remote can
    reach a result object or a log line.
  • Path allowlist. Both sides are realpath'd, so a symlink planted inside
    an allowed root cannot read outside it.

Configuration

- id: checkout-guard
  name: 'dsh-checkout-guard'
  config:
    roots:
      - /Users/you/projects

roots bounds everything the plugin will look at. Unset, it defaults to your
home directory.

Development

npm install
npm test          # unit tests against real git repos in a temp dir
npm run test:boot # loads the plugin into a real cordis Context

There is no build step. src/index.js is the published entry point, byte
for byte. Plugins that compile to lib/ and commit the output have to keep the
two in sync forever, and every test that imports src/ passes while the
artifact an installer runs is stale. Removing the build removes the whole class.

The unit tests create real repositories — real remotes, real pushes, real
divergence — rather than stubbing git. A hand-written double answers the way its
author expects, and the author's expectation about repository state is precisely
what is under test.

tests/boot.test.mjs exits 0 with a SKIP from a bare clone so contributors are
not blocked, and exits 1 under DSH_BOOT_STRICT=1, which CI sets. A skipped
integration test reported as green is worse than no test at all.

中文 · MIT

安装

🧩 让 Agent 自动装(推荐)

装一次目录插件,之后本站所有插件都能让 DeepSeek Harness 自动找、自动装:

dsh plugin add dshbase-catalog

然后对 agent 说「帮我装 dsh-checkout-guard」,它会在目录里找到并自动安装。文档:dshbase-catalog · 已验证场景包。

该插件是 GitHub 源码(未发 npm)——直接从仓库装:

Web profile:

dsh plugin --profile web add github:LeslieWylie/dsh-checkout-guard

Headless(CLI)profile:

dsh plugin --profile headless add github:LeslieWylie/dsh-checkout-guard

实测报告

验证通过:从 GitHub 源码完成 L1 安装 + L2 加载 + L3 运行(dsh 0.1.0-rc.6)。

安全:尚未扫描——我们的每日静态扫描将很快覆盖它。

分享徽章

Developer 里更多

浏览全部 7819 个插件 →