v0.4.0
[0.4.0] - 2026-06-25
The live-runtime cut: the framework primitives that 0.3.0 left built-but-test-only
are now plumbed into the live cast pipeline — and a new gate makes "built-not-plumbed"
a CI failure so it can't happen silently again.
This cut also hard-cuts the Astro host substrate to Astro 7 / @astrojs/cloudflare v14:
czapFetchLayer() is the front-of-pipeline fetch layer, @czap/cloudflare/cache-provider
bridges Astro cache.invalidate() into the CZAP boundary KV tag index, czap astro dev/status/stop delegates to Astro background dev-server management, and czap doctor --target astro probes the Astro dev status endpoint.
Added
@czap/astro— runtime DocumentGraph loader.loadGraphRuntime(serialized, resolve)
lowers a sealedDocumentGraphonto the live boundary cast pipeline (CSS/ARIA/GPU),
with a surgicalcastGraphDeltare-cast seam (only changed cells re-lower; untouched
observers survive). Newclient:graphdirective. The loader is the seam an authoring
producer feeds; the producer itself is downstream.@czap/astro— scene→live-runtime bridge.bridgeSceneToGraph(scene, handle, …)
drives a signal-indexed@czap/sceneagainst the live runtime: a DISCRETE state crossing
emits aGraphPatch→recast, while the CONTINUOUS tween writes a leaf CSS var / GPU
uniform each frame and never patches the graph.@czap/sceneis now a live runtime
consumer (was video/offline-only).@czap/astro— AI-apply seam.castGraphContext(cast the live graph OUT to a
model-facingAIContext) +admitGraphPatchProposal(admit a candidate IN through the
un-bypassablevalidateGraphPatchProposal→applyValidatedPatchtoken-witness chain,
then re-cast the delta). LiteShip exposes the seam; the model producer is downstream.@czap/astro— SVG last-mile directive (client:svg): resolvesdata-czap-entity → SVGElementand applies@czap/scene'sapplySvgAttrsto the live DOM each frame.@czap/stage— headless node video encode.dualExportNode(graph, ffmpegFrameEncoder())
runs the graph→page+video dual-export proof in node/CI via an injected ffmpeg/libx264
FrameEncoder(was browser/WebCodecs-gated). The frame-source digest == page digest
invariant holds headless (frames addressed, bytes injected).@czap/quantizer— AnimatedQuantizer frame-clock injection.AnimatedQuantizer.make(…, { scheduler })
takes an optional@czap/coreScheduler.Shape(raf/fixedStep/audioSync) so the output
interpolation rides the display refresh (or a deterministic render/test clock) instead of its internal
fixed 16ms sleep. Omitted, the 16ms loop is byte-unchanged — existing callers are untouched.@czap/astro— continuous signal→uniform bridge.driveUniformFromSignal(element, input, uniform)
(from@czap/astro/runtime) drives the existingczap:uniform-updateevent continuously from a
continuous signal (e.g.scroll.progress), writing the value into the GLSL/WGSL uniform the GPU runtime
already consumes each (rAF-throttled) frame. Replaces the hand-rolled scroll→uniform glue and its
0..1-vs-0..100 scale footgun.@czap/vite—@quantizecontainer-target opt-out. Newquantize.containerplugin option
retargets the auto-emitted viewport@containercontainment off:rootto a named selector
(e.g.'.czap-vp') for hosts whose layout can't have a size-contained:root. Default:root
unchanged; applies to both the CSS transform and emitted boundary assets.@czap/astro— convention-file watch battery. The integration now calls Astro'saddWatchFile
for the convention primitive sources (boundaries / tokens / themes / styles, via the resolver's own
primitiveSearchPatterns), so editing a definition restarts the dev server and re-collects the
manifest — even for definitions not yet imported by a CSS block.@czap/cli—czap audit --consumer --profile <p>now combines (was mutually exclusive): the
profile becomes the consumer discovery base, so a downstream can run the audit engine against THEIR
OWN installednode_modulestopology, not just LiteShip's@czap/*. The engine seam
(consumerDevopsProfile(cwd, base)) was already there; this wires it to the CLI.- Plumb-completeness gate (
plumb:gate, gauntlet phase 37). A package-plumb ledger
classifies every published packageruntime/tooling/deferred(an unclassified package
fails CI, so a test-only subsystem can't ship hidden) + an unwired-capsule floor. Closes
the hole where built-not-plumbed primitives passed green (the audit's orphan findings were
info-only; no phase asserted producer→consumer plumbing). - Determinism hardening: an ast-grep guard banning re-implemented threshold reverse-scans
outside the canonical f32 kernels, + aBlendTree.computeBlendaccumulation-order-independence
property test (run against the fresh wasm in CI). - New package
@czap/error— a composable tagged-error algebra (a closed variant coproduct
over an openTaggedErrorcontract, value AND type, Effect- and throw-compatible) the whole
stack now adopts as its foundational zero-dep leaf. - New package
@czap/gauntlet— the self-proving rigor engine (ADR-0023): gates, findings,
assurance levels (L0–L4), and the authority ratchet (a gate earns blocking power only by
self-proving against its own red/green/mutation fixtures). Lean (notypescript; the
triangulated repo-IR + the mutation / MC-DC / taint / coverage-guided-fuzz / claim-vs-reality /
traceability / agent-safety gate families are host-injected via@czap/audit, ADR-0012). This
is the rigor work the small live-runtime cut grew into when it exposed the gaps. - FactGate — evidence-bound gates (ADR-0019). Gates can be defined as DATA (
defineFactGate—
requires+decide) instead of arbitrary closures, closing the stale-green hole where arun
body could read undeclared evidence. Cache identity derives from the declared facts; the
discriminant is an unforgeableWeakSet. The always-blocking no-skipped-test gate has a
proven-equivalent FactGate form. - API-docs source-of-truth. Every publishable package is in the TypeDoc roster (guarded), and
a broken{@link}now fails the build (treatWarningsAsErrors) — zero dead links, enforced. - Astro 7 (hard-cut). The workspace targets Astro 7 +
@astrojs/cloudflarev14 (Vite 8 /
Rolldown).@czap/astroneeds no code changes — the integration hooks, middleware, and
client:*contracts are unchanged — and the batteries Astro 7 ships are now consumed:@czap/astro—czapFetchLayer()(ADR-0024): request-time adaptation as a layer in
FRONT of Astro viasrc/fetch.ts. Shares the onecreateEdgeHostAdapter().resolve()with
czapMiddleware; on an opt-inserveFromEdgepath it serves boundary CSS from the edge and skips Astro
entirely.serializeBoundaryCssexposed. Astro'sFetchable/ Hono-compatible.@czap/astro— Diagnostics → Astro logger bridge.bridgeDiagnosticsToAstroLogger/
installDiagnosticsBridgeroute@czap/*runtime diagnostics through Astro's logger
(structuredastro dev --jsonoutput); wired inastro:config:setup.@czap/edge/@czap/cloudflare— active cache invalidation.BoundaryCache.invalidateByPath
(purge by content address) +invalidateByTag(Astro.cache tag parity, index-backed) close
ADR-0017's passive-TTL gap;KVNamespacegains optionaldelete/list, forwarded by the
Cloudflare adapter, degrading to a diagnostic when a provider omits them.@czap/cli—czap doctor --target astro: an Astro 7/_astro/statusdev-server
liveness probe for agent-run background dev sessions.
Changed
@czap/core— factored the DocumentGraph node well-formedness reader (isWellFormedNode,
DocumentGraphNodeSchema) out ofai-cast.tsintodocument-graph-schema.tsso the
runtime loader and the AI seam share one trust gate.