LearnNewsExamplesServices
Frontmatter
id17598
titleThree cockpit lifecycle e2e tests assert the pre-#16743 request shape, so the versioned wire envelope reddens them
stateClosed
labels
bugaitestingagent-os
assigneesneo-opus-grace
createdAtAug 23, 2026, 5:17 AM
updatedAtAug 23, 2026, 4:18 PM
githubUrlhttps://github.com/neomjs/neo/issues/17598
authorneo-opus-grace
commentsCount1
parentIssue17596
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtAug 23, 2026, 4:18 PM

Three cockpit lifecycle e2e tests assert the pre-#16743 request shape, so the versioned wire envelope reddens them

Closed Backlog/active-chunk-18 bugaitestingagent-os
neo-opus-grace
neo-opus-grace commented on Aug 23, 2026, 5:17 AM

Context

Carved from #17596 (AgentOS cockpit e2e reds) per its own AC-1 — "reclassified with a named cause and its own successor ticket". Three of that ticket's failures share one cause; the rest do not and stay with the parent.

Two of the three were not in #17596's original census. That ticket lists five reds; FleetCardLifecycleNL carries two more, invisible because the census was a chosen subset of specs plus a toEqual([{method grep that structurally cannot see a shared assertion helper.

The Problem

installFleetBridge.mjs builds every fleet call through createFleetWireRequest, then:

envelope = await transportSend(shellTransport
    ? {method: wireRequest.method, params: wireRequest.params}
    : wireRequest)

Browser mode sends the protocol offer; shell mode strips it back to {method, params}. Since #16743 ("version the client wire contract", merged as 040fa1cb27) that offer is {capabilities: ['method-schema-v1', 'closed-response-states-v1'], versions: [1]}.

Any spec wiring an HTTP loopback therefore records the full envelope. Two lifecycle specs still asserted the pre-#16743 shape with toEqual exact equality:

spec site shape
FleetGridKeyboardA11y.spec.mjs the Stop-request assertion inline toEqual([{method, params}])
FleetCardLifecycleNL.spec.mjs expectMinimalLifecyclePayload helper toEqual({method, params}), used

Three failing tests, one stale expectation shape. The assertions were correct when written — the wire grew and they did not move with it.

The Architectural Reality

.github/workflows/test.yml runs integration / parity / unit / components; there is no e2e suite in CI (no workflow references test-e2e or playwright.config.e2e). A wire-contract change therefore cannot redden the e2e layer at merge time — it reddens it silently, whenever someone next runs it locally on a browser-capable seat (#17595 owns why that population narrowed).

toEqual against a whole request object is the fragile shape: it couples a payload assertion to envelope structure. The specs' stated intent is minimality of the payload — one agent id, no credential-shaped bytes, no drill-shaped extras — which the envelope never violated.

The contract's absolute values are already owned elsewhere: lint-fleet-vocabulary-parity.mjs and fleetVocabularyParity.spec.mjs compare the ai/services/fleet authority against the apps/agentos/config twin, and prove an insufficient offer fails closed via unsupportedCapability. So a spec that hardcodes capability literals would duplicate that guard brittlely rather than add one.

The Fix

Assert the offer through the exported createFleetWireOffer() builder instead of a literal, at both sites.

Exact equality is kept — it is what enforces the minimal-payload guarantee, and it still rejects any stray key. What changes is that the expectation tracks the contract rather than freezing a snapshot of it, so the next envelope revision moves these specs without editing them.

Acceptance Criteria

  • The three tests pass on dev.
  • The assertions still reject a stray key on the request (the minimal-payload guarantee is not weakened into toMatchObject permissiveness).
  • A control proves the greened assertion can fail on envelope content, not merely on its presence — a deliberately wrong offer must redden it.
  • Both sites explain, in-source, that minimal describes the payload and not the envelope, so the next reader does not re-delete the protocol expectation.

Out of Scope

  • Rows 2–5 of #17596AgentCardSynthesisRenderNL, FleetCockpitDrillRoundTripNL, and two FleetMailboxTabNL journeys. Undiagnosed, unclaimed, different causes; the parent keeps them.
  • Changing the wire contract itself. #16743's envelope is deliberate and stays.
  • Adding e2e to CI — separate decision, own cost.
  • #17595 — the launch-capability boundary, not a spec failure.

Avoided Traps

  • Hardcoding the capability literals. It would have looked stricter while duplicating the parity lint's job and creating a second place to update — the guard that matters (an insufficient offer fails closed) already exists and is not improved by a copy in an e2e spec.
  • Reaching for toMatchObject. It would green the specs by permitting any extra key, silently discarding the minimal-payload property these specs exist to enforce. The bug is a stale expectation, not an over-strict one.
  • Trusting the census that produced the parent. Two of these three were missing from it. The instrument is now recorded with the ticket, so the count can be reproduced instead of believed.

Related

Parent #17596 · #16743 (the envelope this stale-dated) · #17595 (why the layer went unrun) · PR #17593 (surfaced the parent set)

Retrieval Hint: fleet wire protocol envelope createFleetWireOffer toEqual exact equality e2e lifecycle spec stale expectation browser mode shell mode installFleetBridge

Origin Session ID: 1b0d28eb-3461-40b6-bb35-88d6bf09ec94

tobiu referenced in commit 17d41fd - "fix(test): assert the versioned fleet wire envelope in lifecycle e2e specs (#17598) (#17599) on Aug 23, 2026, 4:18 PM
tobiu closed this issue on Aug 23, 2026, 4:18 PM