Skip to content

A decision memory with opinions — records project principles and argues back when they're violated.

An agent journal is a structured decision log that lives in a private GitHub repo. It records the decisions, directions, and philosophies behind a project. Both humans and AI coding agents can propose entries. Only the doraval CLI writes to the remote.

When a change conflicts with a recorded principle, the journal pushes back — not as a blocker, but as an argument with calibrated intensity.

Decisions get lost across Slack threads, commit messages, and agent sessions that start fresh with no memory. An agent makes reasonable choices that accidentally contradict deliberate ones.

The journal is a persistent memory with opinions. It doesn’t block — it argues.

The journal has two layers:

Remote: A private GitHub repo (e.g., saif-shines/saif-shines.md) with global.md for universal principles and projects/<name>.md for project-specific decisions.

Local: doraval maintains a cache at ~/.doraval/ — not in the project directory. No submodules, no symlinks, no config files polluting your repos.

~/.doraval/
├── config.yml # Journal repo + project mappings
├── journals/ # Cached journal files
│ ├── global.md
│ └── doraval.md
└── pending/ # Proposed entries awaiting sync
└── doraval/

Register a project once:

Terminal window
doraval journal init

This asks for the journal repo and project name, stores the mapping in ~/.doraval/config.yml, and fetches the journal files. No per-project config needed.

## Use "drift" not "score" for rubric deviation
​```yaml
pushback: 7
scope: [naming, cli]
author: human
date: 2026-05-25
status: active
​```
We renamed `score` to `drift` because "score" implies a generic quality
rating. The command measures deviation from a rubric — distance from a
standard, not a grade.
FieldDescription
pushback1–10. How hard the journal argues if violated.
scopeTags: naming, cli, architecture, testing, ux, api, docs.
authorhuman or agent:<name>.
dateISO date.
statusactive, superseded, or retired.
superseded_by(Optional) Title of the replacing entry.
RangeLabelWhat it means
1–3Nudge”This diverges slightly. Probably fine, just be aware.”
4–6Friction”This contradicts a deliberate decision. Reconsider.”
7–10Wall”Core philosophy conflict. Override explicitly or update the journal.”

Even pushback 10 is an argument, not a gate.

Two-stage hybrid approach:

  1. Scope-tag filter (cheap): Match the current action’s domain against entry scope tags. Fast and deterministic.
  2. Semantic check (matches only): For entries that pass the filter, the human (v1) or agent (v2) judges whether the change actually contradicts the principle.

Agents and humans propose entries. Only doraval journal sync writes to the remote. No race conditions.

Human/Agent → doraval journal add → ~/.doraval/pending/ → doraval journal sync → GitHub

sync also updates projects/_index.md and auto-archives entries older than 1 year when files exceed 300 lines.

doraval journal init # One-time project registration
doraval journal list # Show active entries
doraval journal check # Check work against principles
doraval journal add <title> # Propose a new entry
doraval journal sync # Push pending, update index, archive
  • doraval skill drift gains Principle drift — flags when a skill contradicts an active journal entry.
  • doraval skill judge uses the journal as context for AI assessment.
  • Entries with pushback >= 7 surface as warnings in doraval skill validate.
  • Not an AGENTS.md replacement. AGENTS.md says how to work. The journal says why decisions were made.
  • Not a changelog. Principles and reasoning, not a list of changes.
  • Not a linter. Opinions with conviction levels, not pass/fail rules.
  • Not a blocker. Every pushback can be overridden — but the conflict must be acknowledged.