Status & roadmap¶
Alpha, deliberately bounded¶
situ is a young library extracted from a research programme. The compiler accepts a bounded dialect and fails closed; the API may still move. It is proven at TodoMVC-to-issue-tracker scale, browser-verified throughout — and not yet hardened for auth, real concurrency, or production operations.
What "done" means here¶
A feature counts only when:
- a Playwright e2e passes in a real browser — the fixture fails on any console error, because a server-side
TestClienthappily passes pages whose client is broken; make lintis clean across ruff (check + format), ty, pyrefly, mypy, andsitu checkover the component trees;- risky compiler changes additionally pass an adversarial review whose confirmed findings are fixed and regression-tested first.
Four standing invariants guard refactors: the differential oracle (every dialect expression, generated over operand-type pairs, evaluated in CPython and in node — situ must agree or refuse to compile; the recorded-disagreement baseline may only shrink, and is currently empty), the decomposition property (a component tree emits the same program as the equivalent monolith, over 200 generated trees), the golden-bytes test (the real demo trees' compiled output — rendered output and wire contract — does not drift), and the seam's CompileErrors. Each is mutation-tested: break what it guards, and it must go red.
The typed dialect¶
The client dialect is specified as a table of typing rules (compiler/lang/rules.py), each verified against CPython, and compiled through a clean parse → check → TypedIR → lower pipeline whose lowerer has no guards — an ill-typed program cannot reach it. This is what makes ==, <, in, arithmetic, len, truthiness, and the rest mean in the browser what they mean in Python. Two consequences for authors: a row the client reads declares its type (data-row="<Record>" + a TypedDict; declui derives it), and the dialect accepts more than the old untyped emitter (k in d, xs[-1], 'ab' * 3, n % m all work now). See the dialect.
Known limits¶
Each is documented where it applies; collected here:
| Area | Status |
|---|---|
Synced |
Reserved, unimplemented. The marker parses; no codegen, bootstrap, or transport exists. The "live" SSE refetch (live=True) is the labelled stand-in: it delivers real cross-client updates, and a local-first replica remains future work. |
| Live hub | In-process (asyncio queues). One server process only; a broker (e.g. Redis) behind the same interface is the scaling path. |
Url siting |
A real navigation: shareable and reload-surviving, and it resets in-progress Local state. Site accordingly. |
| Prop/Emit typing | Matched by name across the parent/child file boundary; a type mismatch passes the checkers and surfaces in e2e. |
| Kit accessibility | WAI-ARIA patterns implemented and keyboard-tested; no full-conformance claim. |
declui required= / filter= / link= / in_= |
Accepted so models type-check; not consumed yet. |
| declui generation | A first-draft generator with eject as the expected workflow — it does not regenerate hand-tuned markup. |
| Edit loop | Components compile once per process; restart to pick up edits (watch/reload is on the roadmap). |
:cells |
The one sanctioned runtime interpreter — user-typed formulas can't be compiled ahead of time. |
Roadmap themes¶
From the design log (notes/24, notes/27, notes/28 in the repository):
- Framework adapters — the mount core is now framework-neutral, and a Flask (WSGI) adapter (
situ.mount.flask) ships alongside the Litestar reference. Next: a Starlette adapter (async-native, noasyncio.runbridge) and movinglitestarfrom a hard dependency to a[litestar]extra (the imports are already lazy, so the Flask path pulls in no Litestar). Synced, for real — a replica + reconciliation engine behind the reserved site.- Typed templates — derive per-component context types from the parsed template (the wire projection and
data-rowalready supply row schemas) and checkcontext()against them. - Finish the type inference — an unannotated handler parameter compared to a numeric signal is the one path still on the old emitter's coercion helpers (
S.eqv/S.setHas, emitted zero times across the corpus but not yet deletable). Infer such a parameter's type from its typed call sites, then delete the helpers. Generate the dialect reference fromrules.pyso the docs cannot drift from the compiler. - declui next slices — the create dialog, richer zone vocabularies (tabs) with the eject line kept explicit, a build-time facade-signature check for generated commands.
- Seam Certificate — emit the trust surface as diffable data (every signal's site, every provide/inject edge, every client↔server boundary).
- DX — watch/recompile on edit; editor support for the binder surface.
Versioning¶
Semantic versioning; user-visible changes land in CHANGES.md. The license is MIT.