Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ bench/real/
# tool working dirs (not release content)
.claude/
.gitnexus/
.dorian/local/ # ephemeral host-hook runtime packet (last-decision.json); never tracked

# internal program/audit working docs — provenance only, never shipped in the release
/docs/design/C4_IMPORT_BINDING_REPORT.md
Expand Down
39 changes: 39 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,45 @@ and security posture are unchanged; the core stays zero-dependency; `REVOKED` re
verification path**. `claude_code.build_plan` gained an optional `manifest=` parameter (backward
compatible) so the loop installer reuses the same scaffolding machinery.

### Added — Governance Foundation (1.4.0)
- **`dorian goal add` / `dorian goal show` / `dorian goal check`** (`src/dorian/goals.py`,
`cmd_goal` in `commands.py`) — a **human-authored goal record** (sidecar
`.dorian/goals/<goal_id>.goal.json`, `schema_version: 1`) plus a deterministic, **path-derived
goal↔claim coverage diff** (`goals.coverage_diff` → `{covered, uncovered}` over git-changed,
in-scope paths vs. warranted paths). `goal check --fail-on-uncovered` exits **4** when an
in-scope changed path has no warrant. The goal's `statement` is **human context only** — never
fed to a model, never used to decide a verdict or "completion".
- **`dorian gate`** (`cmd_gate`) — a host-mappable **preflight body**: reads a tool-call JSON on
stdin, runs the *same pure loop preflight* as `dorian loop preflight`, and prints the
**`continue` / `repair` / `escalate`** decision packet. Emits **only** contract codes —
`0`/`4` via `--fail-on {never|repair|escalate}`, plus `2` for malformed stdin — and **never**
uses exit 2 as a veto, reads a clock, or reads a nonce.
- **Claude Code governance adapter** via **`dorian governance install`** (`src/dorian/governance.py`,
scaffolded through the shared `claude_code.build_plan`/`apply` machinery) — one concrete adapter:
a `SubagentStop` hook that shells `dorian gate` and writes an ephemeral
`.dorian/local/last-decision.json` (the **only** place wall-clock/nonce are stamped), a
**fail-closed** `PreToolUse` veto (the exit-2 tool-block lives in the *host hook*; fails closed
under `unattended`/`godmode`, fails open when attended, freshness window `FRESH_SECONDS = 900`),
a settings example, and bundle docs. **No generic provider abstraction** is introduced.
- **Safe sidecar writer** (`src/dorian/sidecars.py`) — atomic (temp + `os.replace`), deterministic
(sorted-key JSON, `\n`), path-safe (`ensure_within` rejects repo escapes) writer shared by every
`.dorian/` record.
- **Deterministic core import firewall** (`tests/test_firewall_import_closure.py`) — a standing
guard (AST import-closure over the verdict modules) proving no model/network import sits on the
verification path.
- **Docs**: [`docs/DORIAN_PANE.md`](docs/DORIAN_PANE.md) (the pane *vision* — deferred, not shipped),
[`docs/GOVERNANCE_DATA_MODEL.md`](docs/GOVERNANCE_DATA_MODEL.md), a C4-flakiness note in
[`docs/VALIDATION_HONESTY.md`](docs/VALIDATION_HONESTY.md), and a gate fail-closed /
formalization-drift note in [`docs/SECURITY_BOUNDARY.md`](docs/SECURITY_BOUNDARY.md);
`.dorian/local/` is gitignored.

**Deferred / cut (not in v1.4):** claim **provenance** sidecars → **v1.5**; **effort presets** →
**cut from core** (the binding-floor/breadth mapping lives in adapter docs); the **pane / TUI** →
**deferred** (Claude Design owns the final design; v1.4 ships only the CLI + hook spine); a
**generic provider abstraction** → **deferred** until a second concrete adapter exists. Purely
additive — warrant schema, checker grammar, exit codes, fold policy, and security posture are
unchanged; the core stays zero-dependency; **no model touches the verification path**.

## [1.3.0] — 2026-06-28

