Status & roadmap¶
Alpha, and bounded by design¶
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 and browser-verified throughout; it is 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 generates every dialect expression over operand-type pairs and evaluates it in CPython and in node. Situ must agree or refuse to compile; the recorded-disagreement baseline may only shrink (it is currently empty). The decomposition property checks that a component tree emits the same program as the equivalent monolith, over 200 generated trees. The golden-bytes test holds the real demo trees' compiled output (rendered output and wire contract) fixed; the fourth is the seam's CompileErrors. Each invariant 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. The lowerer has no guards: an ill-typed program cannot reach it. This is why ==, <, in, arithmetic, len, truthiness and the rest all mean in the browser what they mean in Python. Authors see two consequences. 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 and collected in this table:
| 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, while 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, because 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 framework-neutral, and three adapters ship: the Litestar reference, a generic ASGI one (
situ.mount.asgi, for FastAPI / Starlette / bare uvicorn) built on the protocol itself so it imports no web framework, and Flask (situ.mount.flask, WSGI). The ASGI one is async-native, so it needs none of the Flask adapter'sasyncio.runbridge. As of 0.4.0litestaris an extra (situ[litestar]): the base install is the compiler plus the ASGI adapter, which needs no web framework at all. 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¶
The project uses semantic versioning; user-visible changes land in CHANGES.md. The license is MIT.