Skip to content

decree for agents & CI

An agent edits code it has no memory of deciding. It never sat in the meeting. It never read the PR thread. It sees the file, not the reason the file is the way it is. So it guesses — and a guess that ships is a decision nobody made.

decree closes that gap. It gives the agent one deterministic check to run before an edit and one to run after, both answering only from declared facts. The check returns an exit code, and the exit code gates the loop.

Run this in an agent session or a CI job. Every step is a real command.

  1. Validate the corpus. Catch a malformed or dangling decision before you trust it.

    Terminal window
    decree lint

    A finding exits exit 1 a finding you can gate CI on . Stop and fix it first.

  2. Rebuild the derived index. Frontmatter is authoring truth; .decree/index.sqlite is a cache. Rebuild it after any corpus change, or the query tools refuse to answer.

    Terminal window
    decree index rebuild
  3. Read the drift before you plan. Stale decisions, ungoverned hotspots, dead governance, and advisory suggestions — plus governance-quality signals: lifecycle_drift (a decision at 100% acceptance criteria still marked draft, or a shipped decision whose governance rotted) and broad_governance (a governs: surface that grew too wide).

    Terminal window
    decree health --json

    Dead governance is a finding and exits exit 1 a finding you can gate CI on . Resolve it before it compounds. Suggested governance, lifecycle_drift, and broad_governance are advisory and exit exit 0 clean · advisory-only .

  4. Check intent before you write a line. State the plan and the files. decree returns the governing decisions and any structural conflict.

    Terminal window
    decree intent-check --plan "add token rotation" --files src/auth/tokens.py --json

    Working alongside other live sessions? Pass their planned paths to get live_conflicts. In a governed session, pass --under to frame the report around your active decision — owned_files, contextual_overlaps, contradictions, and the governs_gaps it repeat-touches but doesn’t declare.

    Terminal window
    decree intent-check --plan "add token rotation" --files src/auth/tokens.py \
    --other-active-files '{"session-b": ["src/auth/tokens.py"]}' \
    --under SPEC-01KT22NMS0D19VMD8VPK4D2MNX --json
  5. Interpret the findings by severity — don’t blindly resolve everything. decree classes each finding so the agent can act without guessing: blocking_findings (a real collision — resolve_conflict_first, a stale owner’s update_decision, or a live isolate_session), advisory_findings (update_spec_first, add_governance, check_ac — proceed and note them), and corpus_hygiene_findings (you’re editing a decree document itself — run lint, not add_governance). Resolve blockers; proceed past advisory and corpus findings, stating why. The human output leads with a Block now / Clean later split for exactly this. For isolate_session, run in a dedicated worktree or split the overlapping file out of one plan.

    Pass --under to frame a multi-decision hot file around your active decision: owned_files is what it governs, contextual_overlaps are the other governors to treat as context unless their acceptance criteria contradict your plan, and contradictions are the paths it does not own. The classes are additive — the exit code is unchanged, so you decide, not the exit alone.

  6. Review intent after the code exists. Same governance corpus, now against the diff.

    Terminal window
    decree intent-review --json

    It also accepts --under for point-of-change governs_gaps.

  7. Lint again, then leave a trail. Re-validate after touching decree documents, and write a changelog fragment while the context is fresh.

    Terminal window
    decree lint
    uv run towncrier create +.feature --content "Add token rotation under SPEC-…"

The gate is the exit code. intent-check and intent-review exit exit 1 a finding you can gate CI on on a blocking finding — a conflict, stale governance, or a live overlap — and exit 0 clean · advisory-only on a clean plan or advisory-only findings. The typed blocking_findings / advisory_findings / corpus_hygiene_findings buckets tell you which kind, so the agent (or CI job) reads the JSON and decides whether to stop or proceed rather than treating every non-zero exit as a wall. lint and dead governance exit exit 1 a finding you can gate CI on , which is what you fail a build on. A broken decree.toml exits exit 2 config error .

