feat(core): wire layer — typed envelopes + ts-rs single-source TypeScript (card e98bb804)#1
Conversation
…ript (card e98bb804) The four traits are the in-process contract; this adds the wire contract that crosses a transport (continuum's JTAG WebSocket being consumer #1): - StateLayer: Ephemeral/Session/Persistent/Semantic cadence enum; defaults to Session so an unannotated update can never claim the 60 Hz lane. - StateEnvelope (state-down): kind + revision + layer + opaque consumer payload. Positron frames; consumers fill. - CommandEnvelope (event-up): kind, consumer-defined command name, params, correlation_id, source. - CommandSource: Human | Observer{observer_id} — typed provenance on every action. An AI acting through a widget is first-class but never anonymous; audit/trust policies key off this without string-sniffing. - ObserverSpec: observer_id + budget_hz + explicit kind opt-ins (perception is budgeted, not ambient). Single-source-of-truth flow: every wire type derives ts_rs::TS and exports to npm/core/src/generated/ (TS_RS_EXPORT_DIR pinned in .cargo/config.toml, regenerated by cargo test — drift cannot hide). @positron/core npm skeleton re-exports the generated types; payload interiors stay consumer-typed by design. Tests: lossless round-trips, pinned CommandSource wire shape, layer default. fmt + clippy clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
VERDICT: BLOCK MERGE (adversarial review, commit 340f5d1) Most of this PR is solid — but one generated type is a contract lie, in the layer whose whole job is contract truth. Blocking finding
So the obvious usage path on each side either silently misbehaves or throws. Fix: Non-blocking risk notes
What checked out (verified, not vibes)
🤖 Generated with Claude Code |
…Spec.layers, CI drift gate (card e98bb804) Review #1 (posted on the PR) blocked on a real bug: u64 revision generated as TS bigint while the JSON wire carries a number — JSON.parse yields number (comparison never matches), JSON.stringify throws on bigint. Both consumer paths broken by the type. Now #[ts(type = "number")] with the rationale documented; 2^53−1 monotonic revisions is not a real constraint. Also from the review: - ObserverSpec.layers: Vec<StateLayer> — the per-layer subscription the StateEnvelope docs advertised but the spec couldn't express. Same explicit-opt-in semantics as kinds (empty = none). - .github/workflows/ci.yml: fmt, clippy -D warnings, test, then git diff --exit-code — the regeneration drift gate is now enforced, not just mechanically possible. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Re-review of b416add — APPROVE (block lifted) All three blocking findings from the prior review are addressed; verified by inspection of the delta (340f5d1..b416add) and by running the full gate locally in a clean worktree at b416add.
Local verification at b416add (temp worktree):
Non-blocking notes:
🤖 Generated with Claude Code |
…ip (card e98bb804) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The four traits are the in-process contract; this adds the wire
contract that crosses a transport (continuum's JTAG WebSocket being
consumer #1):
defaults to Session so an unannotated update can never claim the
60 Hz lane.
consumer payload. Positron frames; consumers fill.
params, correlation_id, source.
every action. An AI acting through a widget is first-class but
never anonymous; audit/trust policies key off this without
string-sniffing.
(perception is budgeted, not ambient).
Single-source-of-truth flow: every wire type derives ts_rs::TS and
exports to npm/core/src/generated/ (TS_RS_EXPORT_DIR pinned in
.cargo/config.toml, regenerated by cargo test — drift cannot hide).
@positron/core npm skeleton re-exports the generated types; payload
interiors stay consumer-typed by design.
Tests: lossless round-trips, pinned CommandSource wire shape, layer
default. fmt + clippy clean.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com