Repository navigation
feat(missions): add byte-bounded panel page reads - #1246
Merged
Merged
Conversation
First server-contract slice of panel-level paging (4b), following task pages (#1241). Task rows are bounded, but the current panel list still grows with summaries, cleanups, actor arrays and open missions. A bounded transport must exist before the UI can move off those existing reads. Add the opt-in panelPage RPC and POST /missions/panel-page route: - Every successful serialized JSON response, including escaping, envelopes and continuations, fits 64 KiB; requests fit 16 KiB. - Sources are summary or cleanup index hints, one compact mission or its own root field, or an existing tasks selector. Directory reads return no maps; mission/task sources read only the named range. - At most 50 exact row pieces fit a response. A row too large for one transfer is split into JSON text slices rather than truncated. - Cursors bind the chosen collection's digest and row/character position. Changed collections refuse the cursor; a partial row supplies no absence or mutation evidence. - The HTTP route validates the selector, response size and owned project and source identity. It has no snapshot or legacy-list fallback. Existing panel, task, content and authoritative APIs stay unchanged. The UI does not consume panelPage yet; activity projection, discovery, completion seeding, cleanup retries and page caches follow separately. No user-visible behavior changes in this slice. Tests recover 400 escaped/nested rows including a 5,000-actor row over 95 bounded transfers; a real journal fixture covers 300 missions, 300 cleanups and 300 task actors. Warm directory traversal performs no storage scans, and mission fields read only their own range. Eight mutations fail the byte-budget, cursor, scope and selector regressions. Server/UI typechecks, 1,498 server tests, 1,845 UI units, 409 serial browser cases, help checks, plugin build and isolated OpenCode 2.2.3 qualification pass. Browser runners include the console-hiding fix.
…plies Panel field and task reads discarded the range damage information they had just observed. Consumers could mistake a damaged reconstruction for clean absence, or treat a field page as complete when the same range already reported unavailable controls, notifications or cleanup. Carry the observed discarded count and all three unavailable flags in every successful range envelope. An unreadable damaged mission now returns damaged; a cleanly absent mission still returns mission-not-found. This uses the existing range observation without reading project hints or another journal. The native output contract also required only available. Replace it with complete, strict success and refusal alternatives, and validate the same portable schema at the HTTP seam before publishing it. Byte limits and source/project identity checks remain independent. Regression tests cover whole-map, field, task and damaged/no-map reads, incomplete/mixed successes, missing refusal reasons and excess fields. All seven red checks fail with their protections removed. Server and UI typechecks, 1,501 server tests, help checks, plugin build and 20 isolated OpenCode 2.2.3 native gates pass. The native test exercises registration, strict outputs and range damage using its private database. Document the retained source-cost limits: full collection hashing per transfer and directory serialization inside the append exclusion.
Contributor
Author
Gatekeeper reviewRound 1 (
Round 2 (
Validation: server/UI typechecks; 1,307 server tests, one environment-gated skip; plugin build; 20 native gates on isolated OpenCode 2.2.3 plus supplemental real-transport checks. Browser/UI runtime suites were not rerun for this unchanged opt-in server surface. Scope: server-only 4b.1. Existing UI reads are unchanged. Source hashing per transfer and directory work inside the append exclusion remain documented costs; bounded activity and UI adoption follow separately. |
pascalandr
added a commit
that referenced
this pull request
Nov 1, 2026
Server-only slice 4b.2 of bounded Missions reads. The byte-bounded panelPage transport (#1246) is in place, but a future picker cannot stop loading all open maps until it can observe their activity separately. Extend panelPage with activity and marks sources: - activity reads one mission range and a window of at most 160 actor roots; actor offsets and an order digest allow traversal. - marks reads up to 16 indexed mission contexts, with up to 10 actors each, sharing the same 160-root observation budget. - Native RPC returns only persisted context. The owning HTTP backend validates and reconstructs that context, then observes native sessions, Forms and permissions outside the journal append exclusion. It returns an observed phase with observation time, coverage, requests and activity. - Observed, partial and unknown remain distinct. A failed observation never establishes idle or request absence, and off-page actors and descendants stay reachable through actor windows. - Context carries range damage, lifecycle request identity and compact receipt counts, graceful Pause/Interrupt-now and owed-report evidence. - Every reply uses the existing 64 KiB exact JSON transport; requests keep the 16 KiB limit. Continuations re-observe and refuse changed content rather than mixing observations. No observation cache or automatic restart is introduced. Factor shared owed-work/task-attribution rules so compact task maps and the observation context agree. Keep digest/evidence imports narrow so UI shared types do not import server-only execution code. Existing UI reads and authoritative/internal maps are unchanged. The next slice adopts the new windows with per-page provenance, explicit retries and last-good display; partial windows must never prove whole-mission absence or authorize recovery. Tests: real route/control/native pipeline with over 160 actors, off-page Forms/permissions, failed/foreign/moved observations, partial coverage, clock-free volatile digests, stale order, journal damage and no native IO under the append lock. Thirteen red checks fail with their protection removed. Warm marks over 50 missions perform no source scans. Eight hundred requests reconstruct over 22 transfers, at most 65,536 bytes. Server/UI typechecks, 1,507 server tests, 1,845 UI units, help checks, plugin build and isolated OpenCode 2.2.3 qualification pass. Native request lists remain whole per Location. Re-observation and full source serialization can be expensive, and churning sources may refuse continuations repeatedly; these are documented display-read limits.
pascalandr
added a commit
that referenced
this pull request
Nov 1, 2026
Server-only **4b.2** of bounded Missions reads, following #1246. No UI conversion or user-visible behavior change yet. ## New sources on `panelPage` ```ts { source: "activity", missionID, actorOffset?, actorOrder?, cursor? } { source: "marks", missionOffset?, missionOrder?, cursor? } ``` - Activity: one named mission range, up to 160 actor roots. - Marks: up to 16 indexed mission contexts × 10 actors, sharing 160 roots. - RPC returns persisted `phase: "context"`; the owning HTTP backend validates it and observes native state outside the append lock, returning `phase: "observed"` with `observedAt`. - Rows carry context, honest coverage, real Form/permission requests and native activity. Actor windows make off-page requests reachable. - Range damage, graceful Pause/Interrupt now, retry identities and report-owed evidence are preserved. - Existing byte limits remain: **64 KiB per response**, **16 KiB per request**. Continuations re-observe and refuse changed content. No retained observation cache or automatic restart. Internal/authoritative reads, existing UI APIs and #926 metadata stay unchanged. Shared owed-work/task-attribution rules are reused by compact maps and projections. ## Measurements and validation - Warm marks across 50 missions: zero source scans. - A 31-root off-page window: 31 root GETs, 32 child lists, 32 inbox reads; one shared read each of active/Shells/Forms/permissions. - 800 exact requests: 22 transfers, maximum 65,536 bytes. - Thirteen red checks cover budgets, scope, coverage, ownership, saved Location, positive attention, uncertainty, digest, append lock, ordering, damage and receipt evidence. - Passing: typechecks; 1,507 server tests; 1,845 UI units; help; plugin build; isolated OpenCode 2.2.3 qualification. One existing environment-gated skip. No browser runs for this opt-in server-only surface. ## Remaining work UI adoption with per-window provenance, parked Retry and last-good display. Partial evidence must never become whole-mission absence or recovery authority. Native request lists still arrive whole per Location, and re-observation/source serialization can be expensive; busy sources may refuse continuations repeatedly.
This was referenced Nov 1, 2026
pascalandr
added a commit
that referenced
this pull request
Nov 1, 2026
First UI adoption slice of panelPage (#1246 and #1249). Selected task windows, attention windows and named task/report reads now use the 64 KiB panel-page transport instead of the legacy task GET route. Picker discovery, selected maps, activity and cleanup display still use the existing mission list; this slice does not complete list boundedness. Add a browser-safe task-page consumer that checks actual response bytes before parsing, validates the complete envelope and requested selector, pins digest, total length and provenance across contiguous slices, and verifies the final UTF-16LE collection hash before publishing a window. Requests stay within 16 KiB. Each logical read uses the secondary-read budget and a 30-second deadline; no automatic cursor restart or legacy task-route fallback is introduced. Keep last-good rows and toolbars on failures. Changed content receives a distinct localized message; explicit Retry begins at the first slice. The task store clones queued selectors and fences reads against owner, project/client generation, reconnect and plugin changes. Obsolete slices never publish, and unwanted missions do not acquire revision-driven reads. Admission and all native mutations remain untouched. Update help in all ten locales for the changed-page retry, and add browser-independent contract tests to CI alongside the store/browser regressions. Eleven red checks cover byte/digest/length/header validation, stale reads, reconnect, parked failures, changed messaging, queued owners, unwanted revision reads and immutable selectors. Measured fixture: 151 tasks, four logical windows, seven HTTP transfers, maximum 65,536 bytes, zero legacy task GETs and zero mutations. Root/UI and server typechecks, actual UI production build, 1,865 UI/contract tests, 1,520 server tests, 456 serial browser cases and help checks pass. No server product code changes in this slice; existing isolated native qualification remains unchanged.
pascalandr
added a commit
that referenced
this pull request
Nov 1, 2026
First UI adoption slice of panelPage (#1246 and #1249). Selected task windows, attention windows and named task/report reads now use the 64 KiB panel-page transport instead of the legacy task GET route. Picker discovery, selected maps, activity and cleanup display still use the existing mission list; this slice does not complete list boundedness. Add a browser-safe task-page consumer that checks actual response bytes before parsing, validates the complete envelope and requested selector, pins digest, total length and provenance across contiguous slices, and verifies the final UTF-16LE collection hash before publishing a window. Requests stay within 16 KiB. Each logical read uses the secondary-read budget and a 30-second deadline; no automatic cursor restart or legacy task-route fallback is introduced. Keep last-good rows and toolbars on failures. Changed content receives a distinct localized message; explicit Retry begins at the first slice. The task store clones queued selectors and fences reads against owner, project/client generation, reconnect and plugin changes. Obsolete slices never publish, and unwanted missions do not acquire revision-driven reads. Admission and all native mutations remain untouched. Update help in all ten locales for the changed-page retry, and add browser-independent contract tests to CI alongside the store/browser regressions. Eleven red checks cover byte/digest/length/header validation, stale reads, reconnect, parked failures, changed messaging, queued owners, unwanted revision reads and immutable selectors. Measured fixture: 151 tasks, four logical windows, seven HTTP transfers, maximum 65,536 bytes, zero legacy task GETs and zero mutations. Root/UI and server typechecks, actual UI production build, 1,865 UI/contract tests, 1,520 server tests, 456 serial browser cases and help checks pass. No server product code changes in this slice; existing isolated native qualification remains unchanged.
pascalandr
added a commit
that referenced
this pull request
Nov 2, 2026
…1264) Main **bounded-inventory UI adoption** following #1246, #1249 and #1250. The live panel now uses `createMissionPanelInventory` → `fetchMissionPanel`; public `fetchMissions` fan-out is removed. ## Contract and UI - Independently verifiable 50-row directory/field windows: echoed `{order,offset,end,total}`, window content digest, collection-order continuation fence. - Inventory summaries carry actor counts. A selected header excludes whole actor/receipt/task collections; those are separately paged. Native-scheduler `document`, cleanup `documentPending` and history `requestID` survive. - Initial durable `finishHighWater` is captured before discovery and seeds once: later-discovered old completions stay seen; new completions above the fixed baseline stay unseen, including deletion/purge counter gaps. - Explicit Show more/Retry for summaries, cleanup, fields, marks and actors; loaded-only search. Selected/reader identities work outside the first inventory page and do not wait for stalled discovery. - Last-good display, owner/generation/page-revision fencing, failed-middle Retry, no automatic changed-cursor restart. Separate actor observations never become atomic whole-mission absence or recovery authority. - Exact cleanup retry/lost-ACK identity preserved. Snapshot/admission/internal/mutation authority stays full. No mass snapshot fallback. - All ten help locales updated. Every response stays within **64 KiB**, request within **16 KiB**; logical reconstruction has explicit budgets/deadlines before allocation and publication. Native per-Location lists and producer-sized enumeration/hash costs remain disclosed. ## Measurements - 50/120 summary rows: 11,915 bytes, one transfer, zero warm range/map reads. - Valid 601-actor selected header: 3,226 bytes. - Explicit actor continuation: 160 root observations, largest measured body 61,471 bytes. - All 2,101 pending cleanups reachable; initial finish baseline remains fixed during new completions. - Notes-only revision: one wanted header, no task transfer or expanded-task reread. ## Qualification fixes included - Directory-only project Location omitted `workspaceID:undefined`, which strict document CAS rejects; adapter now omits only an absent optional field. Regression verifies directory-only and supplied-workspace placement without weakening validation. - Missing edit still returns mission-not-found/404. - Native document-cleanup receipts/replay are checked exactly; safe help-fixture link teardown and a data favicon fix remain test-only. ## Validation and recovery disclosure Implementation recovered after another session's dependency-junction cleanup deleted the original worktree. Tracked changes came from saved Git state; nine new sources were reconstructed from 137 archived successful operations and nine read checkpoints. All sources were checkpointed, then qualified in a new independently installed worktree. Original/evidence/recovery checkpoint remain untouched. Passing: typechecks, real UI build, 1,322 UI tests, 1,381 server tests plus one optional skip, 615 latest-complete serial browser cases, 31 help checks, plugin rebuild and 21 isolated OpenCode 2.2.3 gates. Twelve negative controls caught/restored. This is not a claim that the initial browser sweep was entirely green: one extension-fixture activation failure passed two fresh full-file reruns unchanged. Test manifests are explicit/nonempty; no borrowed dependencies or implicit Node discovery. Qualification report/provenance retained by the coordinator. Current-passage compaction (slice 5) remains the next separate work; scheduler #1259 is already merged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
First server-contract slice of 4b, following #1241. This PR adds an opt-in byte-bounded read; the UI still uses its existing APIs. Panel-level boundedness is not complete yet.
Contract
panelPageRPC andPOST /api/workspaces/:id/missions/panel-page.document,documentPending,requestID) survives serialization.Measurements
Validation
Eight red checks cover byte accounting, cursor integrity, source scope, selector bounds and forbidden fan-out. Passing: typechecks; 1,498 server tests; 1,845 UI units; 409 serial browser cases; help; plugin build; isolated OpenCode 2.2.3 native gates. One existing environment-gated test skipped.
Remaining 4b work
Bounded live activity/attention for off-page actors and nonselected missions, UI adoption with per-page caches/discovery/completion seeding/cleanup retries, then removal of old list fan-out. Each transfer currently serializes/hashes its source collection afresh, with linear per-transfer CPU cost.