Skip to content
322 linesCodeBlameRaw

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.

Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import {
Usage lists Other once: kinds of work without words of their own are added into it5 foldTasks,
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas6 gigabytes,
7 shownMeters,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look8 alertText,
9 alertTone,
10 cardCheckResult,
Merge Stripe Tax, the card fee on card payments, and one free workspace per person11 cardFeeCents,
12 feeAndTax,
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging13 creditLine,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look14 needsAttention,
15 usageGlance,
16 parseCaps,
17 parseLimitRequest,
18 parsePrepay,
19 parseSpendLimit,
20 planStatus,
21 readDollars,
22 requestStatus,
23 share,
24 spendPath,
25 spendRange,
26} from "./billing.ts";
27
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging28test("a credit from g1t reads in a line, with what is left and when it expires", () => {
29 const now = new Date("2026-10-07T12:00:00Z");
30 const grant = { amountMicros: 25_000_000, leftMicros: 12_400_000, expiresAt: "2027-01-05T23:59:59Z", state: "open" as const };
31 assert.equal(creditLine(grant, now), "$25.00 credit, $12.40 left, expires Jan 5, 2027");
32 assert.equal(creditLine({ ...grant, expiresAt: "2026-12-05T23:59:59Z" }, now), "$25.00 credit, $12.40 left, expires Dec 5");
33 assert.equal(creditLine({ ...grant, expiresAt: null }, now), "$25.00 credit, $12.40 left");
34 assert.equal(creditLine({ ...grant, state: "used", leftMicros: 0 }, now), "$25.00 credit, all used");
35 assert.equal(creditLine({ ...grant, state: "revoked", leftMicros: 0 }, now), "$25.00 credit, withdrawn");
36});
37
Merge Stripe Tax, the card fee on card payments, and one free workspace per person38test("the card fee shown before paying is the one billing charges, and prices exclude tax", () => {
39 const fee = { on: true, percentMicros: 29_000, fixedCents: 30 };
40 // The same figures as billing's own tests (ai.rs, tax.rs).
41 assert.equal(cardFeeCents(2_500, fee), 106);
42 assert.equal(cardFeeCents(2_000, fee), 91);
43 assert.equal(cardFeeCents(2_000, { ...fee, on: false }), 0);
44 assert.equal(cardFeeCents(0, fee), 0);
45 assert.equal(cardFeeCents(2_000, null), 0);
46 assert.equal(feeAndTax(59), "Card processing fee $0.59, plus tax where it applies");
47 assert.equal(feeAndTax(0), "Plus tax where it applies");
48});
49
Money is written one way. A single formatter turns millionths of a dollar into dollars, rounding half up on whole micros rather than on a float, so the same sum reads the same on every page: under a cent reads <$0.01 on a total and exactly nothing is $0.00, while the statement's lines, a session's receipt, the price book and an agent's effort costs carry up to four places where the fraction of a cent is the point; the six formatters that each rounded their own way are gone. This month is the calendar month in UTC from its first day to today everywhere, and billing counts the month's not-yet-closed usage in any range that reaches into the current month, so the top bar's pill, Spend, Home and Usage ask for the same days and get the same figure; Home now reads the usage report the others read instead of adding up statements. Usage's pending sentence says what of that usage the close will charge after the discount and included usage, which the billing API returns as pending_charged_micros. A reconciliation test holds the pill, Spend, Home and Usage to one number for one month. The usage and billing guide says how amounts are written and what this month means.50test("dollars are read from what people type", () => {
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look51 assert.equal(readDollars("$1,000"), 1_000_000_000);
52 assert.equal(readDollars(""), null);
53 assert.equal(readDollars("lots"), null);
54});
55
56test("a prepayment is $25 or more, by card up to $10,000, by bank transfer from $1,000", () => {
57 assert.deepEqual(parsePrepay({ amount: "100" }), { ok: true, value: { amountCents: 10_000, method: "card" } });
58 assert.deepEqual(parsePrepay({ amount: "100", custom: "250" }), {
59 ok: true,
60 value: { amountCents: 25_000, method: "card" },
61 });
62 assert.equal(parsePrepay({ custom: "10" }).ok, false);
63 assert.equal(parsePrepay({ custom: "20000" }).ok, false);
64 assert.equal(parsePrepay({ custom: "500", method: "bank_transfer" }).ok, false);
65 assert.deepEqual(parsePrepay({ custom: "20000", method: "bank_transfer" }), {
66 ok: true,
67 value: { amountCents: 2_000_000, method: "bank_transfer" },
68 });
69 assert.equal(parsePrepay({}).ok, false);
70});
71
72test("caps stay in range, and empty goes back to the default", () => {
73 assert.deepEqual(parseCaps({ run: "", issue: "" }), { ok: true, value: { runCapMicros: null, issueCapMicros: null } });
74 assert.deepEqual(parseCaps({ run: "0.10", issue: "1000" }), {
75 ok: true,
76 value: { runCapMicros: 100_000, issueCapMicros: 1_000_000_000 },
77 });
78 assert.equal(parseCaps({ run: "0.05" }).ok, false);
79 assert.equal(parseCaps({ issue: "2000" }).ok, false);
80 assert.equal(parseCaps({ run: "two" }).ok, false);
81});
82
83test("a limit request needs an amount, a reason and a monthly spend; an overage only a reason", () => {
84 assert.deepEqual(parseLimitRequest({ kind: "limit", amount: "5000", reason: " A launch ", expected: "3000" }), {
85 ok: true,
86 value: { kind: "limit", amountMicros: 5_000_000_000, reason: "A launch", expectedMonthlyMicros: 3_000_000_000 },
87 });
88 assert.equal(parseLimitRequest({ kind: "limit", amount: "5000", reason: "" , expected: "1" }).ok, false);
89 assert.equal(parseLimitRequest({ kind: "limit", reason: "x", expected: "1" }).ok, false);
90 assert.deepEqual(parseLimitRequest({ kind: "overage", reason: "A loop ran all night" }), {
91 ok: true,
92 value: { kind: "overage", amountMicros: 0, reason: "A loop ran all night", expectedMonthlyMicros: 0 },
93 });
94});
95
96test("a spend limit is automatic, fixed, the full amount available, or the one-time raise", () => {
97 assert.deepEqual(parseSpendLimit({ mode: "automatic" }), { ok: true, value: { micros: null, useFull: false, raiseOnce: false } });
98 assert.deepEqual(parseSpendLimit({ mode: "fixed", limit: "500" }), {
99 ok: true,
100 value: { micros: 500_000_000, useFull: false, raiseOnce: false },
101 });
102 assert.equal(parseSpendLimit({ mode: "fixed", limit: "0.5" }).ok, false);
103 assert.deepEqual(parseSpendLimit({ mode: "full" }), { ok: true, value: { micros: null, useFull: true, raiseOnce: false } });
104 assert.deepEqual(parseSpendLimit({ mode: "raise" }), { ok: true, value: { micros: null, useFull: false, raiseOnce: true } });
105 assert.deepEqual(parseSpendLimit({ mode: "raise", limit: "150" }), {
106 ok: true,
107 value: { micros: 150_000_000, useFull: false, raiseOnce: true },
108 });
109});
110
111test("the spend limit's range: up to the highest ceiling plus prepaid, then once to twice it, then ask", () => {
112 // A first month at $100, nothing prepaid, the raise unused: $100 alone, $200 once.
113 const range = spendRange({ availableMicros: 100_000_000, ceilingMicros: 100_000_000, raiseOnceMicros: 200_000_000, raisedAt: null });
114 assert.deepEqual(range, { selfServeMicros: 100_000_000, raiseOnceMicros: 200_000_000, raisedAt: null });
115 assert.equal(spendPath(80_000_000, range), "self");
116 assert.equal(spendPath(100_000_000, range), "self");
117 assert.equal(spendPath(150_000_000, range), "raise");
118 assert.equal(spendPath(200_000_000, range), "raise");
119 assert.equal(spendPath(200_000_001, range), "ask");
120 // The raise used: only asking goes further.
121 const used = spendRange({ availableMicros: 200_000_000, ceilingMicros: 200_000_000, raiseOnceMicros: null, raisedAt: "2026-10-01T00:00:00Z" });
122 assert.equal(used.raiseOnceMicros, null);
123 assert.equal(spendPath(300_000_000, used), "ask");
124 // No ceiling: anything goes.
125 assert.equal(spendPath(1e12, spendRange({ availableMicros: null, ceilingMicros: null, raiseOnceMicros: null })), "self");
126 // A raise no higher than what is available is no raise.
127 assert.equal(spendRange({ availableMicros: 300_000_000, ceilingMicros: 100_000_000, raiseOnceMicros: 300_000_000 }).raiseOnceMicros, null);
128});
129
130test("the plan card says where the workspace stands", () => {
131 const free = { plan: "free" as const, trialMicrosLeft: 0, trialVerified: false, firstMonth: false };
132 assert.deepEqual(planStatus(null, free), { kind: "free", label: "Free" });
133 assert.equal(planStatus(null, { ...free, trialVerified: true, trialMicrosLeft: 5_000_000 }).kind, "trial");
134 assert.equal(planStatus(null, { ...free, trialVerified: true }).kind, "free");
135 const subscription = { feature: "plan" as const, status: "active" as const, periodEnd: null, startedBy: "a", startedAt: "" };
136 assert.deepEqual(planStatus({ on: true, subscription }, { ...free, plan: "paid", firstMonth: true }), {
137 kind: "paid",
138 label: "On the g1t plan, first month",
139 });
140 assert.equal(planStatus({ on: true, subscription: { ...subscription, status: "canceling" } }, { ...free, plan: "paid" }).kind, "canceling");
141 assert.equal(planStatus({ on: false, subscription: { ...subscription, status: "past_due" } }, free).kind, "past_due");
142 assert.equal(planStatus({ on: true, included: true, subscription: null }, free).kind, "comped");
143 assert.equal(planStatus(null, { ...free, plan: "internal" }).kind, "comped");
144 assert.equal(planStatus(null, { ...free, plan: "enterprise" }).kind, "enterprise");
145});
146
147test("the overview's Usage card reads the month by what pays", () => {
148 const usage = {
149 free: false,
150 spentMicros: 14_000_000,
151 usedMicros: 11_000_000,
152 byTask: [
153 { key: "review", micros: 2_000_000, runs: 4 },
154 { key: "implement", micros: 12_000_000, runs: 9 },
155 { key: "plan", micros: 0, runs: 1 },
156 ],
157 };
158 const entitlements = { includedMicros: 10_000_000, includedUsedMicros: 10_000_000, trialMicrosLeft: 0 };
159 const plan = usageGlance({ usage, status: { kind: "paid", label: "" }, entitlements, limit: { spentMicros: 4_000_000, spendLimitMicros: 200_000_000 }, trialMicros: 5_000_000 });
160 assert.equal(plan.kind, "plan");
161 assert.deepEqual(plan.credit, { label: "Included usage", usedMicros: 10_000_000, ofMicros: 10_000_000 });
162 assert.deepEqual(plan.onDemand, { micros: 4_000_000, limitMicros: 200_000_000 });
163 // Most first, and nothing that cost nothing.
164 assert.deepEqual(plan.lines.map((line) => line.label), ["Making changes", "Reviews"]);
165 const trial = usageGlance({ usage, status: { kind: "trial", label: "" }, entitlements: { ...entitlements, trialMicrosLeft: 1_500_000 }, limit: null, trialMicros: 5_000_000 });
166 assert.deepEqual(trial.credit, { label: "Trial credit", usedMicros: 3_500_000, ofMicros: 5_000_000 });
167 assert.equal(trial.onDemand, null);
168 assert.equal(usageGlance({ usage, status: { kind: "comped", label: "" }, entitlements, limit: null, trialMicros: 0 }).kind, "comped");
169 assert.equal(usageGlance({ usage, status: { kind: "free", label: "" }, entitlements, limit: null, trialMicros: 0 }).kind, "forge");
170 // While g1t charges nothing, usage is shown at cost.
171 const beta = usageGlance({ usage: { ...usage, free: true }, status: { kind: "paid", label: "" }, entitlements, limit: null, trialMicros: 0 });
172 assert.equal(beta.kind, "beta");
173 assert.equal(beta.spentMicros, 11_000_000);
174});
175
176test("a meter's share stays between 0 and 1", () => {
177 assert.equal(share(5, 10), 0.5);
178 assert.equal(share(15, 10), 1);
179 assert.equal(share(5, 0), 0);
180 assert.equal(share(5, null), 0);
181});
182
183test("after a card check the owner reads whether the trial started", () => {
184 assert.match(cardCheckResult({ trialVerified: true, trialMicrosLeft: 5_000_000 }, 5_000_000), /[$]5 trial is ready/);
185 assert.match(cardCheckResult({ trialVerified: true, trialMicrosLeft: 0 }, 5_000_000), /Prepaid cards can still pay for the plan/);
186 assert.match(cardCheckResult({ trialVerified: false, trialMicrosLeft: 0 }, 5_000_000), /did not finish/);
187});
188
189test("alerts read as sentences", () => {
190 const alert = { meter: "included", level: 90, usedMicros: 9_000_000, limitMicros: 10_000_000, message: "" };
191 assert.equal(alertText(alert), "90% of the plan's included usage: $9.00 of $10.00.");
192 assert.equal(alertText({ ...alert, meter: "spend_limit", level: 100 }), "All of your spend limit: $9.00 of $10.00.");
193 assert.equal(alertTone(50), "ok");
194 assert.equal(alertTone(75), "warning");
195 assert.equal(alertTone(100), "stopped");
196});
197
198test("a workspace needs attention when paused, on a spike, or at 90%", () => {
199 assert.equal(needsAttention(null), false);
200 assert.equal(needsAttention({ paused: null, spike: null, alerts: [] }), false);
201 assert.equal(needsAttention({ paused: "Spend spike", spike: null, alerts: [] }), true);
202 const spike = { id: "s", status: "continued", hourMicros: 1, averageMicros: 1, detectedAt: "" };
203 assert.equal(needsAttention({ paused: null, spike, alerts: [] }), false);
204 assert.equal(needsAttention({ paused: null, spike: { ...spike, status: "open" }, alerts: [] }), true);
205 const at = (level: number) => ({ meter: "spend_limit", level, usedMicros: 0, limitMicros: 0, message: "" });
206 assert.equal(needsAttention({ paused: null, spike: null, alerts: [at(75)] }), false);
207 assert.equal(needsAttention({ paused: null, spike: null, alerts: [at(90)] }), true);
208});
209
210test("a request says where it stands", () => {
211 const request = {
212 id: "r",
213 workspace: "acme",
214 kind: "limit",
215 amountMicros: 1,
216 reason: "",
217 expectedMonthlyMicros: 0,
218 status: "open",
219 createdBy: "a",
220 createdAt: "",
221 };
222 assert.equal(requestStatus(request), "Waiting for an answer");
223 assert.equal(requestStatus({ ...request, status: "approved", decidedMicros: 2_000_000_000 }), "Approved at $2,000");
224 assert.equal(requestStatus({ ...request, status: "declined" }), "Declined");
225});
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas226
227const METERS = [
228 { key: "agents", label: "Agents & sandboxes", micros: 1_200_000, quantity: "4 runs" },
229 { key: "builds", label: "Builds", micros: 0, quantity: null },
230 { key: "requests", label: "Requests & CPU", micros: 0, quantity: null },
231 { key: "domains", label: "Custom domains", micros: 120_000, quantity: "1 custom domain" },
232 { key: "git_storage", label: "Git operations & storage", micros: 0, quantity: "1,200 git operations" },
233 { key: "search_scans", label: "Search & security scans", micros: 3_000, quantity: null },
234];
235
236test("the plan shows every meter, with no quota beside any of them", () => {
237 const shown = shownMeters(METERS, true);
238 assert.deepEqual(
239 shown.map((m) => m.key),
240 ["agents", "builds", "requests", "domains", "git_storage", "search_scans"],
241 );
242 for (const meter of shown) assert.ok(!/ of |apps up/i.test(`${meter.label} ${meter.quantity ?? ""}`));
243});
244
245test("a free workspace sees only what it can use, and anything it used anyway", () => {
246 assert.deepEqual(
247 shownMeters(METERS, false).map((m) => m.key),
248 ["agents", "domains", "git_storage", "search_scans"],
249 );
250});
251
252test("storage reads in powers of ten", () => {
253 assert.equal(gigabytes(1_000_000_000), "1 GB");
254 assert.equal(gigabytes(1_500_000_000), "1.5 GB");
255 assert.equal(gigabytes(500_000_000), "500 MB");
256});
Usage lists Other once: kinds of work without words of their own are added into it257
258test("kinds of work without words of their own are one Other, listed once and last", () => {
259 const slices = [
260 { key: "check", micros: 5, runs: 50 },
261 { key: "review", micros: 3, runs: 5 },
262 { key: "other", micros: 1, runs: 7 },
263 { key: "implement", micros: 9, runs: 4 },
264 { key: "answer", micros: 2, runs: 11 },
265 ];
266 assert.deepEqual(foldTasks(slices), [
267 { key: "review", micros: 3, runs: 5 },
268 { key: "implement", micros: 9, runs: 4 },
269 { key: "other", micros: 8, runs: 68 },
270 ]);
271 assert.deepEqual(foldTasks([{ key: "plan", micros: 1, runs: 1 }]), [{ key: "plan", micros: 1, runs: 1 }]);
272});
Usage, Billing settings and prepaid AI credit; fixes from the UX audit273
274test("AI credit is bought in whole dollars from $10 to $1,000", async () => {
275 const { parseAiPurchase } = await import("./billing.ts");
276 assert.deepEqual(parseAiPurchase({ amount: "25" }), { ok: true, value: { amountCents: 2_500 } });
277 assert.deepEqual(parseAiPurchase({ amount: "custom", custom: "$150" }), { ok: true, value: { amountCents: 15_000 } });
278 assert.equal(parseAiPurchase({ amount: "custom", custom: "5" }).ok, false);
279 assert.equal(parseAiPurchase({ amount: "custom", custom: "12.50" }).ok, false);
280 assert.equal(parseAiPurchase({ amount: "custom", custom: "" }).ok, false);
281});
282
283test("auto-reload's amounts are checked before billing sees them", async () => {
284 const { parseAiReload } = await import("./billing.ts");
285 assert.deepEqual(parseAiReload({ enabled: "on", threshold: "10", target: "25", monthly: "100" }), {
286 ok: true,
287 value: { enabled: true, thresholdMicros: 10_000_000, targetMicros: 25_000_000, monthlyMaxMicros: 100_000_000 },
288 });
289 assert.equal(parseAiReload({ threshold: "10", target: "15", monthly: "100" }).ok, false);
290 assert.equal(parseAiReload({ threshold: "10", target: "25", monthly: "10" }).ok, false);
291 assert.equal(parseAiReload({ threshold: "10", target: "25.5", monthly: "100" }).ok, false);
292});
293
294test("budget alerts keep the levels ticked, highest first", async () => {
295 const { parseBudgetAlerts } = await import("./billing.ts");
296 assert.deepEqual(parseBudgetAlerts({ alerts: ["50", "100", "75", "12"], pause: "on", webhook: "" }), {
297 ok: true,
298 value: { alerts: [100, 75, 50], pauseAtLimit: true, webhook: null },
299 });
300 assert.equal(parseBudgetAlerts({ alerts: [], webhook: "http://x.test" }).ok, false);
301 assert.deepEqual(parseBudgetAlerts({ alerts: [], webhook: "https://hooks.acme.test/g1t" }).ok, true);
302});
303
304test("invoice details read from the form, with the country in capitals", async () => {
305 const { parseInvoiceDetails } = await import("./billing.ts");
306 const form = new FormData();
307 form.set("email", "billing@acme.test");
308 form.set("country", "de");
309 form.set("taxIdType", "eu_vat");
310 form.set("taxId", "DE123456789");
311 const parsed = parseInvoiceDetails(form);
312 assert.ok(parsed.ok);
313 assert.equal(parsed.value.address.country, "DE");
314 form.set("taxId", "");
315 assert.equal(parseInvoiceDetails(form).ok, false);
Merge Stripe Tax, the card fee on card payments, and one free workspace per person316 // Tax is worked out from the address: in the US, the ZIP code is needed.
317 form.set("taxIdType", "");
318 form.set("country", "us");
319 assert.equal(parseInvoiceDetails(form).ok, false);
320 form.set("postalCode", "94107");
321 assert.ok(parseInvoiceDetails(form).ok);
Usage, Billing settings and prepaid AI credit; fixes from the UX audit322});

This file's history is long; its oldest lines are credited to the oldest commit read.