In a parallel agent run, the HTML board is for the person supervising the run. Agents do not need to look at it. They should receive a document ID and use decree’s CLI or MCP surface as their contract.

  1. The orchestrator refreshes the board when they want a snapshot.

    Terminal window
    decree generate-html --output decree-board.html
    decree sprint status
    decree sprint move SPEC-01KT22NMS0D19VMD8VPK4D2MNX --to active

    The board shows open sprint items, buckets, status, acceptance-criteria progress, and done items awaiting rollover. It is read-only; sprint changes happen through CLI commands such as sprint move.

  2. A worker agent gets one sprint item.

    Terminal window
    decree ddd --doc SPEC-01KT22NMS0D19VMD8VPK4D2MNX
    decree intent-check --plan "implement token storage" \
    --files src/auth/tokens.py \
    --under SPEC-01KT22NMS0D19VMD8VPK4D2MNX --json

    If the recommended action is clear, it implements that item. If the check says isolate_session, resolve_conflict_first, or update_spec_first, the loop stops before code is written.

  3. Another worker gets another item in another worktree.

    Terminal window
    git worktree add ../my-app-auth-refresh -b work/auth-refresh
    cd ../my-app-auth-refresh
    decree ddd --doc SPEC-01KW2BEQ5J7JWM93K4YAS9GZAB

    The v3 sprint store keeps those memberships in separate live/<DOC-ID>.yaml files, so routine enrollment and completion merge as a union of files.

  4. Each worker records its own outcome.

    Terminal window
    decree sprint complete SPEC-01KT22NMS0D19VMD8VPK4D2MNX --commit abc1234
    decree intent-review --json
    decree lint

    The orchestrator integrates branches, runs decree lint, refreshes the board if useful, and performs sprint rollover once from the merged state.

HONESTY The generated board is an operator view, not a live scheduler and not a mutation surface. Agents should branch on CLI/MCP output, not on the HTML.

decree mcp serve exposes the query and analysis surface to an agent over stdio. Eight tools, all returning JSON. Every tool is read-only except report.

The payloads are identical to the CLI --json output — same formatter, same schema. The MCP tools and the CLI never diverge.

why

Governing decisions for a file, from declared governs:.

refs

Reverse reference graph for one decision.

stale

Decisions whose referenced files have moved past them.

health

Stale decisions, ungoverned hotspots, dead governance (a finding, exit 1), suggested governance, plus advisory lifecycle_drift and broad_governance — all advisory signals exit 0 and never feed why.

intent_check

Pre-code. Findings typed as blocking_findings / advisory_findings / corpus_hygiene_findings; planned files split into source / corpus / generated. Accepts other_active_fileslive_conflicts and underowned_files / contextual_overlaps / contradictions.

intent_review

Post-code diff against the same corpus. Also accepts under for governs_gaps.

progress

Acceptance-criteria completion for a doc, a chain, or the whole corpus.

report

Regenerate completion reports. The only write tool; supports dry_run.

A query result is a shape an agent can branch on directly:

{
"matches": [
{
"document_id": "SPEC-01KT22NMS0D19VMD8VPK4D2MNX",
"status": "implemented",
"governs": ["src/auth/tokens.py"]
}
],
"conflicts": [],
"live_conflicts": []
}

matches empty means no decision governs the path. conflicts empty means no collision. Both are valid answers — read the next section.

Bootstrap project-local agent skills with the normal init flow:

Terminal window
decree init --with-agents

For an existing decree project, install or refresh them explicitly:

Terminal window
decree agents install --target all --scope project
decree agents status --target all --scope project

This writes reviewable files under .codex/skills and .claude/skills. It does not add Claude Code hooks unless you pass --hooks.

The generated skills guide PRD, ADR, SPEC, lint, and governed implementation work. Portable agent flows can still use decree-governs-suggest: the agent owns the model call, and decree validates the suggestions and owns the write.

decree is deterministic. It resolves no model and reads no API key — LLM execution belongs to the agent runtime, so decree stays a fixed function: same corpus, same question, same answer, no temperature.

It answers only from declared facts — governs: frontmatter and the references between documents. It does not read git blame to guess intent. It does not infer a decision that was never written down.

Empty arrays are valid abstentions. When matches or conflicts come back empty, the answer is “nothing governs this.” The agent must take that at face value and not invent governance to look thorough.

There are no hidden fallbacks. A missing or stale index is a hard error with a hint to rebuild — never a silent guess. decree would rather refuse than fabricate.

HONESTY decree tells you which decision governs a path, not whether that decision is still correct. It checks declared scope, not the wisdom behind it. The judgment stays with you.