Skip to content
206 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.

The sidebar asks billing whether it is on, not for the account, so no page waits on the card processor1import { test } from "node:test";
2import assert from "node:assert/strict";
3
4import { assemble, authorsOf } from "./assemble.ts";
5import { extract } from "./extract.ts";
6import { composeRunContext, HEADER } from "./runcontext.ts";
7import { evaluate } from "./scorecards.ts";
8import { granted } from "../../../packages/contracts/src/access.ts";
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 deploy9import { indexFilter, memoryReadable, merge, readable, allowedKinds, countVisible, runMemoryReadable } from "./visibility.ts";
The sidebar asks billing whether it is on, not for the account, so no page waits on the card processor10
11const project = {
12 id: "prj_1",
13 workspace: "acme",
14 slug: "web",
15 name: "web",
16 description: "The storefront.",
17 private: true,
18 repoId: "rep_1",
19 repo: { namespace: "acme", name: "web" },
20 rootDir: "",
21 defaultBranch: "main",
22};
23const ctx = { project: "web", siblings: ["package-lock.json"] };
24
25test("a project's entities and relations come from its files and surroundings", () => {
26 const files = [
27 { path: "package.json", facts: extract("package.json", JSON.stringify({ name: "@acme/web", scripts: { test: "vitest" }, dependencies: { "@acme/ui": "*" } }), ctx) },
28 { path: "README.md", facts: extract("README.md", "# Web\n\nThe storefront.", ctx) },
29 { path: "wrangler.jsonc", facts: extract("wrangler.jsonc", '{"name":"web","routes":["shop.acme.com/*"]}', ctx) },
30 { path: ".g1t/workflows/ci.yml", facts: extract(".g1t/workflows/ci.yml", "run: npm test", ctx) },
31 ];
32 const built = assemble(project, files, {
33 owners: ["ana"],
34 deploy: { enabled: true, production: { url: "https://web--acme.g1t.page", commit: "abcdef1234", deployedAt: "2026-10-01T00:00:00Z" }, previews: 2, latest: null },
35 integrations: [{ id: "int_1", provider: "sentry", name: "Sentry", kind: "alerts", repo: "acme/web" }],
36 });
37 const keys = built.entities.map((entity) => `${entity.kind}:${entity.key}`);
38 for (const key of ["project:web", "owner:ana", "language:javascript", "package:npm:@acme/web", "doc:web:README.md", "api:web:worker:web", "app:web", "environment:web/production", "environment:web/preview"]) {
39 assert.ok(keys.includes(key), `${key} in ${keys.join(", ")}`);
40 }
41 const relations = built.relations.map((r) => `${r.from.kind}:${r.from.key} ${r.kind} ${r.to.kind}:${r.to.key}`);
42 for (const relation of [
43 "project:web owned_by owner:ana",
44 "project:web documented_by doc:web:README.md",
45 "project:web exposes package:npm:@acme/web",
46 "package:npm:@acme/web depends_on package:npm:@acme/ui",
47 "app:web deploys_to environment:web/production",
48 "app:web exposes api:web:worker:web",
49 "project:web uses language:javascript",
50 "project:web uses integration:int_1",
51 ]) {
52 assert.ok(relations.includes(relation), relation);
53 }
54 assert.equal(built.tests, true);
55 const entry = built.entities.find((entity) => entity.kind === "project")!;
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 deploy56 assert.match(entry.summary!, /The storefront\. Written in JavaScript\. .*Owned by ana\./);
The sidebar asks billing whether it is on, not for the account, so no page waits on the card processor57 assert.equal(entry.data.productionUrl, "https://web--acme.g1t.page");
58});
59
60test("the same inputs build the same catalog", () => {
61 const files = [{ path: "go.mod", facts: extract("go.mod", "module x/y\n", ctx) }];
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 deploy62 const around = { owners: [], deploy: null, integrations: [] };
The sidebar asks billing whether it is on, not for the account, so no page waits on the card processor63 assert.deepEqual(assemble(project, files, around), assemble(project, files, around));
64 // Without deployments there is no app or environment.
65 assert.ok(!assemble(project, files, around).entities.some((entity) => entity.kind === "app" || entity.kind === "environment"));
66});
67
68test("owners are the members who wrote a fifth or more of the recent commits", () => {
69 const commit = (name: string, email = `${name}@example.com`) => ({ author: { name, email } });
70 const commits = [...Array(6)].map(() => commit("Ana")).concat([commit("someone", "bo@acme.com"), commit("bot"), commit("bot"), commit("cy")]);
71 assert.deepEqual(authorsOf(commits, ["ana", "bo", "cy"]), ["ana"]);
72 assert.deepEqual(authorsOf([commit("x", "bo@acme.com")], ["bo"]), ["bo"]);
73 assert.deepEqual(authorsOf([], ["ana"]), []);
74});
75
76test("scorecards pass, fail with a fix, or do not apply", () => {
77 const rules = evaluate({
78 name: "web",
79 owners: [],
80 docs: ["README.md"],
81 tests: false,
82 testCommand: "npm test",
83 deploy: { enabled: true, production: null, latest: { kind: "production", status: "failed", error: "build failed" } },
84 secretFindings: null,
85 });
86 const by = Object.fromEntries(rules.map((rule) => [rule.rule, rule]));
87 assert.equal(by.has_owner.status, "fail");
88 assert.deepEqual(by.has_owner.fix?.checks, ["grep -q '^owners:' .g1t/project.yml"]);
89 assert.equal(by.has_readme.status, "pass");
90 assert.equal(by.has_readme.fix, null);
91 assert.equal(by.has_agents_md.fix?.title, "Add an AGENTS.md to web");
92 assert.match(by.tests_in_ci.fix!.body, /`npm test`/);
93 assert.equal(by.production_green.status, "fail");
94 assert.match(by.production_green.detail, /build failed/);
95 assert.equal(by.no_secret_findings.status, "na");
96 const quiet = evaluate({ name: "lib", owners: ["ana"], docs: ["readme.md", "CLAUDE.md"], tests: true, testCommand: null, deploy: null, secretFindings: 0 });
97 assert.deepEqual(quiet.map((rule) => rule.status), ["pass", "pass", "pass", "pass", "na", "pass"]);
98});
99
100test("the run context marks its sources and keeps to its budget", () => {
101 const input = {
102 projects: [
103 {
104 slug: "web",
105 name: "web",
106 repo: "acme/web",
107 rootDir: "",
108 languages: ["TypeScript"],
109 packages: ["@acme/web"],
110 testCommands: ["npm test"],
111 owners: ["ana"],
112 environments: [{ name: "Production", url: "https://web--acme.g1t.page", status: "ready" }],
113 docs: ["README.md"],
114 },
115 ],
116 memories: [{ id: "mem_1", kind: "gotcha", text: "Tests need TZ=UTC.", source: "AGENTS.md" }],
117 decisions: [{ id: "mem_2", kind: "decision", text: "Decided in #12: keep v1 webhooks.", source: "#12" }],
118 budget: 4000,
119 };
120 const { text, sources } = composeRunContext(input);
121 assert.ok(text!.startsWith(HEADER));
122 assert.match(text!, /Project web \(acme\/web\) \[source: catalog\]:/);
123 assert.match(text!, /\[gotcha\] Tests need TZ=UTC\. \[source: AGENTS\.md\]/);
124 assert.match(text!, /Recent decisions:\n- Decided in #12: keep v1 webhooks\. \[source: #12\]/);
125 assert.deepEqual(sources.sort(), ["catalog:web", "memory:mem_1", "memory:mem_2"]);
126 const tight = composeRunContext({ ...input, budget: HEADER.length + 120 });
127 assert.ok(tight.text!.length <= HEADER.length + 120);
128 assert.deepEqual(composeRunContext({ projects: [], memories: [], decisions: [], budget: 4000 }), { text: null, sources: [] });
129});
130
131test("search reads one workspace, and only what a reader may see", () => {
132 const member = { workspace: "acme", member: true, full: true, visible: new Set<string>() };
133 const outsider = { workspace: "acme", member: false, full: false, visible: new Set(["site"]) };
134 assert.deepEqual(indexFilter(member, {}), { workspace: "acme" });
135 assert.deepEqual(indexFilter(outsider, { project: "site", kinds: ["memory", "doc"] }), { workspace: "acme", private: false, project: "site", kind: { $in: ["doc"] } });
136 assert.ok(!(allowedKinds(outsider) ?? []).includes("memory"));
137 const row = { workspace: "acme", kind: "doc", project: "site", private: false };
138 assert.ok(readable(row, outsider));
139 assert.ok(!readable({ ...row, workspace: "other" }, member), "never another workspace");
140 assert.ok(!readable({ ...row, project: "billing", private: true }, outsider), "a private project not listed for them");
141 assert.ok(!readable({ ...row, kind: "memory" }, outsider), "memory is for members");
142 assert.ok(!readable({ ...row, project: "made-private-since" }, outsider));
143 assert.ok(readable({ ...row, kind: "memory", private: true }, member));
144});
145
146test("a member with no base permission sees only the private projects granted to them", () => {
147 const user = { id: "u", username: "u", kind: "user" as const, workspaces: [{ slug: "acme", role: "member" as const, base_permission: "none" as const }], grants: [{ repo_id: "repo_api", workspace: "acme", role: "read" as const }] };
148 assert.equal(granted(user, { id: "", namespace: "acme", isPrivate: true }), null, "does not read every repository");
149 // What the projects service lists for them: public ones, and the one granted.
150 const reader = { workspace: "acme", member: true, full: false, visible: new Set(["site", "api"]), privateVisible: true, repos: new Set(["acme/site", "acme/api"]) };
151 const row = { workspace: "acme", kind: "issue", project: "api", private: true };
152 assert.ok(readable(row, reader), "the granted private project");
153 assert.ok(!readable({ ...row, project: "billing" }, reader), "another private project");
154 assert.ok(!readable({ ...row, project: "" }, reader), "a private row with no project");
155 assert.ok(readable({ ...row, project: "site", private: false }, reader));
156 assert.ok(readable({ ...row, kind: "memory", project: "" }, reader), "workspace memory is for every member");
157 assert.ok(!readable({ ...row, kind: "memory", project: "billing" }, reader));
158 assert.ok(memoryReadable(null, reader));
159 assert.ok(memoryReadable({ namespace: "Acme", name: "API" }, reader));
160 assert.ok(!memoryReadable({ namespace: "acme", name: "billing" }, reader));
161 assert.ok(!memoryReadable(null, { ...reader, member: false }), "memory is for members");
162 assert.deepEqual(indexFilter(reader, {}), { workspace: "acme" }, "private rows are checked one by one");
163 assert.equal(indexFilter({ ...reader, member: false, privateVisible: false }, {}).private, false);
164});
165
166test("the hub's counts are over what the viewer may read", () => {
167 const rows = [
168 { kind: "project", project: "site", private: 0, n: 1 },
169 { kind: "project", project: "api", private: 1, n: 1 },
170 { kind: "project", project: "billing", private: 1, n: 1 },
171 { kind: "doc", project: "billing", private: 1, n: 7 },
172 { kind: "language", project: null, private: 0, n: 3 },
173 ];
174 const full = { workspace: "acme", member: true, full: true, visible: new Set<string>() };
175 assert.deepEqual(countVisible(rows, full), { project: 3, doc: 7, language: 3 });
176 const none = { workspace: "acme", member: true, full: false, visible: new Set(["site", "api"]), privateVisible: true };
177 assert.deepEqual(countVisible(rows, none), { project: 2, language: 3 }, "billing is not theirs");
178});
179
180test("an agent run is told only what the person it acts for may read", () => {
181 const web = { namespace: "acme", name: "web" };
182 const workspaceMemory = { scope: "workspace", repo: null };
183 const webMemory = { scope: "project", repo: web };
184 const billingMemory = { scope: "project", repo: { namespace: "acme", name: "billing" } };
185 // The workspace's own step: everything.
186 assert.ok(runMemoryReadable(workspaceMemory, null, "acme/web"));
187 // A member who reads everything.
188 const member = { workspace: "acme", member: true, full: true, visible: new Set<string>() };
189 assert.ok(runMemoryReadable(workspaceMemory, member, "acme/web"));
190 assert.ok(runMemoryReadable(billingMemory, member, "acme/web"));
191 // An outside collaborator with Write on acme/web.
192 const outside = { workspace: "acme", member: false, full: false, visible: new Set(["web", "site"]), repos: new Set(["acme/web", "acme/site"]) };
193 assert.ok(!runMemoryReadable(workspaceMemory, outside, "acme/web"), "never the workspace's memory");
194 assert.ok(runMemoryReadable(webMemory, outside, "Acme/Web"), "the project's memory");
195 assert.ok(!runMemoryReadable(billingMemory, outside, "acme/web"));
196 assert.ok(!runMemoryReadable({ scope: "project", repo: { namespace: "acme", name: "site" } }, outside, "acme/web"), "only the run's own project");
197});
198
199test("semantic hits come first, without repeats", () => {
200 const hit = (id: string, score: number) => ({ kind: "doc" as const, id, title: id, snippet: "", project: null, url: null, score, source: "doc", by: null, updatedAt: null });
201 assert.deepEqual(
202 merge([hit("a", 0.5), hit("b", 0.9)], [hit("a", 0.2), hit("c", 0.2)], 10).map((h) => h.id),
203 ["b", "a", "c"],
204 );
205 assert.equal(merge([hit("a", 1)], [hit("b", 1)], 1).length, 1);
206});

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