Back to home@qt-11564

dsh-git-seam

Structured git tools for DeepSeek Harness: diff-before-commit gate + deterministic porcelain parsing (Chinese/UTF-8 paths, Windows)

Stars
0
Language
JavaScript
Created
Aug 29, 2026
Updated
Aug 29, 2026
GitHub repo

Introduction

dsh-git-seam

Structured git tools for DeepSeek Harness (dsh) agents — with a diff-before-commit gate that refuses blind commits and deterministic porcelain parsing that handles Chinese/UTF-8 paths, spaces, and CRLF stably on Windows and Linux.

The agent gets six tools — git_status, git_diff, git_log, git_show, git_branch, git_commit — plus a policy layer that enforces review-before-commit discipline instead of relying on the model to remember it.

Why not just git in bash?

An agent can already run git through the bash tool. What bash cannot give you:

  • A guarantee, not a suggestion. git_commit is refused unless the changes were actually reviewed with git_diff first — same turn, and covering exactly the files the commit would include. Files staged after the review (e.g. via a shell git add) are caught and named. Bash cannot enforce this; it can only hope.
  • Deterministic parsing. Every command runs with LC_ALL=C, GIT_TERMINAL_PROMPT=0, core.quotepath=false, and machine formats (status --porcelain=v1 -z, diff --numstat, log --format=…). Chinese filenames, BOM'd UTF-8 content, spaces, renames, and CRLF are parsed by code, not by the model's luck.
  • Approval you can actually judge. git_commit asks for approval with a real per-file plan: path (+N/-M), untracked paths listed as (new file). Bash escalation shows a command string, not a change list.
  • Loud, actionable failures. Not-a-repo, missing user.email, and ../ traversal return clear errors with the next step, not raw stderr.

Install

# from GitHub (recommended)
dsh plugin --profile web add github:qt-11564/dsh-git-seam

# or from npm (once published)
dsh plugin --profile web add dsh-git-seam

Then restart the profile. Verify with dsh --profile web --dump-config (look for the git-seam row) or just start a conversation — the six git_* tools appear automatically.

Configuration

- id: git-seam
  name: dsh-git-seam   # or ./index.mjs when installed from a local checkout
  config:
    maxBytes: 32768              # output byte budget; truncation notice + spill path beyond it
    requireDiffBeforeCommit: true # the diff-before-commit gate (set false to disable)
    requireCommitApproval: true   # route git_commit through the approval service
    timeoutMs: 30000              # per-command timeout; longer commands are killed

Tools

ToolInputOutput
git_statuscwd?branch, ahead/behind, staged/unstaged/untracked lists, clean flag
git_diffspec? (worktree / --staged / A..B), path?per-file +N/−M stats + truncated unified diff
git_logrange?, path?commits: hash, author, date, subject
git_showref (required), path?commit metadata + stats + truncated diff
git_branchcwd?current branch + all local branches
git_commitmessage (required), paths?new hash + summary; gated and approval-routed

How the gate works

git_commit is checked on tools/pre-execute:

  1. The last git action must be a successful git_diff in the same turn (a diff from a previous turn does not count; a failed diff does not count).
  2. Every file the commit would include must be inside the reviewed diff's covered set: the staged set for path-less commits, the given paths for path commits.
  3. Untracked paths are exemptgit diff structurally cannot show them; their review is read-based (fs tools), and the approval plan still lists them.
  4. A successful commit invalidates the review; the next commit needs a fresh diff.

Denials name the offending files and tell the model what to do (run git_diff again). The gate is an ordinary tools/pre-execute listener — it unloads with the plugin and composes with the rest of the policy chain.

Known Limitations and Deferred Work

  • No destructive history operationsreset, checkout, revert, merge, rebase are out of scope; git_commit is the only mutating tool.
  • No stash, remote operations (push/pull/fetch), or submodules.
  • No blame, GPG signing, or LFS.
  • Remote providers (GitHub/GitLab REST) are deferred — local git only.
  • The gate verifies file coverage, not content freshness: editing a file after its diff and before committing is not detected (a deliberate trade-off to keep the gate cheap and predictable).
  • A commit can still be made by bypassing the tools through bash; the gate protects the tool path, not the sandbox.

Development

npm install            # installs tsx for the selftest
npm test               # 13-case selftest: gate semantics, approval plan, full commit flow

The selftest drives the real plugin module with a mocked ctx against a real git fixture repo (real porcelain output). For the test's @deepseek-ai/dsh-tools import to resolve without publishing, either npm i @deepseek-ai/dsh-tools or drop a dev shim under node_modules/@deepseek-ai/dsh-tools re-exporting your harness checkout's packages/core/tools/src/schema.ts.

License

MIT