mirror of
https://github.com/wu736139669/hapi.git
synced 2026-10-26 22:30:50 +00:00
Two new golden-fixture suites, expectations machine-generated from the web
implementation (same source-of-truth principle as the chat suite):
- shared/fixtures/sse/ (12 cases): session-updated versioned-patch
application via applySessionDetailPatch — strict version gates for
metadata/agentState/todos/teamState, out-of-order arrival, teamState:null
clear, max-monotonic updatedAt, flat last-write-wins fields, sub-minute
activeAt keep-alive drop, scratchlistUpdatedAt trigger, and the pinned
actual behavior that activeTurnStartedAt is NOT applied by the patch path.
Inputs are stored schema-normalized and validated against SessionSchema /
strict SessionPatchSchema at generation time; per-patch applied/unchanged
verdicts are part of the contract.
- shared/fixtures/pagination/ (11 cases): op scripts driving the real
message-window store with a scripted ApiClient — latest page + SSE ingest,
before-cursor older pages, epoch-mismatch reset (window discard + recorded
internal latest request), reset:true replace preserving optimistic rows,
localId echo reconciliation, messages-consumed invokedAt stamping (no
cursor advance), message-cancelled removal, cancel-too-late invoked-row
ingest, hidden-row cursor advance, 400-row trim preserving queued rows,
and queued-state gap recovery. Documents pin the exact requests the store
issued, older-load outcomes, reconcile candidates, and a minimal window
projection (ids/order, queued/optimistic flags, hasMore, epoch, viewMode,
compound cursors).
Generator: web/scripts/fixtures/{sse,pagination}/ extend the K5 framework
(canonical serialization reused; suites pruned of stale files). Web
self-conformance tests replay every fixture against the real implementation
in bun run test:web. README documents schemas, projections, replay
contracts, and native consumption for both suites.
No time injection needed: the store's only Date.now() reads gate
notification throttling, which never reaches persisted or projected state.
136 lines
4.4 KiB
JSON
136 lines
4.4 KiB
JSON
{
|
|
"description": "Older pagination sends the compound (beforeAt, beforeSeq) pair from the current older cursor, prepends the rows, and adopts the response page.nextBefore as the new older cursor and page.hasMore as the exhaustion flag.",
|
|
"expectedState": {
|
|
"epoch": 4,
|
|
"hasMore": false,
|
|
"messages": [
|
|
{
|
|
"createdAt": 9000,
|
|
"id": "a-9",
|
|
"invokedAt": 9000,
|
|
"localId": null,
|
|
"optimistic": false,
|
|
"queued": false,
|
|
"seq": 9
|
|
},
|
|
{
|
|
"createdAt": 10000,
|
|
"id": "a-10",
|
|
"invokedAt": 10000,
|
|
"localId": null,
|
|
"optimistic": false,
|
|
"queued": false,
|
|
"seq": 10
|
|
}
|
|
],
|
|
"newestCursor": {
|
|
"at": 10000,
|
|
"seq": 10
|
|
},
|
|
"olderCursor": {
|
|
"at": 9000,
|
|
"seq": 9
|
|
},
|
|
"viewMode": "tail"
|
|
},
|
|
"fixtureVersion": 1,
|
|
"name": "fetch-older-before-cursor",
|
|
"ops": [
|
|
{
|
|
"expectedRequests": [
|
|
{
|
|
"limit": 200
|
|
}
|
|
],
|
|
"op": "sync-tail",
|
|
"responses": [
|
|
{
|
|
"messages": [
|
|
{
|
|
"content": {
|
|
"content": {
|
|
"data": {
|
|
"message": "a-10",
|
|
"type": "message"
|
|
},
|
|
"type": "codex"
|
|
},
|
|
"role": "agent"
|
|
},
|
|
"createdAt": 10000,
|
|
"id": "a-10",
|
|
"invokedAt": 10000,
|
|
"localId": null,
|
|
"seq": 10
|
|
}
|
|
],
|
|
"page": {
|
|
"direction": "latest",
|
|
"epoch": 4,
|
|
"hasMore": true,
|
|
"limit": 200,
|
|
"nextAfterAt": null,
|
|
"nextAfterSeq": null,
|
|
"nextBeforeAt": 10000,
|
|
"nextBeforeSeq": 10,
|
|
"reset": false,
|
|
"snapshotHeadAt": 10000,
|
|
"snapshotHeadSeq": 10
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"expectedOutcome": {
|
|
"addedRenderableCount": 1,
|
|
"hasMore": false,
|
|
"kind": "applied"
|
|
},
|
|
"expectedRequests": [
|
|
{
|
|
"beforeAt": 10000,
|
|
"beforeSeq": 10,
|
|
"limit": 200
|
|
}
|
|
],
|
|
"op": "fetch-older",
|
|
"responses": [
|
|
{
|
|
"messages": [
|
|
{
|
|
"content": {
|
|
"content": {
|
|
"data": {
|
|
"message": "a-9",
|
|
"type": "message"
|
|
},
|
|
"type": "codex"
|
|
},
|
|
"role": "agent"
|
|
},
|
|
"createdAt": 9000,
|
|
"id": "a-9",
|
|
"invokedAt": 9000,
|
|
"localId": null,
|
|
"seq": 9
|
|
}
|
|
],
|
|
"page": {
|
|
"direction": "before",
|
|
"epoch": 4,
|
|
"hasMore": false,
|
|
"limit": 200,
|
|
"nextAfterAt": null,
|
|
"nextAfterSeq": null,
|
|
"nextBeforeAt": 9000,
|
|
"nextBeforeSeq": 9,
|
|
"reset": false,
|
|
"snapshotHeadAt": null,
|
|
"snapshotHeadSeq": null
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|