From 95dc070c59a202b73f1831c8164e8506193a0366 Mon Sep 17 00:00:00 2001 From: Aryam Goyal Date: Sun, 26 Jul 2026 22:24:05 +0530 Subject: [PATCH] feat: rebuild the site around what FixMap actually does MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The site explained FixMap in abstractions — "scan locally", "rank with reasons", "explain the route" — without ever showing a command or its output, never mentioned --explain or verify, and claimed v0.7.1 while 0.7.3 was published. The browser demo was worse: seven fabricated files whose contents were bags of keywords, rigged so every preset produced a clean win. A demo that cannot fail is not evidence. The demo now runs the real thing. `buildReportFromRepo` is extracted out of `plan.ts` so the report assembly no longer lives behind the filesystem scanner, and `browser.ts` exports it alongside `explainFile` and `verifyPlan`. The page imports the same code the CLI runs and points it at a sample repository written like a real one: resolving imports, committed build output, an examples directory, a lockfile, a type declaration. Three tabs walk the actual workflow — plan, ask why, verify. The default preset is the case FixMap handles worst. "Password reset emails never arrive" is a symptom with no symbol, and it ranks the email template above the file that sends the mail. The next preset adds one identifier and the ranking sharpens, with the reason visible. Showing the weak case and its remedy is more convincing than hiding it, and it is the documented failure mode rather than a surprise a user finds alone. Also new: an anatomy section showing one command and the four outputs it produces, a card per command, six concrete reasons to use it, and a version read from packages/cli/package.json so it cannot go stale again. The hero terminal listed output its own command does not produce. It now shows the exact ranking, confidence labels included, that the printed command returns against the demo's sample repository. Fixes horizontal overflow on mobile: grid children default to min-width:auto, so wide
 blocks stretched the page past the viewport
instead of scrolling inside their own box.

Co-Authored-By: Claude Opus 5 
---
 apps/web/app/demo.tsx          | 375 +++++++++++++++++++++++++++------
 apps/web/app/globals.css       | 183 ++++++++++++++--
 apps/web/app/page.tsx          | 306 ++++++++++++++++++++++-----
 apps/web/app/sample-repo.ts    | 284 +++++++++++++++++++++++++
 packages/action/dist/index.mjs | 265 +++++++++++------------
 packages/core/src/browser.ts   |  20 +-
 packages/core/src/plan.ts      | 147 +------------
 packages/core/src/report.ts    | 155 +++++++++++++-
 8 files changed, 1319 insertions(+), 416 deletions(-)
 create mode 100644 apps/web/app/sample-repo.ts

diff --git a/apps/web/app/demo.tsx b/apps/web/app/demo.tsx
index 38b99cf..cd12614 100644
--- a/apps/web/app/demo.tsx
+++ b/apps/web/app/demo.tsx
@@ -1,87 +1,334 @@
 "use client";
 
 import { useMemo, useState } from "react";
-import { buildTestRoutes, rankContextFiles, type RepoFile, type RepoMap } from "@aryam/fixmap-core/browser";
-
-const sampleFiles = [
-  sampleFile("src/auth/reset-password.ts", "password reset token email authentication", "code"),
-  sampleFile("src/auth/session.ts", "login session cookie authentication", "code"),
-  sampleFile("src/billing/create-invoice.ts", "billing payment invoice customer", "code"),
-  sampleFile("src/email/send-reset.ts", "send password reset email template", "code"),
-  sampleFile("test/auth/reset-password.test.ts", "password reset email token test", "code", true),
-  sampleFile(".github/workflows/ci.yml", "workflow test build pull request", "config"),
-  sampleFile("README.md", "installation guide documentation", "documentation")
-];
+import { buildReportFromRepo, explainFile, verifyPlan } from "@aryam/fixmap-core/browser";
+import { sampleRepo, sampleRepoWithChanges, samplePaths } from "./sample-repo";
 
-const sampleRepo: RepoMap = {
-  root: "sample-repository",
-  files: sampleFiles,
-  packageScripts: [{ name: "test", command: "vitest run", packageDir: "" }],
-  changedFiles: [],
-  diffText: "",
-  packageManager: "npm",
-  diagnostics: []
-};
+type Stage = "plan" | "explain" | "verify";
 
 const presets = [
-  "Password reset emails fail",
-  "Invoices are created twice",
-  "Login sessions expire too early",
-  "Update the installation guide"
+  {
+    label: "Password reset emails never arrive",
+    note: "A symptom with no symbol. This is where a lexical ranker is weakest — watch what happens in the next preset."
+  },
+  {
+    label: "sendMail throws and password reset emails never arrive",
+    note: "The same bug with one symbol named. The transport file climbs, and the reason says why: it defines sendMail."
+  },
+  {
+    label: "TOKEN_TTL_MINUTES is ignored, reset links expire immediately",
+    note: "A named constant is the strongest anchor there is. The file that defines it wins outright."
+  },
+  {
+    label: "Invoices are created twice for the same customer",
+    note: "A different subsystem, no overlap with the auth files, no drift into them."
+  },
+  {
+    label: "make it better",
+    note: "No searchable anchor. FixMap reports nothing and says so, instead of ranking something plausible."
+  }
+];
+
+const scenarios = [
+  { label: "Edited the build output", changed: ["dist/auth/reset-password.js"] },
+  { label: "Shipped with no test", changed: ["src/email/transport.ts"] },
+  { label: "Also touched billing", changed: ["src/email/transport.ts", "src/billing/invoice.ts"] },
+  {
+    label: "Source and test together",
+    changed: ["src/auth/reset-password.ts", "test/auth/reset-password.test.ts"]
+  }
 ];
 
+const explainTargets = samplePaths;
+
 export function Demo() {
-  const [task, setTask] = useState("Password reset emails fail");
-  const result = useMemo(() => {
-    const ranked = rankContextFiles(sampleRepo, { issueText: task }, 4);
-    const routes = buildTestRoutes(sampleRepo, ranked.map((file) => file.path));
-    return { ranked, routes };
-  }, [task]);
+  const [task, setTask] = useState(presets[0]!.label);
+  const [stage, setStage] = useState("plan");
+  const [explainTarget, setExplainTarget] = useState("dist/auth/reset-password.js");
+  const [scenario, setScenario] = useState(0);
+
+  const report = useMemo(() => buildReportFromRepo(sampleRepo, { issueText: task }), [task]);
+  const explanation = useMemo(
+    () => explainFile(sampleRepo, { issueText: task }, explainTarget),
+    [task, explainTarget]
+  );
+  const verification = useMemo(
+    () => verifyPlan(report, sampleRepoWithChanges(scenarios[scenario]!.changed)),
+    [report, scenario]
+  );
+
+  const activePreset = presets.find((preset) => preset.label === task);
+  const command = {
+    plan: `fixmap plan --issue "${truncate(task)}"`,
+    explain: `fixmap plan --issue "${truncate(task)}" --explain ${explainTarget}`,
+    verify: `fixmap verify --report plan.json --diff main...HEAD`
+  }[stage];
 
   return (
-    
-
- -