Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

72 linesCodeBlameRaw
1import assert from "node:assert/strict";
2import { readFileSync, existsSync } from "node:fs";
3import { test } from "node:test";
4import { FEATURES } from "../apps/web/app/lib/features.ts";
5
6const read = (path) => readFileSync(new URL(`../${path}`, import.meta.url), "utf8").replaceAll("\r\n", "\n");
7
8test("llms.txt follows the heading and file-list format and preserves the detailed guide", () => {
9 const index = read("apps/web/public/llms.txt");
10 assert.match(index, /^# g1t\n\n> /);
11 for (const section of index.split(/^## .+$/m).slice(1)) {
12 const lines = section.trim().split("\n").filter(Boolean);
13 assert.ok(lines.length > 0);
14 for (const line of lines) assert.match(line, /^- \[[^\]]+\]\(https:\/\/[^)]+\)(: .+)?$/);
15 }
16 for (const url of ["/features", "/developers", "/agents.md", "/openapi.json", "/reference/versioning.md", "/settings/tokens"])
17 assert.ok(index.includes(url), url);
18 assert.match(read("apps/web/public/agents.md"), /## Set someone up/);
19});
20
21test("agent guides name work items, not the issues they replaced", () => {
22 // Issues became workspace work items: no /repos/…/issues routes, no
23 // issues:* scopes and no `issue` MCP tool remain (see
24 // apps/docs/src/content/docs/work/from-issues.md).
25 const stale = [
26 [/\/issues\b/, "an /issues route"],
27 [/\bissues:(read|write)\b/, "an issues:* scope"],
28 [/`issue`|"name": *"issue"/, "an MCP tool named issue"],
29 [/\bkeep_issue_open\b|\bis:issue\b|\bg1t issue\b|\bg1t work context\b/, "a renamed field, qualifier or command"],
30 ];
31 for (const path of ["apps/web/public/agents.md", "apps/web/public/llms.txt", "apps/web/public/install/claude.sh"]) {
32 const text = read(path);
33 for (const [pattern, what] of stale) {
34 const found = text.match(pattern);
35 assert.equal(found, null, `${path} still names ${what}: ${found?.[0]}`);
36 }
37 }
38 const guide = read("apps/web/public/agents.md");
39 for (const text of ["`work_item`", "/workspaces/{workspace}/work", "work:write", "is:item", "keep_item_open", "/-/work/sessions"])
40 assert.ok(guide.includes(text), text);
41});
42
43test("features is routed, discoverable on desktop and mobile, and has real documentation targets", () => {
44 assert.match(read("apps/web/app/routes.ts"), /route\("features", "routes\/features.tsx"\)/);
45 assert.match(read("apps/web/app/routes/sitemap-xml.ts"), /"\/features"/);
46 const header = read("apps/web/app/components/public-header.tsx");
47 assert.match(header, /<HeaderLink to="\/features">Features<\/HeaderLink>/);
48 assert.match(header, /<Link to="\/features">/);
49 assert.equal(new Set(FEATURES.map((f) => f.id)).size, FEATURES.length);
50 for (const feature of FEATURES)
51 for (const link of feature.links) {
52 if (!link.href.startsWith("https://docs.g1t.sh/")) continue;
53 const slug = new URL(link.href).pathname.replace(/\/$/, "");
54 assert.ok(
55 ["md", "mdx"].some((ext) => existsSync(new URL(`../apps/docs/src/content/docs${slug}.${ext}`, import.meta.url))),
56 link.href,
57 );
58 }
59});
60
61test("built developer pages have branded headings, canonical URLs and Markdown counterparts", () => {
62 for (const slug of ["reference/developers", "reference/versioning", "reference/api", "reference/mcp", "guides/authentication"]) {
63 const html = read(`apps/docs/dist/${slug}/index.html`);
64 assert.match(html, /<title>g1t /);
65 assert.match(html, /<h1[^>]*[^]*?>g1t /);
66 assert.ok(html.includes(`https://docs.g1t.sh/${slug}/`));
67 assert.match(read(`apps/docs/dist/${slug}.md`), /^# g1t /);
68 }
69 const policy = read("apps/docs/dist/reference/versioning.md");
70 for (const text of ["X-G1t-Api-Version", "Deprecation", "Sunset", 'rel="deprecation"', "No REST version is currently deprecated"])
71 assert.ok(policy.includes(text), text);
72});