Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 1 | /** |
| 2 | * The pure parts of request timing and D1 read consistency for the site: | |
| 3 | * the `g1t_d1` cookie, which session each service call asks for, which | |
| 4 | * calls may write, and the `Server-Timing` header. perf.server.ts holds | |
| The docs folder is gone, and what it held lives where people read it: how a self-hosted g1t runs and how to deploy g1t to Cloudflare are pages on docs.g1t.sh under Run g1t yourself, and speed, rate limits and operating g1t.sh are sections of CONTRIBUTING.md; code that cited a file in docs/ now points to the page or section that covers it, or says what it means itself, and applied migrations and the runner images are left as they were. | 5 | * the per-request state; CONTRIBUTING.md, "Speed", says how to use it. |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 6 | */ |
| 7 | ||
| 8 | /** The cookie that carries D1 bookmarks between a person's requests. */ | |
| 9 | export const D1_COOKIE = "g1t_d1"; | |
| 10 | ||
| 11 | /** | |
| 12 | * How long after a write the services a request did not get a bookmark | |
| 13 | * from read their primary. A write can reach a service the site did not | |
| 14 | * call itself (work writing to repos, say), whose bookmark the site never | |
| 15 | * sees; D1 replicas trail the primary by well under a second, so 30 | |
| 16 | * seconds covers that with room to spare. | |
| 17 | */ | |
| 18 | export const PRIMARY_WINDOW_SECONDS = 30; | |
| 19 | ||
| 20 | /** How long the bookmarks are kept: far longer than any replica trails. */ | |
| 21 | export const D1_COOKIE_MAX_AGE = 300; | |
| 22 | ||
| 23 | /** | |
| 24 | * The services whose RPCs open a D1 session (crates/kit/src/d1.rs and | |
| 25 | * @g1t/contracts d1.ts), by the name the site gives their binding. | |
| 26 | */ | |
| 27 | export const SESSION_SERVICES = new Set(["identity", "repos", "work", "search", "billing", "projects", "deployments"]); | |
| 28 | ||
| 29 | /** What the site remembers from a person's last writes. */ | |
| 30 | export type Bookmarks = { | |
| 31 | /** Unix seconds of the last request that may have written, if recent. */ | |
| 32 | at: number | null; | |
| 33 | /** The latest bookmark each service returned after it. */ | |
| 34 | services: Record<string, string>; | |
| 35 | }; | |
| 36 | ||
| 37 | const BOOKMARK = /^[0-9A-Za-z-]{1,256}$/; | |
| 38 | const SERVICE = /^[a-z]{1,32}$/; | |
| 39 | ||
| 40 | /** Reads the `g1t_d1` cookie; anything malformed is dropped. */ | |
| 41 | export function readBookmarks(cookieHeader: string | null): Bookmarks { | |
| 42 | const empty: Bookmarks = { at: null, services: {} }; | |
| 43 | if (!cookieHeader) return empty; | |
| 44 | const match = new RegExp(`(?:^|;\\s*)${D1_COOKIE}=([^;]*)`).exec(cookieHeader); | |
| 45 | if (!match) return empty; | |
| 46 | const found: Bookmarks = { at: null, services: {} }; | |
| 47 | for (const entry of match[1].split("~")) { | |
| 48 | const colon = entry.indexOf(":"); | |
| 49 | if (colon < 1) continue; | |
| 50 | const key = entry.slice(0, colon); | |
| 51 | const value = entry.slice(colon + 1); | |
| 52 | if (key === "at") { | |
| 53 | const at = Number(value); | |
| 54 | if (Number.isSafeInteger(at) && at > 0) found.at = at; | |
| 55 | } else if (SERVICE.test(key) && SESSION_SERVICES.has(key) && BOOKMARK.test(value)) { | |
| 56 | found.services[key] = value; | |
| 57 | } | |
| 58 | } | |
| 59 | return found; | |
| 60 | } | |
| 61 | ||
| 62 | /** The `g1t_d1` cookie's value. */ | |
| 63 | export function writeBookmarks(bookmarks: Bookmarks): string { | |
| 64 | const entries = bookmarks.at ? [`at:${bookmarks.at}`] : []; | |
| 65 | for (const [service, bookmark] of Object.entries(bookmarks.services).sort()) { | |
| 66 | if (SESSION_SERVICES.has(service) && BOOKMARK.test(bookmark)) entries.push(`${service}:${bookmark}`); | |
| 67 | } | |
| 68 | return entries.join("~"); | |
| 69 | } | |
| 70 | ||
| 71 | /** The `Set-Cookie` value for `bookmarks`. */ | |
| 72 | export function bookmarkCookie(bookmarks: Bookmarks, secure: boolean): string { | |
| 73 | return `${D1_COOKIE}=${writeBookmarks(bookmarks)}; Path=/; HttpOnly;${secure ? " Secure;" : ""} SameSite=Lax; Max-Age=${D1_COOKIE_MAX_AGE}`; | |
| 74 | } | |
| 75 | ||
| 76 | /** | |
| 77 | * What a call to `service` sends as `x-d1-bookmark`, or null for none | |
| 78 | * (that service reads its primary, as before sessions): | |
| 79 | * | |
| 80 | * - A request that writes (any method but GET and HEAD) starts every | |
| 81 | * session on the primary, so what it checks before writing is current. | |
| 82 | * - Within `PRIMARY_WINDOW_SECONDS` of the person's last write, the | |
| 83 | * primary, for every service: that write may have reached a service | |
| 84 | * through another one, whose bookmark the site never saw. | |
| 85 | * - Otherwise the bookmark that service returned after that write: never | |
| 86 | * older than what they did, however far a replica trails. | |
| 87 | * - Otherwise the nearest copy. | |
| 88 | */ | |
| 89 | export function sessionFor(service: string, bookmarks: Bookmarks, writing: boolean, nowSeconds: number): string | null { | |
| 90 | if (!SESSION_SERVICES.has(service)) return null; | |
| 91 | if (writing) return "first-primary"; | |
| 92 | if (bookmarks.at && nowSeconds - bookmarks.at < PRIMARY_WINDOW_SECONDS) return "first-primary"; | |
| 93 | return bookmarks.services[service] ?? "first-unconstrained"; | |
| 94 | } | |
| 95 | ||
| 96 | /** | |
| 97 | * Methods that only read. Anything not listed is taken to write, so a new | |
| 98 | * method errs towards a cookie and a primary read, never a stale page. | |
| Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily | 99 | * `get`, `list`, `queue` and `pulls_for_repos` were missing: every project |
| 100 | * page called `get` (repos, projects), so every one set the cookie, was | |
| 101 | * never kept in the public cache, and sent the next 30 s of the person's | |
| Public pages cacheable again: a signed-out GET never sets g1t_d1; stars, about and public_links are reads | 102 | * reads to the primary. `stars`, `about` and `public_links` (2026-10-08) |
| Merge project overview: one branch_drift call, spliced histories, cached tags, 6 repos calls instead of 25 | 103 | * did the same to every project page and Explore for 13 hours. `tags`, |
| 104 | * `commit_checks` and `shortcuts` (every overview), and the Files page's | |
| 105 | * `last_commits`, `languages`, `contributors` and `license`, still made a | |
| 106 | * signed-in view count as a write until 2026-10-08: the cookie, 30 s of | |
| 107 | * primary reads, and no sidebar cache after every overview. | |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 108 | */ |
| 109 | const READS = new Set( | |
| 110 | ( | |
| Chat controls, public profiles, shadcn selects, and no Docs tab in a project | 111 | "account active_agents all_ids get list queue pulls_for_repos blame blob branches by_author by_repo contributions catalog check_invite check_limit " + |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 112 | "check_workspace_deletion check_workspace_rename collaborator_permission compare counts deleted deliveries " + |
| Projects no longer depend on each other: the dependsOn relation, its settings page (old links redirect), the overview card, a pull request's Affects panel and preview stacks, reference variables and agents' notes on what a project uses are gone; the table is dropped in a later deploy | 113 | "domains entitlements entity explore features git_access has_feature invoices ledger limit " + |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 114 | "limit_requests links log logs managed_pulls memories_by_id memory_context my_repo_invitations " + |
| 115 | "outside_collaborators overview path_by_id prices profile profile_workspaces public_namespaces read_session " + | |
| 116 | "readable ready_issues references registration repo_access resolve resolve_branch resolve_path resolve_slug " + | |
| The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how. | 117 | "routes run run_context run_cost runner_activity runner_groups runner_settings runners runs scorecards search search_memories usage_report " + |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 118 | "settings statement statement_entries status status_by_id suggest tree usage usage_meters user_by_username " + |
| Merge main into Artifacts Phase 2 | 119 | "user_for_session user_for_access_token usernames waiting_workspaces workflows workspace workspace_invites github_enabled " + |
| Merge project overview: one branch_drift call, spliced histories, cached tags, 6 repos calls instead of 25 | 120 | "stars about public_links branch_drift tags last_commits languages contributors license releases release " + |
| People and teams are front and centre: one directory of people and agents with presence, local time, titles, teams and what each owns; profiles with manager and reports and the agents they work with; an org chart with each team's agents beside the person who leads it; and teams of any mix, with a lead, a channel, a budget agents keep to and the agents on them. Every agent is told its teams each turn (who leads, who owns what, who's around and who to page), and the team page shows exactly what. Member management is Members and invites; the people and teams guide says how. | 121 | "stargazers starred commit_checks shortcuts spend person_budgets usage_report templates install_requests extension_installs " + |
| A GitHub App installed straight on GitHub can be added to a workspace: Import from GitHub lists the installations your GitHub account can see that this workspace hasn't added, each with Add for owners, and coming back from GitHub without g1t's own start asks which of your workspaces to add it to instead of stopping; the GitHub guide says how. | 122 | "people_directory team_agents team_context team_members github_visible_installations" |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 123 | ).split(" "), |
| 124 | ); | |
| 125 | ||
| Public pages cacheable again: a signed-out GET never sets g1t_d1; stars, about and public_links are reads | 126 | /** |
| 127 | * Whether a response sets the `g1t_d1` cookie. A signed-out GET never | |
| 128 | * does, whatever it called: nobody signed out can write anything their | |
| 129 | * next page must read, and a cookie keeps the page out of the public | |
| 130 | * cache. Signing in on a GET (GitHub) starts a session, so it does. | |
| 131 | */ | |
| 132 | export function setsBookmark(request: { writing: boolean; wrote: boolean; hasSession: boolean; signedIn: boolean }): boolean { | |
| 133 | if (request.writing || request.signedIn) return true; | |
| 134 | return request.wrote && request.hasSession; | |
| 135 | } | |
| 136 | ||
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 137 | /** Whether an RPC to `method` may write. */ |
| 138 | export function mayWrite(method: string): boolean { | |
| 139 | if (READS.has(method)) return false; | |
| 140 | return !(method.startsWith("get_") || method.startsWith("list_")); | |
| 141 | } | |
| 142 | ||
| 143 | /** The method name of an RPC URL (`https://service/rpc/<method>`). */ | |
| 144 | export function rpcMethodOf(input: string): string { | |
| 145 | const at = input.indexOf("/rpc/"); | |
| 146 | return at < 0 ? "" : input.slice(at + 5).split(/[?#]/)[0]; | |
| 147 | } | |
| 148 | ||
| 149 | /** One service's calls during a request. */ | |
| 150 | export type ServiceTiming = { | |
| 151 | calls: number; | |
| 152 | /** Summed wall time of its calls, from here. */ | |
| 153 | wallMs: number; | |
| 154 | /** Summed time its own `server-timing: svc;dur` reported. */ | |
| 155 | serviceMs: number; | |
| Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily | 156 | /** |
| 157 | * Of that, summed time it reported waiting on its database | |
| 158 | * (`db;dur`, crates/kit/src/d1.rs `Timing`) and in how many round trips. | |
| 159 | * Absent for services that do not time them. | |
| 160 | */ | |
| 161 | dbMs?: number; | |
| 162 | dbTrips?: number; | |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 163 | }; |
| 164 | ||
| 165 | /** The `svc;dur=N` a service reports, or null. */ | |
| 166 | export function serviceDuration(header: string | null): number | null { | |
| 167 | if (!header) return null; | |
| 168 | const match = /(?:^|,)\s*svc;dur=([0-9.]+)/.exec(header); | |
| 169 | return match ? Number(match[1]) : null; | |
| 170 | } | |
| 171 | ||
| Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily | 172 | /** |
| 173 | * The `db;dur=N;desc="T round trips, …"` a service reports: its summed | |
| 174 | * database time and round trips, or null. | |
| 175 | */ | |
| 176 | export function databaseTime(header: string | null): { ms: number; trips: number } | null { | |
| 177 | if (!header) return null; | |
| 178 | const match = /(?:^|,)\s*db;dur=([0-9.]+)(?:;desc="(\d+) round trips?)?/.exec(header); | |
| 179 | return match ? { ms: Number(match[1]), trips: Number(match[2] ?? 0) } : null; | |
| 180 | } | |
| 181 | ||
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 182 | /** Total time covered by overlapping [start, end] intervals. */ |
| 183 | export function coveredMs(intervals: [number, number][]): number { | |
| 184 | const sorted = [...intervals].sort((a, b) => a[0] - b[0]); | |
| 185 | let total = 0; | |
| 186 | let end = -Infinity; | |
| 187 | let start = -Infinity; | |
| 188 | for (const [from, to] of sorted) { | |
| 189 | if (from > end) { | |
| 190 | if (end > start) total += end - start; | |
| 191 | start = from; | |
| 192 | end = to; | |
| 193 | } else if (to > end) { | |
| 194 | end = to; | |
| 195 | } | |
| 196 | } | |
| 197 | if (end > start) total += end - start; | |
| 198 | return total; | |
| 199 | } | |
| 200 | ||
| 201 | /** A Server-Timing metric name: a token, so `/` and spaces become `.`. */ | |
| 202 | export function metricName(name: string): string { | |
| 203 | return name.replace(/^routes\//, "").replace(/[^A-Za-z0-9_.-]+/g, "."); | |
| 204 | } | |
| 205 | ||
| 206 | /** | |
| 207 | * The `Server-Timing` header for a request: the whole, the loaders, the | |
| 208 | * time spent waiting on services (overlap counted once), then each | |
| 209 | * service. DevTools shows them in this order under Network → Timing. | |
| 210 | */ | |
| 211 | export function serverTiming(input: { | |
| 212 | totalMs: number; | |
| 213 | loaders: { id: string; ms: number; kind: "loader" | "action" }[]; | |
| 214 | rpcMs: number; | |
| 215 | services: Record<string, ServiceTiming>; | |
| 216 | sessions: string; | |
| 217 | }): string { | |
| 218 | const parts = [`total;dur=${input.totalMs};desc="web to first byte"`]; | |
| 219 | for (const loader of input.loaders) { | |
| 220 | parts.push(`${loader.kind}.${metricName(loader.id)};dur=${loader.ms}`); | |
| 221 | } | |
| 222 | const calls = Object.values(input.services).reduce((sum, timing) => sum + timing.calls, 0); | |
| 223 | if (calls > 0) parts.push(`rpc;dur=${input.rpcMs};desc="${calls} service calls, overlap counted once"`); | |
| 224 | const ranked = Object.entries(input.services).sort((a, b) => b[1].wallMs - a[1].wallMs); | |
| 225 | for (const [name, timing] of ranked) { | |
| Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily | 226 | const db = timing.dbTrips ? `, db ${timing.dbMs ?? 0}ms in ${timing.dbTrips} round trip${timing.dbTrips === 1 ? "" : "s"}` : ""; |
| 227 | const inside = timing.serviceMs > 0 ? `, ${timing.serviceMs}ms inside${db}` : ""; | |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 228 | parts.push(`${metricName(name)};dur=${timing.wallMs};desc="${timing.calls} call${timing.calls === 1 ? "" : "s"}${inside}"`); |
| 229 | } | |
| 230 | if (input.sessions) parts.push(`d1;desc="${input.sessions}"`); | |
| 231 | return parts.join(", "); | |
| 232 | } |
This file's history is long; its oldest lines are credited to the oldest commit read.