Skip to content

intent-check — catch a collision before you write a line

decree intent-check --plan … --files … is the pre-code planning guard. You describe the change in a sentence and name the files it will touch, and decree tells you which decisions stand in the way — before you have written a single line.

Scenario You're about to change how src/auth/tokens.py stores refresh tokens.

Without decree

You write the change, push the branch, and open a PR. Only in review does a teammate notice that two decisions claim that file — one shipped, one still in-flight with open acceptance criteria. You found out too late, after the work was done.

With decree

One command, run against the plan, surfaces the collision at planning time:

Terminal window
$ decree intent-check --plan Change token refresh storage --files src/auth/tokens.py
[intent-check] exit 1: findings present (conflicts, live-session overlaps, or stale governance).
Intent check — pre-PR governance map
Plan: Change token refresh storage
Block now (1):
✗ resolve_conflict_first: src/auth/tokens.py is governed by SPEC-00000000000000000000000001, SPEC-00000000000000000000000002. Decide which decision is authoritative before implementing.
Clean later (3):
~ update_spec_first [SPEC-00000000000000000000000002]: SPEC-00000000000000000000000002 (Token rotation policy) governs planned files and has unchecked acceptance criteria. Check off or amend ACs before implementing on top.
~ check_ac [SPEC-00000000000000000000000002]: SPEC-00000000000000000000000002 has an unchecked AC under 'Acceptance Criteria': Rotation job runs on schedule
~ check_ac [SPEC-00000000000000000000000002]: SPEC-00000000000000000000000002 has an unchecked AC under 'Acceptance Criteria': Old tokens revoked on rotation
Recommended next command:
decree intent-check --under SPEC-00000000000000000000000001 --plan "..." --files ... (name the authoritative decision; treat the other governors as contextual)
Planned files (1):
• src/auth/tokens.py
Governing decisions (2):
▸ SPEC-00000000000000000000000001 implemented exact governs src/auth/tokens.py
JWT token storage
▸ SPEC-00000000000000000000000002 draft exact governs src/auth/tokens.py
Token rotation policy
Stale governance (0):
(none)
Unchecked acceptance criteria (2):
☐ SPEC-00000000000000000000000002 [Acceptance Criteria] Rotation job runs on schedule
☐ SPEC-00000000000000000000000002 [Acceptance Criteria] Old tokens revoked on rotation
Conflicts (1):
✗ src/auth/tokens.py: SPEC-00000000000000000000000001, SPEC-00000000000000000000000002
Live-session conflicts (0):
(none)
Recommended actions (4):
→ update_spec_first [SPEC-00000000000000000000000002]: SPEC-00000000000000000000000002 (Token rotation policy) governs planned files and has unchecked acceptance criteria. Check off or amend ACs before implementing on top.
→ check_ac [SPEC-00000000000000000000000002]: SPEC-00000000000000000000000002 has an unchecked AC under 'Acceptance Criteria': Rotation job runs on schedule
→ check_ac [SPEC-00000000000000000000000002]: SPEC-00000000000000000000000002 has an unchecked AC under 'Acceptance Criteria': Old tokens revoked on rotation
→ resolve_conflict_first: src/auth/tokens.py is governed by SPEC-00000000000000000000000001, SPEC-00000000000000000000000002. Decide which decision is authoritative before implementing.
→ exit 1

VALUE The two-decision collision, the in-flight SPEC, and its unchecked acceptance criteria show up before you code — not in a review comment after.

HONESTY intent-check reports the structural conflict — two decisions declare the same path. It does not judge whether they truly contradict; that semantic call is the agent’s or reviewer’s job.

Give intent-check a plan summary and the files the plan will touch. It reports the decisions that govern those files, which of them are stale, which acceptance criteria are still unchecked, and any structural conflicts — two decisions claiming the same path. All of it lands before a diff exists, so you adjust the plan instead of unwinding code.

Every finding carries a class, so an agent can act without guessing: blocking_findings (a real collision), advisory_findings (surfaced — proceed and note them), and corpus_hygiene_findings (you’re editing a decree document itself). Planned files are split into source, corpus, and generated — so refining a SPEC’s own design is never mistaken for ungoverned code. The human report leads with a Block now / Clean later summary and one recommended next command. The classes are additive and the exit code is unchanged: they inform the decision, they don’t gate it.

