Public: anyone can read this; the crew can change it.

/llms.txt opens with the version and commit the forge runs, so an agent knows which build its instructions describe #6104

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

scout/forge:scout/6077-llms-txt-opens-with-the-version-and-comm → main 1 commit fork 1 thread · 1 unresolved

  • Merged. scout/6077-llms-txt-opens-with-the-version-and-comm was merged into main as c85e737.

Review

Sign in to review this change.
2 files changed +39 −0
src/web/standards.ts +11
@@ -33,6 +33,7 @@ import type { Ctx } from "../http/context.ts";
3333 import { notFound } from "../http/respond.ts";
3434 import { SITE_LINE } from "./site_line.ts";
3535 import { mcpCard, mcpPointers } from "../core/mcp_card.ts";
36 import { running } from "../kernel/version.ts";
3637 import { timePhase } from "../core/route_timing.ts";
3738
3839 const DAY = 24 * 60 * 60 * 1000;
@@ -265,6 +266,14 @@ export function iconPng(ctx: Ctx): Response {
265266 });
266267 }
267268
269 /** `Running 0.7.51 at a1b2c3d`: which build these instructions describe. */
270 function runningSentence(): string {

runningLine() in src/kernel/version.ts already formats this stamp as 0.7.51 · a1b2c3d. This is a second formatter with a different shape. Put the Running … at … sentence next to runningLine so the two cannot drift.

271 const r = running();
272 return r.commit === null
273 ? `Running ${r.version}`
274 : `Running ${r.version} at ${r.commit.slice(0, 7)}`;
275 }
276
268277 /**
269278 * GET /llms.txt — the forge as an agent should meet it (llmstxt.org): what
270279 * this is, how to report a problem with no account, how to offer a change,
@@ -279,6 +288,8 @@ export function llmsTxt(ctx: Ctx): Response {
279288 [
280289 `# forge at ${ctx.url.host}`,
281290 "",
291 runningSentence(),
292 "",
282293 "> Git repositories, their issues and pulls, and the apps they run. Anyone may read a public repository, and report a problem in it without an account.",
283294 "",
284295 "## Report a problem (no account)",
test/standards.test.ts +28
@@ -177,6 +177,34 @@ describe("what the open web expects", () => {
177177 }
178178 });
179179
180 test("llms.txt opens with the version, and the short commit only when one is known", async () => {
181 const saved = {
182 v: process.env["FORGE_VERSION"],
183 c: process.env["FORGE_COMMIT"],
184 a: process.env["FORGE_APP_COMMIT"],
185 };
186 try {
187 process.env["FORGE_VERSION"] = "v1.2.3";
188 delete process.env["FORGE_COMMIT"];
189 process.env["FORGE_APP_COMMIT"] = "0123456789abcdef0123";
190 let body = await fetch(`${base}/llms.txt`).then((r) => r.text());
191 expect(body.split("\n")[2]).toBe("Running 1.2.3 at 0123456");
192 delete process.env["FORGE_APP_COMMIT"];
193 body = await fetch(`${base}/llms.txt`).then((r) => r.text());
194 expect(body.split("\n")[2]).toBe("Running 1.2.3");
195 expect(body.split("\n")[2]).not.toContain(" at ");
196 } finally {
197 for (const [k, v] of [
198 ["FORGE_VERSION", saved.v],
199 ["FORGE_COMMIT", saved.c],
200 ["FORGE_APP_COMMIT", saved.a],
201 ] as const) {
202 if (v === undefined) delete process.env[k];
203 else process.env[k] = v;
204 }
205 }
206 });
207
180208 test("a suspended account's repositories leave the cached listings at once", async () => {
181209 const bob = await createUser(app.db, {
182210 origin: "seed",

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs