Dogfooding dent8 on dent8
This repo uses dent8 as its own shared, verified fact base — the “stale-CLAUDE.md killer”
thesis, lived. This note records how the fact base was set up and every rough edge hit along
the way. Honesty over polish: where a command needed too many flags or an error lied, it is
here.
What was set up
Section titled “What was set up”- Seeded store.
scripts/dogfood-seed.shrebuilds.dent8/deterministically fromscripts/dogfood-facts.jsonl. The.dent8/store itself is gitignored (machine-local paths and the local event log), so the script plus the facts file are the committed source of truth. The script runsdent8 init, sources the generated env, seeds the human > CI > agent trust profile (dent8 authority defaults), and captures 15 human-authored facts assource:humanat High authority. - 15 real facts, each verified against the repo (no invented values): MSRV 1.94; the
three CI gates (
cargo test --workspace,cargo fmt --all -- --check,cargo clippy --workspace --all-targets -- -D warnings); commit conventions (single author, Conventional Commits, no Co-Authored-By / AI attribution); the default authority profile; the frozen eval tallies (16/4/27 core arbitration, 25/9/13 with the content-hook lane); the content-check hook contract; and the v0.4 roadmap focus plus frozen items. - Hooks wired in
.claude/settings.json:SessionStart→dent8 context(inject the believed facts) plus a native-memory integrity check;SessionEnd→dent8 capture .dent8/proposals.jsonl --consume --keep-failed(flush agent-queued proposals through the firewall);PreToolUse/PostToolUseguard native-memory writes. Each hook command sources.dent8/envwhen present (so it reads the seeded store, not the permissive default) and no-ops quietly whendent8isn’t built. - Flagship README example built from this repo’s real
dent8 contextpack.
Capture was fully clean: 15 accepted, 0 contested, 0 rejected, 0 invalid, every line
printing ACCEPTED … (authority=high) — zero silent no-ops.
Prioritized fix list
Section titled “Prioritized fix list”P1 — first-run blockers and silent-wrong-store footguns
Section titled “P1 — first-run blockers and silent-wrong-store footguns”initandauthority defaultsregistries can diverge.dent8 initgrantssource:local max=highin.dent8/authority.json. The dogfood/capture trust story wantshuman > CI > agent, which is a separatedent8 authority defaultscall — and unless.dent8/envhas already been sourced (soDENT8_AUTHORITYpoints at the init registry),authority defaultswrites to a different file (./dent8-authority.jsonin the cwd). It is easy to end up with two registries and a confusing deny-by-default. Fixed:initnow seeds thehuman > CI > agentprofile into.dent8/authority.jsonitself (merge-only, keeping itssource:localgrant), and — with the store-resolution fix in #3 — theauthoritysubcommands resolve to that same discovered.dent8/authority.jsonwhenDENT8_AUTHORITYis unset, so there is one registry per store.- The README “Try it” walkthrough was broken on a clean checkout (fixed in this PR).
Two independent bugs a first-run user hits: (a)
.dent8/identity-alice.envwas sourced outsideset -a, soDENT8_GRANTwas never exported and the firstdent8 assertfailed exit 2 (“missing –authority”); (b) with--identity, the low-authority supersede was rejected for a source mismatch (“grant source … does not match write source …”) rather than the “Low can’t override High” arbitration story the prose promised. The corrected walkthrough drops--identity, passes explicit--authority/--source, and sources env insideset -a— verified verbatim on a fresh store: the supersede now rejects withinsufficient authority: low may not override or remove an incumbent of high. - Env must be re-sourced in every shell, or writes silently hit a different store.
DENT8_AUTHORITY,DENT8_LOG, andDENT8_REQUIRE_AUTHORITY=1live only in.dent8/env. A command run withoutset -a; . .dent8/env; set +afalls back to the permissive dev default log (./dent8-log.jsonl), so a user who forgets can read/write a different, empty store and think their facts vanished.initprints the source snippet, which helps, but nothing guards the omission. The committed hooks now guard against this by sourcing.dent8/envthemselves. Fixed: store resolution now discovers.dent8/by walking up from the cwd (git-style) when the env vars are unset, so an ad-hoc command from anywhere inside the project reads/writes the real store instead of a parallel./dent8-log.jsonl— an explicit env override still wins, and a fresh directory with no.dent8/upward still falls back to the cwd default.
P2 — papercuts on the golden path
Section titled “P2 — papercuts on the golden path”- Bare
dent8 factsexits 2. It is a command group whose only subcommand islist;dent8 factsalone dumps help to stderr and exits non-zero. Following intuition to see your facts fails. Make barefactsdefault tofacts list. - No install/PATH step is surfaced in the flow. From a clone
dent8is not on PATH, so every command becomes./target/debug/dent8 …(theinit“Next:” hint and the seed output even print the absolute path). A one-linecargo install --path crates/dent8-cli(or a symlink) hint ininitoutput would close it. dent8 contextmarkdown embeds a volatile millisecond timestamp (<!-- generated by dent8 context at 1783547370878 -->). Pasting the pack into a tracked file produces a spurious one-line diff on every regenerate. A--no-timestamp/ deterministic mode would make the pack safe to commit..dent8/proposals.jsonlis not created byinit. It is the file theSessionEndhook drains, but it does not exist until something writes it, and a missing file is treated as an empty session (silent no-op) — so a path typo loses proposals silently. The seed script nowtouches it;initarguably should too.dent8 eval(CLI) prints a 5/5 headline that is not the honest tally. The externally-grounded numbers (16/4/27 arbitration, 25/9/13 with the content-hook lane) live only indocs/evals.mdand the lib tests, so a user who runs the CLI never sees them. Surface the 47-case per-class breakdown behind a flag (e.g.dent8 eval --full).
P3 — minor
Section titled “P3 — minor”dent8 context --helpdoes not state that text output is markdown (you infer it).- First build is ~60s and pulls the full arrow/parquet/sqlx tree even for the default
sqlite build, because
dent8-exportis a workspace member compiled alongside the CLI. capture --keep-failedre-writes a rejected line verbatim, so a malformed proposal is retried forever until a human fixes or deletes it — worth a note in the capture docs.
What worked well
Section titled “What worked well”- Capture is loud and idempotent. Every proposal prints
ACCEPTED/REJECTEDwith its authority and a final tally; no silent drops.--forceoninitplus a cleanrm -rf .dent8made the seed fully repeatable. - Provenance is real. Every believed fact carries
(authority, source, uri)and is replayable viadent8 explain— the whole point of the fact base, and it holds up. - Deny-by-default is announced, not silent:
authority defaultstells you unlisted sources are now blocked.
Using the fact base (for agents on this repo)
Section titled “Using the fact base (for agents on this repo)”scripts/dogfood-seed.sh— rebuild the local store.dent8 context— read the believed facts (theSessionStarthook injects them automatically).- To add or correct a fact, append a proposal to
.dent8/proposals.jsonl; theSessionEndhook flushes it viadent8 capture … --consume --keep-failed. Human corrections enter assource:humanat High; agent inferences assource:agentat Low. The fact base — not a hand-edited rules file — is authoritative.