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

d21_handlers_reports.ts 191 lines · 8581 bytes raw
// c21 — handlers: the /reports cluster. Demo mockup pages plus the
// live readout assembled from the deploy-time commit + test bundles.
// Extracted from c21_app.ts per the SAMA Atomic rule.

import {
  renderPage,
  renderNotFound,
  htmlResponse,
} from "./b51_render_layout.ts";
import {
  reportsLandingMd,
  execSummaryMd,
  agentDrilldownMd,
  testsOverviewMd,
} from "./b51_render_reports.ts";
import {
  DEMO_REPORTS,
  DEMO_PERIOD,
  DEMO_ORG,
  DEMO_REPOS,
  DEMO_SNAPSHOTS,
  DEMO_STABILITY,
} from "./a31_reports_demo.ts";
import { buildLiveReports } from "./c14_real_reports.ts";
import { buildLiveTestData } from "./c14_real_tests.ts";
import {
  LIVE_REPO_OWNER,
  LIVE_REPO_NAME,
  LIVE_FETCH_COUNT,
} from "./a31_site_config.ts";

// -------- shared banners + context builders --------

const DEMO_BANNER_HTML = `<div class="report-mockup-banner">demo data — design preview with synthetic numbers. Want the real readout? <a href="/reports/live">/reports/live</a> renders the same shape from live tdd.md commits. <a href="/blog/2026-05/tweag-handbook-tdd">why tdd.md needs this</a></div>`;

const LIVE_BANNER_HTML = `<div class="report-mockup-banner">live data — sourced from <a href="https://github.com/${LIVE_REPO_OWNER}/${LIVE_REPO_NAME}">${LIVE_REPO_OWNER}/${LIVE_REPO_NAME}</a> via the public commits API (5-min cache). Agent attribution comes from <code>Co-Authored-By:</code> footers; commits without one are excluded. Phase coverage measures % of commits tagged <code>red:/green:/refactor:</code>.</div>`;

const demoContext = () => ({
  reports: DEMO_REPORTS,
  period: DEMO_PERIOD,
  scopeLabel: `${DEMO_REPOS} repos · ${DEMO_ORG}`,
  bannerHtml: DEMO_BANNER_HTML,
  narrative: {
    changedHeading: "what changed this quarter",
    changedBody:
      "Cursor's score dropped 15 points after agent-mode became default in March; test-deletion incidents climbed from 2% to 14% of refactor commits, concentrated in the `api-gateway` repo. Claude Code's score rose after a phase-tagged commit prefix was added to CLAUDE.md at the end of January. Aider stays steadily high — auto-commit-per-edit prevents most cross-phase cheating on its own.",
    doingHeading: "what we're doing",
    doingBody:
      "- **Cursor in `api-gateway`**: agent-mode disabled for refactor prompts, CONVENTIONS rule \"never delete a test in a refactor commit\" pinned ([details →](/reports/demo/agents/cursor)).\n- **Roll out Claude Code**: copy the CLAUDE.md template that worked in `billing-service` to the other three repos.\n- **Next reading**: 2026-04-30, mid-Q2, to check whether the Cursor fix holds.",
  },
  footerLinks:
    "[per-agent drill-down: Claude Code](/reports/demo/agents/claude-code) · [Cursor](/reports/demo/agents/cursor) · [Aider](/reports/demo/agents/aider) · [tests overview](/reports/demo/tests) · [back to /reports](/reports)",
});

const liveContext = async () => {
  const live = await buildLiveReports(LIVE_REPO_OWNER, LIVE_REPO_NAME, LIVE_FETCH_COUNT);
  const period = live.earliest && live.latest
    ? `${live.earliest.slice(0, 10)} → ${live.latest.slice(0, 10)}`
    : "no commits fetched";
  const drillLinks = live.reports
    .map((r) => `[${r.name}](/reports/live/agents/${r.slug})`)
    .join(" · ");
  return {
    reports: live.reports,
    period,
    scopeLabel: `${LIVE_REPO_OWNER}/${LIVE_REPO_NAME} · ${live.totalCommits} commits sampled${live.unknownCount > 0 ? ` (${live.unknownCount} unattributed, excluded)` : ""}`,
    bannerHtml: LIVE_BANNER_HTML,
    footerLinks: `${drillLinks ? drillLinks + " · " : ""}[tests overview](/reports/live/tests) · [demo preview](/reports/demo) · [back to /reports](/reports)`,
  };
};

// -------- /reports landing --------

export const reportsLandingHandler = async (): Promise<Response> => {
  const html = await renderPage({
    title: "Reports — tdd.md",
    description: "Per-agent TDD-discipline reporting over real project repos: trend, failure-mode breakdown, and an exec summary fit for a quarterly readout.",
    bodyMarkdown: reportsLandingMd(),
    ogPath: "https://tdd.md/reports",
    noindex: true,
  });
  return htmlResponse(html);
};

