dogwatch

how a statement earns the right to be published

15 rules. 16 planted records. 0 taken on faith.

dogwatch verify runs on every committed record on every push. A violation that merely warns fails the build. Each rule below has a deliberately-broken record behind it — open one and press Verify to watch the checker catch it in your own browser.

The honesty rubric

schema generated from the same Zod source the runner uses

R1

checks[] is empty, or a check is stuck at a non-terminal verdict

E_NO_CHECKS / E_CHECK_NONTERMINALno-checkscheck-nonterminal
R2 / R3

a finding pointing at a check that isn't a finding, or a finding-verdict check with no finding for it

E_ORPHAN_FINDING / E_UNREPORTED_CHECKorphan-findingunreported-check
R4

a finding without a real source: an absolute https URL, a retrieval timestamp inside the run window, and an evidence path that resolves inside the same record

E_UNSOURCED_FINDINGunsourced-finding
R5

an empty-findings run whose absence-of-evidence section doesn't match the actual pass count

E_NO_ABSENCE_SECTIONno-absence-section
R6

a skipped or errored check with no machine-readable reason, or missing from notChecked

E_SILENT_SKIPsilent-skip
R7 / R8

an action or gate not backed by a real, matching audit event

E_ACTION_UNBACKED / E_GATE_UNBACKEDaction-unbackedgate-unbacked
R9

a cost that doesn't sum to its own breakdown, or LLM usage claimed with no provider-reported tokens behind it

E_COST_UNBACKEDcost-unbacked
R10

an advisory note published with no model call behind it, or citing a finding id or URL that isn't in this record's own evidence

E_ADVISORY_UNGROUNDEDadvisory-ungrounded
R11

a broken or unverified audit hash chain, or a discontinuity from the previous run with no gap record explaining it

E_CHAIN_BROKENchain-broken
R12

a record whose content no longer matches the hash committed alongside it — the tamper-evidence check

E_RECORD_TAMPEREDrecord-tampered
R13

a finding statement that wasn't re-derived byte-for-byte from stored evidence by the rule that owns it

E_MANUFACTURED_FINDINGmanufactured-finding
R14

a metric wearing a severity, or sharing an id with a check or finding

E_METRIC_AS_FINDINGmetric-as-finding
R15

a secret-shaped string, or a header outside the published allowlist, anywhere in a record

E_SECRET_LEAKsecret-leak

Those 16 records are committed under fixtures/violations/ and asserted against their exact error codes by the eval suite. They are planted failures, not published runs, and are marked noindex accordingly.

What the rules are protecting

R13: a finding is never written, only derived
A finding's statement is the return value of that rule's own template function, applied to recorded evidence — never written by a human or a model. R13 re-derives every finding from scratch, offline, over the stored evidence, and requires the result to match the published statement byte-for-byte. There is no other code path in the type system that can produce a Finding.
The advisory model, and why its opinion cannot change anything
On a night with findings, one advisory call (Haiku 4.5, forced tool schema, Zod-validated on the way back) reads the structured evidence already in the record — never a page body — and returns a severity, a note, and a proposed action. That action is published and ignored: the deterministic rule table already decided. When the model disagrees with the rule, the record publishes both plus agreesWithRule: false, so the disagreement rate is an artifact rather than a reassurance. A quiet night makes no call at all.
The autonomy ladder, and the one thing deliberately left ungated
L2, automatic: everything inside this repo — publishing the record, committing artifacts, opening and closing dogwatch's own gate issues. L3, human gate: every write to a repo dogwatch does not own. Publishing the record itself is deliberately ungated: withholding a run behind an approval would make the watch only as live as an inbox, and would defeat the one promise this product makes.

What this is not

  • An installable product. Nothing here is published to npm; forking it and pointing it at your own surfaces is unsupported.
  • A claim about anyone else's software. dogwatch watches six surfaces James operates, and refuses to probe the rest.
  • An uptime monitor. One request, one runner, one region, once a night — no SLA, no paging, no synthetic score.
  • A performance judgement. Timings and download counts are recorded and rendered, never judged, never a finding.