English | 简体中文
A plan-first workflow for AI coding agents. It does not change how the agent writes code. It controls when the agent may start: the agent writes a short plan, stops, waits for your approval, builds, and runs its checks once at the end.
The project ships two components from one repository and one installer:
| Component | For | What you get |
|---|---|---|
skill |
Qoder, and any agent client that reads the SKILL.md format |
The workflow skill: SKILL.md plus four document templates |
dsh |
DSH (DeepSeek Harness) | A "quick dev" agent mode next to the built-in standard mode: the same skill, a small plugin that opens plan mode when a plan is due, and the mode declaration |
This project merges two earlier repositories,
dsh-quick-devandcode-project-flow. See History and Migrating from dsh-quick-dev or code-project-flow.The project is called plan-gate; the skill it installs is still called
code-project-flow. See Skill name.
- Why
- How it works
- Install
- Skill name
- Migrating from dsh-quick-dev or code-project-flow
- The DSH quick dev mode
- Security and permissions
- Customising
- Repository layout
- Development and tests
- History
- Contributing · License
AI-assisted coding tends to fail in four ways:
| Failure | What it looks like |
|---|---|
| Writes before agreeing | Requirements are still fuzzy, twenty files already changed |
| Drifts further each round | The same spot breaks again, so it grows another branch, wrapper or flag |
| Context blowup | Every new session re-reads the whole repository, mostly detail this task never touches |
| Fake green | Tests mock around the real path; it passes locally and breaks when it ships |
The workflow answers them with four documents, five phases and four overriding principles, and turns "may I start?" into an explicit approval step instead of a vague "go ahead" in the chat.
- Read – the rules and design documents first. If the design document does not exist, the agent drafts it from the actual shape of the code, not an ideal one, and leaves the structure and the two flows for you to review.
- Write the brief –
TASK.md, in plain language (the ASD-STE100 simplified-technical style: short sentences, one word for one thing, active voice), with exactly seven sections: why; how, down to functions and paths (files not listed must not be touched); what it touches; what not to do on the side; conflicts with the design document; details that need your sign-off; acceptance boundary. Then it stops. - Confirm – until you explicitly say go, nothing changes. "Keep refining" sends your feedback back to the brief.
- Build – if the brief lists a conflict with the design document, that sentence goes into the design document first. No tests and no harness runs while building.
- Close out – one run only: check the round against the brief's acceptance boundary, then run every registered harness with real data, no fake mocks. A failure is fixed in the code; registered checks are never loosened or deleted to get a green result. The agent then proposes write-backs to the design and harness documents, with before and after sentences. They are written only if you agree, and a "no" is never asked twice. Finally
TASK.mdis deleted.
| File | Who writes it | What it owns | |
|---|---|---|---|
| Doc 1 | AGENTS.md |
You only | Agent rules, the four overriding principles, who owns what |
| Doc 2 | MAP.md |
Agent proposes, you approve | Design: feature choices, project structure, user flow, data flow (eight fixed sections) |
| Doc 3 | HARNESS.md |
Agent proposes, you approve | Registered regression loops ("harnesses"); their code lives in harness/ |
| Doc 4 | TASK.md |
Agent writes, you confirm, deleted at close-out | This round only, down to functions and paths (seven fixed sections) |
Where the documents live depends on the component:
skill:AGENTS.mdin the project root, the other three underdocs/(docs/MAP.md,docs/HARNESS.md,docs/TASK.md).dsh: all four in the project root. DSH auto-loads instruction files by bare file name while walking up from the working directory, so a file in a subfolder would never load. The installer renders the skill for this layout; the source is the same.
The documents are also the workflow's state. A new session reads Docs 1–3 and knows which step it is on, without chat memory. Templates: references/.
They live in Doc 1 and win over any other instruction:
- No patches – fix the place that produced the error; no extra branch, wrapper, compatibility layer, flag or special case next to it.
- Self-explanatory code – names and structure say what the code does; comments only hold what a reader would guess wrong (why, who calls it, what it guarantees).
- No residue – unused functions, files, flags, commented-out code, stale harnesses and the task brief are removed at close-out.
- Deployment parity – the path that works locally is the path that ships; no per-machine special cases, no fake data.
SKILL.md, the four templates and the DSH mode's built-in guidance are Chinese. This README explains them in English. The agent reads Chinese rules and fills Chinese templates; your code and comments stay in your project's language. Pull requests adding English templates are welcome (see CONTRIBUTING.md).
Requirements: bash (macOS, Linux, WSL, Git Bash) or PowerShell 5.1+ on Windows, and git to clone. For the dsh component, DSH must have been started at least once, so that profiles/ exists.
git clone https://github.com/PakhomLeo/plan-gate.git
cd plan-gate
./install.sh --dry-run # see what would change
./install.sh # install the auto-detected componentsgit clone https://github.com/PakhomLeo/plan-gate.git
cd plan-gate
powershell -ExecutionPolicy Bypass -File .\install.ps1 -DryRun
powershell -ExecutionPolicy Bypass -File .\install.ps1-ExecutionPolicy Bypass applies to this one process only; it does not change your machine's policy.
What it looks like: the real output of ./install.sh from v1.0.0, run with no options in a temporary HOME (/tmp/demo), followed by a listing of the installed files.
install.sh |
install.ps1 |
Meaning |
|---|---|---|
--components skill,dsh |
-Components skill,dsh |
What to install: skill, dsh or all. Default: auto-detect (see below) |
--skills-dir DIR |
-SkillsDir DIR (alias -SkillsRoot) |
Skills folder for skill. Default: ~/.qoder-cn/skills, or ~/.qoder/skills |
--dsh-home DIR |
-DshHome DIR |
DSH home for dsh. Default: $DSH_HOME, then ~/.dsh |
--uninstall |
-Uninstall |
Remove what the installer installed |
--migrate-legacy |
-MigrateLegacy |
Move installs made by the earlier installers to a backup folder, then continue |
--dry-run |
-DryRun |
Print planned changes, change nothing |
Auto-detect picks skill when a Qoder skills folder exists or --skills-dir is given, and dsh when $DSH_HOME/profiles exists or --dsh-home is given. With neither, it installs skill into ~/.qoder-cn/skills. If the skill is already installed under ~/.qoder/skills, updates go there.
Exit codes: 0 done, 1 error, 2 bad arguments, 3 finished but skipped a step (for example an earlier install that needs --migrate-legacy).
Any client that loads SKILL.md skills from a folder can use the skill component:
./install.sh --components skill --skills-dir /path/to/your/client/skillsStart a new agent session afterwards; skills load at session start.
Every release has these assets, built by .github/workflows/release.yml with scripts/make-release.sh:
| Asset | What |
|---|---|
plan-gate-vX.Y.Z.tar.gz, plan-gate-vX.Y.Z.zip |
The tagged source tree, including both installers |
install.sh, install.ps1 |
The same installers as separate files |
SHA256SUMS |
sha256 of the four files above |
The checksums are a release asset. They are not a file committed to the repository, and they verify the downloaded release assets only. They protect against a broken or altered download. They do not protect against a compromised GitHub account, because the checksums come from the same place. The commands below download the archive, check it, and only then run the installer from the extracted folder, so nothing else is fetched.
macOS / Linux (use shasum -a 256 -c - instead of sha256sum -c - on macOS without coreutils):
V=v1.0.0; B=https://github.com/PakhomLeo/plan-gate/releases/download/$V
mkdir -p plan-gate-dl && cd plan-gate-dl \
&& curl -fsSLO "$B/plan-gate-$V.tar.gz" && curl -fsSLO "$B/SHA256SUMS" \
&& grep " plan-gate-$V.tar.gz\$" SHA256SUMS | sha256sum -c - \
&& tar xzf "plan-gate-$V.tar.gz" && bash "plan-gate-$V/install.sh"Windows (PowerShell):
$V = 'v1.0.0'; $B = "https://github.com/PakhomLeo/plan-gate/releases/download/$V"; $f = "plan-gate-$V.zip"
Invoke-WebRequest "$B/$f" -OutFile $f; Invoke-WebRequest "$B/SHA256SUMS" -OutFile SHA256SUMS
$want = (((Get-Content SHA256SUMS) -match " $([regex]::Escape($f))$") -split '\s+')[0]
if ((Get-FileHash $f -Algorithm SHA256).Hash -ne $want) { throw 'SHA256 mismatch: do not run it' }
Expand-Archive $f -DestinationPath .
powershell -ExecutionPolicy Bypass -File ".\plan-gate-$V\install.ps1"Add installer options at the end of the last line, for example --components dsh or -Components dsh. To check a file you already downloaded: sha256sum -c --ignore-missing SHA256SUMS (Linux), shasum -a 256 -c --ignore-missing SHA256SUMS (recent macOS), or Get-FileHash FILE -Algorithm SHA256 and compare with the line in SHA256SUMS (Windows).
Installing only makes the skill available. To route every coding task through it, add this to your global ~/.qoder-cn/AGENTS.md (or a project's AGENTS.md). Keep it verbatim; it matches the skill's Chinese trigger description:
凡写代码、改代码、把功能落到仓库的任务,默认使用 skill code-project-flow。
开工先写 docs/TASK.md 并停下等确认。Without that line, the skill fires on words such as 开工 (start work), 收工 (close out), MAP, 当次说明 (task brief) or harness, or when you ask for it by name. The installer never edits your AGENTS.md.
Update: pull the checkout and run the installer again. It rewrites only the files listed in its .plan-gate-manifest and removes files that an earlier version shipped and this one does not.
./install.sh --uninstall # or: --components dsh --uninstall.\install.ps1 -UninstallUninstall removes the files in the manifest, the plugin if its content matches a shipped version, and the preset block. A patch layer is then byte-for-byte what it was before. Files you added to the skill folder stay, and so does the folder.
The repository and project are called plan-gate. The skill it installs keeps its old name, code-project-flow: the folder is skills/code-project-flow/ and SKILL.md says name: code-project-flow. The reasons:
- The Qoder default line above says
默认使用 skill code-project-flow. Users have it in theirAGENTS.md, and the installer never edits that file. A new name would silently turn that line off. - Existing installs live in
skills/code-project-flow/. With the same name, an upgrade replaces the old skill in place, so the agent never sees two copies of the same workflow. - The trigger words and the DSH mode's guidance refer to the skill by this name.
For the same reason, the DSH preset id (preset-quick-dev), the plugin file (quick-dev-plan-arm.mjs) and the mode name stay as they were. Only names that never left the installer changed: the manifest is .plan-gate-manifest, backups go to ~/.plan-gate-backups/, and the piped-mode variables are PLAN_GATE_REF and PLAN_GATE_REPO_URL.
The installer recognises what the two former installers wrote, in the places they wrote it. This was checked against their source. The tests run the former installers, unmodified, to make real old installs and migrate them (see Development and tests).
| Former installer | What it wrote | How the new installer recognises it |
|---|---|---|
code-project-flow install.sh / install.ps1 |
A git clone --depth 1 of github.com/PakhomLeo/code-project-flow into <skills>/code-project-flow. <skills> was the first argument (-SkillsRoot), else ~/.qoder-cn/skills or ~/.qoder/skills. Updates ran git pull --ff-only. |
A skill folder (SKILL.md with name: code-project-flow) without .plan-gate-manifest, whose .git/config has that origin. Reported as code-project-flow git checkout. |
dsh-quick-dev install.sh / install.ps1 |
$DSH_HOME/skills/code-project-flow/ (SKILL.md and references/, no marker file); $DSH_HOME/plugins/quick-dev-plan-arm.mjs; one - insert: block with id: preset-quick-dev in every profiles/*/cordis.patch.yml. An interrupted run could leave cordis.patch.yml.dsh-quick-dev.tmp. |
The skill folder without manifest under $DSH_HOME/skills/ (dsh-quick-dev copy). The plugin by its sha256: plan-gate ships the same file. The preset block by its id. The leftover by its name. |
| Copy by hand, or another git checkout | A skill folder without manifest | Reported as manual copy or git checkout of unknown origin. |
$DSH_HOME defaults to ~/.dsh, as before. For each old skill folder, the installer also lists the files that the former installer did not write (your notes, for example). They are never removed: they stay in the folder, or move with it into the backup.
| Item | Without --migrate-legacy |
With --migrate-legacy (or "y" at the prompt) |
|---|---|---|
| Old skill folder | Left untouched. Warning, exit code 3. For dsh, the plugin and preset are then not touched either. |
The whole folder, including .git and your files, moves to ~/.plan-gate-backups/<time>/. A fresh copy with a manifest is installed in the same place. |
| Plugin with the shipped content | Replaced in place (same file). | Same. |
| Plugin you edited | Kept. Warning, exit code 3. |
Moved to the backup, then replaced. |
preset-quick-dev block |
Replaced in place: one block per layer, the rest of the layer unchanged. | Same. |
cordis.patch.yml.dsh-quick-dev.tmp |
Reported only. | Moved to the backup. |
Nothing is ever deleted. Delete the backup folder yourself when you no longer need it. The installer also prints a note when it sees an old install in a place this run does not manage.
git clone https://github.com/PakhomLeo/plan-gate.git && cd plan-gate
./install.sh --dry-run # what it found and what would change
./install.sh --migrate-legacy # skill and dsh, as auto-detected
./install.sh --components dsh --migrate-legacy # dsh-quick-dev only
./install.sh --components skill --skills-dir /path/to/skills --migrate-legacy # a former first argumentgit clone https://github.com/PakhomLeo/plan-gate.git; cd plan-gate
powershell -ExecutionPolicy Bypass -File .\install.ps1 -DryRun
powershell -ExecutionPolicy Bypass -File .\install.ps1 -MigrateLegacy
powershell -ExecutionPolicy Bypass -File .\install.ps1 -Components dsh -MigrateLegacy
powershell -ExecutionPolicy Bypass -File .\install.ps1 -Components skill -SkillsDir C:\path\to\skills -MigrateLegacyAfter migrating, ./install.sh --uninstall removes the new install, and every patch layer is again byte-for-byte what it was before dsh-quick-dev changed it.
What changed for existing users:
- The skill is now copied, not cloned.
git pullinside the skills folder is no longer the update path; pull this repository and run the installer again. - The
dshskill copy now uses the newest workflow text (plain-language replies in the ASD-STE100 style), whichdsh-quick-devalready used in its mode guidance. - Positional
./install.sh /path/to/skillsstill works and prints a deprecation note; use--skills-dir.
The dsh component adds a mode named 快速开发模式 ("quick dev"), shown second in the new-session picker. After installing, restart DSH and start a blank session; DSH only switches modes on a session without history.
What the installer writes into $DSH_HOME:
| Where | What |
|---|---|
skills/code-project-flow/ |
The workflow skill, rendered for the project-root document layout |
plugins/quick-dev-plan-arm.mjs |
Opens plan mode when a plan is due |
profiles/*/cordis.patch.yml |
One top-level - insert: entry with id preset-quick-dev, in every existing profile |
The mode declaration (dsh/preset/quick-dev.patch.yml) is a copy of DSH's standard mode plugin list with four changes: a persona suffix asking for plain-language replies, auto-loaded instruction files widened to AGENTS.md, CLAUDE.md, MAP.md, HARNESS.md, TASK.md with a 200 KB budget, a plan-mode prompt that explains the workflow and then restates every rule of DSH's standard plan-mode prompt (for example: agreement in the chat is not approval; no edits except the plan file, no commits, no formatters while planning; exit_plan_mode is the only way to submit; stay in plan mode if review is unavailable), and one extra plugin row. The other rows were copied unchanged from standard mode when the preset was written, so the tool list is the same.
The plugin (dsh/plugin/quick-dev-plan-arm.mjs) exists because a new DSH session starts outside plan mode and the model has no tool to enter it. It turns plan mode on for root agents when the working directory has AGENTS.md and no TASK.md, and again after a round's TASK.md disappears. It skips subagents, adds no tools, blocks no tool call, and only logs a warning if anything fails.
Known boundaries (by design):
- Only blank sessions can switch modes (a DSH rule).
- DSH lists the mode under "custom" in settings; the picker order comes from
order: 1.5. - Modes do not inherit. When DSH updates its standard mode, this copy does not follow; re-check
dsh/preset/quick-dev.patch.ymlagainst new DSH releases. - The workflow is guidance, not a fence. It never removes tools per phase, because changing the tool table would invalidate the prompt cache.
- DSH source code is not modified.
Installers (install.sh, install.ps1):
- Never use
sudoor elevation. They write only to the chosen skills folder, the DSH home, and the backup folder (only with--migrate-legacy). - Overwrite or remove only what they installed: files listed in
.plan-gate-manifest, a plugin whose hash matches a shipped version, and the one preset block. Anything else is reported and skipped. - Recommended install: clone and run. The release one-liner verifies the archive against the release's
SHA256SUMSbefore it runs anything. Pipinginstall.shstraight from the network intobashstill works (it then clones the repository;PLAN_GATE_REFpins a tag), but nothing is verified, so it is not documented as an install method.
What the agent gets:
- The skill is text only. Its front matter has
nameanddescription; it declares no tools, permissions or auto-approval. - The DSH mode uses the same tool rows as DSH's standard mode (shell, file system, web fetch, subagents and so on). It adds no tools, sets no sandbox or approval policy, and keeps DSH's own approval behaviour. In the preset, the plugin-manager tool, the external
codexandclaude-codesubagent rows andtool-ralphare disabled. - The plugin only makes the agent more restricted (it turns plan mode on). Approving a plan is always your action.
Report vulnerabilities as described in SECURITY.md.
references/AGENTS.md is the template meant for you to edit; put your copy in the project root. The agent must not change it.
Note: the template is written for exploratory projects. While a project is in development, it tells the agent not to add extra security layers, retries or caching to temporary components. It also says the agent must not remove or bypass existing authentication, permission checks or input validation, and must still validate external input. For production code, review that paragraph and set your own bar.
SKILL.md is editable too, but it is the workflow itself; changes alter how the five phases run. Edit the source in this repository (with docs/ paths) and reinstall; the installer renders the DSH layout.
Good fit: exploratory projects where blocks may be thrown away; long-lived repositories that suffer from drift; wanting a plan before code. Poor fit: throwaway scripts, and requirements you expect the agent to discover by writing.
.
├── SKILL.md # skill entry point: the five-phase rules (Chinese)
├── references/ # the four document templates (Chinese)
│ ├── AGENTS.md MAP.md HARNESS.md TASK.md
├── dsh/
│ ├── preset/quick-dev.patch.yml # DSH mode declaration (profile patch layer block)
│ └── plugin/quick-dev-plan-arm.mjs
├── install.sh install.ps1 # one installer, two platforms, same behaviour
├── tests/
│ ├── install-test.sh # end-to-end test of install.sh in a temp HOME
│ ├── parity-test.sh # install.sh vs install.ps1, byte-identical results
│ ├── release-test.sh # release assets, SHA256SUMS, download-verify-run
│ ├── legacy-test.ps1 # migration from real former installs, PowerShell side
│ ├── legacy-fixtures.sh # runs the former installers to make real old installs
│ └── fixtures/legacy/ # git bundles of the former repositories (test data)
├── scripts/ # make-release.sh (assets + SHA256SUMS), diagram generator, PNG export
├── docs/assets/ # SVG diagrams (light and dark aware), install screenshot
├── VERSION CHANGELOG.md LICENSE CONTRIBUTING.md SECURITY.md
└── README.md README.zh-CN.md
SKILL.md and references/ are still at the repository root, so a clone into a skills folder under the skill's name (git clone https://github.com/PakhomLeo/plan-gate.git code-project-flow) still works. The installer is the supported path.
shellcheck install.sh scripts/*.sh tests/*.sh
bash tests/install-test.sh # install.sh, every case in a throwaway HOME
bash tests/parity-test.sh # needs PowerShell 7 (pwsh)
pwsh -NoProfile -File tests/legacy-test.ps1 # install.ps1 vs the former installers' install.ps1
bash tests/release-test.sh # release assets, SHA256SUMS, download-verify-runReleases: push a tag vX.Y.Z that matches VERSION; .github/workflows/release.yml runs the tests, builds the assets with scripts/make-release.sh and publishes them.
The tests never touch your real home folder or the network. The migration cases run the former installers, unmodified, from git bundles of the former repositories in tests/fixtures/legacy/. See CONTRIBUTING.md.
Version 1.0.0 of plan-gate merges two repositories by the same author:
- code-project-flow (2026-09-28 – 2026-10-03): the workflow skill for Qoder, with
docs/document layout and agit cloneinstaller. - dsh-quick-dev (2026-09-29 – 2026-10-21): the DSH quick dev mode, with a copy of the skill in the project-root layout, the plan-arm plugin and the preset.
The two skill copies are now one source. See CHANGELOG.md.
See CONTRIBUTING.md.
MIT © 2026 PakhomLeo
