Delivery indicators: how work reaches main, per week and per unit
GET /delivery is a gated, read-only page (plus a JSON twin) and delivery report its command twin on every surface: for one repository, the leading indicators of agent-run development computed from facts the system already keeps — GitHub's record of the merged pull requests (their reviews, pushes, workflow runs and the board issue each links) and the run history — grouped by Monday-start week and by unit (a board issue). Nothing is written to GitHub: its facts are read on an interval and kept as one snapshot per repository on the state Worker, every load serves that snapshot and says how old it is (?fresh=1 on the page, --fresh on the command, read GitHub now), the run history joins live on every load, and the arithmetic is one pure function a recorded trunk pass pins.
- Code:
src/core/delivery.ts(buildDeliveryReport,indicatorsOf,parseFindings,coauthorsOf,weekStartOf,weeksOf,resolveDeliveryRange,pullRequestOfRun,runFactsOf,renderDeliveryReport,snapshotAgeText,parseDeliveryConfig+SNAPSHOT_EVERY_MINUTES,REPO_SLUG,DeliverySource+DeliveryFetch+InMemoryDeliverySource,DeliveryService+createDeliveryService+NullDeliveryService);src/core/deliverySnapshot.ts(SnapshottingDeliverySource— the Decorator over the GitHub source that serves, refreshes incrementally and keeps the snapshot, with itsstartRefreshLoop;mergeSnapshot— the pure merge of a read into the snapshot;SNAPSHOT_WEEKS,SNAPSHOT_TICK_MS,REFRESH_OVERLAP_MS,snapshotAgeMinutes);src/core/deliverySnapshotStore.ts(DeliverySnapshot+DeliverySnapshotPatch+isDeliverySnapshot+isDeliverySnapshotPatch+isPullRequestFacts+applyPatch— the documents the bot and the Worker validate alike;buildDeliverySnapshotStorefinds the state Worker throughsrc/core/stateWorkerRef.ts(stateWorkerOf,StateWorkerBlocks,SecretReader— shared with the costs snapshot store);DeliverySnapshotStore+InMemoryDeliverySnapshotStore+WorkerDeliverySnapshotStore;buildDeliverySnapshotStore);src/execution/githubDelivery.ts(GithubDeliverySource+DEFAULT_MAX_PULL_PAGESand its pure parsersparsePullListPage,selectMerged,parseTimeline,parseWorkflowRuns,firstHeadOf,linkedIssueNumber,parseIssue);deploy/cloudflare-memory/worker.ts(DeliveryDO,POST /delivery/get|put|merge) anddeploy/cloudflare-memory/wrangler.template.jsonc(DELIVERYbinding, migrationv8);src/core/commands/delivery.ts(delivery.report);src/channels/deliveryView.ts(parseDeliveryRoute,createDeliveryViewHandler— serves the shared web shell with aDeliverySeed, see live-view.md's Rendering paragraph); the page inweb/:web/green/pages/Delivery.vue,web/src/lib/delivery.ts,web/green/routes.ts(the/deliveryroute beside the others — the router only mounts the page the shell was served for), thedeliverysection ofweb/green/lib/navigation.ts(the nav's list, whichweb/green/components/Shell.vueand the shell read);src/core/commandCatalogue.ts(deliveryFromConfig— the one service the page and the command share, and the snapshot source the bot's loop refreshes);src/index.ts(builds the store and the service from thedelivery:block, starts the refresh loop for the configured repositories, gates/delivery*beside/runs*,/residents*and/costs*);src/core/authz/policy.ts(thedelivery:readrow). - Tests:
src/core/delivery.test.ts(the arithmetic over the recorded trunk pass and its edges; the config, the service's stamp, the text),src/core/deliverySnapshot.test.ts(the snapshot source and its refresh loop over a hand-moved clock),src/core/deliverySnapshotStore.test.ts(the document guard, both stores, the store selection),deploy/cloudflare-memory/delivery.test.ts(theDeliveryDOroutes in workerd),src/execution/githubDelivery.test.ts(the parsers over the API's recorded shapes; the source over an injected fetch),src/core/commands/delivery.test.ts,src/channels/deliveryView.test.ts(routing + seed),web/src/pages/delivery.test.ts(rendering),src/core/authz/policy.test.ts(the command's row),web/green/pages/personalReports.test.ts. - Docs: Code map, dashboard routes, Turn features on and off (the
githubrow), costs.md (the sibling gated page whose shape this one takes), command-registry.md (item 28: the command's capability), agent-review.md (the verdict format the findings are read from), run-history.md (the state Worker the snapshot store shares).
Configuration
delivery:
repos: [acme/api, acme/web] # the page serves these; the first is its default
reviewers: [] # logins whose reviews are verdicts, beside the App's own identity
agentLogins: [] # agents beyond the `[bot]` suffix
agentCoauthors: [Claude] # `Co-Authored-By:` names that mark a commit as an agent's
snapshot:
everyMinutes: 60 # minutes between two reads of a repository's facts (5–1440; default 60)The page and the command need the github capability (the App triple or GH_TOKEN): every read is the App's read-scoped installation token. Without the block the command still answers --repo owner/name; the page answers 503 naming the block. A malformed block throws at startup. The snapshot lives on the state Worker whichever *.worker block names it (runtimeOverrides.worker, runHistory.worker, schedules.worker or memory.worker, the same MEMORY_TOKEN bearer — the snapshot is a cache and earns no block of its own); without one it is kept in memory, a restart loses it and the process says so at startup.
Behavior
- Four indicators and the plain counts, one pure function.
buildDeliveryReporttakes the merged pull requests' facts and the runs, and returns per-week rows, per-unit rows, per-pull-request rows and the totals, each carrying the sameDeliveryIndicators: pull requests merged and how many were agent-authored (the author is a[bot]login or a configured agent login); issue → merge as the median and mean hours from the linked board issue's opening — or the pull request's own opening when none is linked — to the merge; first-pass CI as passed / known, where a pull request passes when every decisive pull-request-triggered workflow run (pull_requestorpull_request_target; apush-triggered run on the branch is not the pull request's own check and is never judged) on its first head concludedsuccessat attempt one, fails on any red run or any rerun, and is not counted when no such run exists; review rounds as the review agent's verdicts (reviews by a configured reviewer login — the App's own identity by default) per reviewed pull request, with the fix rounds (a verdict that followed a push since the previous verdict; a re-verdict with no push is a disposition, not a fix); findings by severity from the verdict bodies'- [severity] F<n> …lines (blocking,major,minor,nit,fyi;blockerreads asblocking; prose repeating a finding is not one), the blocking ones being the count the plan asks for, and the no-human-edit share — the findings on pull requests where every push after the first verdict was an agent's, over all findings; and the agent runs the history keys to the pull requests (count and minutes). A push is an agent's when its actor is a bot or configured agent login, or when a commit it carried names an agent co-author — the maintainer's own agent pushes under the maintainer's login, so the login alone would call every one of those human. The auto-approve identity's approvals are not verdicts. - Weeks start on Monday, UTC, and every week in range has a row.
weekStartOfputs a merge in the week of its Monday;weeksOflists every Monday from the week ofsinceto the week ofuntil, so a week with no merge is a row of zeros and nulls (median, share and per-PR ratios arenullwith nothing to divide), never an error. A pull request merged outside the range is left out. Rows come back in pull request number order; units in issue number order with the unlinked pull requests last under(no issue). - The range is
--weeksor--since, ending today.resolveDeliveryRange:weekscounts Monday-start weeks back from the current week (default 4, clamped 1..26);since(YYYY-MM-DD) names the first day instead and the week count follows from it; a malformed value is the default; a start after today is today. On the page,?weeks=and?since=are the same knobs; the command's--sincedecides when both are given. - The facts come from four GitHub reads per repository, read-only.
GithubDeliverySource: the closed pull requests newest-touched first, pages of 100 until a row last touched before the range began (a row's update time is never before its merge time, so nothing merged in range can follow) or the page cap (DEFAULT_MAX_PULL_PAGES, 8 pages — the newest 800 closed pull requests; a capped read costs the pages plus about three calls per merged row, under half of an App installation's 5,000 calls an hour, and only a first read orfreshreaches it) — the report saystruncatedwhen the cap ended the read. An incremental read (touched, the snapshot's refresh of item 10) goes back to the instant it names instead of the range's start: the first row touched before it ends the listing, and a listed row whose update time the caller already holds (known) is not read again — its facts stand. Each fact carries the listing'supdatedAt, which is what the next incremental read compares. Per merged pull request, its timeline (reviews with author, state, head and body; commits with theirCo-Authored-By:trailers; force-pushes with their actor, which carry the co-authors of the commits the timeline now lists, since GitHub records nothing of what a force-push replaced), its head branch's workflow runs (head, trigger, conclusion, attempt — a retry shows in the attempt, which a check suite does not record), and the board issue its body links (a closing keyword —closes,fixes,resolves— or aboard itemreference, followed by#<n>or the issue's URL in the report's own repository; a bare mention or the board's parent is not a link, and neither is another repository's issue URL, since the issue is read from the report's repository where that number is some other issue) for its creation time. The first head is the earliestpull_requestrun's head, else the earliest review's, else the current head. A 404 on the issue or on Actions is an absent fact; any other non-2xx throws with the status and a redacted, capped body. Every parser is pure and tested on the API's recorded shapes. The fetch also says from when it is complete (completeFrom): the range's start when the listing was exhausted or reached older rows (the instant it went back to, on an incremental read), the oldest update it reached when the cap ended it — a pull request merged after that instant was updated after it, so it is among the rows read — which is what lets a snapshot answer a narrower range without a falsetruncated(item 10). - The run history joins under the caller's own visibility. The runs the report keys are the caller's finished runs of the repository since the range began — listed under
predicateFor(actor, "runs:read", "run")exactly as the runs index decides, up to the list cap — and a run names its pull request through the…/pull/<n>in its label; a run of another repository or one naming no pull request adds nothing. A caller who may read no runs gets the pull requests' facts alone, never a refusal. The web handler asks the same question of the gate's identity. - One service for the page and the command; a Null Object without GitHub.
createDeliveryServiceresolves the range, fetches through itsDeliverySource(in production the snapshot source of item 10, handedfreshwhen asked), merges the identities (the config's under the process's — the App's login as a reviewer), builds the report and stamps it withsnapshotAt— when the facts were read: the snapshot's time, or now for a live read — and withcompleteFromwhen the source says from when its facts are complete (a bare source says nothing, and the report carries none);repos()are the configured repositories;unavailable()is undefined.NullDeliveryService(a process with no GitHub credential) has no repository,unavailable()says why, and refuses every report with the same reason. The page serves configured repositories only (an unknown one is 404); the command takes anyowner/name. delivery reporton every surface.delivery report [--repo owner/name] [--since YYYY-MM-DD] [--weeks n] [--fresh], actiondelivery:read, effect read, gated on thegithubcapability (hidden everywhere without it — command-registry item 28); the browser baseline holds every group's read, so a signed-in viewer runs it, a chat user needs the grant, adispatch-only token is refused. The bare form takes the first configured repository and isinvalid_inputnaming--repowhen none is configured; a repository that is notowner/nameisinvalid_input; the Null Object and an upstream failure areunavailablewith the reason;--freshreads GitHub now and refreshes the snapshot (item 10). The JSON is the report,snapshotAt,truncatedandcompleteFromin it; the text (render) opens with the repository, the range,as of <day> <hh:mm> UTC, <age>(just now,n minutes ago,n hours ago,n days ago) and — when the report is truncated —the newest N pull requests only, complete from <day> <hh:mm> UTC(the instant left out when the report names none), then one block per week — headedWeek of <Monday> (incomplete)when the week began beforecompleteFrom(weekIncomplete: the week holding that instant is partial, so it counts; a truncated report that names no instant marks no week) — merged, issue → merge, first-pass CI, review rounds, findings with the no-human-edit share, agent runs — then the units, in single-spaced lines chat carries as they are.- Routes.
/deliveryand/delivery.json→ the first configured repository;/delivery/<owner>/<name>and/delivery/<owner>/<name>.json; each segment is word characters, dots and dashes, never dots alone. GET-only (405 otherwise). No GitHub credential → 503 with the Null Object's reason; no repository configured → 503 namingdelivery.repos; unknown repository → 404; upstream failure → 502 with a capped reason, never a 500.?weeks=,?since=and?fresh=1pass to the service; the handler asks the service on every request and the service answers from the snapshot (item 10), so a page load costs no GitHub read unless it saysfresh. The JSON twin is exactly the seed's report,snapshotAt,truncatedandcompleteFromin it, servedno-store— the freshness is the snapshot's, not the HTTP cache's. - Page. The shared web shell with the report and the repository list as the
DeliverySeed;web/green/pages/Delivery.vuein the costs page's shape and tokens: the six tiles over the range (merged, issue → merge, first-pass CI, review rounds, no human edit, blocking caught) — over a truncated report a line says they coverthe newest N pull requests onlyand from when the read is complete, and the Merged tile's note counts the newest pull requests rather than the range's weeks — a table by week whose rows for the weeks that began beforecompleteFromare muted and marked(incomplete)with a note under the table saying what they hold (nothing is marked on a complete report, or on one that names no instant), a table by unit (issue and pull request links to GitHub), the range switch and the repository switcher, and in the footer — always in view —As of <Mon d, hh:mm UTC>, <age>with aread GitHub nowlink that keeps the page's own query and addsfresh=1(the age ticks by the minute while the page is open), then the method one click away with the identities judged by and the JSON twin named; hostile strings render as text (the seed island escapes every angle bracket; the components never render raw markup); the same hardened headers as/runs. The site nav lists Delivery whengithubis on (live-view.md item 18). - The snapshot: one window of facts per repository, refreshed incrementally on an interval, served to every request that fits. The
DeliverySourcethe service reads in production isSnapshottingDeliverySource, a Decorator overGithubDeliverySource(deliveryFromConfig): per repository it keeps oneDeliverySnapshot— the pull requests' facts over the widest range the page offers (SNAPSHOT_WEEKS= 13 Monday-start weeks ending today), each row with GitHub's update time,snapshotAt(when the last read began),truncatedandcompleteFrom— in memory and on aDeliverySnapshotStore. A request whose range starts inside the snapshot's window is served from it:buildDeliveryReportfilters the facts to the range as it always did (so the report is the one a live read atsnapshotAtwould have given),truncatedis whether the range starts beforecompleteFrom, and the report carries the snapshot'ssnapshotAtandcompleteFrom. A range reaching further back than the window (--sinceearlier than 13 weeks ago) is a live read over that range, stamped now, and leaves the snapshot alone. With no snapshot yet — the first boot of an installation, a repository just configured — the first request reads the newest rows of the window once (up to the source's page cap, item 4), stores them and is served from them; requests arriving meanwhile share that one read. A refresh is incremental (refresh): it lists the rows touched since the previous read began, lessREFRESH_OVERLAP_MS(ten minutes — room for a listing that lags or a clock that skews), hands the source the update times the snapshot holds so a row that has not moved is not read again (item 4), and merges the result into the snapshot — so the hourly cost follows the repository's activity (one listing call per hundred touched rows and about three per row that moved), not the window.freshreads the newest rows of the window whole again — the same read as the first — and merges those in. The merge (mergeSnapshot, pure, the same for a first read, a refresh andfresh): the read's rows replace theirs by number, the rest survive, and rows merged before the window's start are dropped; the snapshot is complete from the earlier of the twocompleteFrominstants when the read reached back to the previous read's time (they overlap), from the read's own reach when it stopped short of it (a gap it cannot vouch for — a capped listing after a long outage), and never before the window's start;truncatedis whether that instant is after the window's start. So a capped first read fills in by accretion as the weeks pass and heals once the window's start moves past itscompleteFrom, andfreshnever discards a row its capped read did not reach. The store is theDeliveryDOon the state Worker (WorkerDeliverySnapshotStore,POST /delivery/get {repo}→{snapshot | null},POST /delivery/put {snapshot}→{ok, prs},POST /delivery/merge {patch}→{ok, prs}or 404, the same bearer as memory and run history): one row per pull request under a meta row per repository, read back in pull request number order — a busy repository's window is many MB of review bodies and workflow runs, which is why it is rows and not one document. A first read is written whole (put: one transaction replacing the repository's rows); a refresh is written as its patch (merge: the rows re-read replace theirs by number, the numbers that aged out go, the meta is replaced, one transaction), so the hourly write is the change, not the window; a merge into a repository the Worker holds no snapshot for is refused (404 — a partial snapshot would claim a completeness it lacks), the client answers false, and the bot writes the snapshot whole instead. The Worker validates both shapes (isDeliverySnapshot,isDeliverySnapshotPatch, shared by relative import), refuses a repository that is notowner/nameand a pull request whose facts exceed a fraction of the row limit (413), and fences the request body at its own ceiling.InMemoryDeliverySnapshotStoreis the second implementation and the process's fallback without a state Worker. The store is read once per process per repository (memory answers after that) and written on every refresh. The refresh loop is the bot's own timer (startRefreshLoop, started insrc/index.tsfor the configured repositories; the CLI starts none and reads — on a first or--freshread, writes — the same store): a tick a minute, unref'd, runs once at start and then refreshes each repository whose snapshot is missing or older thandelivery.snapshot.everyMinutes(default 60, bounds 5–1440), one repository at a time — so a stale snapshot after a restart is refreshed at once and a young one is left alone, and no repository is read more often than the interval. It is not a schedule-registry entry: the interval is config, the Worker crons are static, and a refresh is a cache write, not a run. Failures degrade, never refuse: a store that cannot be read is an absent snapshot (a warning, then a read that computes and stores); a store that refuses a write is a warning — the snapshot in memory still serves and the next refresh writes again, whole when the store holds nothing to patch; a GitHub read that fails during a refresh is a warning and the snapshot keeps serving with its age growing until a tick succeeds; a GitHub read that fails with no snapshot to fall back on is the upstream failure of items 7 and 8.
Validation criteria
| # | Criterion | Proof |
|---|---|---|
| 1 | Over the recorded trunk pass (six merged pull requests in one week): the counts, the issue-to-merge medians and means from the board issue or the opening, first-pass CI five of six with the retried one failing, nine verdicts and two fix rounds (the disposition round counted as a verdict but not a fix), eight findings with two blocking all resolved with no human edit, the agent minutes keyed by label, one unit row per issue plus the unlinked row, and the week row equal to the totals (item 1) | [unit] src/core/delivery.test.ts::buildDeliveryReport — the trunk pass week::* |
| 2 | A range with no merges is rows of zeros and nulls; a merge outside the range is left out; a human push after the first verdict counts that pull request's findings against the share; a bot login or a configured agent login is an agent pusher, a push before the first verdict never a human edit; no verdict → no rounds, no findings, no judgement; first-pass CI unknown without a first head or a pull_request run and false on a red one; agent authorship by login; Monday-start weeks; identities and truncation carried (items 1, 2) | [unit] src/core/delivery.test.ts::buildDeliveryReport — the edges::* |
| 3 | Finding lines by severity, blocker folded, prose ignored (item 1) | [unit] src/core/delivery.test.ts::parseFindings::reads the review agent's finding lines by severity and ignores everything else |
| 4 | --weeks back from the current Monday, default 4, clamped; --since names the day and the count follows; garbage is the default; a future start is today (item 3) | [unit] src/core/delivery.test.ts::resolveDeliveryRange::* |
| 5 | A run keys to the pull request its label names, on the report's repository only (item 5) | [unit] src/core/delivery.test.ts::runFactsOf / pullRequestOfRun::keys a run to the pull request its label names, on the report's repository only |
| 6 | The text is one block per week then the issues (labelled Issues: — one row per board issue, record 0066), single-spaced; an empty week says so; a cut-short read is stated on the first line as the newest N pull requests only, complete from an instant when the report names one, and the weeks that began before that instant are headed incomplete — none on a complete report or one naming no instant (item 7) | [unit] src/core/delivery.test.ts::renderDeliveryReport::* |
| 7 | Config: absent → undefined; lists validated; malformed throws by name (Configuration) | [unit] src/core/delivery.test.ts::parseDeliveryConfig::absent → undefined; repos and identities validated; a malformed block throws by name |
| 8 | The service resolves the range once, hands it to the runs callback, merges identities, reports an unconfigured repository by name and refuses a malformed one; stamps the report with the source's read time, else now, and with the source's completeFrom when it names one, and hands fresh to the source; the Null Object has no repository and refuses with the reason (item 6) | [unit] src/core/delivery.test.ts::createDeliveryService / NullDeliveryService::* |
| 9 | Listing rows map to the facts and the merged-in-range selection says when older rows were reached; an incremental read's cutoff is the instant it goes back to, and a row touched before it is not that read's even when merged in range (item 4) | [unit] src/execution/githubDelivery.test.ts::parsePullListPage / selectMerged::* |
| 10 | The timeline yields every review and every push — a commit with its co-authors, a force-push with the listed commits' — and nothing else; malformed rows are dropped (item 4) | [unit] src/execution/githubDelivery.test.ts::parseTimeline::* |
| 11 | Workflow runs map to head, trigger, conclusion and attempt; the first head is the earliest pull-request-triggered run's, else the earliest review's, else the current head (item 4) | [unit] src/execution/githubDelivery.test.ts::parseWorkflowRuns::*, ::firstHeadOf::* |
| 12 | The linked issue is a closing keyword or a board item reference, as a number or the report repository's own issue URL; a bare mention, the parent board and another repository's issue URL are none; a pull request at the issues route is not an issue (item 4) | [unit] src/execution/githubDelivery.test.ts::linkedIssueNumber::*, ::parseIssue::* |
| 13 | The source assembles one pull request's facts from the four reads with the read token on every call, each fact carrying the listing's update time; pages while rows stay in range and says truncated at the cap (8 pages by default), complete from the oldest update it reached — from the range's start on a complete read; an incremental read lists the rows touched since its instant, reads only those whose update time the caller does not hold, and is complete from that instant — from the oldest update reached when the cap ends it first; a missing issue, disabled Actions and an empty timeline are absent facts; a failing read throws with the status and a capped body; no credential → nothing fetched (item 4) | [unit] src/execution/githubDelivery.test.ts::GithubDeliverySource::* |
| 14 | delivery report: the first configured repository by default with the caller's visible runs keyed in; --repo, --weeks, --since (--since decides when both are given); the report carries snapshotAt and the text opens with as of; --fresh reaches the source; a caller with no runs:read gets the pull requests alone; a malformed repository and the bare form without config are invalid_input; the Null Object and an upstream failure are unavailable; the definition is a read under delivery:read gated on github (items 5, 7) | [unit] src/core/commands/delivery.test.ts::delivery.report::* |
| 15 | The delivery:read row admits a browser session, an admin and an operator, and refuses a plain chat user, a dispatch-only token and a credential with no grants (item 7) | [unit] src/core/authz/policy.test.ts::* |
| 16 | Routing: index, repository page and JSON twin match; one-segment, traversal-shaped, over-long and foreign paths do not (item 8) | [unit] src/channels/deliveryView.test.ts::parseDeliveryRoute::* |
| 17 | Handler: falls through for other paths; 503 with the Null Object's reason or naming delivery.repos; 405 non-GET; the service asked on every request, with the hardened headers and the report + repositories as the seed; ?weeks/?since/?fresh=1 passthrough (?fresh=0 is not fresh); 404 for an unconfigured repository; the viewer's own runs under the policy predicate; JSON twin no-store with snapshotAt, truncated and completeFrom; upstream failure → capped 502; a renderer that throws once the report is in hand → one 502, the headers written once (items 5, 8) | [unit] src/channels/deliveryView.test.ts::createDeliveryViewHandler::* |
| 18 | Page: hostile titles inert; the six tiles; a row per week and per unit with issue and pull request links; an empty range says so; a cut-short read is said where it is read — the line over the tiles covers the newest N pull requests only, complete from an instant, the Merged tile counts the newest, the weeks that began before the instant are muted and marked incomplete with a note, and a complete report (or one naming no instant) marks no week; the nav with Delivery current; range switch and repository switcher; the footer's As of <time>, <age> with the read GitHub now link keeping the query — and nothing about a read time on a report without one; method, identities and the JSON twin stated; the formatters (item 9) | [unit] web/src/pages/delivery.test.ts::DeliveryPage::*, web/src/pages/delivery.test.ts::delivery formatters::* |
| 19 | Deployed: the Merged tile equals GitHub's own count over a complete range — for an n whose range starts at or after the JSON's completeFrom (truncated false), totals.prsMerged of /delivery/<owner>/<name>.json?weeks=n equals the count of the GitHub search repo:<owner>/<name> is:pr is:merged merged:<range.since>..<snapshotAt> (the instant in GitHub's YYYY-MM-DDTHH:MM:SS+00:00 form); over a wider range the page says The tiles cover the newest N pull requests only, marks the weeks before completeFrom (incomplete), and delivery report --weeks n says the same on its first line; the footer's age is under the configured interval; --fresh on the CLI reads the newest rows and the next page load shows an age under a minute and a completeFrom no later than before; the command answers the same JSON on the CLI (items 7, 9, 10) | [agent] after deploy: sign in, load /delivery/<owner>/<name>.json?weeks=13 and read completeFrom, snapshotAt; pick the widest n whose range starts at or after completeFrom, load /delivery/<owner>/<name>.json?weeks=n and run gh api graphql -f query='{search(query:"repo:<owner>/<name> is:pr is:merged merged:<range.since>..<snapshotAt>",type:ISSUE){issueCount}}' — the counts are equal; load the page at a wider n and read the coverage line and the muted rows; npm run cli -- delivery report --repo <owner>/<name> --weeks <n> --fresh prints a first line as of <now> and the same totals; reload the page and read an age under a minute |
| 20 | Config: snapshot.everyMinutes is 60 by default, must be a whole number of minutes within the bounds, and a malformed value or block throws by name (Configuration) | [unit] src/core/delivery.test.ts::parseDeliveryConfig::snapshot.everyMinutes is the refresh interval — a whole number of minutes within bounds, 60 by default; anything else throws by name |
| 21 | The text names the snapshot's time and age on its first line, and nothing about one when the report carries none; the age reads just now, minutes, hours, days (item 7) | [unit] src/core/delivery.test.ts::renderDeliveryReport::names the snapshot's time and age on the first line when the report carries one, and says nothing about it when it does not |
| 22 | Snapshot served with its age: the first read of a repository reads GitHub once over the window, stores it and serves the request, completeFrom in the fetch; the next read is the stored facts stamped with the read time, GitHub not asked; fresh reads the newest rows whole (no touched instant) and merges them in — a stored row the capped read did not reach survives, the read's reach joins the snapshot's completeness — and serves the new snapshot; a range beyond the window is live and leaves the snapshot alone; concurrent first reads share one read (item 10) | [unit] src/core/deliverySnapshot.test.ts::SnapshottingDeliverySource::the first read of a repository reads GitHub once over the snapshot window…, ::fresh reads the newest rows whole (no touched instant) and merges them into the snapshot…, ::a range reaching further back than the window is a live read over that range and leaves the snapshot alone, ::concurrent first reads share one GitHub read |
| 23 | Snapshot survives a restart: a second process over the same store serves the stored snapshot without a GitHub read; a store that fails is an absent snapshot — a warning, then a read that computes and stores, the facts kept in memory; a capped snapshot is truncated for a range starting before completeFrom and complete after (item 10) | [unit] src/core/deliverySnapshot.test.ts::SnapshottingDeliverySource::a snapshot on the store is served after a restart without a GitHub read…, ::a capped snapshot is truncated for a range starting before its complete-from instant and complete for one starting after |
| 24 | Interval respected: the loop refreshes each configured repository once per interval and never more often, at start only a snapshot missing or older than the interval, retries a failed refresh on the next tick with a warning, ticks by the minute unref'd, and stops (item 10) | [unit] src/core/deliverySnapshot.test.ts::SnapshottingDeliverySource.startRefreshLoop::* |
| 25 | The store: the document guards refuse a malformed snapshot or patch by field and take a row without an update time; the in-memory store returns copies per repository and its merge applies a patch — the rows by number, the dropped numbers gone, the meta replaced — or is false with nothing stored; the Worker client puts and merges with the bearer and reads back verbatim — a second client over the same Worker reads what the first wrote — its merge is true when applied and false on the Worker's 404 (nothing to merge into, or a Worker from before the route), and it throws with the Worker's words on a malformed answer, a refused bearer, a missing route or a refused write; the store is the Worker's behind any *.worker block with its bearer, else memory with a warning naming what a restart costs (item 10) | [unit] src/core/deliverySnapshotStore.test.ts::isDeliverySnapshot::*, ::isDeliverySnapshotPatch::*, ::InMemoryDeliverySnapshotStore::*, ::WorkerDeliverySnapshotStore (HTTPS client to the state Worker)::*, ::buildDeliverySnapshotStore::* |
| 26 | DeliveryDO: advertised on /healthz; unauthenticated 401, non-POST 405; get of an unknown repository is null; put stores and get returns the snapshot verbatim in pull request number order; a later put replaces it whole and another repository's is untouched; merge is 404 with nothing to merge into, else the rows it carries replace theirs by number, the numbers it names go, the meta is replaced and another repository is untouched; a malformed snapshot or patch, a repository that is not owner/name and a bad get are 400, an oversize body or row 413, an unknown route 404 (item 10) | [unit] deploy/cloudflare-memory/delivery.test.ts::DeliveryDO routes::* |
| 27 | Incremental refresh: a later refresh lists the rows touched since the previous read less the ten-minute overlap, with the update times the snapshot holds; a touched row replaces its stored facts, an untouched row survives, a row merged before the window is dropped; the store receives the patch, not the whole snapshot; the merged snapshot serves the next request without a GitHub read (item 10) | [unit] src/core/deliverySnapshot.test.ts::SnapshottingDeliverySource::a later refresh is incremental… |
| 28 | The merge rule: the read's rows replace theirs by number, the rest survive, rows merged before the window are dropped, number order kept; a read that reached back to the previous read's time joins its completeness — the earlier instant, never before the window's start, healing as the window slides past it — and one that stopped short is complete from its own reach alone; with no previous snapshot the read is the snapshot (item 10) | [unit] src/core/deliverySnapshot.test.ts::mergeSnapshot::* |
| 29 | A store with nothing to merge into — an earlier write it refused — is written whole on the next refresh, and the warning is the refused write's alone (item 10) | [unit] src/core/deliverySnapshot.test.ts::SnapshottingDeliverySource::a store with nothing to merge into… |
Attached browser work scope
A trusted personal work scope selects original published pull requests using the current read predicate and canonical ownership callback. Excluded publications contribute no PR, issue or aggregate rows. Coverage remains partial when the installation cannot prove the complete publication set. All people and unscoped legacy callers retain the shared delivery report.
| Criterion | Evidence |
|---|---|
| Only selected owned publications contribute PR rows, issue rows, weeks and totals; unscoped legacy reports retain their publications | [unit] src/channels/deliveryView.test.ts::createDeliveryViewHandler::filters pull requests and every aggregate using the canonical selected owner publication set |
| Incomplete personal delivery stays distinct from a confirmed empty result and retains freshness and counted identities | [unit] web/green/pages/personalReports.test.ts::Green personal reports::* |