dsh-doublecheck 0.6.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/README.es.md +199 -220
- package/README.hi.md +199 -228
- package/README.md +199 -225
- package/README.pt.md +199 -220
- package/README.zh.md +201 -225
- package/lib/domain/gate.d.ts +263 -0
- package/lib/domain/gate.js +658 -0
- package/lib/domain/projection.d.ts +8 -3
- package/lib/domain/projection.js +12 -0
- package/lib/domain/report.d.ts +2 -2
- package/lib/domain/stages.d.ts +1 -1
- package/lib/events.d.ts +46 -4
- package/lib/grill/index.d.ts +1 -1
- package/lib/guard/command.d.ts +2 -2
- package/lib/guard/command.js +3 -0
- package/lib/guard/gate.d.ts +170 -0
- package/lib/guard/gate.js +518 -0
- package/lib/guard/index.d.ts +15 -3
- package/lib/guard/index.js +81 -4
- package/lib/guard/prose.d.ts +17 -0
- package/lib/guard/prose.js +14 -0
- package/lib/guard/review.d.ts +2 -2
- package/lib/index.d.ts +10 -9
- package/lib/index.js +1 -0
- package/lib/invariant.d.ts +3 -1
- package/lib/invariant.js +15 -0
- package/lib/types.d.ts +8 -1
- package/lib/types.js +2 -0
- package/package.json +52 -6
- package/skills/delivery-proof/SKILL.md +12 -0
- package/strict.patch.yml +37 -0
package/README.md
CHANGED
|
@@ -1,284 +1,258 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# dsh-doublecheck
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
[](https://www.npmjs.com/package/dsh-doublecheck)
|
|
7
|
-
[](LICENSE)
|
|
8
|
-
[](https://github.com/topics/dsh-plugin)
|
|
9
|
-
[](https://github.com/PerryLink/dsh-doublecheck/actions/workflows/ci.yml)
|
|
5
|
+
**The delivery quality gate for DeepSeek Harness: grill the requirements, test the implementation, prove the delivery — then gate the handoff with a deliverable/rework decision.**
|
|
10
6
|
|
|
11
|
-
|
|
7
|
+
*Requirements get interrogated before the first edit; delivery is proven, never claimed.*
|
|
12
8
|
|
|
13
|
-
|
|
9
|
+
[](LICENSE)
|
|
10
|
+
[](https://github.com/topics/dsh-plugin)
|
|
11
|
+
[](#)
|
|
12
|
+
[](https://github.com/PerryLink/dsh-doublecheck/actions)
|
|
13
|
+
[](https://github.com/PerryLink/dsh-doublecheck/releases)
|
|
14
|
+
[](https://www.npmjs.com/package/dsh-doublecheck)
|
|
15
|
+
[](https://www.npmjs.com/package/dsh-doublecheck)
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
[English](README.md) · [简体中文](README.zh.md) · [Español](README.es.md) · [Português](README.pt.md) · [हिन्दी](README.hi.md)
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
- Disciplined teams do this in humans: requirements review → failing test → passing test → self-review → delivery proof. Agents deserve the same loop, enforced by the harness, not by vibes.
|
|
19
|
+
</div>
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
---
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
grill ──▶ design ──▶ red ──▶ green ──▶ review ──▶ verify
|
|
24
|
-
│ │
|
|
25
|
-
│ (v0.1) (v0.2+) (v0.3) (v0.4)
|
|
26
|
-
│
|
|
27
|
-
└─ requirements furnace: six dimensions, consensus gate,
|
|
28
|
-
structured spec committed to the session and the workspace
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
| Stage | Meaning | Status |
|
|
32
|
-
|---|---|---|
|
|
33
|
-
| **grill** | Interrogate the six requirement dimensions; refuse to implement until consensus. | ✅ v0.1 |
|
|
34
|
-
| **design** | Spec committed via `doublecheck_spec`. | ✅ v0.1 |
|
|
35
|
-
| **red** | A failing test run proves the gap; implementation edits need it on record. | ✅ v0.2 |
|
|
36
|
-
| **green** | A passing test run after the edits closes the loop. | ✅ v0.2 |
|
|
37
|
-
| **review** | A forked adversary critic audits the delivery against the spec. | ✅ v0.3 |
|
|
38
|
-
| **verify** | `doublecheck_report` + a per-dimension verification workflow prove the delivery. | ✅ v0.4 |
|
|
39
|
-
|
|
40
|
-
## Features
|
|
41
|
-
|
|
42
|
-
- 🔥 **`grill-requirements` skill** — a bundled Agent-Skills-format skill that interrogates the task across six dimensions (**goal, scope, acceptance criteria, failure modes, priorities, non-goals**) using DSH's native `ask_user_question` UI, refuses to write code until consensus, and records the contract.
|
|
43
|
-
- 🧰 **Stage skills for the whole loop** — `red-green-tdd` (write the failing test, run red, implement, run green), `delivery-review` (adversarial self-review against the spec once green), and `delivery-proof` (consolidate the evidence into the delivery report before claiming completion) join `grill-requirements`, so all six stages have model guidance, not just the first.
|
|
44
|
-
- 📜 **`doublecheck_spec` tool** — commits the grilled spec to the session log and writes a markdown copy to the workspace, so the contract survives the conversation. Empty or whitespace-only dimensions are rejected at the commit (v0.6): the grill must settle all six before the spec counts.
|
|
45
|
-
- 🔄 **Task-change re-grill** — a committed spec covers its own task: a new direct-user request after the latest spec commit reopens the grill gate for that follow-up instead of silently inheriting the old contract.
|
|
46
|
-
- 🛡️ **Discipline guard** — a soft gate on the tool policy pipeline. Vague task + no spec + heading for `edit`/`write` → **remind**, **hold for human approval**, or **block**, depending on `intensity`.
|
|
47
|
-
- 🟥🟩 **Red/green evidence gates** (`modules.tdd`) — hard checks over the session log: an implementation edit requires a **failing test run on record** since the last passing run (writing test files is always allowed — that is how the red step happens), and a turn that ends with edits but no passing run gets a green reminder injected. Custom guard tools work out of the box: the gates read both `file_path` and `path` argument keys, and a call that names no file at all is not treated as an implementation edit.
|
|
48
|
-
- 👁️ **Adversary review** (`modules.adversary`) — once the delivery reaches green, a forked critic subagent (DSH's native subagent seam, default `fork` provider) audits the session against the committed spec with an adversarial stance and returns structured findings, sorted blocker-first. `remind` injects the critique; `warn`/`block` additionally steer one round to make the model answer the findings. `adversaryModel` routes the critic to a separate model; the critic's tool allowlist is read-only by default. Findings ride the durable `doublecheck-review` message source. The review re-arms after the critic settles: implementation edits after the latest review record trigger another round, and cancelling the turn aborts the in-flight critic.
|
|
49
|
-
- 🌐 **Fully localized model surface** — every model-visible string the package injects or answers with (reminders, deny/ask feedback, review steering, switch notices, `/doublecheck` replies, and the critic's task prompt) honors `language: 'en' | 'zh'`; the workspace spec/report documents keep their stable English headings.
|
|
50
|
-
- 📊 **Doublecheck report + verification workflow** (`doublecheck_report`, v0.4) — consolidates the session's discipline evidence (spec, red/green timeline, review findings, edits) into a delivery report with a derived verdict (`grill → draft → red → green → objections/verified → proven/challenged/unverified`), written to the workspace. With `verify`, per-dimension checkers run through DSH's workflow seam (`verifyMode: all` fans out one parallel checker per dimension; `single` runs one combined checker) and their verdicts fold into the report — `proven` requires a verdict for every dimension.
|
|
51
|
-
- 🚦 **Delivery gate** — at the turn boundary, a delivery that reached green with no `doublecheck_report` on record gets a report-expected reminder before completion claims; a successful report advances the stage fold to `verify`.
|
|
52
|
-
- 🔁 **Durable state** — every model-visible artifact (spec, reminders, deny feedback, review findings, the `/doublecheck on|off` switch) lands in the session log; gate decisions derive from the log alone (`tool/call` + `tool/result`, including Code Mode sub-dispatches), so resumed and forked sessions enforce identically. `remindOnce` is durable too: a session that already received a reminder never gets it twice, even after a restart. The switch fold rides an incremental snapshot, so long sessions stay O(new events) per tool call.
|
|
53
|
-
- ⌨️ **`/doublecheck` session command** — `status` reports the effective switch, the configured modules, the enforcement intensity, and the folded stage facts (spec, test color, review, edit count); `report` folds the delivery report on the spot; `on|off` writes the durable `doublecheck/state` override and injects a switch notice.
|
|
54
|
-
- 📚 **`doublecheck_skills` tool** — lists and loads the package's skills through the official skill registry seam.
|
|
55
|
-
- 🔒 **Strict overlay** — `strict.patch.yml` turns every gate on at `block` intensity in one patch layer (ships with the package).
|
|
56
|
-
- 🧩 **Standalone invariant companion** — the `dsh-doublecheck/invariant` row is a real subpath export: it reports package-owned write-path contradictions (spec/report/review shape) through the host `invariants` registry without loading the guard.
|
|
57
|
-
|
|
58
|
-
## Demo
|
|
59
|
-
|
|
60
|
-
A real headless run with `intensity: block` and every gate enabled, transcript recorded from the durable session log:
|
|
23
|
+
## Compatibility
|
|
61
24
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
25
|
+
| Surface | Status |
|
|
26
|
+
|---|---|
|
|
27
|
+
| Harness | DeepSeek Harness `0.1.0-rc.6` |
|
|
28
|
+
| Node | `^22.19.0 \|\| >=24.0.0` |
|
|
29
|
+
| Platforms | All (pure host; no native code, no direct network requests of its own) |
|
|
30
|
+
| Model | Any (the guard itself never calls a model; the critic and reviewer phases run as harness subagents) |
|
|
65
31
|
|
|
66
|
-
|
|
67
|
-
`Error: Blocked by the dsh-doublecheck requirements guard: the task statement is vague and no doublecheck_spec exists for this session.`
|
|
68
|
-
2. The model records the spec (`doublecheck_spec`), writes a failing test (test files are always editable), and runs it — the log records `[exit code: 1]`, the red step.
|
|
69
|
-
3. Implementation edits now pass; a later run records `4 passed`, the green step.
|
|
70
|
-
4. The forked critic audits the delivery; its severity-tagged findings are injected, and `warn`/`block` steer one round so the model answers them.
|
|
71
|
-
5. `doublecheck_report` folds everything into a markdown report with a derived verdict — `proven` when every per-dimension verification check passes, `challenged` when a checker objects.
|
|
32
|
+
## What you get
|
|
72
33
|
|
|
73
|
-
|
|
34
|
+
`dsh-doublecheck` installs two plugin rows that read and enforce from the same durable session log:
|
|
74
35
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
dsh --profile <name> --dump-config # expect a "# == dsh-doublecheck" layer
|
|
78
|
-
```
|
|
36
|
+
1. **`doublecheck-grill`** — the requirements furnace: the bundled `grill-requirements` skill plus the model-facing `doublecheck_skills`, `doublecheck_spec`, and `doublecheck_report` tools and the per-dimension verification workflow.
|
|
37
|
+
2. **`doublecheck-guard`** — the discipline guard: the grill gate, the red/green evidence gates, the adversary review, the `/doublecheck` and `/gate` commands, the `doublecheck.gate` settings namespace, and the four-phase delivery gate.
|
|
79
38
|
|
|
80
|
-
|
|
39
|
+
Together they enforce the **discipline loop** — *grill → design → red → green → review → verify*:
|
|
81
40
|
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
|
|
41
|
+
```text
|
|
42
|
+
grill ──▶ design ──▶ red ──▶ green ──▶ review ──▶ verify
|
|
43
|
+
│
|
|
44
|
+
└─ six requirement dimensions, consensus gate,
|
|
45
|
+
structured spec committed to the session + workspace
|
|
85
46
|
```
|
|
86
47
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
48
|
+
| Stage | Meaning |
|
|
49
|
+
|---|---|
|
|
50
|
+
| **grill** | Interrogate the six requirement dimensions; refuse to implement until consensus. |
|
|
51
|
+
| **design** | The settled spec is committed via `doublecheck_spec`. |
|
|
52
|
+
| **red** | A failing test run proves the gap before implementation edits. |
|
|
53
|
+
| **green** | A passing test run after the edits closes the loop. |
|
|
54
|
+
| **review** | A forked adversary critic audits the delivery against the spec. |
|
|
55
|
+
| **verify** | `doublecheck_report` + a per-dimension verification workflow prove the delivery. |
|
|
92
56
|
|
|
93
|
-
|
|
57
|
+
## Quick start
|
|
94
58
|
|
|
95
59
|
```sh
|
|
96
|
-
|
|
97
|
-
|
|
60
|
+
# 1. install the bundle into your profile
|
|
61
|
+
dsh plugin --profile web add "github:PerryLink/dsh-doublecheck#main"
|
|
98
62
|
|
|
99
|
-
|
|
63
|
+
# or from npm (published releases)
|
|
64
|
+
dsh plugin --profile web add dsh-doublecheck
|
|
100
65
|
|
|
101
|
-
|
|
102
|
-
dsh
|
|
66
|
+
# 2. restart and verify the row
|
|
67
|
+
dsh --profile web --dump-config | grep -E -A3 'id: doublecheck-(grill|guard)'
|
|
103
68
|
```
|
|
104
69
|
|
|
105
|
-
|
|
70
|
+
Both rows (`doublecheck-grill` and `doublecheck-guard`) activate automatically with the profile.
|
|
106
71
|
|
|
107
|
-
##
|
|
108
|
-
|
|
109
|
-
- Verified against the `0.1.0-rc.6` peers (`@deepseek-ai/cordis ^4.0.1`); last verified 2026-08-14 on Windows with Node 22.
|
|
110
|
-
- The durable session switch (`/doublecheck on|off` → `doublecheck/state`) needs the host's `ignorable` append surface (post-rc.6 harness): on rc.6 hosts the options bag is ignored and the event stays required-on-read, so prefer in-memory switching there until the harness is upgraded.
|
|
111
|
-
|
|
112
|
-
## Permissions & data
|
|
72
|
+
## Install & uninstall
|
|
113
73
|
|
|
114
|
-
- **
|
|
115
|
-
- **
|
|
116
|
-
- **
|
|
117
|
-
- **
|
|
74
|
+
- **git channel** (latest `main`): `dsh plugin --profile web add "github:PerryLink/dsh-doublecheck#main"` — the `prepare` script builds with production dependencies only.
|
|
75
|
+
- **npm channel** (published releases): `dsh plugin --profile web add dsh-doublecheck`.
|
|
76
|
+
- **tarball channel**: `pnpm pack` in this repo, then `dsh plugin --profile web add ./dsh-doublecheck-<version>.tgz`.
|
|
77
|
+
- **uninstall**: `dsh plugin --profile web remove dsh-doublecheck` (or remove the rows from the profile patch).
|
|
118
78
|
|
|
119
|
-
|
|
79
|
+
For a zero-configuration strict mode (every gate on at `block` intensity, gate coverage required), apply the shipped overlay on top of the bundle patch: `dsh --profile web --patch ./node_modules/dsh-doublecheck/strict.patch.yml`.
|
|
120
80
|
|
|
121
|
-
|
|
122
|
-
|---|---|
|
|
123
|
-
| No `# == dsh-doublecheck` layer in `--dump-config` | The bundle patch is missing or a row is `disabled` — check the profile patch order and row ids. |
|
|
124
|
-
| The gates never react | Run `/doublecheck status`: the session switch may be off, or every `modules.*` entry is false in the guard row. |
|
|
125
|
-
| "Adversary review did not run: the subagents seam is not mounted" | This profile composition provides no subagent provider — mount one (spine compositions do) or disable `modules.adversary`. |
|
|
126
|
-
| `doublecheck_report` shows `verification: null` | The `workflowEngine` seam is missing or the run was rejected/aborted — the report states this instead of guessing. |
|
|
127
|
-
| The report says `unverified` | Verification ran but not every spec dimension returned a verdict — re-run with `verify: true`; `proven` requires all six. |
|
|
128
|
-
|
|
129
|
-
## Configure
|
|
130
|
-
|
|
131
|
-
Override any row **by id** in the profile's `cordis.patch.yml`. A patch replaces the row's whole config — restate every key:
|
|
132
|
-
|
|
133
|
-
```yaml
|
|
134
|
-
- id: doublecheck-grill
|
|
135
|
-
config:
|
|
136
|
-
specFile: 'specs/doublecheck-spec.md' # default: 'doublecheck-spec.md'
|
|
137
|
-
reportFile: 'specs/doublecheck-report.md' # default: 'doublecheck-report.md'
|
|
138
|
-
reportVerify: true # run the verify workflow by default
|
|
139
|
-
verifyProvider: 'fork' # provider for the per-dimension checkers
|
|
140
|
-
reportTestToolNames: ['bash', 'pwsh']
|
|
141
|
-
reportTestCommandPatterns:
|
|
142
|
-
- '(?:^|[;&|]\s*)(?:(?:pnpm|npm|npx|yarn|bun)(?:\s+run)?\s+(?:test|vitest|jest|mocha)(?:\s|$))'
|
|
143
|
-
- '(?:^|[;&|]\s*)(?:(?:pytest|go\s+test|cargo\s+test|make\s+test|ctest)(?:\s|$))'
|
|
144
|
-
- '(?:^|[;&|]\s*)(?:node\s+--test(?:\s|$))'
|
|
145
|
-
- '(?:^|[;&|]\s*)(?:deno\s+test|uv\s+run\s+pytest)(?:\s|$)'
|
|
146
|
-
reportMutationTools: ['edit', 'write']
|
|
147
|
-
reportTestFilePatterns:
|
|
148
|
-
- '(^|[\\/])(tests?|__tests__|specs?)([\\/]|$)'
|
|
149
|
-
- '\\.(test|spec)\\.[A-Za-z0-9]+$'
|
|
150
|
-
|
|
151
|
-
- id: doublecheck-guard
|
|
152
|
-
config:
|
|
153
|
-
intensity: warn
|
|
154
|
-
modules:
|
|
155
|
-
grill: true
|
|
156
|
-
tdd: true # red/green evidence gates (v0.2)
|
|
157
|
-
adversary: true # forked critic review (v0.3)
|
|
158
|
-
adversaryModel: null # or e.g. 'deepseek-v4-pro' for a separate critic model
|
|
159
|
-
adversaryProvider: 'fork' # subagent provider the critic runs on
|
|
160
|
-
adversaryMaxFindings: 5 # findings cap injected into the session
|
|
161
|
-
adversaryTools: ['read', 'glob', 'grep'] # critic tool allowlist (read-only)
|
|
162
|
-
adversaryTimeoutMs: 120000 # hard budget for one critic run
|
|
163
|
-
guardTools: ['edit', 'write']
|
|
164
|
-
vagueTaskMaxChars: 200
|
|
165
|
-
remindOnce: true
|
|
166
|
-
testToolNames: ['bash', 'pwsh']
|
|
167
|
-
testCommandPatterns:
|
|
168
|
-
- '(?:^|[;&|]\s*)(?:(?:pnpm|npm|npx|yarn|bun)(?:\s+run)?\s+(?:test|vitest|jest|mocha)(?:\s|$))'
|
|
169
|
-
- '(?:^|[;&|]\s*)(?:(?:pytest|go\s+test|cargo\s+test|make\s+test|ctest)(?:\s|$))'
|
|
170
|
-
- '(?:^|[;&|]\s*)(?:node\s+--test(?:\s|$))'
|
|
171
|
-
- '(?:^|[;&|]\s*)(?:deno\s+test|uv\s+run\s+pytest)(?:\s|$)'
|
|
172
|
-
testFilePatterns:
|
|
173
|
-
- '(^|[\\/])(tests?|__tests__|specs?)([\\/]|$)'
|
|
174
|
-
- '\\.(test|spec)\\.[A-Za-z0-9]+$'
|
|
175
|
-
```
|
|
81
|
+
## Configuration
|
|
176
82
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
### `intensity`
|
|
180
|
-
|
|
181
|
-
| Value | Behavior on a gated `edit`/`write` |
|
|
182
|
-
|---|---|
|
|
183
|
-
| `remind` (default) | Call proceeds; a reminder rides the result context into the next model request. |
|
|
184
|
-
| `warn` | Call is held for one-time human approval via the approval seam (denies when no channel exists). |
|
|
185
|
-
| `block` | Call is denied with feedback directing the model to fix the discipline first. |
|
|
186
|
-
|
|
187
|
-
### Tuning
|
|
83
|
+
All tunables are Schemastery `Config` fields (changeable from cordis.yml). An id-targeted override replaces the whole row — restate every key you need. `cordis.patch.yml` documents each key inline; Schema defaults are the single source of tuning defaults.
|
|
188
84
|
|
|
189
85
|
| Key | Default | Meaning |
|
|
190
86
|
|---|---|---|
|
|
191
|
-
| `
|
|
192
|
-
| `
|
|
193
|
-
| `
|
|
194
|
-
| `
|
|
195
|
-
| `
|
|
87
|
+
| `specFile` | `'doublecheck-spec.md'` | Workspace file for the committed spec markdown (grill row). |
|
|
88
|
+
| `reportFile` | `'doublecheck-report.md'` | Workspace file for the delivery report (grill row). |
|
|
89
|
+
| `reportVerify` | `true` | Run the verification workflow by default (grill row). |
|
|
90
|
+
| `verifyProvider` | `'fork'` | Subagent provider for the per-dimension checkers (grill row). |
|
|
91
|
+
| `verifyMode` | `'all'` | `all` = one parallel checker per dimension; `single` = one combined checker (grill row). |
|
|
92
|
+
| `intensity` | `'remind'` | Enforcement strength of the grill, red/green, and review gates (`remind` / `warn` / `block`). |
|
|
93
|
+
| `enableByDefault` | `true` | Master switch for sessions without a `/doublecheck on\|off` record. |
|
|
94
|
+
| `language` | `'en'` | Injected reminder/deny/review/gate prose language (`en` / `zh`). |
|
|
196
95
|
| `guardTools` | `['edit', 'write']` | Mutation tool names both gates watch. |
|
|
197
|
-
| `vagueTaskMaxChars` | `200` | Longer tasks are never treated as vague.
|
|
198
|
-
| `remindOnce` | `true` | Inject each
|
|
96
|
+
| `vagueTaskMaxChars` | `200` | Longer tasks are never treated as vague. |
|
|
97
|
+
| `remindOnce` | `true` | Inject each reminder at most once per session (durable across restarts). |
|
|
199
98
|
| `testToolNames` | `['bash', 'pwsh']` | Shell tool names that can run tests. |
|
|
200
99
|
| `testCommandPatterns` | *(pnpm/npm/yarn/bun test, pytest, go/cargo/make test, node --test, deno test, uv run pytest)* | Regexes a command must match to count as a test run. |
|
|
201
100
|
| `testFilePatterns` | *(test dirs, `*.test.*` / `*.spec.*`)* | Regexes identifying test files — always editable, exempt from the red gate. |
|
|
101
|
+
| `modules.grill` | `true` | Off disables the grill gate. |
|
|
102
|
+
| `modules.tdd` | `true` | On enables the red/green evidence gates. |
|
|
103
|
+
| `modules.adversary` | `false` | On enables the forked critic review at green. |
|
|
202
104
|
| `adversaryModel` | `null` | Critic model route; `null` = main model self-reviews. |
|
|
203
|
-
| `adversaryProvider` | `'fork'` | Subagent provider
|
|
105
|
+
| `adversaryProvider` | `'fork'` | Subagent provider the critic runs on. |
|
|
204
106
|
| `adversaryMaxFindings` | `5` | Findings cap (1–20) injected into the session. |
|
|
205
107
|
| `adversaryTools` | `['read', 'glob', 'grep']` | Critic tool allowlist; keep it read-only. |
|
|
206
108
|
| `adversaryTimeoutMs` | `120000` | Hard time budget for one critic run. |
|
|
109
|
+
| `gate.enabled` | `true` | Master switch for the gate panel and the turn-boundary red notice. |
|
|
110
|
+
| `gate.planSuggestion` | `true` | Append the plan-mode re-check suggestion to red reports. |
|
|
111
|
+
| `gate.reportFile` | `'gate-report.md'` | Workspace file for the gate report. |
|
|
112
|
+
| `gate.requirements.checklist` | *(six spec-dimension questions)* | Pluggable key-question checklist: `{ id, question, specDimension, required }`. |
|
|
113
|
+
| `gate.requirements.minConfirmed` | `6` | Minimum required questions that must pass (1..required count). |
|
|
114
|
+
| `gate.requirements.interrogateTool` | `'ask_user_question'` | Tool name whose calls count as interrogation evidence. |
|
|
115
|
+
| `gate.tests.requirePassingRun` | `true` | A non-passing (or missing) latest test run is a red light. |
|
|
116
|
+
| `gate.tests.allowFailingRuns` | `0` | Failing runs after the latest green allowed before red. |
|
|
117
|
+
| `gate.tests.requireCoverage` | `false` | On requires coverage evidence in the test output. |
|
|
118
|
+
| `gate.tests.minCoveragePct` | `80` | Minimum coverage percentage (0–100). |
|
|
119
|
+
| `gate.consistency.*` | `provider: 'fork'`, `model: null`, `tools: ['read','glob','grep']`, `timeoutMs: 120000`, `maxFindings: 5` | The local consistency reviewer's knobs (`model: null` = main model). |
|
|
120
|
+
| `gate.review.engine` | `'auto'` | `auto` = dsh-auto-review verdict records when present, else the local reviewer; `local` = always local. |
|
|
121
|
+
| `gate.review.provider` | `'fork'` | The local review reviewer's provider (its `model`/`tools`/`timeoutMs`/`maxFindings` match `gate.consistency.*`). |
|
|
122
|
+
|
|
123
|
+
Misconfiguration fails loud at load: invalid regexes, empty or duplicated name lists, out-of-range thresholds, and duplicate checklist ids throw instead of silently doing nothing. `strict.patch.yml` is the all-gates-block overlay that restates the guard row at `intensity: block` with every module on and the coverage requirement enabled.
|
|
124
|
+
|
|
125
|
+
## Tools & surfaces
|
|
126
|
+
|
|
127
|
+
| Surface | Kind | Notes |
|
|
128
|
+
|---|---|---|
|
|
129
|
+
| `doublecheck_skills` | tool | Lists and loads the package's four bundled skills through the skill registry seam. |
|
|
130
|
+
| `doublecheck_spec` | tool | Commits the grilled six-dimension spec to the session log and a workspace markdown copy. |
|
|
131
|
+
| `doublecheck_report` | tool | Folds the discipline evidence into a delivery report (optional per-dimension verification workflow). |
|
|
132
|
+
| `/doublecheck status\|report\|on\|off` | command | Switch, modules, intensity, stage facts, folded report, and the durable on/off override. |
|
|
133
|
+
| `/gate status\|run\|config` | command | Live checklist progress, the settled deliverable/rework report, and the effective config. |
|
|
134
|
+
| `grill-requirements`, `red-green-tdd`, `delivery-review`, `delivery-proof` | skill | Bundled discipline skills covering all six loop stages. |
|
|
135
|
+
| `doublecheck.gate` | settings namespace | The pluggable checklist, exposed to settings-capable UIs (`expose: true`, `applies: restart`). |
|
|
136
|
+
| `strict.patch.yml` | overlay | Every gate on at `block` intensity plus the coverage requirement, in one patch layer. |
|
|
137
|
+
| `dsh-doublecheck/invariant` | companion row | Reports package-owned write-path contradictions through the host `invariants` registry. |
|
|
207
138
|
|
|
208
|
-
|
|
139
|
+
## Gate phases
|
|
209
140
|
|
|
210
|
-
|
|
141
|
+
The delivery gate aggregates the session's durable evidence into a configurable four-phase checklist and settles one **deliverable / rework required** decision. Every phase folds the session log alone (replay IS the state), so a run re-derives identically after resume or fork.
|
|
211
142
|
|
|
212
|
-
|
|
|
213
|
-
|
|
214
|
-
|
|
|
215
|
-
|
|
|
216
|
-
|
|
|
217
|
-
|
|
|
218
|
-
| `reportTestToolNames` / `reportTestCommandPatterns` | *(same defaults as the guard row)* | Report-scoped test-run classification. |
|
|
219
|
-
| `reportMutationTools` / `reportTestFilePatterns` | *(same defaults as the guard row)* | Report-scoped implementation-edit classification. |
|
|
143
|
+
| Phase | Checks | Evidence source | Model cost |
|
|
144
|
+
|---|---|---|---|
|
|
145
|
+
| Requirements interrogation | Key-question checklist confirmed item by item (six spec-dimension questions by default) | Committed `doublecheck_spec` + `ask_user_question` calls | none |
|
|
146
|
+
| Test evidence | Latest run color, failing runs after green, optional coverage threshold | Shell test runs in the session log (`[exit code: N]`, coverage percentages) | none |
|
|
147
|
+
| Implementation consistency | Diff ↔ requirement mapping: every edit must serve a spec dimension | Local forked reviewer (structured findings, read-only tools) | one subagent |
|
|
148
|
+
| Review conclusion | The delivery verdict; `engine: auto` consumes dsh-auto-review's durable verdict records when present, else the local reviewer | `autoReview/verdict` / `autoReview/rejection` events, or the local forked reviewer | one subagent (local) |
|
|
220
149
|
|
|
221
|
-
|
|
150
|
+
Red lights are failed checks (a missing spec, a failing latest run, coverage below minimum, an unmapped edit, blocker/major findings) — each carries a rework suggestion. Warnings and skips never flip the decision. The gate integrates [dsh-auto-review](https://github.com/PerryLink/dsh-auto-review) as a weak dependency: `review.engine: auto` folds its verdict records when present and degrades to the local reviewer otherwise; the gate never synthesizes approval requests.
|
|
222
151
|
|
|
223
|
-
##
|
|
152
|
+
## Example report
|
|
224
153
|
|
|
225
|
-
|
|
226
|
-
|---|---|
|
|
227
|
-
| Bundled skills | `ctx.skills.registerProvider()` — skill capability seam, `source: bundled` |
|
|
228
|
-
| Catalog/loader tool | `ctx.tools.register()` — `doublecheck_skills` |
|
|
229
|
-
| Spec commit + workspace file | `doublecheck_spec` tool + `ctx.fs` write (optional) |
|
|
230
|
-
| Requirements gate | `tools/pre-execute` waterfall — `allow` / `ask` (approval seam) / `deny` |
|
|
231
|
-
| Red gate | `tools/pre-execute` waterfall — hard check of failing-test evidence before implementation edits |
|
|
232
|
-
| Reminder injection | `tools/post-execute` waterfall — `additionalContexts` → logged as `user/message` |
|
|
233
|
-
| Green gate | `agent/turn-stopping` serial — injects a completion reminder when edits lack a passing run |
|
|
234
|
-
| Adversary review | `ctx.subagents.start()` — forked critic with structured findings schema, injected at green; `warn`/`block` steer one round |
|
|
235
|
-
| Delivery report | `doublecheck_report` tool — session-log fold + workspace markdown |
|
|
236
|
-
| Verification workflow | `ctx.workflowEngine.start()` — one parallel checker per spec dimension, structured checks |
|
|
237
|
-
| Durable state | session log fold over `tool/call` + `tool/result` + `tool/code-dispatch` + injected structured sources; model-visible ⟺ logged |
|
|
238
|
-
| Session command | `ctx.commands.register()` — `/doublecheck status|report|on|off`; `on|off` writes the durable `doublecheck/state` session event |
|
|
239
|
-
| Internal events | `doublecheck/spec`, `doublecheck/reminder`, `doublecheck/review`, `doublecheck/report` (typed via declaration merging, `@mode emit`) |
|
|
240
|
-
|
|
241
|
-
No agent-loop changes. Every registration is a reversible `ctx.effect` / `ctx.on` / service `register()`.
|
|
242
|
-
|
|
243
|
-
## What the model sees
|
|
244
|
-
|
|
245
|
-
- The `grill-requirements` skill joins the session skill catalog and loads through the built-in `skill` tool (or `doublecheck_skills`).
|
|
246
|
-
- `ask_user_question` stays the native DSH way to interrogate the user; the skill only choreographs it (and degrades to prose questions in headless runs with no provider).
|
|
247
|
-
- Reminders arrive as `{kind:'plugin'}` context, so transcript UIs present them as injection metadata.
|
|
248
|
-
- The adversary critique arrives the same way after the critic settles, with severity-tagged findings; under `warn`/`block` the loop is steered one round so the model answers them.
|
|
249
|
-
- `doublecheck_report` returns the consolidated report as a tool result (spec, test timeline, review, verification, verdict), so "prove the delivery" is one call away.
|
|
250
|
-
- `/doublecheck` answers in the transcript directly: `status` shows the switch, modules, intensity, and stage facts, `report` prints the folded report, `on|off` flips the session switch.
|
|
251
|
-
|
|
252
|
-
## Session command
|
|
154
|
+
`/gate run` returns this markdown — paste it into a PR description:
|
|
253
155
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
156
|
+
````markdown
|
|
157
|
+
# Delivery gate report
|
|
158
|
+
|
|
159
|
+
> **Verdict: rework required** — 2 red item(s)
|
|
160
|
+
> The gate is red. Re-open the work in plan mode to re-check the open items before delivering.
|
|
161
|
+
|
|
162
|
+
## 1. Requirements interrogation — PASS
|
|
163
|
+
- [✔] **What outcome must the delivery produce?** — spec dimension "goal" committed
|
|
164
|
+
- [✔] **What is in scope, and what is out of scope?** — spec dimension "scope" committed
|
|
165
|
+
- [✔] **Which observable checks prove the work is done?** — spec dimension "acceptanceCriteria" committed
|
|
166
|
+
- [✔] **What can go wrong, and what is the correct behavior in each case?** — spec dimension "failureModes" committed
|
|
167
|
+
- [✔] **What is traded when goals conflict; what is optional?** — spec dimension "priorities" committed
|
|
168
|
+
- [✔] **What does the user explicitly not want?** — spec dimension "nonGoals" committed
|
|
169
|
+
|
|
170
|
+
## 2. Test evidence — FAIL
|
|
171
|
+
- [✔] **passing test run** — latest test run passed
|
|
172
|
+
- [✔] **failing cases after green** — 0 failing run(s) after green (allowed: 0)
|
|
173
|
+
- [✖] **coverage evidence** — 61% coverage below the 80% minimum — rework: raise coverage above the configured minimum
|
|
257
174
|
|
|
258
|
-
|
|
259
|
-
-
|
|
260
|
-
- `on` / `off` — writes the durable `doublecheck/state` event (survives restart, resume, and fork — replay IS the state) and injects a model-visible switch notice.
|
|
175
|
+
## 3. Implementation consistency — WARN
|
|
176
|
+
- [⚠] **[minor] src/telemetry.ts touched without a requirement** — [minor] the edit adds a metric no spec dimension covers
|
|
261
177
|
|
|
262
|
-
|
|
178
|
+
## 4. Review conclusion — PASS
|
|
179
|
+
- [✔] **dsh-auto-review conclusion** — 3 call(s) approved by dsh-auto-review (latest risk: low)
|
|
263
180
|
|
|
264
|
-
##
|
|
181
|
+
## Red items
|
|
182
|
+
1. **tests/coverage** — 61% coverage below the 80% minimum — *rework: raise coverage above the configured minimum*
|
|
183
|
+
2. **consistency/finding-1** — [minor] the edit adds a metric no spec dimension covers — *rework: src/telemetry.ts touched without a requirement*
|
|
265
184
|
|
|
266
|
-
|
|
185
|
+
## Audit
|
|
186
|
+
- review engine: dsh-auto-review
|
|
187
|
+
- generated at: 2026-08-14T12:00:00.000Z
|
|
188
|
+
- counts, ids, and verdicts only: no file contents or session text are embedded, and recognized secrets are redacted.
|
|
189
|
+
````
|
|
267
190
|
|
|
268
|
-
##
|
|
191
|
+
## Permissions & data
|
|
192
|
+
|
|
193
|
+
- **Reads**: the session log (`tool/call` / `tool/result` / `tool/code-dispatch`, injected `user/message` sources, and the foreign `autoReview/*` verdict records) in-process only; the optional plan-mode service state.
|
|
194
|
+
- **Writes**: `doublecheck-spec.md`, `doublecheck-report.md`, and `gate-report.md` in the session workspace (paths configurable) through the `ctx.fs` seam; the durable `doublecheck/state` and `doublecheck/gate` session events.
|
|
195
|
+
- **Model calls**: the gate's consistency and local-review phases (one subagent each per `/gate run`), the optional adversary review, and the `doublecheck_report` verification workflow start subagent runs; nothing else calls a model or the network.
|
|
196
|
+
- **Never touched**: credentials, environment variables, or any file outside the session workspace. The workshop manifest declares `filesystem:read` and `filesystem:write` only. Gate reports carry counts, ids, and verdicts only; recognized secrets in reviewer texts are redacted before storage or display.
|
|
197
|
+
|
|
198
|
+
## Security boundaries
|
|
199
|
+
|
|
200
|
+
- **Model-visible ⟺ logged.** Every injected reminder, review, and gate notice rides the standard channels and lands in the session log; the durable spec/state/gate facts ride tool results or `SessionEventMap` members.
|
|
201
|
+
- **Fail closed / fail loud.** Guard and gate config are validated in `apply` (assertions throw); a reviewer or adversary seam that cannot run settles as an honest "unavailable"/skip notice instead of a fake verdict.
|
|
202
|
+
- **Audit-safe reports.** Gate and delivery reports record counts, ids, and verdicts only — no file contents or session text — and model-produced finding texts pass a secret redactor before storage or display.
|
|
203
|
+
- **No network of its own.** The plugin makes no direct network requests; the critic and reviewer subagents ride the harness subagent seam.
|
|
204
|
+
- **Weak dependency on dsh-auto-review.** It is never imported or hard-required; the gate folds its durable verdict records and degrades to the local reviewer, and never synthesizes approval requests.
|
|
205
|
+
|
|
206
|
+
## Known limitations
|
|
207
|
+
|
|
208
|
+
- **Durable writes on rc.6.** `/doublecheck on\|off` → `doublecheck/state` and `/gate run` → `doublecheck/gate` need the host's `ignorable` append surface (post-rc.6); on rc.6 hosts the options bag is ignored and the event stays required-on-read, so the switch stays in-memory and the gate record lives in the command result + workspace file only until the harness is upgraded.
|
|
209
|
+
- **Optional seams.** The `doublecheck.gate` settings namespace registers only when the settings service is mounted; the `/gate status` plan-mode line reads the optional `ctx.planMode` (shows `unknown` without it); the adversary review needs `ctx.subagents`; verification needs `workflowEngine`.
|
|
210
|
+
- **Local degrade.** `gate.review.engine: auto` degrades to the local reviewer when dsh-auto-review is absent or has no verdict records this session — the report names the reason instead of inventing a verdict.
|
|
211
|
+
|
|
212
|
+
## Development
|
|
269
213
|
|
|
270
214
|
```sh
|
|
271
|
-
pnpm install
|
|
272
|
-
pnpm run
|
|
273
|
-
pnpm run
|
|
274
|
-
pnpm run test
|
|
275
|
-
pnpm run
|
|
215
|
+
pnpm install # node ^22.19 || >=24
|
|
216
|
+
pnpm run build # tsc --noEmitOnError (lib/ is committed)
|
|
217
|
+
pnpm run prepare # tsc --noEmitOnError (git-install channel)
|
|
218
|
+
pnpm run prepublishOnly # build + full test suite
|
|
219
|
+
pnpm run typecheck # tsc --noEmit + tests tsconfig
|
|
220
|
+
pnpm run lint # eslint src tests
|
|
221
|
+
pnpm test # vitest run
|
|
222
|
+
pnpm run test:coverage # vitest run --coverage
|
|
223
|
+
pnpm run pack:check # build + pack the tarball
|
|
276
224
|
```
|
|
277
225
|
|
|
278
|
-
##
|
|
226
|
+
## Topics
|
|
279
227
|
|
|
280
|
-
|
|
228
|
+
`dsh`, `dsh-plugin`, `deepseek-harness`, `engineering-discipline`, `requirements`, `guard`, `skill`, `quality-gate`, `delivery-gate`
|
|
229
|
+
|
|
230
|
+
## Contributors
|
|
231
|
+
|
|
232
|
+
- [@PerryLink](https://github.com/PerryLink) — creator and maintainer: the grill → design → red → green → review → verify discipline loop, the four-phase delivery gate, the five-language docs, and the CI/release pipeline.
|
|
233
|
+
|
|
234
|
+
## PerryLink DSH Plugin Family
|
|
235
|
+
|
|
236
|
+
This project is one of the [15 DeepSeek Harness plugins](https://github.com/PerryLink) maintained by [PerryLink](https://github.com/PerryLink). If this one helps you, the others likely will too:
|
|
237
|
+
|
|
238
|
+
| Plugin | One-liner |
|
|
239
|
+
|---|---|
|
|
240
|
+
| [dsh-mcp-panel](https://github.com/PerryLink/dsh-mcp-panel) | Read-only MCP runtime panel: /mcp command + Settings tab with status, tools and errors |
|
|
241
|
+
| **[dsh-doublecheck](https://github.com/PerryLink/dsh-doublecheck)** | Engineering-discipline guard + delivery quality gate: requirements grill, test gates, adversary review, /gate deliverable/rework panel |
|
|
242
|
+
| [dsh-background-agents](https://github.com/PerryLink/dsh-background-agents) | Durable background child agents with a Web UI sidebar, messaging and interrupt |
|
|
243
|
+
| [dsh-lsp-actions](https://github.com/PerryLink/dsh-lsp-actions) | LSP diagnostics, formatting, completion, code actions and rename over language servers |
|
|
244
|
+
| [dsh-output-styles](https://github.com/PerryLink/dsh-output-styles) | Claude Code outputStyles-equivalent runtime style switching |
|
|
245
|
+
| [dsh-checkpoint-rewind](https://github.com/PerryLink/dsh-checkpoint-rewind) | Claude Code /rewind-equivalent: snapshots, session forks, one-shot restore |
|
|
246
|
+
| [dsh-permission-rules](https://github.com/PerryLink/dsh-permission-rules) | Claude Code-style declarative allow/deny/ask permission rules with audit |
|
|
247
|
+
| [dsh-auto-review](https://github.com/PerryLink/dsh-auto-review) | Second-model auto-review on the approval chain, fail-closed by default |
|
|
248
|
+
| [dsh-memento](https://github.com/PerryLink/dsh-memento) | Approval-gated cross-session memory: ctx.memory seam + SQLite + memory tool |
|
|
249
|
+
| [dsh-skill-pack-security](https://github.com/PerryLink/dsh-skill-pack-security) | Security-audit skill pack: secret scan, dependency and supply-chain review |
|
|
250
|
+
| [dsh-session-pin](https://github.com/PerryLink/dsh-session-pin) | Pin sessions in the Web sidebar with durable ordering |
|
|
251
|
+
| [dsh-composer-history](https://github.com/PerryLink/dsh-composer-history) | Terminal-style input history for the web composer: arrows, Ctrl+R search |
|
|
252
|
+
| [dsh-github](https://github.com/PerryLink/dsh-github) | GitHub PR/issues integration for DSH, every write gated by approval |
|
|
253
|
+
| [dsh-plugin-guide](https://github.com/PerryLink/dsh-plugin-guide) | Plugin-development knowledge base as an on-demand agent skill |
|
|
254
|
+
| [dsh-claude-move](https://github.com/PerryLink/dsh-claude-move) | Migrate Claude Code sessions, memory, skills and CLAUDE.md into DSH |
|
|
281
255
|
|
|
282
256
|
## License
|
|
283
257
|
|
|
284
|
-
[Apache
|
|
258
|
+
[Apache License 2.0](LICENSE) © 2026 dsh-doublecheck contributors
|