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 showmyapp 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:
| input | how it is made machine-independent |
|---|---|
| file paths | relative to the repo root, always /-separated |
| ordering | sorted by codepoint, never by locale or filesystem walk order |
| content | newline-normalised (CRLF → LF), BOM stripped, then sha256 |
| everything else | not 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 4f2a9c1b8e03commission context diff 4f2a9c1b8e034f2a9c1b8e03 → 71d0aa93b2c5
changed CLAUDE.md
added docs/adr/0002-bun.md
removed .claude/settings.json
re-read before continuing: CLAUDE.md, docs/adr/0002-bun.mdWith 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 myappWhat 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 --allAn 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 myappEvery command above is executed by tests/context.test.ts.
Related
- Config reference — every
context.*field. - CLI reference —
commission context showandcommission context diff. - Vocabulary — the terms this page uses.
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.