Drift & the 3-way model¶
adept has no lockfile. The filesystem itself is the source of truth, and hash
comparisons tell adept exactly what changed and in which direction. Two independent
comparisons run: the 3-way model between project and library, and a per-harness
comparison between canonical and the rendered output on disk.
The 3-way model: project vs. library¶
For every skill, adept compares three content hashes:
- Project canonical —
<root>/.adeptability/skills/<id>/(or<root>/skills/<id>/in a library layout). This is "ours." - Base —
<root>/.adeptability/base/<id>/, the last-synced snapshot. This is the common ancestor. - Library canonical —
$ADEPT_LIBRARY/skills/<id>/. This is "upstream."
Because skill identity is (id, content-hash), adept can hash each side and reason about
divergence without any version numbers or a lockfile.
| State | Meaning |
|---|---|
synced |
Neither side changed since base — nothing to do. |
ahead |
Project canonical changed; the library didn't. Your local edit. |
behind |
Library changed; project canonical didn't. Upstream moved. |
diverged |
Both sides changed since base — a real conflict. |
This is what lets adept tell "you edited it" apart from "upstream changed it" — see
Libraries for how the base snapshot fits in.
Harness drift: canonical vs. rendered output¶
Separately, adept renders each skill in memory and compares the result against what's
actually on disk in each enabled harness (.claude/…, .cursor/…, …). Each expected file —
including sidecars — classifies as:
| State | Meaning |
|---|---|
SYNCED |
On-disk bytes match the expected render. |
DRIFTED |
The file exists but its bytes differ — the harness side was edited. |
MISSING |
The expected file isn't on disk yet. |
CONFLICT |
The path has the wrong shape — a directory, broken symlink, or unreadable target. |
Inspecting drift¶
adept status # one-line drift summary per harness; exits 2 if anything is out of sync
adept diff # exactly which files are drifted / missing / conflicting
adept diff --harness cursor
adept diff output groups per harness:
HARNESS SYNCED DRIFTED MISSING CONFLICT
claude-code 3 1 0 0
[claude-code]
drift .claude/skills/pr-review/SKILL.md
Resolving harness drift¶
- Canonical is right → publish:
adept sync(add--forceto overwrite drifted harness files,--dry-runto preview). - Harness edit is right → adopt:
adept sync-from(interactive), or--allfor non-interactive adoption from every harness,--forceto overwrite canonical,--dry-runto preview. - Conflict: review with
adept diff, then decide which side wins and run the corresponding command with--force.
Enforcing it in git¶
Install a pre-commit hook that blocks commits when there's drift — see the
Git drift hook guide. In CI, run adept status and branch on its
exit code (2 = drift/dirty).