// -------- /reports/demo --------

export const reportsDemoHandler = async (): Promise<Response> => {
  const ctx = demoContext();
  const html = await renderPage({
    title: "TDD-discipline report · Q1 2026 (demo) — tdd.md",
    description: "Mockup of the management-level TDD-discipline report — single page, three agents, with trend and narrative.",
    bodyMarkdown: execSummaryMd(ctx),
    ogPath: "https://tdd.md/reports/demo",
    noindex: true,
  });
  return htmlResponse(html);
};

export const reportsDemoTestsHandler = async (): Promise<Response> => {
  const html = await renderPage({
    title: "Tests overview (demo) — tdd.md",
    description: "Mockup of the per-test overview: current pass/fail snapshot per repo plus test stability over the quarter.",
    bodyMarkdown: testsOverviewMd({
      period: DEMO_PERIOD,
      bannerHtml: DEMO_BANNER_HTML,
      snapshots: DEMO_SNAPSHOTS,
      stability: DEMO_STABILITY,
    }),
    ogPath: "https://tdd.md/reports/demo/tests",
    noindex: true,
  });
  return htmlResponse(html);
};

export const reportsDemoAgentHandler = async (req: { params: { slug: string } }): Promise<Response> => {
  const slug = req.params.slug as (typeof DEMO_REPORTS)[number]["slug"];
  const ctx = demoContext();
  const md = agentDrilldownMd(slug, ctx);
  if (!md) {
    const html = await renderNotFound(`/reports/demo/agents/${slug}`);
    return htmlResponse(html, 404);
  }
  const entry = DEMO_REPORTS.find((r) => r.slug === slug)!;
  const html = await renderPage({
    title: `${entry.name} drill-down (demo) — tdd.md`,
    description: `Per-agent drill-down mockup for ${entry.name}: trend, failure-mode breakdown, recent flagged commits with coaching links.`,
    bodyMarkdown: md,
    ogPath: `https://tdd.md/reports/demo/agents/${slug}`,
    noindex: true,
  });
  return htmlResponse(html);
};

// -------- /reports/live --------

export const reportsLiveHandler = async (): Promise<Response> => {
  const ctx = await liveContext();
  const html = await renderPage({
    title: "TDD-discipline report · live — tdd.md",
    description: `Live discipline report built from the real commit history of syntaxai/tdd.md (last ${LIVE_FETCH_COUNT} commits, 5-min cache).`,
    bodyMarkdown: execSummaryMd(ctx),
    ogPath: "https://tdd.md/reports/live",
    noindex: true,
  });
  return htmlResponse(html);
};

export const reportsLiveTestsHandler = async (): Promise<Response> => {
  const data = await buildLiveTestData(LIVE_REPO_OWNER, LIVE_REPO_NAME);
  const ranOn = data.ranAt ? new Date(data.ranAt).toISOString().slice(0, 10) : null;
  const period = data.runsCount === 0
    ? "no runs in bundle"
    : `last run ${ranOn} · ${data.runsCount} run${data.runsCount === 1 ? "" : "s"} cumulative`;
  const unavailableNote = data.runsCount === 0
    ? "No test runs bundled yet. The next deploy will run `bun test --reporter=junit` on the current HEAD and publish the result here. Stability (flaky %, deletion) builds up as more runs land in the bundle — the demo at [/reports/demo/tests](/reports/demo/tests) shows where this is heading."
    : undefined;
  const html = await renderPage({
    title: "Tests overview · live — tdd.md",
    description: `Live test snapshot of ${LIVE_REPO_OWNER}/${LIVE_REPO_NAME} — ${data.runsCount} run${data.runsCount === 1 ? "" : "s"} bundled.`,
    bodyMarkdown: testsOverviewMd({
      period,
      bannerHtml: LIVE_BANNER_HTML,
      snapshots: data.snapshots,
      stability: data.stability,
      unavailableNote,
      placeholderTests: data.placeholderTests,
    }),
    ogPath: "https://tdd.md/reports/live/tests",
  });
  return htmlResponse(html);
};

export const reportsLiveAgentHandler = async (req: { params: { slug: string } }): Promise<Response> => {
  const ctx = await liveContext();
  const slug = req.params.slug as (typeof DEMO_REPORTS)[number]["slug"];
  const md = agentDrilldownMd(slug, ctx);
  if (!md) {
    const html = await renderNotFound(`/reports/live/agents/${slug}`);
    return htmlResponse(html, 404);
  }
  const entry = ctx.reports.find((r) => r.slug === slug)!;
  const html = await renderPage({
    title: `${entry.name} drill-down · live — tdd.md`,
    description: `Live drill-down for ${entry.name} on syntaxai/tdd.md — trend, failure-mode breakdown, recent commits.`,
    bodyMarkdown: md,
    ogPath: `https://tdd.md/reports/live/agents/${slug}`,
    noindex: true,
  });
  return htmlResponse(html);
};