Skip to content

Umbrella: resync store_state payloads with base-studio-code develop (contract v2 drift) #234

Description

@kevinthelago

@

The problem

The frame contract is in sync. src/lib/tunnel/tunnelProtocol.fixtures.json is content-identical
to base-studio-code develops src/features/tunnel/lib/tunnelProtocol.fixtures.json, and
tunnelProtocol.fixtures.test.ts decodes every fixture into our typed models and deep-equals back,
so any frame-level drift fails in both directions.

The payloads are not. store_state is {domain, rev, json} where json is an opaque serialized
string, so every per-domain payload shape inside it is completely unguarded. Drift has accumulated
silently: all 351 tests pass while several pages render blank or stubbed.

Confirmed examples:

  • Desktop split glances ProjectLite.status into health + activity (#2541). We still read
    p.status (src/lib/pages/glancePage.ts:85), so every project node falls back to idle and the
    fault/health colouring is dead.
  • Desktop audit rows are {ts: ISO-8601 string, pane, toolName, target}
    (src/features/security/lib/auditLog.ts:22). We parse {at: number, action, detail, actor}
    (src/lib/mirror/securityView.ts:64). Only paneactor resolves; every row renders as .

Target: develop, not main

base-studio-code main is at #2435 (2026-07-06). develop is at #3440 (current). Every contract
reference our code cites — #2497, #2498, #2511, #2530 — exists only on develop. Syncing against
main would move us backwards.
All investigation and all fixture copies must use ?ref=develop.

Approach

One issue per domain. Each is investigated against the real desktop surfaces on develop before any
code is written — resolving every referenced type to its actual definition rather than trusting the
payload interface alone, and checking TYPES not just field names (the security bug is a
string-vs-number, not a rename).

Children

Linked as they are filed.

Harness status

glance, security, alerts, org, themes, skills, automations and mcp have Layer A decoders + Layer B smoke tests. Only two domains remain in PENDING_DOMAINS, each citing its issue — moving a domain from PENDING_DOMAINS into DECODERS is the definition of done for its issue.

Known harness limit (found in #241): the fixture cannot catch pass-through bloat, because a minimal PROJECTION_INPUTS entry satisfies a type whose heavy fields are optional. Needs a sibling invariant desktop-side — fixture inputs must exercise optional fields the builder passes through.

The structural fix

Per-domain fixes are mechanical and will rot again the moment either side ships a rename. The durable
fix is a payload-level parity harness with the same "cannot land on one side without failing the
other" property the frame fixtures already have. Tracked as its own child.

Related: the mobile copy of the frame fixtures differs from the desktops by line endings only
(CRLF vs LF), which already technically violates the BYTE-IDENTICAL claim in the files own
$comment. A .gitattributes pin folds into the harness work.

Related

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions