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.
| Merge memory from docs: only docs on how to work here, whole sentences, no near-duplicates, stale doc suggestions cleared | 1 | import { test } from "node:test"; |
| 2 | import assert from "node:assert/strict"; | |
| 3 | ||
| 4 | import { assemble } from "./assemble.ts"; | |
| 5 | import { extract } from "./extract.ts"; | |
| 6 | import { aspirational, bulletsOf, classify, harvestable, planLike, sentencesOf, wholeSentences } from "./harvest.ts"; | |
| 7 | ||
| 8 | const ctx = { project: "g1t", siblings: [] }; | |
| 9 | ||
| 10 | test("memory comes from docs on how to work here, never plans, feedback or history", () => { | |
| 11 | for (const path of ["README.md", "AGENTS.md", "CLAUDE.md", "CONTRIBUTING.md"]) { | |
| 12 | const role = path.startsWith("README") ? "readme" : path.startsWith("CONTRIBUTING") ? "contributing" : "agents"; | |
| 13 | assert.ok(harvestable(path, role), path); | |
| 14 | } | |
| 15 | for (const path of ["docs/DEPLOYING.md", "docs/testing.md", "docs/architecture.md", "docs/SELF_HOSTING.md", "runbooks/restore.md", "docs/getting-started.md"]) { | |
| 16 | assert.ok(harvestable(path, "doc"), path); | |
| 17 | } | |
| 18 | for (const path of ["docs/PLAN.md", "docs/CLOUDFLARE_FEEDBACK.md", "docs/CHANGELOG.md", "docs/roadmap.md", "docs/DEMO.md", "docs/INCIDENTS.md", "docs/PERFORMANCE.md", "docs/release-notes.md"]) { | |
| 19 | assert.ok(!harvestable(path, "doc"), path); | |
| 20 | } | |
| 21 | // project.yml adds a doc, or leaves one out, and leaving out wins. | |
| 22 | assert.ok(harvestable("docs/PERFORMANCE.md", "doc", { docs: ["docs/PERFORMANCE.md"], skip: [] })); | |
| 23 | assert.ok(harvestable("docs/notes/x.md", "doc", { docs: ["docs/notes/*"], skip: [] })); | |
| 24 | assert.ok(!harvestable("README.md", "readme", { docs: [], skip: ["README.md"] })); | |
| 25 | assert.ok(!harvestable("docs/testing.md", "doc", { docs: ["docs/testing.md"], skip: ["docs/*"] })); | |
| 26 | }); | |
| 27 | ||
| 28 | const FEEDBACK = `# Building a platform: a field report | |
| 29 | ||
| 30 | ### A1. What is a billable operation? (blocking) | |
| 31 | ||
| 32 | - **What we tried.** Price from cost: pass storage through to each workspace with a modest | |
| 33 | uniform overhead, so a bill tracks what it really costs us. | |
| 34 | - **What we hit.** Pricing defines operations only loosely. | |
| 35 | - **What it means.** Our capacity model gives a 15x spread. | |
| 36 | - **Ask.** A table: each binding method and each endpoint, billable or not. | |
| 37 | ||
| 38 | ### Conventions we would like | |
| 39 | ||
| 40 | - **Ask.** Metrics with the same event names as the invoice, per repository. | |
| 41 | `; | |
| 42 | ||
| 43 | const PLAN = `# Plan | |
| 44 | ||
| 45 | ## For people who do not write code | |
| 46 | ||
| 47 | - **Roles.** A person can plan and approve work without ever cloning a | |
| 48 | repo. The roles that were sketched here map onto the five repository | |
| 49 | roles that are built. | |
| 50 | ||
| 51 | ### Rules every automation obeys | |
| 52 | ||
| 53 | - **Deduplication.** The same Sentry issue firing 500 times maps to one | |
| 54 | issue. | |
| 55 | - **Loop protection.** Work started by an automation cannot retrigger the | |
| 56 | same automation without a person in between. | |
| 57 | ||
| 58 | ## Roadmap | |
| 59 | ||
| 60 | ## Later | |
| 61 | ||
| 62 | - g1t will learn from docs. | |
| 63 | `; | |
| 64 | ||
| 65 | test("a doc that reads as feedback or a plan says nothing, whatever its name", () => { | |
| 66 | assert.ok(planLike(FEEDBACK)); | |
| 67 | assert.deepEqual(extract("CONTRIBUTING.md", FEEDBACK, ctx).hints, []); | |
| 68 | assert.ok(planLike(PLAN)); | |
| 69 | assert.deepEqual(extract("docs/testing.md", PLAN, ctx).hints, []); | |
| 70 | const files = [ | |
| 71 | { path: "docs/PLAN.md", facts: extract("docs/PLAN.md", "# Working on g1t\n\n## Conventions\n\n- Run the whole suite before you push, every time.\n", ctx) }, | |
| 72 | { path: "docs/CLOUDFLARE_FEEDBACK.md", facts: extract("docs/CLOUDFLARE_FEEDBACK.md", FEEDBACK, ctx) }, | |
| 73 | ]; | |
| 74 | const project = { id: "p", workspace: "w", slug: "g1t", name: "g1t", description: null, private: false, repoId: "r", repo: { namespace: "w", name: "g1t" }, rootDir: "", defaultBranch: "main" }; | |
| 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 deploy | 75 | const around = { owners: [], deploy: null, integrations: [] }; |
| Merge memory from docs: only docs on how to work here, whole sentences, no near-duplicates, stale doc suggestions cleared | 76 | assert.deepEqual(assemble(project, files, around).hints, [], "docs/PLAN.md is not a source of memory"); |
| 77 | // Unless project.yml says it is. | |
| 78 | const withConfig = [...files, { path: ".g1t/project.yml", facts: extract(".g1t/project.yml", "memory:\n docs:\n - docs/PLAN.md\n", ctx) }]; | |
| 79 | assert.deepEqual(assemble(project, withConfig, around).hints.map((hint) => hint.path), ["docs/PLAN.md"]); | |
| 80 | }); | |
| 81 | ||
| 82 | test("a bullet is taken whole, with the lines it wraps onto", () => { | |
| 83 | const bullets = bulletsOf( | |
| 84 | "## Conventions\n\n- **Loop protection.** Work started by an automation cannot retrigger the\n same automation without a person in between.\n- Short one.\n\nA paragraph.\n\n```\n- not a bullet\n```\n", | |
| 85 | ); | |
| 86 | assert.deepEqual(bullets, [ | |
| 87 | { text: "**Loop protection.** Work started by an automation cannot retrigger the same automation without a person in between.", heading: "Conventions" }, | |
| 88 | { text: "Short one.", heading: "Conventions" }, | |
| 89 | ]); | |
| 90 | // Bullets in a plan section, and its subsections, are left out. | |
| 91 | assert.deepEqual(bulletsOf("## Roadmap\n\n### Next\n\n- One.\n\n## Testing\n\n- Two.\n").map((b) => b.text), ["Two."]); | |
| 92 | }); | |
| 93 | ||
| 94 | test("never cut inside a sentence: whole sentences up to the limit, or nothing", () => { | |
| 95 | assert.deepEqual(sentencesOf("Run `npm test` first. It reads README.md, e.g. the setup. Done!"), [ | |
| 96 | "Run `npm test` first.", | |
| 97 | "It reads README.md, e.g. the setup.", | |
| 98 | "Done!", | |
| 99 | ]); | |
| 100 | assert.equal(wholeSentences("Short and whole", 40), "Short and whole"); | |
| 101 | assert.equal(wholeSentences("First sentence is here. Second sentence pushes it past the limit.", 30), "First sentence is here."); | |
| 102 | assert.equal(wholeSentences("One very long sentence that never ends before the limit is reached at all", 30), null); | |
| 103 | }); | |
| 104 | ||
| 105 | test("plans and wishes are not memory; kinds are earned, not assumed", () => { | |
| 106 | assert.ok(aspirational("g1t will learn from docs.", "doc")); | |
| 107 | assert.ok(aspirational("Tests should run on every push.", "contributing")); | |
| 108 | assert.ok(aspirational("**Ask.** A usage endpoint.", "doc")); | |
| 109 | assert.ok(aspirational("**What we tried.** Pass storage through.", "doc")); | |
| 110 | assert.ok(!aspirational("Run `cargo test` in the crate you changed.", "contributing")); | |
| 111 | // In AGENTS.md "should" states a rule. | |
| 112 | assert.ok(!aspirational("You should run the formatter before committing.", "agents")); | |
| 113 | assert.ok(aspirational("TODO: document the release flow.", "agents")); | |
| 114 | ||
| 115 | assert.deepEqual(classify("Never edit generated files by hand.", "Conventions", "contributing"), { kind: "gotcha", confidence: 0.6 }); | |
| 116 | assert.deepEqual(classify("Use the shared client for every call.", "Conventions", "contributing"), { kind: "convention", confidence: 0.6 }); | |
| 117 | assert.deepEqual(classify("The API lives in apps/api and serves api.g1t.sh.", "Conventions", "readme"), { kind: "fact", confidence: 0.5 }); | |
| 118 | }); | |
| 119 | ||
| 120 | test("CONTRIBUTING's before-you-push bullets are suggested whole; nothing is cut", () => { | |
| 121 | const facts = extract( | |
| 122 | "CONTRIBUTING.md", | |
| 123 | "# Contributing\n\n## Before you push\n\n- `cargo test` in the crate or service you changed.\n- `npx tsc -b --force` in `apps/web` (the incremental build misses changes\n in `packages/contracts`).\n- Look at what you changed in a browser. Screenshots catch what type\n checks do not.\n\n## Deploying\n\nPushes to `main` deploy themselves.\n", | |
| 124 | ctx, | |
| 125 | ); | |
| 126 | assert.deepEqual( | |
| 127 | facts.hints.map((hint) => [hint.kind, hint.text, hint.confidence]), | |
| 128 | [ | |
| 129 | ["fact", "`cargo test` in the crate or service you changed.", 0.5], | |
| 130 | ["fact", "`npx tsc -b --force` in `apps/web` (the incremental build misses changes in `packages/contracts`).", 0.5], | |
| 131 | ["convention", "Look at what you changed in a browser. Screenshots catch what type checks do not.", 0.6], | |
| 132 | ], | |
| 133 | ); | |
| 134 | for (const hint of facts.hints) assert.match(hint.text, /[.!?)`]$/); | |
| 135 | }); |
This file's history is long; its oldest lines are credited to the oldest commit read.