Correcting the vault
Knowledge changes. A domain definition shifts after a refactor. An ADR turns out to be wrong. A lesson misremembered the conclusion.
Strata has four ways to handle it. Each carries a different blast radius.
The four operations
Section titled “The four operations”| Operation | When | Skill |
|---|---|---|
| Correct | One paragraph is wrong; note overall stays useful | /strata:correct |
| Invalidate | The whole note is no longer current; keep history visible | /strata:correct (invalidate path) |
| Supersede (decisions only) | A new ADR replaces an older one with a bidirectional link | /strata:decide --supersedes <old> |
| Forget | The note must disappear entirely (PHI, secrets, mistake) | /strata:forget |
All four leave a different audit trail. Correct keeps the note and
records what changed. Invalidate keeps the note and marks it dead.
Supersede keeps both notes and links them. Forget moves the note to
.trash/ with a reason logged.
Correct
Section titled “Correct”Use for focused edits where the note’s overall shape stays intact.
# Replace bodycat <<'EOF' | /strata:correct domain/order-aggregate.md \ --reason "OrderPriced now emitted before OrderConfirmed, not after"# Order Aggregate
<new body>EOF
# Update one frontmatter field/strata:correct domain/order-aggregate.md \ --set status=stable \ --reason "Adopted in production after two-week rollout"The script:
- Reads the note and frontmatter.
- Applies
--setupdates and optional body replacement. - Appends
{at, by, reason}to acorrections:list. - Bumps
updated:to today. - Refreshes the FTS index.
--set is repeatable. --reason is strongly recommended. It’s the
durable audit trail.
Auto-invocation
Section titled “Auto-invocation”Fires on “fix the note about X”, “the part about Y should say Z”,
or “update the status of <slug>”. Claude proposes the edit, you
approve, the script writes.
Invalidate
Section titled “Invalidate”Use when a whole note is no longer current but historical context
still matters. This is the invalidate path of the unified
/strata:correct skill — say “stop using this”, “this is no longer
true”, or “deprecate this note” and Claude routes to the invalidate
flow with required --reason and optional --replaced-by.
# The script under the hood (auto-invoked by `/strata:correct`):"${CLAUDE_PLUGIN_ROOT}/bin/run-python.sh" \ "${CLAUDE_PLUGIN_ROOT}/scripts/invalidate-note.py" \ domain/old-aggregate-pattern.md \ --reason "Aggregate split into Order + Payment in 2026-05-24 refactor" \ --replaced-by "domain/order-aggregate.md"The note stays in the vault. Readable in Obsidian, in git log, in
audit reviews. But:
status: invalidatedjoins the frontmatter.invalidated_at,invalidated_by,invalidation_reasonare recorded.- Optional
replaced_by:link points to the successor. - Optional
--invalid-since YYYY-MM-DDrecords when the fact stopped being true — separate frominvalidated_at, which is just when you recorded it. Keeping both answers “how long were we acting on a wrong assumption?”, which a single timestamp can’t. - Default search filters it out.
recallandfindskip invalidated notes. - Opt back in with
include_invalidated=truewhen you need history.
--reason is required. Invalidation without an explanation is just
deletion in disguise.
Auto-invocation
Section titled “Auto-invocation”Fires on “that’s no longer true”, “stop using <note>”, “this is outdated”, “deprecate <note>”.
Supersede (decisions only)
Section titled “Supersede (decisions only)”Decisions get special treatment. A new ADR can formally retire an older one with bidirectional linking.
/strata:decide "Use Postgres with pgvector" \ --supersedes "2026-03-15-pinecone-for-embeddings"The new ADR records supersedes: [2026-03-15-pinecone-for-embeddings].
The old ADR gets superseded_by: [<new-path>] written back into its
frontmatter, and its status flips to superseded. The chain survives
re-indexing on any machine.
Why not invalidate? Because supersession captures the reasoning
through the new ADR’s body. The whole point of an ADR is the
reasoning, so the successor carries that load. A one-line --reason
on invalidate can’t.
Strata never deletes a superseded decision — it expires and rewrites.
The old file stays as history; supersession just flips its status and
drops it from the live list. One refinement worth the keystrokes: when
you supersede, prepend a past-tense line to the old ADR (“Superseded by
<new> — we used to do X”) via /strata:correct, so a reader who lands
on it directly isn’t misled into thinking it’s current. Leave the rest
of the body alone; the original reasoning is exactly what you’re keeping.
Forget
Section titled “Forget”The hard delete. Use only when the note shouldn’t exist at all.
/strata:forget pr-context/feat-x/2026-05-24-secrets-leaked.md \ --reason "Contained API key from .env, removed per GDPR request"The note moves to <vault>/<repo>/.trash/ with a JSONL audit log
entry recording who, when, why, and SHA256. Recoverable. .trash/
is preserved unless you explicitly clean it.
--reason is required. Never auto-invokes. Forget only fires on
explicit user request. The audit trail must reflect intent.
Auto-detection of drift
Section titled “Auto-detection of drift”Three signals flag notes for likely correction.
code_refs that no longer resolve. When a note’s frontmatter lists
code_refs: [Foo, Bar] and one of those symbols doesn’t exist in
the current graph.json, /strata:review surfaces the note.
Path claims that broke. For ADRs and lessons extracted via bootstrap,
plan_correlate re-runs to detect when previously-resolved paths no
longer exist.
Staleness by usage. /strata:review also scores durable notes on an
importance-weighted decay curve: a decision that’s old (by its own
frontmatter date) and rarely recalled surfaces as a candidate to
refresh, supersede, or invalidate. Recalling a note resets its clock,
so notes the team actually uses don’t get flagged.
None of these auto-correct. All surface in review for you to decide between correct, invalidate, supersede, or forget.
Next: MCP tools. Every tool exposed to Claude, every argument.