syntaxai/tdd.md · main · src / d21_handlers_goals.ts

d21_handlers_goals.ts 132 lines · 5493 bytes raw
// c21 — handlers: /goals index + /goals/:slug detail. Mirrors the
// /sama and /blog index+detail pattern. ALL_GOALS is the registry;
// b32_goals_meta parses the YAML frontmatter on each detail page.

import { ALL_GOALS, type GoalEntry, type GoalStatus } from "./a31_goals.ts";
import { parseGoalFrontmatter } from "./b32_goals_meta.ts";
import { renderDocsPage } from "./b51_render_docs_layout.ts";
import { htmlResponse, renderNotFound } from "./b51_render_layout.ts";

const STATUS_LABEL: Record<GoalStatus, string> = {
  shipped: "✓ shipped",
  lossy: "⚠ lossy",
  lost: "✗ lost",
  pending: "⏳ pending",
  abandoned: "✗ abandoned",
};

const LOSSY_BANNER = `> ⚠ **Recovered partially.** The /goal text below was reconstructed from conversation summary, not verbatim from the PR body. Original wording may differ from what the user typed.\n\n`;

const LOST_BLOCK = `> ✗ **Source could not be recovered.** This PR was /goal-driven, but neither the PR body nor any available conversation context preserved the verbatim /goal text. The metadata above is what remains — see the linked PR + merge commit for the implementation, and the related blog posts for narrative context.\n`;

const prLink = (n: number | null): string =>
  n === null ? "—" : `[#${n}](https://github.com/syntaxai/tdd.md/pull/${n})`;

const commitLink = (sha: string | null): string =>
  sha === null ? "—" : `[\`${sha}\`](/GIT/tdd.md/commit/${sha})`;

const relatedLinks = (slugs: ReadonlyArray<string>): string =>
  slugs.map((s) => `[${s}](/blog/${s})`).join(" · ");

const goalsLandingBody = (): string => {
  const sorted = [...ALL_GOALS].sort((a, b) => b.date.localeCompare(a.date));
  if (sorted.length === 0) {
    return `# goals\n\n*No /goals archived yet.*`;
  }
  const rows = sorted
    .map(
      (g: GoalEntry) =>
        `| ${g.date} | [${g.title}](/goals/${g.slug}) | ${STATUS_LABEL[g.status]} | ${prLink(g.prNumber)} | ${commitLink(g.mergeSha)} |`,
    )
    .join("\n");
  return `# goals

The /goal slash commands that drove the work on this site. Each entry is the verbatim contract the agent was held against — *Done when* post-conditions, *Constraints (anti-fudge)*, and *Load-bearing files to read FIRST*. See [the drama post](/blog/2026-05/sama-v2-goal-chain-gap) for why these now live in git.

| date | title | status | PR | commit |
|---|---|---|---|---|
${rows}

Lookup by merge SHA: \`grep -l "merge_sha: <short-sha>" goals/\`. The frontmatter on every file carries the SHA; the canonical permalink is \`/goals/<slug>\`.
`;
};

export const goalsLandingHandler = async (): Promise<Response> => {
  const html = await renderDocsPage({
    title: "goals — tdd.md",
    description:
      "The /goal slash commands that drove every PR on tdd.md, archived as first-class artifacts in git.",
    bodyMarkdown: goalsLandingBody(),
    ogPath: "https://tdd.md/goals",
    active: "goals",
    pathForDocs: "/goals",
    editPathOverride: null,
  });
  return htmlResponse(html);
};

const renderBadges = (entry: { status: GoalStatus; date: string; prNumber: number | null; mergeSha: string | null; relatedPosts: ReadonlyArray<string> }): string => {
  const badges = `**Status:** ${STATUS_LABEL[entry.status]} · **Date:** ${entry.date} · **PR:** ${prLink(entry.prNumber)} · **Commit:** ${commitLink(entry.mergeSha)}`;
  const related = entry.relatedPosts.length === 0
    ? ""
    : `\n\n**Related posts:** ${relatedLinks(entry.relatedPosts)}`;
  return `${badges}${related}`;
};

export const goalSlugHandler = async (
  req: { params: { slug: string } },
): Promise<Response> => {
  const slug = req.params.slug;
  const entry = ALL_GOALS.find((g) => g.slug === slug);
  if (!entry) {
    const html = await renderNotFound(`/goals/${slug}`);
    return htmlResponse(html, 404);
  }

  // status: "lost" — registry entry only, no file on disk. Render
  // metadata-only at 200 (not 404) with the "source could not be
  // recovered" callout. See /blog/2026-05/sama-v2-goal-chain-gap for context.
  if (entry.status === "lost") {
    const body = `# ${entry.title}\n\n${renderBadges(entry)}\n\n---\n\n${LOST_BLOCK}`;
    const html = await renderDocsPage({
      title: `${entry.title} — tdd.md`,
      description: `The /goal command that drove ${entry.title}. Status: lost — source not recoverable.`,
      bodyMarkdown: body,
      ogPath: `https://tdd.md/goals/${slug}`,
      active: "goals",
      pathForDocs: `/goals/${slug}`,
    });
    return htmlResponse(html);
  }

  const file = Bun.file(`./goals/${slug}.md`);
  if (!(await file.exists())) {
    const html = await renderNotFound(`/goals/${slug}`);
    return htmlResponse(html, 404);
  }
  const raw = await file.text();
  const parsed = parseGoalFrontmatter(raw);
  if (parsed === null) {
    const html = await renderNotFound(`/goals/${slug}`);
    return htmlResponse(html, 404);
  }

  // status: "lossy" — prepend the recovered-partially banner so the
  // rendered page is unambiguous about provenance.
  const bodyContent = entry.status === "lossy"
    ? `${LOSSY_BANNER}${parsed.body}`
    : parsed.body;

  const body = `# ${entry.title}\n\n${renderBadges(entry)}\n\n---\n\n${bodyContent}`;

  const html = await renderDocsPage({
    title: `${entry.title} — tdd.md`,
    description: `The /goal command that drove ${entry.title}. Status: ${entry.status}.`,
    bodyMarkdown: body,
    ogPath: `https://tdd.md/goals/${slug}`,
    active: "goals",
    pathForDocs: `/goals/${slug}`,
  });
  return htmlResponse(html);
};