Updates & Lessons

Teach it once. It remembers across every release.

The runtime evolves; your customizations shouldn't have to be re-fought on every upgrade. INSPIRE records how you've taught a skill as lessons, and re-applies them to each new release — never a line-by-line merge, never a wipe.

Status. Two things ship today: the lessons catalog, with the write-once one-line format, and /inspire:update — a real command that upgrades a project from any released version, replaying the layout changes and reconciling content file by file. What remains the design for v1 is the semantic half: materializing a lesson into the skill it teaches, and re-deriving your lessons onto a new base rather than merging text. So the sections below split — the upgrade mechanics are released; the four-outcome lesson classification is still the model.

The unit

A lesson is one line that changes how a skill behaves.

Not a config file, not a fork of the skill — a single instruction, in your context, that the skill internalizes. "When generating a NestJS controller, keep DTOs in a separate file." That's a lesson.

One line, atomic

Short by design

A lesson is a single imperative — at most a positive/negative pair (do this / not that), with an optional example as support only. The one-line limit makes each lesson indivisible, so the catalog stays small and every lesson is easy to reason about.

Relevant here

Local first

You capture a lesson because it matters to you, in this project — not because it's destined for the official runtime. Whether it generalizes across projects is decided upstream, from the pattern many teams' lessons form, never by a single author.

Materialized, not consulted. A lesson is written into the skill, so the taught behavior becomes the behavior — the agent acts on it, it doesn't check a footnote and apply it if it happens to notice. Lessons are the source of truth; the skill file is the result. A hand edit to a skill that you don't capture as a lesson is drift — not destroyed, an update keeps it, but it isn't knowledge either: nothing re-applies it when the skill is rebuilt, and every future release that touches the same file becomes a conflict you arbitrate by hand. Exactly like an out-of-band change to declared infrastructure.

The model · lesson re-derivation is roadmap

An update rebuilds. It never merges line-by-line.

Skills are natural language, not code — a textual three-way merge can stitch two edits together into a skill that reads fine and means the wrong thing. So an update takes the new base and re-applies your surviving lessons onto it, from scratch.

/inspire:update ships the deterministic half. One command upgrades a project from any released version to the installed plugin's: it fingerprints what you have against the per-version hash manifests INSPIRE ships, asserts that version's layout, replays the structural moves between there and here, then reconciles content file by file. A pre-0.3 install is the longest chain. The lesson re-derivation below — classifying each lesson against the new base and rebuilding the skill — is the semantic half.

How it tells your edit from a stale file. Three hashes per path: what INSPIRE shipped at your version, what is on disk, and what is about to be installed. Untouched-but-stale updates silently; edited-but-unchanged-upstream is kept silently; only a file both sides changed, differently, asks you anything. The baseline is the shipped manifests, not .inspire.lock — the lock lives on your machine, records provenance only, and pre-0.3 installs often wrote none at all. A file INSPIRE never shipped is kept by construction — your own additions inside an owned skill directory, a custom stack profile say, survive every update. Your knowledge base seeds additively at init and at update, and a path already on disk is never replaced; a release can retire a seed it shipped, but removal is silent only when the file is provably unedited — an edited copy is asked about, and unresolved defaults to keeping yours. Run it read-only first with the plan mode — it writes nothing, not one byte, and shows the whole thing grouped by concept. At the tail of a real run, it offers to run the trust report too — an upgrade is exactly the moment installed skills diverge en masse from what wrote the vault.

When a release restructures a skill. A skill's content can move between files — a monolithic SKILL.md splitting into a compact entry plus references/ files, say. Your edit to the old file asks like any other conflict, and the report flags when the asked-about file has new reference files sitting beside it: your customization may belong in one of them, the merge step can place it there while taking the new entry, and keeping your file whole is also fine — both copies stay live, to reconcile whenever you choose.

Fetch a pinned release

The new runtime is pulled at a specific version into a scratch area — never entangling your project's git history. Your lessons stay exactly where they are.

Classify each lesson

In parallel, every lesson is checked against the new base: has this release already learned it, reversed it, or left it untouched? A per-skill changelog makes this cheap; without one it still works, just slower.

Rebuild & review

The skill is regenerated as new base + your surviving lessons. A plan shows what will change — and warns of any uncaptured hand edits about to be lost — before anything is written.

Four outcomes

What happens to each lesson.

The default is conservative: when a call is uncertain, your lesson is kept. Silently dropping a taught behavior is the one failure worth guarding against.

AbsorbedThe new base does this natively. The lesson is archived — the behavior ships with the release, so the project stops teaching it.
UntouchedThe base is unchanged here. The lesson is kept and re-applied to the new skill.
PartialThe base absorbed part of it. The old lesson is superseded; a new one is written carrying only the residual — the part still not covered.
ContradictedThe base deliberately went the other way. You decide — by default your local lesson wins; accepting the reversal is an explicit choice.

The teaching debt shrinks. Every release the base learns a little more of what forks were teaching it, so archived lessons accumulate and the set you must re-teach gets smaller over time — not larger.

Getting it in

INSPIRE touches only what it owns.

Installing or updating the runtime is surgical: it reconciles the files INSPIRE placed and nothing else. Whatever else lives in your workspace is yours, and stays untouched.

A namespace, not a directory

The runtime owns a known set of paths — the inspire-* skills, the validators, the hooks. Install and update add and reconcile exactly those; your own skills, hooks and settings are never removed or overwritten.

Two ways in

Both are the same command. Install the plugin once, then run /inspire:init in the target repo. Greenfield — an empty repo gets the whole scaffold. Brownfield — an existing repo gets the runtime in place; point it at the code you already have, and onboard it with /inspire-extract. No forking the template, no restructuring, no second repo.

Your code stays where it is

Where production code and the prototype live is configuration, not a fixed folder. A greenfield project gets source/ and prototype/; an existing project points the runtime at its own layout.

Your agents don't forget what you taught them.

Every release re-teaches the new base — and drops what it already knows.