docs: reconcile demand-driven-hosting design doc to settled model#4736
Draft
sanity wants to merge 2 commits into
Draft
docs: reconcile demand-driven-hosting design doc to settled model#4736sanity wants to merge 2 commits into
sanity wants to merge 2 commits into
Conversation
The design doc (merged via #4659, "LOCKED 2026-07-01") predated a week of confirmed decisions (2026-07-02..07-08) and carried one outright-wrong claim. Reconcile it against the newer ground truth in .claude/rules/hosting-invariants.md and the build spec. Corrections: - Section 9, Piece H: fix the wrong claim that the redesign is "behavioral, not a wire-format change." R3/R4 add version-gated wire changes (summary-first PUT message, a subscribe flag on GET/PUT, and the SUBSCRIBE variant repurposed as Renewal), engineered non-breaking (variants kept, new surfaces version-gated), not zero wire change. - Section 9: add the SUBSCRIBE-retirement piece (R4, step 10) that the doc omitted entirely: subscribe-flag-on-GET/PUT, standalone SUBSCRIBE deprecated-not-deleted and repurposed as Renewal, client ContractRequest::Subscribe preserved via a deprecation adapter to GET-with-subscribe. - Section 9, Piece A: replace the stale eviction model. Eviction is now ONE demand-ordered decision over ascending (local_subscription_count, downstream_subscriber_count, recency, key bytes); no separate admission, no OOM valve, no displacement-chain cap. Reads and PUTs are a permanent demand signal (River UI / web containers, read but never subscribed, must stay hosted), reversing the old "heavily-read = transient cruft, superseded by subscribe-implies-pinned" framing. Subscriptions outrank reads (recency clock starts at subscription termination); a subscribed contract IS evicted when nothing ranks lower; min_ttl dropped. - Section 9, Pieces B/E: no separate admission (emergent from the single eviction); every-hop placement is already live (v0.2.93); #4664 removes the durable-regardless-of-demand copy, not the every-hop store. - Section 1 and Section 10: routed GET/PUT reads are a third demand source (every-hop placement under the gauge), reconciled with the no-durable-regardless-of-demand rule. - Section 5d: reconcile the admission-refusal framing to the emergent single-eviction model (no NACK). Refs #4642, #4659. [AI-assisted - Claude] Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0199hK8Vdn5DAWcXJsxZHk8H
Fold two follow-ups into the demand-driven-hosting reconcile. 1. Move the authoritative build spec into the repo. It lived in an ephemeral ~/code/tmp path that gets deleted, so copy it to docs/design/hosting-spec.md, add a header marking it the build-spec companion to demand-driven-hosting.md and noting that .claude/rules/hosting-invariants.md (the most-current synthesis) wins on any conflict, and reference it from the design doc's header plus the "build spec" mention in section 9. 2. Resolve the section 5a/6 renewal-gate underspecification. Decision 1 (GET/PUT reads are a permanent demand signal) plus the shipped #4725 renewal-gate fix make interest-gated renewal include recent real GET/PUT access. Update the renewal/keep-hosting predicate from "local client OR strictly-farther downstream" to "local client OR strictly-farther downstream OR recent real GET/PUT access" in sections 5a, 5d(a), 6, and the section 10 summary of demand-driven-hosting.md, and in the interest-gated-renewal definition of hosting-spec.md. The stop-hosting gate stays the exact inverse. A read-only/PUT-only never-subscribed contract (River UI / web containers) is kept renewed by its GET/PUT recency, per invariant 3. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0199hK8Vdn5DAWcXJsxZHk8H
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.
Problem
docs/design/demand-driven-hosting.md(merged via #4659, marked "LOCKED 2026-07-01") had drifted behind a week of confirmed design decisions (2026-07-02 through 07-08) and carried one outright-wrong claim. It is the canonical WHY-and-HOW reference the invariants file points at, so a stale copy misleads future agents touching hosting/eviction/subscription code.Approach
Reconcile the doc against the newer ground truth, in priority order:
.claude/rules/hosting-invariants.md(updated all week with Ian's confirmed decisions)hosting-spec.md)This is a reconciliation, not a rewrite: sections 2, 3, 4, 5a-5c, 6, 7, 8 (the subscription-chain / computed-upstream / renewal / collapse mechanics) are still current and untouched. Fixes concentrate in Section 9 (the redesign-piece references, where the stale eviction/admission/wire claims live) plus light touches on Sections 1, 5d, 10.
Corrections
subscribeflag on GET/PUT, and the standalone SUBSCRIBE variant repurposed asRenewal). They are engineered non-breaking (variants kept + repurposed, new surfaces version-gated), which is not the same as no wire change.subscribeflag; standalone SUBSCRIBE deprecated-not-deleted and repurposed asRenewal(variant kept for bincode/wire-compat); clientContractRequest::Subscribepreserved via a deprecation adapter to GET-with-subscribe; it IS a version-gated wire change.(subscriber_count, last_get_seq)ranking and the "gradation bites at admission + OOM valve" framing with the settled model: ONE demand-ordered decision over ascending(local_subscription_count, downstream_subscriber_count, recency, key bytes); no separate admission, no OOM valve, no displacement-chain cap; a subscribed contract IS evicted when nothing ranks lower;min_ttldropped.Testing
Docs-only change; no code touched. Style checked: no em-dashes and no "not X, but Y" antithesis in added prose.
Flagged as uncertain (left unchanged)
The interaction between reads-as-demand and the Section 5a/6
contract_in_userenewal gate is underspecified in the ground truth: the build spec still defines interest-gated renewal as (local client OR downstream subscriber), while the newer invariants say reads/PUTs also keep a contract "renewed in the update mesh." I did not invent a resolution, so Sections 5a/6 (and the corresponding clause in the Section 10 summary) are left as-is. This should be pinned before the renewal code is touched.Refs #4642, #4659.
[AI-assisted - Claude]