Available since v0.1.0
fs-trigger="invariant"
StableContinuously monitors a condition for the lifetime of the page. Unlike user-triggered assertions, invariants stay pending as long as the condition holds — only failures (violations) and recoveries (pass after failure) are reported to the collector.
Syntax
<nav
fs-assert="layout/nav-visible"
fs-trigger="invariant"
fs-assert-visible="#main-nav">
</nav>
Semantics
- Quiet when healthy. While the condition holds, no collector traffic.
- Loud when broken. A violation fires a failure report immediately.
- Recoveries are reported. A failed invariant that later passes again sends a recovery signal.
- Auto-passed on unload. On page close, any still-pending invariant is sent as the "all clear" signal.
- No timeout. Invariants are perpetual — they live for the page lifetime and ignore
fs-assert-timeout.
When to use it
- Page-level contracts ("the nav should always be visible", "no error banner should ever appear")
- Continuous layout validation across route changes in an SPA
- Guardrails around legal / compliance UI that should always be present
- Cross-cutting invariants (no toast stack overflow, no stuck loading spinners)
Example
<!-- Nav must always be visible -->
<nav
fs-assert="layout/nav-visible"
fs-trigger="invariant"
fs-assert-visible=".main-nav">
</nav>
<!-- Error banner must never appear -->
<div
fs-assert="layout/no-error-banner"
fs-trigger="invariant"
fs-assert-hidden=".global-error-banner">
</div>
<!-- Immutable legal notice -->
<div id="legal-notice"
fs-assert="layout/legal-stable"
fs-trigger="invariant"
fs-assert-stable="#legal-notice">
</div>
Pairs well with
fs-assert-visible— the primary pairingfs-assert-hidden— for "should never appear" contractsfs-assert-stable— "should never be mutated" contracts
Gotchas
- Don't combine with
fs-assert-after. Invariants skip the immediate resolution path thatafterdepends on — it would never be checked. Combining the two logs a warning. - Event-based types are discouraged.
updated,loaded, andemittedrequire witnessing a mutation or event, but invariants evaluate perpetually against current state. The agent allows it but warns. Use state types (visible,hidden,added,removed,stable). - Conditional siblings and MPA are not supported on invariant-triggered assertions.
See also
mount— the one-shot alternative- Assertions index
- Patterns cookbook #10