Skip to content
311 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";
Merge workspace invitations: nobody joins a workspace without saying yes, people are found by username, your own invites can bring someone in, and nobody is left without a workspace (identity 0040)2import { readFileSync } from "node:fs";
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look3import { test } from "node:test";
4
Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page)5import { ACCOUNT_SETTINGS } from "./account-settings.ts";
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look6import { CONTACT } from "./legal.ts";
7import {
Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page)8 G1T_INVITES,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look9 HAVE_AN_INVITE,
Merge workspace invitations: nobody joins a workspace without saying yes, people are found by username, your own invites can bring someone in, and nobody is left without a workspace (identity 0040)10 bringIntoChoices,
Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page)11 inviteDraft,
12 inviteKind,
13 invitePageCopy,
14 invitesPage,
15 peoplePages,
16 workspaceInviteCopy,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look17 INVITES_CONTACT,
18 cleanCode,
Merge invite emails that confirm the address: the emailed link carries a proof only that email has, so signing up from it needs no code; shared links and typed codes still confirm19 cleanProof,
20 invitePath,
21 inviteSignUpCopy,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look22 inviteFor,
23 inviteLink,
24 inviteState,
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas25 landingFor,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look26 looksAutomated,
27 moreInvitesMailto,
28 remainingLine,
Merge shared invite links: label, uses, expiry, domains; joined through recorded (identity 0038)29 sharedDomainsHint,
30 sharedInviteLine,
31 sharedInviteLink,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look32 signUpCopy,
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas33 suggestUsername,
34 welcomeCookie,
35 clearWelcome,
36 welcomes,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look37} from "./invites.ts";
38
39const CODE = "g1t-k7m2-q9xd-4hpw-abcd-0123-4567-89ef-ghjk";
40
41test("while invite-only, nobody is offered a plain sign-up", () => {
Sign-up buttons say Sign up everywhere; only the sign-up page says registration takes an invite42 // Sign up everywhere; only the sign-up page says registration takes an invite.
43 assert.deepEqual(signUpCopy(), { primary: "Sign up", secondary: null });
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look44 assert.equal(HAVE_AN_INVITE, "/register#invite");
45});
46
47test("asking for more invites goes to support with the [g1t Invites] subject", () => {
48 assert.equal(INVITES_CONTACT, CONTACT.support);
49 assert.equal(moreInvitesMailto(), "mailto:hey@flagon.io?subject=%5Bg1t%20Invites%5D%20More%20invites");
50 assert.equal(
51 moreInvitesMailto("acme"),
52 "mailto:hey@flagon.io?subject=%5Bg1t%20Invites%5D%20More%20invites%20for%20acme",
53 );
54});
55
56test("an invite link is on g1t.sh unless told otherwise", () => {
57 assert.equal(inviteLink(CODE), `https://g1t.sh/invite/${CODE}`);
58 assert.equal(inviteLink(CODE, "http://localhost:8787/"), `http://localhost:8787/invite/${CODE}`);
59});
60
Merge invite emails that confirm the address: the emailed link carries a proof only that email has, so signing up from it needs no code; shared links and typed codes still confirm61const PROOF = "4f9c2a7e0b13d5c84f9c2a7e0b13d5c84f9c2a7e0b13d5c84f9c2a7e0b13d5c8";
62
63test("an invite email's proof is kept only when it looks like one, and goes along to the invite's page", () => {
64 assert.equal(cleanProof(PROOF), PROOF);
65 assert.equal(cleanProof(` ${PROOF.toUpperCase()} `), PROOF);
66 assert.equal(cleanProof("not-a-proof"), null);
67 assert.equal(cleanProof("abc"), null);
68 assert.equal(cleanProof("a".repeat(500)), null);
69 assert.equal(cleanProof(null), null);
70 assert.equal(invitePath(CODE, PROOF), `/invite/${CODE}?proof=${PROOF}`);
71 assert.equal(invitePath(CODE, null), `/invite/${CODE}`);
72 assert.equal(invitePath(CODE), `/invite/${CODE}`);
73});
74
75test("signing up from the invite email says the address is confirmed already; otherwise the code step applies", () => {
76 const base = { address: "ada@example.com", emailProven: false, workspace: { name: "Flagon, Inc." }, repository: null };
77 const proven = inviteSignUpCopy({ ...base, emailProven: true });
Merge workspace invitations: nobody joins a workspace without saying yes, people are found by username, your own invites can bring someone in, and nobody is left without a workspace (identity 0040)78 assert.equal(proven.intro, "You can join Flagon, Inc. as soon as you create it: accept the invitation then.");
Merge invite emails that confirm the address: the emailed link carries a proof only that email has, so signing up from it needs no code; shared links and typed codes still confirm79 assert.match(proven.confirmed ?? "", /^ada@example\.com is confirmed: you came here from the invite we emailed to it/);
80 assert.match(proven.hint, /confirmed already/);
81 assert.doesNotMatch(proven.hint, /code/);
82
83 // No proof (a code typed in, or a link passed on): nothing new is said.
84 const plain = inviteSignUpCopy(base);
Merge workspace invitations: nobody joins a workspace without saying yes, people are found by username, your own invites can bring someone in, and nobody is left without a workspace (identity 0040)85 assert.equal(plain.intro, "You can join Flagon, Inc. as soon as you confirm your email: accept the invitation then.");
Merge invite emails that confirm the address: the emailed link carries a proof only that email has, so signing up from it needs no code; shared links and typed codes still confirm86 assert.equal(plain.confirmed, null);
87 assert.equal(plain.hint, "Your invite was sent here. We email it a code to confirm it before you start.");
88
89 // An invite for anyone with the code has no address to prove.
90 const open = inviteSignUpCopy({ ...base, address: null, emailProven: true, workspace: null });
91 assert.equal(open.confirmed, null);
92 assert.equal(open.intro, "It takes a minute.");
93 assert.equal(open.hint, "We email it a code to confirm it before you start.");
94
95 const repo = inviteSignUpCopy({ ...base, workspace: null, repository: { name: "flagon-io/g1t" }, emailProven: true });
96 assert.equal(repo.intro, "You get flagon-io/g1t as soon as you create it.");
97});
98
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look99test("a pasted link or code is tidied to the code", () => {
100 assert.equal(cleanCode(CODE), CODE);
101 assert.equal(cleanCode(` ${CODE} `), CODE);
102 assert.equal(cleanCode(`https://g1t.sh/invite/${CODE}`), CODE);
103 assert.equal(cleanCode(`https://g1t.sh/register?invite=${CODE}&next=%2F`), CODE);
104 assert.equal(cleanCode("g1t-k7m2 q9xd"), "g1t-k7m2q9xd");
105 assert.equal(cleanCode(null), "");
106 assert.equal(cleanCode("x".repeat(500)).length, 80);
107});
108
109test("each invite says where it stands and whom it is for", () => {
110 const base = { redeemedBy: null, email: null, workspace: null };
111 assert.deepEqual(inviteState({ ...base, status: "pending" }), { label: "Pending", tone: "pending" });
112 assert.deepEqual(inviteState({ ...base, status: "redeemed", redeemedBy: "ada" }), { label: "Joined as @ada", tone: "done" });
Merge email confirmation gate: a code and a link, nothing until confirmed (identity 0036)113 assert.deepEqual(inviteState({ ...base, status: "awaiting_confirmation", redeemedBy: "ada" }), {
114 label: "@ada is confirming their email",
115 tone: "pending",
116 });
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look117 assert.deepEqual(inviteState({ ...base, status: "expired" }), { label: "Expired", tone: "dead" });
118 assert.deepEqual(inviteState({ ...base, status: "revoked" }), { label: "Revoked", tone: "dead" });
119 assert.equal(inviteFor({ ...base, status: "pending" }), "Anyone with the link");
Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page)120 assert.equal(inviteFor({ ...base, status: "pending", email: "ada@example.com", workspace: "acme" }), "ada@example.com");
121 assert.equal(inviteFor({ ...base, status: "pending", invitee: "daweazl", workspace: "flagon-io" }), "@daweazl");
122 // Which kind each is, beside whom it is for.
123 assert.deepEqual(inviteKind({ workspace: null }), { kind: "g1t", label: "Invite to g1t" });
124 assert.deepEqual(inviteKind({ workspace: "flagon-io" }), { kind: "workspace", label: "Invite to join flagon-io" });
Merge workspace invitations: nobody joins a workspace without saying yes, people are found by username, your own invites can bring someone in, and nobody is left without a workspace (identity 0040)125 assert.deepEqual(inviteState({ ...base, status: "awaiting_answer", redeemedBy: "daweazl" }), { label: "Waiting for @daweazl to accept", tone: "pending" });
126 assert.deepEqual(inviteState({ ...base, status: "declined", invitee: "daweazl" }), { label: "@daweazl declined", tone: "dead" });
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look127});
128
129test("what is left reads plainly", () => {
130 assert.equal(remainingLine({ limit: 5, used: 2, remaining: 3 }), "3 of 5 invites left");
131 assert.equal(remainingLine({ limit: 1, used: 0, remaining: 1 }), "1 of 1 invite left");
132 assert.equal(remainingLine({ limit: 5, used: 5, remaining: 0 }), "You have used all 5 of your invites");
133 assert.equal(remainingLine({ limit: null, used: 40, remaining: null }), "No limit on your invites");
134});
135
136test("bots that fill the hidden field or answer instantly are turned away", () => {
137 const form = (fields: Record<string, string>) => ({ get: (name: string) => fields[name] ?? null });
138 const now = 1_000_000;
139 assert.equal(looksAutomated(form({ website: "http://spam.example" }), now), true);
140 assert.equal(looksAutomated(form({ started: String(now - 200) }), now), true);
141 assert.equal(looksAutomated(form({ started: String(now - 10_000) }), now), false);
142 assert.equal(looksAutomated(form({}), now), false);
143 assert.equal(looksAutomated(form({ website: " " }), now), false);
144});
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas145
146test("a username is suggested from the invited address", () => {
147 assert.equal(suggestUsername("ada.lovelace@example.com"), "ada-lovelace");
148 assert.equal(suggestUsername("Margaret_Hamilton+g1t@example.com"), "margaret-hamilton");
149 assert.equal(suggestUsername("--x--@example.com"), "x");
150 assert.equal(suggestUsername(`${"a".repeat(38)}.b@example.com`), "a".repeat(38));
151 assert.equal(suggestUsername("...@example.com"), "");
152 assert.equal(suggestUsername(null), "");
153});
154
155test("an invite lands in its workspace, else its repository", () => {
156 assert.equal(landingFor({ workspace: { slug: "Flagon-IO" }, repository: null }), "flagon-io");
157 assert.equal(landingFor({ workspace: null, repository: { name: "flagon-io/g1t" } }), "flagon-io/g1t");
158 assert.equal(landingFor({ workspace: null, repository: null }), null);
159});
160
161test("the welcome is for one place, and ends", () => {
162 const set = welcomeCookie("flagon-io/g1t", true);
163 assert.match(set, /^g1t_welcome=flagon-io%2Fg1t; Path=\/; Max-Age=300; HttpOnly; SameSite=Lax; Secure$/);
164 const header = `a=1; ${set.split(";")[0]}; b=2`;
165 assert.equal(welcomes(header, "flagon-io/g1t"), true);
166 assert.equal(welcomes(header, "flagon-io"), false);
167 assert.equal(welcomes("g1t_welcome=flagon-io", "Flagon-IO"), true);
168 assert.equal(welcomes("g1t_welcome=%E0%A4%A", "flagon-io"), false);
169 assert.equal(welcomes("g1t_welcome=..%2F..%2Fx", "../../x"), false);
170 assert.equal(welcomes(null, "flagon-io"), false);
171 assert.match(clearWelcome(false), /^g1t_welcome=; Path=\/; Max-Age=0; HttpOnly; SameSite=Lax$/);
172});
Merge shared invite links: label, uses, expiry, domains; joined through recorded (identity 0038)173
174test("a shared invite link names its group above the sign-up form", () => {
175 assert.equal(sharedInviteLine("Cloudflare judges"), "Invited as part of Cloudflare judges");
176 assert.equal(sharedInviteLine(" Hacker News readers "), "Invited as part of Hacker News readers");
177 // A one-person invite has no group, and says nothing of the kind.
178 assert.equal(sharedInviteLine(null), null);
179 assert.equal(sharedInviteLine(undefined), null);
180 assert.equal(sharedInviteLine(" "), null);
181});
182
183test("a shared invite link is sign-up with its code filled in", () => {
184 assert.equal(sharedInviteLink(CODE), `https://g1t.sh/register?invite=${CODE}`);
185 assert.equal(sharedInviteLink(CODE, "http://localhost:5173/"), `http://localhost:5173/register?invite=${CODE}`);
186 // The register page reads the code back out of its own link.
187 assert.equal(cleanCode(sharedInviteLink(CODE)), CODE);
188});
189
190test("a shared link limited to domains says which, on the email field", () => {
191 assert.equal(sharedDomainsHint([]), undefined);
192 assert.equal(sharedDomainsHint(null), undefined);
193 assert.equal(sharedDomainsHint(["cloudflare.com"]), "This invite is for addresses at cloudflare.com. Use yours there.");
194 assert.equal(
195 sharedDomainsHint(["a.com", "b.com", "c.com"]),
196 "This invite is for addresses at a.com, b.com or c.com. Use yours there.",
197 );
198});
Merge workspace invitations: nobody joins a workspace without saying yes, people are found by username, your own invites can bring someone in, and nobody is left without a workspace (identity 0040)199
Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page)200test("an invite to g1t can also invite its person to a workspace you own that can add people, never chosen for you", () => {
Merge workspace invitations: nobody joins a workspace without saying yes, people are found by username, your own invites can bring someone in, and nobody is left without a workspace (identity 0040)201 const memberships = [
202 { slug: "flagon-io", name: "Flagon, Inc.", role: "owner" as const },
203 { slug: "side", name: "side", role: "owner" as const },
204 { slug: "friends", name: "Friends", role: "member" as const },
205 ];
Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page)206 // Free ones and ones you only belong to are not offered; nothing is chosen, not even the current one.
Merge workspace invitations: nobody joins a workspace without saying yes, people are found by username, your own invites can bring someone in, and nobody is left without a workspace (identity 0040)207 const here = bringIntoChoices(memberships, ["side"], "flagon-io");
Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page)208 assert.deepEqual(here, { options: [{ slug: "flagon-io", name: "Flagon, Inc." }], note: null });
209 assert.equal("chosen" in here, false);
210 // In a free workspace: not offered, and the form says why.
211 assert.match(bringIntoChoices(memberships, ["side"], "side").note ?? "", /side is on the free plan, so it cannot add people/);
Merge workspace invitations: nobody joins a workspace without saying yes, people are found by username, your own invites can bring someone in, and nobody is left without a workspace (identity 0040)212 // In one you are only a member of.
213 assert.match(bringIntoChoices(memberships, [], "friends").note ?? "", /Only the owners of friends/);
Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page)214 assert.deepEqual(bringIntoChoices([], [], null), { options: [], note: null });
215});
216
217/** A submitted form, as `inviteDraft` reads it. */
218const form = (fields: Record<string, string>) => ({ get: (name: string) => fields[name] ?? null });
219
220test("an invite to g1t sends no workspace unless its box is ticked", () => {
221 // Off by default: a form without the box sends no `join`, even with a workspace left in it.
222 assert.deepEqual(inviteDraft(form({ intent: "create-invite", email: " ada@example.com ", charge: "mine" })), {
223 email: "ada@example.com",
224 workspace: null,
225 });
226 const untickedButFilled = inviteDraft(form({ email: "", join: "flagon-io", join_role: "owner" }));
227 assert.equal("join" in untickedButFilled, false);
228 assert.equal("joinRole" in untickedButFilled, false);
229 assert.equal(untickedButFilled.email, null);
230 // Ticked: the workspace and its role go with it.
231 assert.deepEqual(inviteDraft(form({ also_join: "on", join: "flagon-io", join_role: "owner", charge: "flagon-io" })), {
232 email: null,
233 workspace: "flagon-io",
234 join: "flagon-io",
235 joinRole: "owner",
236 });
237 // Ticked with no workspace chosen: still none. Any role but owner is member.
238 assert.equal("join" in inviteDraft(form({ also_join: "on", join: "" })), false);
239 assert.equal(inviteDraft(form({ also_join: "on", join: "acme", join_role: "admin" })).joinRole, "member");
Merge workspace invitations: nobody joins a workspace without saying yes, people are found by username, your own invites can bring someone in, and nobody is left without a workspace (identity 0040)240});
241
Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page)242test("the invites form keeps the workspace behind an unticked box", () => {
Merge workspace invitations: nobody joins a workspace without saying yes, people are found by username, your own invites can bring someone in, and nobody is left without a workspace (identity 0040)243 const section = readFileSync(new URL("../components/invites-section.tsx", import.meta.url), "utf8");
Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page)244 assert.match(section, /useState\(false\)/);
245 assert.match(section, /name="also_join"/);
246 // The workspace and role fields are drawn only once the box is ticked, so nothing else is sent.
247 assert.match(section, /\{alsoJoin && \(\s*<div[^]*?name="join"[^]*?name="join_role"/);
Chat controls, public profiles, shadcn selects, and no Docs tab in a project248 // No workspace is chosen for them: the select starts on its placeholder, and is required.
249 assert.match(section, /name="join"\s*required\s*placeholder="Choose a workspace"/);
Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page)250 assert.doesNotMatch(section, /bringInto\.chosen|Bring them into/);
251});
252
253test("invites to g1t are made only while sign-up takes one; after that only the list stays", () => {
254 assert.deepEqual(invitesPage("invite", 0), { form: true, listed: true });
255 assert.deepEqual(invitesPage(null, 0), { form: true, listed: true });
256 // Open: no form; the menus list the page only with invites to look back on.
257 assert.deepEqual(invitesPage("open", 0), { form: false, listed: false });
258 assert.deepEqual(invitesPage("open", 3), { form: false, listed: true });
259 assert.match(G1T_INVITES.open, /^Anyone can sign up for g1t now/);
260 assert.match(G1T_INVITES.open, /workspace's People page/);
261});
262
263test("the two invites say which they are", () => {
264 // Settings → Invites: an account, and no workspace.
265 assert.equal(G1T_INVITES.heading, "Invite people to g1t");
266 assert.equal(ACCOUNT_SETTINGS.invites.heading, G1T_INVITES.heading);
267 assert.equal(ACCOUNT_SETTINGS.invites.title, G1T_INVITES.nav);
268 assert.equal(ACCOUNT_SETTINGS.invites.about, G1T_INVITES.about);
269 assert.match(G1T_INVITES.about, /lets one person make an account\. It does not add them to any workspace/);
270 assert.equal(G1T_INVITES.alsoJoin, "Also invite them to a workspace");
271 // A workspace's People page: an invitation to accept or decline, which signs up whoever has no account.
272 const closed = workspaceInviteCopy("Flagon, Inc.", true);
273 assert.equal(closed.heading, "Invite to Flagon, Inc.");
274 assert.match(closed.hint, /invitation to join Flagon, Inc\..*join only if they accept/);
275 assert.match(closed.hint, /If they do not have a g1t account yet, the invitation also lets them sign up/);
276 assert.equal(closed.elsewhere, "To invite someone to g1t without adding them to Flagon, Inc., use Settings → Invites.");
277 // Once anyone can sign up, there is no invite to g1t to point to.
278 const open = workspaceInviteCopy("Flagon, Inc.", false);
279 assert.equal(open.elsewhere, null);
280 assert.doesNotMatch(open.hint, /one of yours/);
281 // Settings → Invites points to the People pages of the workspaces you own, the current one first.
282 assert.deepEqual(
283 peoplePages(
284 [
285 { slug: "side", name: null, role: "owner" },
286 { slug: "Flagon-io", name: "Flagon, Inc.", role: "owner" },
287 { slug: "friends", name: "Friends", role: "member" },
288 ],
289 "flagon-io",
290 ),
291 [
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.292 { slug: "flagon-io", name: "Flagon, Inc.", to: "/flagon-io/-/members" },
293 { slug: "side", name: "side", to: "/side/-/members" },
Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page)294 ],
295 );
296});
297
298test("an invite's page names the invite it is", () => {
299 const base = { kind: "account" as const, invitedBy: { username: "syntaqx" }, workspace: null, repository: null, hasAccount: false };
300 const g1t = invitePageCopy(base, false);
301 assert.equal(`${g1t.before}${g1t.place ?? ""}${g1t.after}`, "@syntaqx invited you to g1t");
302 assert.match(g1t.about, /lets you make an account\. It does not add you to anyone's workspace/);
303 const join = invitePageCopy({ ...base, workspace: { name: "Flagon, Inc." } }, false);
304 assert.equal(`${join.before}${join.place}${join.after}`, "@syntaqx invited you to join Flagon, Inc. on g1t");
305 assert.equal(join.place, "Flagon, Inc.");
306 assert.match(join.about, /invitation to join Flagon, Inc\., which you accept or decline/);
307 assert.match(join.about, /You do not have a g1t account yet, so it also lets you make one/);
308 // Someone with an account, or signed in, just accepts.
309 assert.match(invitePageCopy({ ...base, kind: "workspace", workspace: { name: "Flagon, Inc." }, hasAccount: true }, false).about, /Accepting joins you to Flagon, Inc\./);
310 assert.equal(invitePageCopy({ ...base, invitedBy: null }, false).before, "The g1t team invited you to g1t");
Merge workspace invitations: nobody joins a workspace without saying yes, people are found by username, your own invites can bring someone in, and nobody is left without a workspace (identity 0040)311});

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