Repository navigation
ui-server: design bounded storage growth history and low-space guidance #2014
Description
Context
Part of #1779. Follow-on implementation from #1782, whose S1=A, S2=A, S3=A, S4=B and complete-design approval are settled. Read docs/decisions/design-kit/storage.md (introduced by the #1782 design-finalization PR), docs/plans/storage-accounting.md, docs/plans/storage-lifecycle.md, docs/decisions/native-brain-storage.md, and ROADMAP.md's binding decisions. No implementation slice may publicly register an interim read-only Storage pane; first pane delivery includes safe binary removal and the complete journey.
Source checked at 04ef3552190d8f56eab09dd6c3580101b6385ba4:
snapshotOf, packages/core/src/lib/stats-history.ts:132-172, and thin, the same file:232-244, retain corpus history rather than server capacity evidence. freeSpaceBytes, packages/core/src/lib/stats.ts:213-224, supplies caller availability. Accounting discovery supplied the initial sizing candidates; the reconciled ruling below supersedes their record allocation while retaining the 256 KiB payload ceiling.
Out of scope
No production alerting, polling, history persistence or retention-default changes. No core stats contract reuse, per-file inventory history, automatic cleanup, capacity-provider seam, journal/backup expiry or reopening approved S1-S4.
Scope
Produce the separately deferred growth/low-space design: bounded aggregate history, sampling/refresh cost, comparable scopes, signals and useful next actions. Initial Storage delivery retains explicit refresh and operation-triggered measurements; this work does not block that delivery.
Acceptance criteria
- Specify server ownership, exact aggregate fields and schema/version provenance, sample/byte limits, cadence/coalescing, replacement/thinning and measurement costs; account for history storage itself.
- Define comparability across basis, coverage, root/capacity changes and unknown/partial samples. Insufficient evidence yields no growth rate or exhaustion estimate, never zero.
- Draw capacity-specific low-space/growth states at 320px and desktop, with refresh age and affected write targets. Headroom-consuming operations remain clearly identified; refusal/manual capacity provision is a legitimate outcome.
- Apply the approved policy below in the proposal and durable decision record, recording alternatives and tradeoffs. Qualify warning entry/recovery and notification lifecycle, including refusal recovery, missing evidence, timezone/clock changes, tier scheduling anchors, revocation, deduplication/restart and deferred delivery without recurring reminders. File native server-history and UI-guidance implementation children of Epic: understand and manage brain repository and deployment storage #1779 with exact criteria/contracts and failing-first/runtime/browser proof obligations. This issue produces the revised design, not production implementation.
- Explicitly defer remote/provider usage, host/container stores, per-file Git attribution, derivative grouping, workspace cleanup and new expiry/retention policy; explain which evidence/ruling would justify a separately scoped proposal.
Verification
Synthetic Odysseus traces with steady growth, bursts, reclamation, capacity/root change, partial/unknown observations, retained-only pressure and concurrent writes. Show candidate sample-storage cost and decision examples, wireframes and accessible state copy. No paid/provider access or actual cleanup. Docs preflight; implementation runtime/browser proof belongs to later issues.
Contract impact
None in this spike. Future server history/HTTP/config additions need separately scoped additive contracts and consumer changesets.
Delivered design prerequisite: #1782 (closed through #2015).
Approved reconciled policy and qualified design
Decision (maintainer, 2026-10-16), reconciled bundle: Approve the merged direction after explicitly comparing the PR #2044 bundle with the concurrent detailed rulings.
- Retain 64 six-hour, 90 daily and 32 weekly observations (186 total), from the same scans and transactions. This replaces both the 128-total-slot proposal and the 128-recent/90-daily allocation. Keep four historical capacities and the 256 KiB serialized-payload ceiling. Compact records/shared scope metadata must demonstrate the worst-case bound before implementation; physical SQLite/WAL overhead is reported separately.
- Preserve actual endpoints, gaps and scope changes. Keep observed rates and sufficiently qualified short-/long-window capacity exhaustion scenarios; differing scenarios are not confidence intervals. Define and synthetically qualify exact evidence rules before implementation readiness.
- Keep 10%/5% direct capacity thresholds with 12%/7% recovery margins, and the recorded 30-day/7-day forecast entry and 45-day/10-day recovery rules. Missing forecasts cannot suppress direct warnings or clear active causes. Two qualifying fresh observations at least 60 seconds apart remain required for recovery.
- Show Storage warnings and the persistent app indicator. Use existing authorized, opt-in Web Push subscriptions for one Critical notification per capacity episode per subscription, durably deduplicated. Suppress stale deliveries and introduce no recurring reminders initially. This explicitly replaces the earlier daily-reminder selection. Preserve the compatible strict device-local 22:00–08:00 quiet-hours ruling for initial notices and bounded retries; unknown timezone is not guessed.
The user approved this reconciled recommendation in the implementation session. The compatible later forecast-window ruling selects 7-day and 30-day windows. Either qualified forecast within 30 days can enter Low; both within seven days can enter forecast-driven Critical. Recovery uses 45-day and ten-day margins with the same either/both distinction, every active cause and two qualifying fresh observations at least 60 seconds apart. An owner-confirmed no-space refusal independently enters Critical; unknown evidence cannot erase it.
Use existing owner-authorized, opt-in Web Push subscriptions and revocation. Generic authenticated content access does not grant operational-storage visibility. The pane and indicator remain usable if push is unavailable or declined. Initial notices and bounded retries observe strict device-local [22:00, 08:00) quiet hours; unknown timezone defers delivery. Revalidate current authorization, severity, episode and freshness before dispatch. A transport receipt does not prove device display, and ambiguous outcomes are not automatically replayed. There are no daily reminders in this reconciled initial scope.
The earlier 128-total-slot and 128-recent/90-daily allocations, no-forecast/in-pane-only proposal and daily-reminder selection are historical where they conflict with this approved bundle. The original comments preserve those rulings. The later 7-day/30-day ruling refines the reconciled forecast design; it does not reselect the superseded retention or recurrence options.
Delivered design and implementation boundary
The revised proposal, offline qualification experiment and durable docs/decisions/storage-guidance.md record were delivered in #2060 at squash fec9a379da878c59d2e7577c6c940dc6ee5d4a03. Native #1779 implementation issues #2058 (server history/state/delivery) and #2059 (UI guidance) carry the reconciled specification and runtime/browser proof obligations. The initial complete pane #2009–#2013 remains independent of this extension. This closed spike does not claim production history, notifications or cleanup; implementation remains in the authorized Storage delivery chain.
2026-10-16 qualification: compact four-capacity maximum-width sample is 901 bytes; enforced design caps total 255,419 bytes, including 186 samples and dictionary/singleton framing. Offline traces retain 217 days of weekly endpoints and exercise short/long evidence, gaps, scope/total changes, bursts, reclamation, cause recovery and deduplicated/quiet-hours delivery. Runtime/physical-overhead proof is explicitly assigned to implementation. Native #1779 children #2058 (server history/state/delivery) and #2059 (UI guidance) carry the reconciled rules and required proof; initial #2013 remains independent.
2026-10-17 correction: removed a concurrently appended, superseded policy section that still selected 128 recent samples, no weekly tier and daily reminders. The body now agrees with the approved reconciled ruling, compatible later forecast windows, delivered decision and implementation children. No policy is newly selected and no historical comment is removed.
Activity
schlessera commentedon Oct 16, 2026
Claiming the independently scoped growth/low-space design while the core inventory implementation completes hosted proof. Claim token: storage-2014-20261016-b8d5. Intended branch:
docs/2014-storage-growth-b8d5. This produces a bounded proposal and explicit policy decisions; it does not activate production sampling or alerts and does not block the approved initial Storage pane.schlessera commentedon Oct 16, 2026
The scoped proposal and synthetic qualification are in #2020. It defines exact aggregate fields, global payload/sample/scope bounds, sampling cost, comparison gaps, observed rates, capacity-specific states and 320px/desktop layouts. The worst-case synthetic sample is 1,717 bytes; the proposed retained payload ceiling is 231,424 bytes. DB/WAL physical overhead remains separately measured.
The proposal does not approve production policy. The maintainer choices are six-hour sampling with the bounded ring versus explicit-only refresh; observed endpoint rates without exhaustion estimates versus deferred growth; and in-pane 10%/5% guidance with 12%/7% hysteresis versus capacity/refusal figures alone. Once the ruling is recorded, the follow-on server and UI issues can carry its exact rules. This does not block the approved initial pane in #2009–#2013.
13 remaining items
schlessera commentedon Oct 16, 2026
Decision (maintainer, 2026-10-16), warning recovery: Choose option C: recovery margins plus two qualifying fresh observations at least 60 seconds apart.
Recovery evidence for an owner-confirmed no-space refusal must be explicit in the revised design; a missing reading must not erase it. Extend synthetic qualification to cover competing causes, threshold oscillation, failed refresh, missing projections and recovery following refusal.
Notification scope remains open. Retain
needs: decision; the revised design, exact forecast evidence rules, durable record and implementation issue finalization remain required.schlessera commentedon Oct 16, 2026
Decision (maintainer, 2026-10-16), notification scope: Choose option D, explicitly correcting the initial B answer before it was recorded.
Show warnings in the Storage pane and a persistent app indicator reflecting the highest active severity across capacities, with details and actions in Storage. Add outward notifications for Critical so an owner may be reached while the app is closed. This supersedes the original in-pane-only proposal.
No delivery channel, recipient/subscription authority, reminder cadence or repeated pop-up behavior has yet been selected. Specify Critical episode identity, deduplication, stale-delivery/recovery behavior and delivery privacy, reusing existing notification machinery where appropriate. Selecting a feature does not authorize sending a notification during this decision review.
Exact forecast windows/evidence rules and notification delivery policy remain to be resolved; retain
needs: decision. Revise and qualify the proposal and durable decision record before implementation readiness.schlessera commentedon Oct 16, 2026
Decision (maintainer, 2026-10-16), Critical delivery channel: Choose option A: existing authenticated Web Push subscriptions.
Reuse the existing concrete push transport, opt-in device subscriptions and revocation machinery. Storage visibility and push delivery must remain within authorized owner access; a generic authenticated content reader must not gain operational storage information through notifications. No new email/webhook channel or extension seam is selected. The Storage pane and persistent app indicator remain available where push is unavailable or permission is declined.
Critical episode/destination deduplication, recurrence and timing remain to be selected. Existing Action-specific priority/batching policy does not automatically apply to storage warnings. Exact forecast windows/evidence rules also remain to be specified. Retain
needs: decisionpending the remaining policy rulings. No notification is sent as part of this review.schlessera commentedon Oct 16, 2026
Decision (maintainer, 2026-10-16), Critical notification recurrence: Choose option B: one initial notification, then daily reminders while Critical remains active.
Persist episode and per-eligible-device submission history so repeated scans, refreshes, process restarts and bounded delivery retries do not duplicate successful submissions. Reminder state is per affected capacity episode; the delivery design may coalesce multiple due capacities without losing coverage. Confirmed recovery stops reminders; a later Critical episode can notify again. Revalidate current severity and authorization before sending, and do not issue a backlog of missed reminders. Stale or unknown evidence must not be advertised as fresh confirmation of Critical pressure.
Quiet-hour/timing policy remains to be selected. No extra material-worsening notification stream or new delivery channel is selected. Exact forecasting evidence rules and revised design/qualification remain required; retain
needs: decision.schlessera commentedon Oct 16, 2026
Decision (maintainer, 2026-10-16), Critical delivery timing: Choose option A: all storage pushes observe strict local quiet hours from 22:00 inclusive until 08:00 exclusive, evaluated per eligible device.
Apply quiet hours to initial Critical notifications, daily reminders and every retry, with no forecast or actual-refusal exception. Reuse authenticated destination timezone reporting and retain the existing conservative behavior for a missing/unusable zone. Revalidate authorization, episode state/severity and evidence freshness before deferred delivery. Consolidate due notices without replaying a backlog of missed reminders. The Storage pane and persistent indicator remain available during quiet hours.
Specify the exact daily scheduling anchor, clock/timezone-change behavior and per-destination receipts in the revised design under these constraints. Exact forecasting windows/evidence rules remain to be selected; retain
needs: decisionpending that ruling and do not treat the old no-forecast/in-pane-only proposal as current approval.schlessera commentedon Oct 16, 2026
Decision (maintainer, 2026-10-16), reconciled bundle: Approve the merged direction after explicitly comparing the PR #2044 bundle with the concurrent detailed rulings.
The user approved this reconciled recommendation in the implementation session. The remaining work is design qualification, durable documentation and scoped implementation issues, followed by the implementation chain already authorized. Initial Storage #2009–#2013 remains independent. No notification is sent by this policy review.
schlessera commentedon Oct 16, 2026
Claim storage-2014-20261016-e1a8: recording and qualifying the approved reconciled policy on branch docs/2014-reconciled-growth-e1a8, then filing the authorized implementation chain.
schlessera commentedon Oct 16, 2026
Decision (maintainer, 2026-10-16), forecast windows: Choose option B: compare 7-day and 30-day observation windows.
This completes the policy questions in this review. The body now consolidates all selected rules and supersedes the old no-forecast/in-pane-only/128-total-slot proposal. Earlier choice comments remain the decision history. Design criteria affected by the changed policy are reopened rather than claimed complete.
Remove
needs: decisionand addagent-readyfor the existing design spike. Its remaining work is the revised proposal, synthetic qualification of evidence/estimator/lifecycle parameters, durable decision record, indicator/notification design and exact implementation-child filing. A spike that produces the design is not blocked awaiting that same design. This does not authorize production implementation or claim runtime proof; it does not block the initial Storage pane.schlessera commentedon Oct 16, 2026
Delivered the reconciled, explicitly approved growth/low-space design in #2060, squash
fec9a379da878c59d2e7577c6c940dc6ee5d4a03. The durable decision, compact-history feasibility experiment, forecast qualification, severity/recovery and one-notification-per-episode rules are recorded. Implementation is filed as #2058 and #2059 under #1779 and remains part of the requested delivery chain.PR run 38879395172 passed all selected proof on checkout
2ead203dcbc3e5cff5911ccdf92c91777d25ea59, with parentsabe5086df48883bc270a36edb127b05519398332anddb7b80395ed5328e90177ebd1d1630a9e918c7ae, treeb66c9651b2b71ca99406417759c7afca22ad77d7. The matching-head squash retained that parent and tree and is on main. Automatic main-push run 38880333446 also passed every selected job; checkout logs from changeset 116905257004, verify 116905486047 and proof 116905636886 identify the actual squash. Other runtime categories were intentionally unselected for this design-only change. PR and issue retain milestone 0.44.0; the spike is closed, without claiming production implementation.schlessera commentedon Oct 17, 2026
2026-10-17 consistency correction: the body still contained a second policy section selecting 128 recent samples, no weekly tier and daily reminders after the approved reconciled section. It now consistently specifies 64 six-hour / 90 daily / 32 weekly observations and one Critical notice per episode/subscription, matching the approved reconciliation, #2060 and
docs/decisions/storage-guidance.md.The compatible later 7-day/30-day forecast-window ruling, warning/recovery rules, strict quiet hours and authorization remain. The original comments preserve decision history. This is a body correction under the existing approval, not a new ruling, reopened spike or claim that the implementation has merged.
schlessera commentedon Oct 17, 2026
The policy consistency audit found a concrete #2058 defect: the long scenario still capped observations at 28 days, although the compatible later maintainer ruling selects 7-day/30-day windows. PR #2172 now includes correction
4440e0f9b, aligning the implementation, design experiment, specification, durable decision and user documentation. Existing 64/90/32 retention, sample/byte limits, evidence minimums, sampling cost and warning/delivery policy are unchanged.Failing-first evidence:
STORAGE_LONG_SCENARIO_USES_30_DAY_POLICYdrops two eligible daily endpoints under the old limit. The independent design trace returns 47 days instead of 45.483870967741936 under the old limit. Both pass after the correction; 62 history/pressure/citation tests pass with 213 assertions. The regression checks included/excluded endpoint effects and the exact 30-day boundary. Lint and the complete pending changeset plan pass (all 19 packages minor).The earlier
4376cf9cdpreflight was intentionally interrupted before its speech-bundle stage because this correction changes the delivery candidate; its 950 passing fast checks are preserved without claiming a complete pass. All 10 owned processes exited without forced cleanup. Full preflight is now running on4440e0f9bagainst unchanged main85873db77, with the bundle observations intact. This is a policy correction, not a diagnosis or repair of #2334; its historical failed receipt remains.