The **Dorian Claim Warrants for Claude Code** integration: one command scaffolds a project-local Claude
Expand Down
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ now and is re-checked on every future change, so a confident summary doesn't qui
- [Why not just watch files?](#why-not-just-watch-files)
- [How it works](#how-it-works)
- [Using dorian with Claude Code](#using-dorian-with-claude-code)
- [Governance foundation (preview)](#governance-foundation-preview)
- [What gets committed](#what-gets-committed)
- [Getting started](#getting-started)
- [Writing claims an agent can be held to](#writing-claims-an-agent-can-be-held-to)
Expand Down Expand Up @@ -365,6 +366,33 @@ success, replace tests/review, or sandbox execution — and `REVOKED` is a steer
not a halt. Full guide: [`docs/DORIAN_LOOP_GUARD.md`](docs/DORIAN_LOOP_GUARD.md); how it fits
loop engineering: [`docs/LOOP_ENGINEERING_ALIGNMENT.md`](docs/LOOP_ENGINEERING_ALIGNMENT.md).

## Governance foundation (preview)

The deterministic spine of the *"give your goal and go to sleep"* direction — a goal record, a
preflight gate, and a Claude Code adapter that can enforce the loop decision. **The pane/TUI is not
shipped** (see [`docs/DORIAN_PANE.md`](docs/DORIAN_PANE.md)); this is the CLI + hook layer it will
sit on.

- **`dorian goal add --id <id> --title <t> [--statement … --scope <glob> …]`** — record a
**human-authored** goal (written to `.dorian/goals/<id>.goal.json`) with a path-scoped coverage
contract. The `statement` is context for humans; it never feeds a verdict. Read it back with
**`dorian goal show --id <id>`**.
- **`dorian goal check --id <id> [--since <ref>] [--fail-on-uncovered]`** — a deterministic,
path-derived **coverage diff**: which changed, in-scope paths are not yet covered by a warrant
(exit **4** with `--fail-on-uncovered`). It does **not** judge whether the goal is "done".
- **`dorian gate`** — reads a tool-call JSON on stdin and emits the same
**`continue`/`repair`/`escalate`** decision as Loop Guard; exits `0`/`4` on the decision (or `2`
only for malformed input) and never uses exit 2 as a veto.
- **`dorian governance install`** — scaffold the **Claude Code** governance adapter: a
`SubagentStop` hook that runs `dorian gate`, plus a **fail-closed** `PreToolUse` veto (blocks a
mutating tool on a standing `escalate` under a strict policy — `unattended`, or
`DORIAN_EFFORT=godmode`; fails open when a human is attended). It is **steering plus a host-side
veto, not a sandbox**.
Comment on lines +386 to +390

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Document the sensitive-path exception.

This is not fully fail-open when attended: sensitive-path escalate cases still block. Please call that out here or link to the enforcement-modes matrix so this section does not overstate the behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 386 - 390, The README section for dorian governance
install overstates attended behavior; update the description to note the
sensitive-path exception, where certain escalate cases still block even when
attended. Either add that caveat directly in this paragraph or point readers to
the enforcement-modes matrix, and make sure the wording around the PreToolUse
veto and fail-open behavior matches the actual enforcement in the governance
adapter.


Data model and trust boundary: [`docs/GOVERNANCE_DATA_MODEL.md`](docs/GOVERNANCE_DATA_MODEL.md),
[`docs/SECURITY_BOUNDARY.md`](docs/SECURITY_BOUNDARY.md). Provenance is deferred to v1.5; effort
presets are not in core.

## What gets committed

- the artifact (e.g. `docs/changes/login.md`),
Expand Down
110 changes: 110 additions & 0 deletions docs/DORIAN_PANE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# Dorian Pane (vision)

*The "give your goal and go to sleep" surface. This document describes a **future** product
direction built on the deterministic primitives that ship in v1.4 — it is not a shipped feature,
and it makes no final design decisions.*

> **Status: deferred — NOT part of v1.4.** v1.4 ships the CLI spine (`dorian goal`, `dorian gate`)
> and a Claude Code hook adapter. The pane is the surface those records are *designed to feed* once
> built. **Claude Design owns the final TUI/pane design;** this doc only specifies the data
> contracts and product jobs behind it.

---

## What the pane is for

A long-running coding agent can churn for hours. Today a human reads scrollback to answer "is this
still on track, and do I need to step in?" The pane's job is to answer that from **deterministic
evidence** — warrants, coverage, and loop decisions — instead of from the agent's own narration.

"Give your goal and go to sleep" is a **product direction, not a guarantee.** What v1.4 actually
guarantees is narrow and real: a human-authored goal with a path-scoped coverage contract, a
deterministic gate that emits `continue`/`repair`/`escalate`, and a host adapter that can fail
closed under an unattended policy. The pane would make that loop *legible* — it does not make the
agent more autonomous than the underlying determinism allows.

## What the pane is **not**

- **Not a verdict author.** The pane *displays* deterministic results; it never computes trust,
never runs a model, and never decides whether a goal is "done." Goal completion is **not**
model-evaluated — coverage is a path-derived floor (see `docs/GOVERNANCE_DATA_MODEL.md`).
- **Not a sandbox or a security boundary.** It is a read-mostly viewer over the same records the
CLI writes. Enforcement lives in the host hooks, not the UI.
- **Not multi-provider (yet).** v1.4 ships exactly one concrete adapter — Claude Code. The pane is
described against that adapter; a generic provider abstraction is deferred until a second concrete
adapter exists.

## The views (data jobs, not layouts)

Each view is defined by the **deterministic record it reads**. Layout, ordering, and visual
treatment are Claude Design's call.

| View | Question it answers | Source record (v1.4) |
|---|---|---|
| **Goal** | What did the human ask for, and under what policy? | `.dorian/goals/<id>.goal.json` (`title`, `statement`, `policy_ref`) |
| **Scope / denylist** | Which paths are in/out of jurisdiction? | `goal.scope`, `goal.deny_paths`; gate packet `scope`, `sensitive_globs` |
| **Warrants** | What has the agent sworn and proven? | `<artifact>.warrant` sidecars + the warrant store |
| **Coverage** | Which changed, in-scope paths are *not* yet warranted? | `goals.coverage_diff` → `{covered, uncovered}` |
| **Gate / loop decision** | Continue, repair, or escalate — and why? | gate packet: `decision`, `reason`, `loop_instruction`, `trust_summary`, `broken_claims[]` |
| **Repair** | How many repair attempts, against what cap? | gate packet `repair` `{attempts, max}` |
| **Escalation** | Does a human need to act, and on what? | gate packet `human_escalation` `{required, reason, message}` |
| **Host adapter state** | Is enforcement live, fresh, and identity-matched? | `.dorian/local/last-decision.json` (`created_at_epoch`, `repo_root`, `base_ref`, `nonce`); policy mode |

The **escalation** and **host adapter** views are where "go to sleep" earns or loses trust: they
must surface a stale packet, an identity mismatch, or a standing `escalate` *prominently*, because
under a strict policy those are exactly the states that fail closed.

## The deterministic data contract (what the pane may rely on)

Everything the pane renders comes from records this repo already writes deterministically:

- **Goal record** — `schema_version: 1`, byte-stable JSON (`docs/GOVERNANCE_DATA_MODEL.md` §2).
- **Gate decision packet** — `schema_version: 1`, the stdout of `dorian gate`, model-free and
clock-free (§5). The pane reads this as the single source of "what should happen next."
- **Last-decision packet** — `.dorian/local/last-decision.json`, the gate packet plus host-stamped
freshness/identity fields, **ephemeral and gitignored** (§6). The pane treats it as *runtime
state*, never as history.

The pane must not invent fields or persist its own authoritative state; if it needs history, that is
a future record type (a sibling sidecar with its own `schema_version`), not a mutation of the frozen
warrant schema.

---

## Claude Design handoff

**Ownership.** Dorian/Opus owns the deterministic data contracts and the governance invariants
(what is true, what may influence a verdict, what fails open vs. closed). **Claude Design owns the
final pane/TUI design** — layout, information hierarchy, typography, color, interaction model, and
component choices. Nothing in this doc fixes those decisions.

**Data Claude Design can rely on being available.** The eight views above, each backed by the cited
record. All of it is local, deterministic, and already produced by the v1.4 CLI/adapter — no new
verification path is required to build the pane.

**Failure states the design must represent first-class** (not as afterthoughts):

- **No fresh decision** — `.dorian/local/last-decision.json` missing or older than the freshness
window (`FRESH_SECONDS = 900`). Under a strict policy this *fails closed*; the pane must make that
obvious, not silent.
- **Identity mismatch** — packet `repo_root`/`base_ref`/`nonce` disagree with the current run.
- **Standing escalate** — a decision the agent cannot self-clear; needs a human.
- **Degraded/errored claims** — `trust_summary` non-zero `degraded`/`errored`; a verdict exists but
is weaker than "all green."

**Accessibility requirements** (constraints, not designs): decisions must be distinguishable without
relying on color alone (the three decisions and the fail-open/closed state each need a non-color
signal); all evidence must be reachable as text for screen readers and for copy-into-a-bug-report;
the pane must remain legible in a plain terminal.

**Decisions explicitly deferred to Claude Design:** the actual layout and navigation; how much
evidence to show inline vs. on demand; live-tail vs. snapshot refresh model; how repair/escalation
history is visualized; any keyboard/interaction grammar.

---

## See also

- `docs/GOVERNANCE_DATA_MODEL.md` — the exact records and fields the pane reads.
- `docs/DORIAN_LOOP_GUARD.md` — the `continue`/`repair`/`escalate` decision the pane surfaces.
- `docs/SECURITY_BOUNDARY.md` — why enforcement lives in the host hooks, not the pane.
Loading