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.

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