Two decisions declare src/auth/tokens.py. The in-flight one has unchecked acceptance criteria. intent-check leads with Block now (the conflict) and Clean later (the unchecked criteria), then one recommended next command.

Terminal window
$ decree intent-check --plan Change token refresh storage --files src/auth/tokens.py
[intent-check] exit 1: findings present (conflicts, live-session overlaps, or stale governance).
Intent check — pre-PR governance map
Plan: Change token refresh storage
Block now (1):
✗ resolve_conflict_first: src/auth/tokens.py is governed by SPEC-00000000000000000000000001, SPEC-00000000000000000000000002. Decide which decision is authoritative before implementing.
Clean later (3):
~ update_spec_first [SPEC-00000000000000000000000002]: SPEC-00000000000000000000000002 (Token rotation policy) governs planned files and has unchecked acceptance criteria. Check off or amend ACs before implementing on top.
~ check_ac [SPEC-00000000000000000000000002]: SPEC-00000000000000000000000002 has an unchecked AC under 'Acceptance Criteria': Rotation job runs on schedule
~ check_ac [SPEC-00000000000000000000000002]: SPEC-00000000000000000000000002 has an unchecked AC under 'Acceptance Criteria': Old tokens revoked on rotation
Recommended next command:
decree intent-check --under SPEC-00000000000000000000000001 --plan "..." --files ... (name the authoritative decision; treat the other governors as contextual)
Planned files (1):
• src/auth/tokens.py
Governing decisions (2):
▸ SPEC-00000000000000000000000001 implemented exact governs src/auth/tokens.py
JWT token storage
▸ SPEC-00000000000000000000000002 draft exact governs src/auth/tokens.py
Token rotation policy
Stale governance (0):
(none)
Unchecked acceptance criteria (2):
☐ SPEC-00000000000000000000000002 [Acceptance Criteria] Rotation job runs on schedule
☐ SPEC-00000000000000000000000002 [Acceptance Criteria] Old tokens revoked on rotation
Conflicts (1):
✗ src/auth/tokens.py: SPEC-00000000000000000000000001, SPEC-00000000000000000000000002
Live-session conflicts (0):
(none)
Recommended actions (4):
→ update_spec_first [SPEC-00000000000000000000000002]: SPEC-00000000000000000000000002 (Token rotation policy) governs planned files and has unchecked acceptance criteria. Check off or amend ACs before implementing on top.
→ check_ac [SPEC-00000000000000000000000002]: SPEC-00000000000000000000000002 has an unchecked AC under 'Acceptance Criteria': Rotation job runs on schedule
→ check_ac [SPEC-00000000000000000000000002]: SPEC-00000000000000000000000002 has an unchecked AC under 'Acceptance Criteria': Old tokens revoked on rotation
→ resolve_conflict_first: src/auth/tokens.py is governed by SPEC-00000000000000000000000001, SPEC-00000000000000000000000002. Decide which decision is authoritative before implementing.
→ exit 1

decree owns no session state. You supply the other sessions’ planned paths; decree only computes the overlap. It reports that two sessions claim the file — not who should win.

A hot file often belongs to more than one decision over time — a first slice, an evolution, a shared contract. Reported flat, that reads as a conflict every time. Pass --under SPEC-… and intent-check frames the report around the decision you’re working under:

