# Drift and reconcile

Specs and code want to diverge. You edit code under deadline and forget the
spec; you draft a spec and never build it; a refactor changes a shape the spec
still describes the old way. Left alone, that divergence — **drift** — makes
`.forge/specs/` untrustworthy, and an untrustworthy spec is worse than none.
Forge gives you two commands to keep the two sides honest: `/forge.drift`
**detects** divergence, and `/forge.reconcile` **resolves** it. Both are
non-destructive to run, so you can call them freely at any point.

## Drift is spec-versus-code divergence

Drift is any place where your specs and your code no longer describe the same
system. `forge drift` — the CLI command — cross-references `.forge/specs/`
against the codebase and sorts every divergence into one of three classes.

| Class | Meaning | The gap |
| --- | --- | --- |
| **Ghost** | Code with no spec | The system does something no spec describes |
| **Phantom** | Spec with no code | A spec describes something the system does not do |
| **Mutated** | Code and spec disagree | Both exist, but their shapes have diverged |

```mermaid
flowchart TD
  Start{Compare spec &lt;-&gt; code} -->|code, no spec| G[Ghost]
  Start -->|spec, no code| P[Phantom]
  Start -->|both, shapes disagree| M[Mutated]
```

::: info Detection is deterministic — for the CLI
`forge drift` is a pure Go function — same inputs, same classification, every
run. It classifies; it does not fix. It never blocks, so you can run it as often
as you like without disturbing an in-flight change. Fixing is
`reconcile`'s job. This determinism claim covers the CLI only — the
`/forge.drift` skill below adds a fourth category that a pure function cannot
compute.
:::

## `/forge.drift` adds a fourth class the CLI cannot see: Inverted

`forge drift` (CLI) and `/forge.drift` (agent skill) share a command name but
**not an engine** — the same split [documented for `forge roadmap` vs.
`/forge.roadmap`](/guide/commands#cross-cutting). The CLI above is
static-analysis-only: it can verify Ghost, Phantom, and Mutated because those
are all structural comparisons between a declared shape and an implemented
one — a route, a field name, an entity. `/forge.drift`, the LLM-driven skill,
detects those same three classes plus a fourth: **Inverted**.

An Inverted finding is not about code at all. It fires when the
implementation/architecture layer — `plan.md`'s Technical Context, or
`infra.md` — contradicts an intent-level Non-Functional Requirement or
Failure Condition declared in `spec.md`. Two examples: an NFR requires
recovery within 30 seconds of an AZ failure, but `infra.md` describes a
single-AZ deployment; or a platform pivot from Vercel to GCP lands in
`infra.md` while `plan.md` still assumes the old platform. In both cases the
code can be structurally perfect — every route and field matching its spec —
while the system still targets the wrong scale, platform, or recovery
posture. That is why Inverted is *non-structural*: it survives a
Ghost/Phantom/Mutated check untouched and would silently invalidate
downstream tasks if nothing looked for it.

Inverted detection cannot be deterministic because judging it requires
reading comprehension a parser doesn't have: deciding whether an architecture
"can satisfy" a recovery-time or scale target, or whether two free-text
documents disagree about a platform, is a judgment call, not a structural
diff. `drift.Classify` — the CLI's engine — never attempts it and is not
meant to; it stays a pure function over parseable code/spec shapes.
`/forge.drift` also renders its own emoji legend for its report (👻 Ghost, 👁
Phantom, 🔀 Mutated, 🔄 Inverted), distinct from the CLI's plain-text output.

## Catch drift early

Make `drift` part of your rhythm, not just a final gate. The longer a Ghost or a
Phantom sits, the more work accretes around a wrong assumption. Run it alongside
[`forge analyze`](/guide/commands) — the 100-point quality score — so you see
both how good the current state is and where it has quietly slipped out of sync.

```sh
forge drift        # classify Ghost / Phantom / Mutated
forge analyze      # 100-point quality score for the current state
```

Catching drift while it is one Mutated requirement is cheap. Catching it after
ten changes have built on the divergence is not.

## Reconcile brings the two sides back together

Where `drift` reports, `/forge.reconcile` **resolves**. It reads the artifact
you just created or changed, scans everything it could conflict with — other
specs, plans, tasks, and the [foundation baselines](/guide/foundations)
(constitution, security, infra, brand, design) — and walks you through each
conflict it finds. Reconciliation runs **automatically after any
spec-modifying command**, so contradictions get caught as they are introduced
rather than accumulating; you can also run it by hand at any time.

```mermaid
flowchart LR
  Spec[spec-modifying command] --> R[reconcile]
  R --> Q{Conflicts?}
  Q -->|no| Clear[all clear]
  Q -->|yes| Res[interactive resolution]
  Res --> Log[reconciliation log]
```

### Severity-ordered detection passes

Reconcile runs a fixed sequence of focused detection passes, **ordered by
severity** so the most dangerous conflicts surface first:

| # | Pass | Severity | Catches |
| --- | --- | --- | --- |
| 1 | Contradiction | **Critical** | Direct logical conflicts — "use PostgreSQL" vs "use MongoDB exclusively" |
| 2 | Constitution violation | **Critical** | New content that breaks a declared MUST/SHALL principle |
| 3 | Terminology drift | High | Different words for one concept — "customer" vs "user" |
| 4 | Scope overlap | High | Two specs independently specifying the same feature |
| 5 | Dependency conflict | Medium | Assumptions that contradict an existing plan |
| 6 | Brand & design inconsistency | Medium | Hardcoded values instead of design-token references |
| 7 | Infrastructure misalignment | Medium | Assuming a service the infra baseline does not define |
| 8 | Security baseline misalignment | Medium | A public endpoint where the baseline requires auth |

### Interactive, one conflict at a time

Conflicts are presented individually. For each, you choose how it resolves —
keep the new artifact, keep the existing one, merge them under a rule you
describe, or defer it. Every decision is appended to a **reconciliation log**, so
the resolution history is auditable and deferred items get re-evaluated the next
time the same artifacts are reconciled.

## Constitution violations cannot be deferred

The one rule that has no "later": a **constitution violation must be resolved
before you proceed**. Defer a terminology quibble or a scope overlap if you must
— they will resurface in the log. A constitution violation cannot be deferred at
all. It is a **critical** pass for a reason: the constitution is the standing
truth every change is measured against, and a spec that violates it is a spec
building on a contradiction.

::: warning No deferring constitution conflicts
`reconcile` will not let a constitution violation be logged-and-forgotten. It
stands in the way until you resolve it — because it also
[caps your `analyze` score](/guide/foundations#the-constitution-caps-your-score),
a deferred violation would silently penalize every quality assessment that
follows.
:::

## Where they sit in the workflow

`drift` and `reconcile` are **cross-cutting** — not phases on the spine, but
non-destructive commands you can call at any point. `reconcile` fires
automatically on the way out of every spec-modifying command; `drift` is yours
to run whenever you want a read on how far code and spec have parted. Together
they keep `.forge/specs/` an honest description of the system, so the specs you
promote on [archive](/guide/workflow) are worth trusting.

## Next steps

- [Foundation phases](/guide/foundations) — the baselines reconcile measures specs against.
- [The workflow](/guide/workflow) — where cross-cutting commands fit the spine.
- [Commands](/guide/commands) — `forge drift`, the `/forge.reconcile` agent skill, and the full surface.
- [Best practices](/guide/best-practices) — run analyze and drift on a rhythm.
