dunstan 0.1.13 → 0.1.15
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/README.md +90 -4
- package/dist/dunstan.mjs +1700 -376
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# Dunstan
|
|
2
2
|
|
|
3
|
+
<p align="left"><img src="brand/dunstan-icon.png" alt="Dunstan logo" width="96"></p>
|
|
4
|
+
|
|
5
|
+
**Verify an AI coding agent's pull request claims, with a verdict anyone can rerun.** The agent
|
|
6
|
+
says which files it changed, which tests ran and which issues it closed; Dunstan checks each claim
|
|
7
|
+
against the pull request, its commits and its CI runs, and reports the verdict as a check run. Every
|
|
8
|
+
verdict comes with a record: `dunstan verify` recomputes it offline and `dunstan rerun` re-reads
|
|
9
|
+
the sources, so a reviewer or customer can check it themselves. Deterministic, no LLM.
|
|
10
|
+
|
|
11
|
+
Add it to a workflow; the agent's report goes in the pull request body
|
|
12
|
+
(`npx -y dunstan template --base main` writes the block for you):
|
|
13
|
+
|
|
14
|
+
```yaml
|
|
15
|
+
on:
|
|
16
|
+
pull_request:
|
|
17
|
+
types: [opened, edited, synchronize, reopened, ready_for_review]
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
20
|
+
pull-requests: read
|
|
21
|
+
issues: read
|
|
22
|
+
deployments: read
|
|
23
|
+
checks: write
|
|
24
|
+
actions: read
|
|
25
|
+
jobs:
|
|
26
|
+
handback:
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
steps:
|
|
29
|
+
- uses: BargLabs/dunstan@v0.1.15 # pin the full commit SHA in production
|
|
30
|
+
with:
|
|
31
|
+
report-source: pr-body
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
More in [`docs/action.md`](docs/action.md).
|
|
35
|
+
|
|
3
36
|
Dunstan holds a coding agent's completion report to the record.
|
|
4
37
|
|
|
5
38
|
An agent finishes and writes a handback: files changed, tests run, references closed, head commit,
|
|
@@ -29,15 +62,18 @@ report a pull request's handback before it says done ([`plugins/dunstan/`](plugi
|
|
|
29
62
|
/plugin install dunstan@barglabs
|
|
30
63
|
```
|
|
31
64
|
|
|
32
|
-
The plugin runs the MCP server with `npx -y dunstan@0.1.
|
|
65
|
+
The plugin runs the MCP server with `npx -y dunstan@0.1.15 mcp`, the `dunstan` npm package at that
|
|
33
66
|
exact version: one self-contained file, no dependencies.
|
|
34
67
|
|
|
35
68
|
**The token.** When you enable the plugin, Claude Code asks for an optional GitHub token and keeps it
|
|
36
69
|
in your system's secure credential store. Use a fine-grained personal access token with read-only
|
|
37
70
|
permissions, limited to the repositories you check, with an expiry; the permissions are in
|
|
38
71
|
[`docs/mcp.md`](docs/mcp.md#a-read-only-github-token). Leave it empty to read public repositories
|
|
39
|
-
anonymously.
|
|
40
|
-
`unverifiable`, never `fail
|
|
72
|
+
anonymously. Two kinds of claim need a token, even on a public repository: GitHub's GraphQL API
|
|
73
|
+
refuses anonymous calls, so a `closes` reference is `unverifiable`, never `fail`; and GitHub answers
|
|
74
|
+
an artifact download only with a token (401 "Requires authentication" anonymously, observed
|
|
75
|
+
2026-11-02), so a `tests` count is `unverifiable` (`source_unreadable:artifact`). The plugin never
|
|
76
|
+
reads a token from your environment.
|
|
41
77
|
|
|
42
78
|
**What it reads, and from where.** The server runs on your machine and calls GitHub's API directly
|
|
43
79
|
from it: the pull request, its changed files, commits, check runs, workflow runs and test artifacts,
|
|
@@ -96,6 +132,34 @@ handback covers what the issue asked for: an accurate report of the wrong work p
|
|
|
96
132
|
|
|
97
133
|
What to declare: [`docs/agents.md`](docs/agents.md#the-instruction-block).
|
|
98
134
|
|
|
135
|
+
## Survey: how much of a repository's handbacks can be checked
|
|
136
|
+
|
|
137
|
+
`dunstan survey` (DRAFT) runs `dunstan check` over a repository's recent closed pull requests and
|
|
138
|
+
reports settleability: which claims the record could not settle, why, and what would let it settle
|
|
139
|
+
them. It is read-only and needs no token to start.
|
|
140
|
+
|
|
141
|
+
```sh
|
|
142
|
+
dist/dunstan.mjs survey --repo <owner/name> --last 30 [--author <agent-login>] --out survey.json --summary survey.md
|
|
143
|
+
dist/dunstan.mjs verify survey.json # offline: every embedded record, the selection, the aggregate and the digest
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
It reports two rates, each with its numerator, denominator and Wilson 95% interval:
|
|
147
|
+
|
|
148
|
+
- **the share of claims the record could not settle**, (unverifiable + not record-checkable) / all
|
|
149
|
+
claims, led by a table of the reasons, each with its remedy;
|
|
150
|
+
- **the share of settled claims the record contradicts**, contradicted / (supported +
|
|
151
|
+
contradicted).
|
|
152
|
+
|
|
153
|
+
With `--advisory` it also runs the advisory prose reader and counts its notes in a table of their
|
|
154
|
+
own. Advisory notes never enter either rate. A tests claim can be settled only with `GITHUB_TOKEN`
|
|
155
|
+
set and a JUnit record that CI uploads: GitHub serves no artifact to an anonymous reader, and a
|
|
156
|
+
test run CI never recorded, or a local run declared as one, is not record-checkable. The survey
|
|
157
|
+
record says whether it read with a token, and an anonymous survey's summary says its
|
|
158
|
+
cannot-settle share is higher for it. The survey measures what the record can settle. A survey
|
|
159
|
+
record is unsigned: `verify` proves it consistent with itself and every embedded record valid, not
|
|
160
|
+
that its listing is what GitHub returned, so to trust its completeness, run it again online.
|
|
161
|
+
Details: [`docs/survey.md`](docs/survey.md).
|
|
162
|
+
|
|
99
163
|
## Declare before done
|
|
100
164
|
|
|
101
165
|
Checking a declared claim is exact. Finding the claims in prose is where readers fail: a hosted
|
|
@@ -111,7 +175,8 @@ dist/dunstan.mjs suggest --report-file report.md # prose claims the block does
|
|
|
111
175
|
```
|
|
112
176
|
|
|
113
177
|
`template` fills `headCommit` and `filesChanged` (HEAD against its merge base with the remote's
|
|
114
|
-
default branch, or `--base`)
|
|
178
|
+
default branch, or `--base`). With `--tests-ci` it fills `tests` from the JUnit record CI published
|
|
179
|
+
at HEAD, read as the gate reads it; with `--tests-local` it declares a local run as one (below). It
|
|
115
180
|
never fills `references` or `mergedAt`, and when git cannot answer it prints no block. `suggest`
|
|
116
181
|
runs the advisory extractor over the prose outside the fence and lists each claim it proposes that
|
|
117
182
|
the block does not declare, to declare or reword. It is never a verdict, writes nothing to a record
|
|
@@ -119,6 +184,27 @@ and always exits 0; the MCP server offers it as `dunstan_suggest_declarations`.
|
|
|
119
184
|
instruction block to copy into `AGENTS.md` or `CLAUDE.md`, and example output:
|
|
120
185
|
[`docs/agents.md`](docs/agents.md).
|
|
121
186
|
|
|
187
|
+
## Make test claims checkable
|
|
188
|
+
|
|
189
|
+
Most claims about tests in a completion report ("all tests pass", "142 passed") cannot be checked
|
|
190
|
+
from a repository's records today: the tests ran on the agent's machine, or CI ran them and
|
|
191
|
+
published no counts. Dunstan settles a `tests` claim only against a JUnit file a CI run uploaded.
|
|
192
|
+
Two changes make such claims checkable:
|
|
193
|
+
|
|
194
|
+
1. **CI publishes the record.** One upload step after the test command: an artifact named
|
|
195
|
+
`dunstan-junit` holding `junit.xml`, uploaded even when the tests fail. Recipes for pytest,
|
|
196
|
+
jest, vitest, Maven, Gradle and Go, with `dunstan junit-merge` for runners that write one file
|
|
197
|
+
per test class: [`docs/ci-test-records.md`](docs/ci-test-records.md).
|
|
198
|
+
2. **The agent declares CI's counts.** After CI has finished on its last push, `dunstan template
|
|
199
|
+
--tests-ci --tests-command <cmd> --tests-workflow <path> --tests-job <name>` reads the counts
|
|
200
|
+
from that record, as the gate will, and declares them. A run made only locally is declared with
|
|
201
|
+
`--tests-local <file>` as `{"kind": "local"}`, which the gate reports `unverifiable`
|
|
202
|
+
(`local_run_not_in_record`), never `pass`.
|
|
203
|
+
|
|
204
|
+
Reading the artifact needs a token: without one a `tests` row is `unverifiable`
|
|
205
|
+
(`source_unreadable:artifact`). Each `tests` row the record cannot settle is printed with a
|
|
206
|
+
`remedy:` line saying what to do.
|
|
207
|
+
|
|
122
208
|
## The GitHub Action
|
|
123
209
|
|
|
124
210
|
One step in a workflow, one required check in branch protection:
|