Terminal window
$ decree intent-check --plan Change token refresh storage --files src/auth/tokens.py --under SPEC-00000000000000000000000001
[intent-check] exit 1: findings present (conflicts, live-session overlaps, or stale governance).
Intent check — pre-PR governance map
Plan: Change token refresh storage
Block now (1):
✗ resolve_conflict_first: src/auth/tokens.py is governed by SPEC-00000000000000000000000001, SPEC-00000000000000000000000002. Decide which decision is authoritative before implementing.
Clean later (3):
~ update_spec_first [SPEC-00000000000000000000000002]: SPEC-00000000000000000000000002 (Token rotation policy) governs planned files and has unchecked acceptance criteria. Check off or amend ACs before implementing on top.
~ check_ac [SPEC-00000000000000000000000002]: SPEC-00000000000000000000000002 has an unchecked AC under 'Acceptance Criteria': Rotation job runs on schedule
~ check_ac [SPEC-00000000000000000000000002]: SPEC-00000000000000000000000002 has an unchecked AC under 'Acceptance Criteria': Old tokens revoked on rotation
Recommended next command:
Proceed under SPEC-00000000000000000000000001; the other governors are contextual — resolve only if their acceptance criteria contradict your plan.
Active decision: SPEC-00000000000000000000000001
Owned files (1): src/auth/tokens.py
Contextual overlaps (1):
~ src/auth/tokens.py — also governed by SPEC-00000000000000000000000002 (context, not a contradiction)
Planned files (1):
• src/auth/tokens.py
Governing decisions (2):
▸ SPEC-00000000000000000000000001 implemented exact governs src/auth/tokens.py
JWT token storage
▸ SPEC-00000000000000000000000002 draft exact governs src/auth/tokens.py
Token rotation policy
Stale governance (0):
(none)
Unchecked acceptance criteria (2):
☐ SPEC-00000000000000000000000002 [Acceptance Criteria] Rotation job runs on schedule
☐ SPEC-00000000000000000000000002 [Acceptance Criteria] Old tokens revoked on rotation
Conflicts (1):
✗ src/auth/tokens.py: SPEC-00000000000000000000000001, SPEC-00000000000000000000000002
Live-session conflicts (0):
(none)
Recommended actions (4):
→ update_spec_first [SPEC-00000000000000000000000002]: SPEC-00000000000000000000000002 (Token rotation policy) governs planned files and has unchecked acceptance criteria. Check off or amend ACs before implementing on top.
→ check_ac [SPEC-00000000000000000000000002]: SPEC-00000000000000000000000002 has an unchecked AC under 'Acceptance Criteria': Rotation job runs on schedule
→ check_ac [SPEC-00000000000000000000000002]: SPEC-00000000000000000000000002 has an unchecked AC under 'Acceptance Criteria': Old tokens revoked on rotation
→ resolve_conflict_first: src/auth/tokens.py is governed by SPEC-00000000000000000000000001, SPEC-00000000000000000000000002. Decide which decision is authoritative before implementing.
→ exit 1

The Active decision block spells out the frame — what your decision owns, which other governors are contextual, and any path it does not own (a real contradiction) — and the recommended next command guides you to proceed under it. The same three keys (owned_files, contextual_overlaps, contradictions) are in the --json output for programmatic consumers.

VALUE ”Work under SPEC-…01; treat SPEC-…02 as context” is a call an agent can make deterministically — instead of stopping on every hot file two decisions happen to share.

A separate advisory, directory_overlaps, surfaces co-governance the exact-path conflict query can’t see: a file owned by one decision exactly and another via a directory governs: entry. It’s advisory — it never flips the exit code.

  • Before an agent starts implementing — hand it the governing decisions and conflicts as deterministic context, not a guess.
  • Before opening a PR — gate CI on a clean plan so collisions surface at planning time, not in review.
  • When two agents or people might touch the same file — pass their planned paths and catch the live overlap before either writes a line.

intent-check exits exit 1 a finding you can gate CI on on a blocking finding — structural conflicts, live-session overlaps, or stale governance — exit 0 clean · advisory-only when the plan is clean or has only advisory / corpus-hygiene findings, and exit 2 config error on a config error, such as an invalid --under id. The blocking_findings / advisory_findings / corpus_hygiene_findings classes and the --under framing keys are additive: they never change the exit code.

All flags

| Flag | What it does | |------|--------------| | --plan TEXT | One-sentence to one-paragraph description of the planned change. | | --files PATH [PATH ...] | One or more repo-relative paths the plan will touch. | | --other-active-files JSON | JSON map of other active session ids to the paths they plan to touch, e.g. '{"session-b": ["src/foo.py"]}'. Planned files overlapping a live session surface as live-session conflicts. | | --under ID | Active decision id. Frames the report around it — owned_files, contextual_overlaps, contradictions — and surfaces the advisory governs_gaps its own commits repeat-touch (≥2) but it doesn’t declare. Invalid id exits 2. | | --json | Emit JSON for programmatic consumers. | | --project PATH | Operate on the project at this path (default: cwd). | | --with-abstention | Route governance lookups through the calibrated method. | | --target-precision P | Desired precision floor for non-abstain responses. |


Next: intent-review — gate the diff after you code.