Skip to content
commission

The guidance a task was claimed under

You will be able to version the files that define how work is done alongside the work itself, and have commission tell an in-flight session — by name, with the command to fix it — when those rules changed underneath it.

Audience: anyone whose repo carries a CLAUDE.md, an .claude/ directory, or a folder of decision records. Assumes: a project with a .commission.json (config reference).

The problem

An agent session reads CLAUDE.md, claims a task, and works for two hours. Somebody else amends CLAUDE.md in the meantime. Nothing in the task tracker changed, so nothing warns — the session finishes against rules that no longer exist, and the review that catches it happens days later, if at all.

Commission already refuses to let a task’s status drift from its truth. Guidance drift is the same failure one level up, and it is invisible for exactly the same reason: nobody recorded which version of the rules the work started from.

What commission tracks

Declare the committed files that define how work is done:

{
  "version": 1,
  "project": "myapp",
  "context": {
    "track": ["CLAUDE.md", ".claude/**", "docs/adr/**"],
    "ignore": ["**/*.draft.md"],
    "warnOnDrift": true
  }
}

Declaring nothing is fine — the default set is CLAUDE.md, AGENTS.md, .claude/**, .cursor/rules/**, and docs/adr/**, which is what most repos already have.

Commission hashes each tracked file and combines those hashes into one fingerprint for the project:

commission context show
myapp guidance 4f2a9c1b8e03 — 4 file(s), 11.2k
root: /Users/you/code/myapp

tracked (committed — this is what the fingerprint covers):
  1a2b3c4d5e6f     3.1k  .claude/agents/reviewer.md
  6f5e4d3c2b1a     0.4k  .claude/settings.json
  9e8d7c6b5a49     6.8k  CLAUDE.md
  3f3e3d3c3b3a     0.9k  docs/adr/0001-sqlite.md  (seen 2026-07-27 05:41)

The rule: project guidance, never private settings

Commission versions project guidance. It never versions a user’s private settings.

That is a product boundary, not a default you can talk your way past. The tracked set defaults to committed paths, and the personal ones — .commission.local.json, any *.local.json, .env and .env.*, editor and OS droppings — are excluded from the fingerprint even when context.track explicitly names them.

The reason is mechanical. A fingerprint is only useful if two people looking at the same commit see the same number. Anything one machine holds privately would make the shared fact disagree with itself, and every teammate would look permanently stale to every other. Nothing you keep to yourself belongs in a hash everyone compares.

Machine-local guidance, honoured but not shared

.commission.local.json is gitignored and yours. It can add guidance for your machine:

{
  "version": 1,
  "context": { "track": ["notes/**"] }
}

Those files are scanned, hashed, and listed under local only in commission context show — but they are not part of the fingerprint. The local layer is additive-only as far as the shared number is concerned: it cannot remove a committed file from the tracked set either, because a subtraction made on your laptop would move the number your teammates compare against, which is precisely the staleness this split exists to prevent.

The fingerprint is stable across machines

The fingerprint is a property of the commit, not of the checkout. Every input to it is chosen so that two clones agree:

inputhow it is made machine-independent
file pathsrelative to the repo root, always /-separated
orderingsorted by codepoint, never by locale or filesystem walk order
contentnewline-normalised (CRLF → LF), BOM stripped, then sha256
everything elsenot hashed — no mtime, no size, no inode, no absolute path, no clock

A Windows checkout with CRLF endings at C:\src\myapp and a macOS one at ~/code/myapp produce the same fingerprint from the same commit. A difference always means the guidance genuinely differs.

Drift, and the command that fixes it

The fingerprint is recorded on the claim — not on the task. A task outlives many claims and the answer is different for each of them; “which rules was this session operating under” is a fact about the session.

When guidance moves under an in-flight claim, commission next and commission show say so inline, above the commands:

⚠ project guidance changed since you claimed this (4f2a9c1b8e03 → 71d0aa93b2c5): CLAUDE.md changed
  re-read: CLAUDE.md
  see it: commission context diff 4f2a9c1b8e03
commission context diff 4f2a9c1b8e03
4f2a9c1b8e03 → 71d0aa93b2c5
  changed CLAUDE.md
  added   docs/adr/0002-bun.md
  removed .claude/settings.json

re-read before continuing: CLAUDE.md, docs/adr/0002-bun.md

With no argument, commission context diff compares against the guidance you claimed under, which is the question an agent almost always has. A fingerprint prefix resolves as long as it is unambiguous.

The comparison is by meaning, not by timestamp: a file rewritten with identical bytes is not a change, and a file reverted to what it was is not drift.

commission doctor reports the same thing across the whole project:

context:myapp  ✗  2 claim(s) predate a guidance change (now 71d0aa93b2c5): myapp-14@claude:auth, myapp-19@claude:api — CLAUDE.md
   fix: commission context diff 4f2a9c1b8e03 --project myapp

What warns versus what refuses

Drift always warns and never refuses. Guidance changing while work is in flight is normal — someone amended the rules mid-implementation — and refusing would strand work that is otherwise fine. Exit codes are unaffected; a drifted commission show still exits 0.

Commission refuses about facts it owns: an unchecked criterion, a missing gate artifact, a task already claimed by someone else. It reports about facts the repository owns. The warning still carries a fix, because every commission warning does — what changed, and the command that shows it.

Set "warnOnDrift": false to silence the warning on a repo that does not want it. The fingerprint is still recorded either way, so commission context diff keeps working and turning the warning back on loses nothing.

Reading it from --json

Warnings are structured fields, never prose an agent has to parse. commission show --json and commission next --json carry:

{
  "context": {
    "fingerprint": "71d0aa93b2c5…",
    "tracked": 4,
    "claimedUnder": "4f2a9c1b8e03…",
    "drift": {
      "kind": "context_drift",
      "since": "4f2a9c1b8e03…",
      "fingerprint": "71d0aa93b2c5…",
      "claimedAt": "2026-07-27T05:41:02.117Z",
      "added": ["docs/adr/0002-bun.md"],
      "changed": ["CLAUDE.md"],
      "removed": [".claude/settings.json"],
      "reread": ["CLAUDE.md", "docs/adr/0002-bun.md"],
      "command": "commission context diff 4f2a9c1b8e03…"
    }
  }
}

context is null when the project tracks nothing; drift is null when the guidance has not moved. Branch on reread to know what to read again, and on command to show a human the rest.

Drift with several agents in flight

Drift is a fact about a claim, so with N agents working, the answer is different for each of them. The one that claimed before the change gets the warning; the one that claimed after does not, because for it nothing moved.

commission inbox collects them for a human, one item per project rather than one per claim:

commission inbox --project myapp --all

An item there answers the question a warning cannot: is anyone working against rules that no longer exist right now, and does that matter enough to interrupt them? Nothing is refused either way — see what warns versus what refuses above.

The practical habit when you change guidance mid-flight: change it, then say so on the tasks it affects.

commission note myapp-14 -m "CLAUDE.md now requires a note per criterion — re-read before closing"

A note is carried in the next context bundle. A warning is only seen by whoever reads the task next.

The whole sequence

# 1. declare what defines how work is done (or accept the defaults)
commission config init myapp

# 2. see what Commission is versioning, and what it hashes to
commission context show
commission context show --json

# 3. work — the fingerprint is recorded when the task is claimed
commission next --project myapp --claim

# 4. …someone amends CLAUDE.md…

# 5. the next read of the task says so, by name
commission show myapp-14
commission context diff

# 6. and doctor reports it across the project
commission doctor --project myapp

Every command above is executed by tests/context.test.ts.

This page is docs/guides/context.md in the Commission repository, rendered in place — the site keeps no copy of it. The repository is private, so there is no edit link to follow.