g1t/apps/web/app/lib/checklist.test.ts

122 lines4,836 bytesCodeBlame

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 {
5 type ChecklistFacts,
6 agentWasAssigned,
7 dismiss,
8 dismissKey,
9 hasInstructions,
10 isDismissed,
11 productionChecklist,
12 progress,
A project is an app or a library: libraries show their package and how to ship a release, not production13 releaseChecklist,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look14} from "./checklist.ts";
15
16const fresh: ChecklistFacts = {
17 base: "/acme/web",
18 hasCode: false,
19 deploysEnabled: false,
20 productionDeployed: false,
21 domains: 0,
22 previewOpened: false,
23 instructions: false,
24 agentAssigned: false,
25};
26
27test("a new project has everything to do, in order", () => {
28 const items = productionChecklist(fresh);
29 assert.deepEqual(
30 items.map((item) => item.key),
31 ["code", "deploy", "domain", "preview", "instructions", "agent"],
32 );
33 assert.deepEqual(progress(items), { done: 0, total: 6, complete: false });
34});
35
36test("each step is done from its own fact", () => {
37 const items = productionChecklist({ ...fresh, hasCode: true, productionDeployed: true, domains: 2 });
38 assert.deepEqual(progress(items), { done: 3, total: 6, complete: false });
39 const all = productionChecklist({
40 ...fresh,
41 hasCode: true,
42 productionDeployed: true,
43 domains: 1,
44 previewOpened: true,
45 instructions: true,
46 agentAssigned: true,
47 });
48 assert.equal(progress(all).complete, true);
49});
50
51test("unknown facts count as not done", () => {
52 const items = productionChecklist({ ...fresh, domains: null, instructions: null });
53 assert.equal(items.find((item) => item.key === "domain")?.done, false);
54 assert.equal(items.find((item) => item.key === "instructions")?.done, false);
55});
56
57test("each step links to where it is done", () => {
58 const off = productionChecklist(fresh);
59 assert.equal(off.find((item) => item.key === "deploy")?.to, "/acme/web/settings/deployments");
60 const on = productionChecklist({ ...fresh, deploysEnabled: true });
61 assert.equal(on.find((item) => item.key === "deploy")?.to, "/acme/web/deployments");
62 assert.equal(on.find((item) => item.key === "domain")?.to, "/acme/web/settings/domains");
63 assert.equal(on.find((item) => item.key === "agent")?.to, "/acme/web/issues/new");
64});
65
66test("instructions are AGENTS.md or CLAUDE.md at the root", () => {
67 assert.equal(hasInstructions(["README.md", "AGENTS.md"]), true);
68 assert.equal(hasInstructions(["claude.md"]), true);
69 assert.equal(hasInstructions(["README.md", "AGENTS.mdx", "docs"]), false);
70});
71
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent72test("g1t counts as assigned from a run, a pull request or an issue", () => {
73 const none = { runAgents: ["claude-code"], pullAgents: ["claude-code"], issues: [{ assignees: ["ana"], agent: null }] };
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look74 assert.equal(agentWasAssigned(none), false);
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent75 assert.equal(agentWasAssigned({ ...none, runAgents: ["g1t"] }), true);
76 assert.equal(agentWasAssigned({ ...none, pullAgents: ["g1t"] }), true);
77 assert.equal(agentWasAssigned({ ...none, issues: [{ assignees: ["G1T"], agent: null }] }), true);
78 assert.equal(agentWasAssigned({ ...none, issues: [{ assignees: [], agent: "g1t" }] }), true);
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look79});
80
81test("dismissing is remembered per project, and storage that throws is ignored", () => {
82 const map = new Map<string, string>();
83 const store = { getItem: (key: string) => map.get(key) ?? null, setItem: (key: string, value: string) => void map.set(key, value) };
84 assert.equal(isDismissed(() => store, "/acme/web"), false);
85 assert.equal(dismiss(() => store, "/Acme/Web"), true);
86 assert.equal(isDismissed(() => store, "/acme/web"), true);
87 assert.equal(isDismissed(() => store, "/acme/api"), false);
88 assert.equal(dismissKey("/Acme/Web"), "g1t:checklist-dismissed:/acme/web");
89 const blocked = {
90 getItem: () => {
91 throw new Error("blocked");
92 },
93 setItem: () => {
94 throw new Error("blocked");
95 },
96 };
97 assert.equal(isDismissed(() => blocked, "/acme/web"), false);
98 assert.equal(dismiss(() => blocked, "/acme/web"), false);
99});
A project is an app or a library: libraries show their package and how to ship a release, not production100
101test("a library's checklist ships a release instead of deploying", () => {
102 const facts = {
103 base: "/flagon-io/php-log",
104 hasCode: true,
105 instructions: false,
106 agentAssigned: false,
107 hasWorkflow: false,
108 released: true,
109 releaseTo: "/flagon-io/-/packages/composer/psr/log",
110 };
111 const items = releaseChecklist(facts);
112 assert.deepEqual(
113 items.map((item) => item.key),
114 ["code", "checks", "release", "instructions", "agent"],
115 );
116 assert.deepEqual(progress(items), { done: 2, total: 5, complete: false });
117 assert.equal(items.find((item) => item.key === "checks")?.to, "/flagon-io/php-log/actions");
118 assert.equal(items.find((item) => item.key === "release")?.to, "/flagon-io/-/packages/composer/psr/log");
119 assert.ok(items.every((item) => !/deploy|production|domain|preview/i.test(item.title)));
120 // An unknown workflow list counts as not done.
121 assert.equal(releaseChecklist({ ...facts, hasWorkflow: null }).find((item) => item.key === "checks")?.done, false);
122});