Know when your metadata cache went stale
Directive lets you tag any definition and search by tag:
system.meta.byTag('pii'); // every definition tagged 'pii'
system.meta.byCategory('auth'); // every definition in a category
Both walk every definition in the system. That is fine occasionally and expensive on a hot path, so anything that asks per-operation caches the answer. And then it has no way to learn the answer went stale, short of asking again, which is the thing it was avoiding.
system.meta.revision() is an integer you can compare instead.
let tagged = system.meta.byTag('pii');
let seenAt = system.meta.revision();
function currentTags() {
const now = system.meta.revision();
if (now !== seenAt) { // one integer compare
tagged = system.meta.byTag('pii');
seenAt = now;
}
return tagged;
}
Comparing costs nothing. Rebuilding costs a walk. You now pay the second one only when something actually moved.
Read the contract narrowly
Only equality is meaningful. Not the starting value, not the step size, not the direction. Do not persist it, do not compare one system's revision against another's, and do not assume it increments by one.
The number is also deliberately generous about moving. A rebuild you did not need is harmless. A rebuild you skipped is not, so it errs toward waking you up.
Today it moves when a module is registered. That is a narrower guarantee than "moves whenever a byTag result could change," and it is stated narrowly on purpose, because we would rather widen it later than have you build on a promise we have not kept yet.
What it was built for
Our own personal-data guardrail, which is the first consumer.
factPIIGuardrail screens fact writes against the set of keys tagged pii, and that set used to be built once at startup. Register a module later and its tagged facts were not on the list, so a write to one took the same path an untagged key takes: no scan, no redaction, nothing reported. The guardrail could not check for new tags on every write without walking every definition on every write.
That is what an integer compare buys. The PII screen sees more of your data now covers what changed there.
Upgrading
npm install @directive-run/core@latest
Purely additive. Worth reaching for if you cache anything derived from meta.byTag or meta.byCategory, or if you have been re-walking on every call because there was no cheaper option.
Related
- Long chains run once – A reconcile chain of any length now dispatches each requirement exactly once, and settle() comes back when you swap a derivation. Four fixes to things the runtime was doing without telling anyone.
- A cancelled agent is not a failed one – race now reports the agents it stopped as cancelled rather than failed, and dag timeouts actually cut work off. If you build dashboards on orchestrator events, this changes what they show.
- Three of our published rates were wrong – We checked every rate table in @directive-run/ai against the providers' own pricing pages and corrected three. Then we gave the tables an expiry date so it cannot happen quietly again.
Directive is free and open source. If this was useful, consider supporting the project.

