Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions apps/web/app/_components/interactive-map-stage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ function resultForIssue(issue: string): { example: Example; index: number } {

const stageMeta: Array<{ key: StageKey; label: string; hint: string }> = [
{ key: "files", label: "Files", hint: "Finding relevant code" },
{ key: "checks", label: "Checks", hint: "Building validations" },
{ key: "risks", label: "Risks", hint: "Assessing impact" }
{ key: "checks", label: "Tests", hint: "Finding checks" },
{ key: "risks", label: "Risks", hint: "Reviewing impact" }
];

function OutputCard({
Expand All @@ -103,9 +103,9 @@ function OutputCard({
onSelect: () => void;
}) {
const config = {
files: { icon: FileText, title: "Files to inspect", count: "7 files", metric: "Confidence", value: "High" },
checks: { icon: CheckCircle, title: "Checks to run", count: "8 checks", metric: "Confidence", value: "High" },
risks: { icon: Warning, title: "Risks to review", count: "6 risks", metric: "Impact", value: "Medium" }
files: { icon: FileText, title: "Files to open first", count: "7 files", metric: "Match", value: "Strong" },
checks: { icon: CheckCircle, title: "Tests and checks", count: "8 checks", metric: "Support", value: "Found" },
risks: { icon: Warning, title: "Risks worth reviewing", count: "6 risks", metric: "Impact", value: "Medium" }
}[stage];
const Icon = config.icon;

Expand All @@ -125,7 +125,7 @@ function OutputCard({
<span className="stage-card-rows">
{items.map((item, index) => (
<span key={item} style={{ "--row-index": index } as CSSProperties}>
<b>{index + 1}</b><code>{ready ? item : "Scanning repository signals…"}</code><small>{stage === "files" ? (index === 0 ? "Exact match" : "High signal") : stage === "checks" ? "Evidence" : "Why"}</small>
<b>{index + 1}</b><code>{ready ? item : "Scanning the repository…"}</code><small>{stage === "files" ? (index === 0 ? "Strong match" : "Connected") : stage === "checks" ? "Suggested" : "Why it matters"}</small>
</span>
))}
</span>
Expand Down Expand Up @@ -195,12 +195,12 @@ export function InteractiveMapStage() {
</select>
<CaretDown size={14} weight="bold" aria-hidden />
</label>
<span className="stage-local-status"><i /> Local demo</span>
<span className="stage-local-status"><i /> Runs here</span>
</div>

<div className="stage-body">
<div className="stage-input-column">
<div className="stage-input-heading"><span>1</span><strong>Describe the issue<br />in plain English</strong></div>
<div className="stage-input-heading"><span>1</span><strong>Describe what needs fixing</strong></div>
<div className="stage-issue-field">
<label className="sr-only" htmlFor="fixmap-hero-issue">Software issue</label>
<textarea id="fixmap-hero-issue" value={issue} maxLength={500} onChange={(event) => setIssue(event.target.value)} />
Expand All @@ -209,7 +209,7 @@ export function InteractiveMapStage() {
<ArrowRight size={19} weight="bold" aria-hidden />
</button>
</div>
<div className="stage-trust-note"><ShieldCheck size={19} weight="duotone" aria-hidden /><span><strong>Starting map, not proof.</strong>Review results before making changes.</span></div>
<div className="stage-trust-note"><ShieldCheck size={19} weight="duotone" aria-hidden /><span><strong>A starting point, not a verdict.</strong>Open the files and run the checks before changing code.</span></div>
</div>

<div className="stage-output-column">
Expand Down
6 changes: 3 additions & 3 deletions apps/web/app/_components/site-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ function NavLinks() {
Get started <CaretDown size={14} weight="bold" aria-hidden />
</summary>
<div className="nav-dropdown-panel">
<Link href="/get-started#cli"><strong>CLI</strong><span>Run FixMap from a terminal</span></Link>
<Link href="/get-started#mcp"><strong>MCP</strong><span>Connect a coding agent</span></Link>
<Link href="/get-started#action"><strong>GitHub Action</strong><span>Map every pull request</span></Link>
<Link href="/get-started#agent"><strong>Coding agent</strong><span>Add the /fixmap command</span></Link>
<Link href="/get-started#terminal"><strong>Terminal</strong><span>Try or install the CLI</span></Link>
<Link href="/get-started#pull-requests"><strong>Pull requests</strong><span>Post a map automatically</span></Link>
</div>
</details>
<a className="nav-github" href={repoUrl}>
Expand Down
81 changes: 42 additions & 39 deletions apps/web/app/demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,23 @@ type Stage = "plan" | "explain" | "compare" | "verify";
const presets = [
{
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."
note: "Start here. The task describes a symptom without naming a file or code symbol, so FixMap has to find the strongest repository signals."
},
{
label: "sendMail throws and password reset emails never arrive",
note: "The same bug with one symbol named. The transport rises into the top three, and its reason says why: it defines sendMail."
note: "The same problem now names sendMail. Watch the email transport move to the top because that file defines the symbol."
},
{
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."
note: "A named constant gives FixMap a strong anchor. The file that defines it moves to the top."
},
{
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."
note: "This task is too vague to ground. FixMap returns no suggestions instead of presenting a plausible guess as evidence."
}
];

Expand Down Expand Up @@ -126,10 +126,10 @@ export function Demo() {
<div className="stage-tabs" role="group" aria-label="FixMap stages">
{(
[
["plan", "1 · Plan", "Where do I start?"],
["explain", "2 · Ask why", "Why not this file?"],
["compare", "3 · Compare", "Did better context move?"],
["verify", "4 · Verify", "Did the change match?"]
["plan", "1 · Find files", "Where should I start?"],
["explain", "2 · Ask why", "Why this file?"],
["compare", "3 · Refine task", "Did the result improve?"],
["verify", "4 · Check change", "Did the work drift?"]
] as const
).map(([value, label, hint]) => (
<button
Expand All @@ -147,9 +147,9 @@ export function Demo() {

<div className="demo-shell">
<div className="demo-input">
<label htmlFor="task">The task</label>
<label htmlFor="task">Describe the software problem</label>
<textarea id="task" value={task} onChange={(event) => setTask(event.target.value)} rows={3} />
<div className="preset-list" role="group" aria-label="Example tasks">
<div className="preset-list" role="group" aria-label="Example software problems">
{presets.map((preset) => (
<button
key={preset.label}
Expand All @@ -163,22 +163,23 @@ export function Demo() {
</div>
{activePreset ? <p className="preset-note">{activePreset.note}</p> : null}

<label className="picker-label" htmlFor="context-limit">Context limit: {limit}</label>
<input id="context-limit" type="range" min="1" max="8" value={limit} onChange={(event) => setLimit(Number(event.target.value))} />
<label className="picker-label"><input type="checkbox" checked={excludeBuild} onChange={(event) => setExcludeBuild(event.target.checked)} /> Exclude generated <code>dist/**</code></label>
<label className="picker-label"><input type="checkbox" checked={workingTree} onChange={(event) => setWorkingTree(event.target.checked)} /> Include the selected scenario as a working-tree change set</label>

<p className="demo-command">
<span>Same result from the CLI</span>
<code>{command}</code>
</p>
<details className="demo-advanced">
<summary>Adjust limits, exclusions, and CLI output</summary>
<label className="picker-label" htmlFor="context-limit">Maximum file suggestions: {limit}</label>
<input id="context-limit" type="range" min="1" max="8" value={limit} onChange={(event) => setLimit(Number(event.target.value))} />
<label className="picker-label"><input type="checkbox" checked={excludeBuild} onChange={(event) => setExcludeBuild(event.target.checked)} /> Ignore generated <code>dist/**</code> files</label>
<label className="picker-label"><input type="checkbox" checked={workingTree} onChange={(event) => setWorkingTree(event.target.checked)} /> Include unsaved working-tree changes</label>
<p className="demo-command">
<span>Run the same example from a terminal</span>
<code>{command}</code>
</p>
</details>

<div className="privacy-note">
<span aria-hidden="true">●</span>
<p>
<strong>This is FixMap itself, not a mockup.</strong> The page imports the same
ranking, explanation, and verification code the CLI runs, and executes it on a
sample repository in your browser. Nothing you type is sent anywhere.
<strong>This is the real FixMap engine.</strong> It runs on a sample repository in
this tab. Nothing you type is uploaded.
</p>
</div>
</div>
Expand Down Expand Up @@ -210,8 +211,8 @@ function PlanPanel({ report }: { report: ReturnType<typeof buildReportFromRepo>
return (
<>
<div className="results-head">
<span>Context files</span>
<small>{report.contextFiles.length} ranked</small>
<span>Files to inspect first</span>
<small>{report.contextFiles.length} suggestions</small>
</div>

{report.contextFiles.length > 0 ? (
Expand All @@ -220,30 +221,34 @@ function PlanPanel({ report }: { report: ReturnType<typeof buildReportFromRepo>
<span className="result-number">{String(index + 1).padStart(2, "0")}</span>
<div>
<code>{file.path}</code>
<p>{file.reasons.join("; ")}</p>
<details className="result-reasons">
<summary>Why FixMap suggested this file</summary>
<p>{file.reasons.join("; ")}</p>
<small>Ranking score: {file.score}</small>
</details>
</div>
<span className={`confidence ${file.confidence}`}>
{file.confidence} · {file.score}
{file.confidence} match
</span>
</article>
))
) : (
<div className="empty-result">
<strong>Nothing ranked.</strong>
<p>FixMap returns an empty report rather than a plausible guess.</p>
<strong>FixMap could not ground this task.</strong>
<p>Add a symptom, file name, or code symbol. FixMap will not invent a confident-looking result for a vague request.</p>
</div>
)}

{report.testRoutes.length > 0 ? (
<div className="route-preview">
<span>Run this</span>
<span>Test or check to run</span>
<code>{report.testRoutes[0]!.command}</code>
</div>
) : null}

{report.impact?.files.length ? (
<div className="panel-block">
<p className="panel-heading">Likely impact · inspect, not assumed edits</p>
<p className="panel-heading">Other files this change may affect</p>
{report.impact.files.slice(0, 5).map((file) => (
<p key={file.path}>
<span className={`severity ${file.confidence === "high" ? "warning" : "info"}`}>{file.confidence}</span>
Expand All @@ -260,7 +265,7 @@ function PlanPanel({ report }: { report: ReturnType<typeof buildReportFromRepo>

{report.risks.length > 0 ? (
<div className="panel-block">
<p className="panel-heading">Risk</p>
<p className="panel-heading">Risks worth reviewing</p>
{report.risks.map((risk) => (
<p key={risk.area}>
<span className={`severity ${risk.severity}`}>{risk.severity}</span>
Expand Down Expand Up @@ -331,10 +336,8 @@ function ExplainPanel({
) : null}

<p className="panel-footnote">
A ranked list explains what it chose. This answers the question it cannot: why the file
you expected is missing. The four answers are genuinely different — it ranked lower than
you thought, it scored below the cutoff, it was excluded on purpose, or the scan never
saw it.
This tells you whether the file ranked lower, fell below the cutoff, was excluded on
purpose, or was never scanned.
</p>
</>
);
Expand All @@ -351,15 +354,15 @@ function ComparePanel({ comparison }: { comparison: ReturnType<typeof compareRep
];
return (
<>
<div className="results-head"><span>Earlier plan vs. current task</span><small>{changes.length} changed</small></div>
<div className="results-head"><span>What changed after you clarified the task</span><small>{changes.length} changes</small></div>
<p className="explain-summary">{comparison.summary}</p>
{changes.map((delta) => (
<article className="finding" key={`${delta.status}-${delta.path}`}>
<span className="severity info">{delta.status}</span>
<div><code>{delta.path}</code><p>rank {delta.previousRank ?? "—"} → {delta.currentRank ?? "—"}; score {delta.previousScore ?? "—"} → {delta.currentScore ?? "—"}</p></div>
</article>
))}
<p className="panel-footnote">Compare makes task refinement measurable: save a JSON plan, add the missing symbol or path, and confirm the real fix site rises.</p>
<p className="panel-footnote">A clearer task should move the real fix site closer to the top. Compare shows whether it actually did.</p>
</>
);
}
Expand All @@ -378,9 +381,9 @@ function VerifyPanel({
return (
<>
<div className="results-head">
<span>Plan vs. diff</span>
<span>Planned work vs. changed files</span>
<small className={hasError ? "status-excluded" : "status-ranked"}>
exit {hasError ? 1 : 0}
{hasError ? "Needs review" : "No blocking errors"}
</small>
</div>

Expand Down
31 changes: 17 additions & 14 deletions apps/web/app/demo/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import { sampleRepo, sampleRepoWithChanges } from "../sample-repo";

export const metadata: Metadata = {
title: "Live demo",
description: "Try FixMap Plan, Explain, Compare, focus controls, and Verify on a sample repository in your browser.",
description: "Give FixMap a sample task and see the files, tests, impact, and risks it surfaces before a change begins.",
alternates: { canonical: "/demo" },
openGraph: {
title: "Live FixMap demo",
description: "Run the real FixMap ranking and verification engine in your browser.",
description: "See the real FixMap engine choose files, tests, impact, and risks in your browser.",
url: "/demo"
}
};
Expand All @@ -30,15 +30,15 @@ export default function DemoPage() {
<main>
<section className="subpage-hero compact-hero page-shell">
<p className="eyebrow">Live demo</p>
<h1>See the map form <em>in real time.</em></h1>
<h1>See FixMap choose <em>where to start.</em></h1>
<p>
Try Plan, Explain, Compare, exclusions, limits, and Verify against a small sample repository. This is the same core
logic used by the CLI, running locally in your browser—not a recording or staged result.
Pick a sample software problem. FixMap will show the files to inspect first, the checks that can prove the change,
nearby impact, and risks worth reviewing. The real engine runs below—not a recording or staged result.
</p>
<div className="inline-facts">
<span><Browser size={20} aria-hidden /> Runs in this tab</span>
<span><Browser size={20} aria-hidden /> Real FixMap engine</span>
<span><LockKey size={20} aria-hidden /> Nothing is uploaded</span>
<span><Sparkle size={20} aria-hidden /> Start with the first preset</span>
<span><Sparkle size={20} aria-hidden /> Choose an example below</span>
</div>
</section>

Expand All @@ -48,12 +48,14 @@ export default function DemoPage() {

<section className="section page-shell">
<div className="premium-section-intro compact">
<p className="eyebrow">Example agent conversation</p>
<h2>Plan → edit carefully → verify.</h2>
<p>The FixMap turns below are generated from this page&rsquo;s sample repository at build time, using the same renderer as the CLI.</p>
<p className="eyebrow">Optional technical detail</p>
<h2>See the complete agent conversation.</h2>
<p>Open the transcript to follow the exact Plan → edit → Verify workflow generated from this sample repository.</p>
</div>

<div className="doc-layout">
<details className="demo-transcript">
<summary>Open the complete Plan → edit → Verify example</summary>
<div className="doc-layout">
<article className="doc-section">
<h3>User</h3>
<p>{agentTask}. Can you fix it?</p>
Expand Down Expand Up @@ -106,12 +108,13 @@ const transport = createTransport({
<li><strong>Run tests:</strong> FixMap routes checks; it does not pretend to execute them.</li>
</ol>
</aside>
</div>
</div>
</details>
</section>

<section className="section page-shell demo-next">
<div><p className="eyebrow">Ready for your repository?</p><h2>Take the same workflow to the terminal.</h2></div>
<div><p>Run one command for a public GitHub issue, or use FixMap locally for private source and working-tree diffs.</p><Link className="button primary" href="/get-started">Choose a setup <ArrowRight size={18} weight="bold" aria-hidden /></Link></div>
<div><p className="eyebrow">Ready for your repository?</p><h2>Give the next task a better starting point.</h2></div>
<div><p>Try FixMap once, add <code>/fixmap</code> to a coding agent, or run it automatically on pull requests.</p><Link className="button primary" href="/get-started">Choose how to use FixMap <ArrowRight size={18} weight="bold" aria-hidden /></Link></div>
</section>
</main>
);
Expand Down
Loading