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
2 changes: 1 addition & 1 deletion apps/web/app/_components/site-footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export function SiteFooter() {
<p>A practical map before the first edit. Free, local-first, and open source.</p>
</div>
<div className="footer-links">
<div><strong>Explore</strong><Link href="/product">Product</Link><Link href="/demo">Live demo</Link><Link href="/evidence">Evidence</Link></div>
<div><strong>Explore</strong><Link href="/product">Product</Link><Link href="/demo">Live demo</Link><Link href="/evidence">Evidence</Link><Link href="/changelog">Changelog</Link></div>
<div><strong>Use FixMap</strong><Link href="/get-started">Get started</Link><Link href="/docs">Docs</Link><a href={marketplaceUrl}>GitHub Action</a></div>
<div><strong>Project</strong><a href={repoUrl}><GithubLogo size={16} weight="fill" aria-hidden /> GitHub</a><a href={npmUrl}>npm</a><a href={`${repoUrl}/issues`}>Issues</a></div>
</div>
Expand Down
1 change: 1 addition & 0 deletions apps/web/app/_components/site-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const links = [
{ href: "/product", label: "Product" },
{ href: "/demo", label: "Live demo" },
{ href: "/evidence", label: "Evidence" },
{ href: "/changelog", label: "Changelog" },
{ href: "/docs", label: "Docs" }
];

Expand Down
261 changes: 261 additions & 0 deletions apps/web/app/changelog/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
import type { Metadata } from "next";
import {
ArrowRight,
ChartLineUp,
CheckCircle,
Plus,
ShieldCheck,
Sparkle,
Wrench
} from "@phosphor-icons/react/ssr";
import { repoUrl, siteStats } from "../_lib/site-data";

export const metadata: Metadata = {
title: "Changelog",
description: "See what is new, improved, and fixed in every recent FixMap release.",
alternates: { canonical: "/changelog" }
};

type ChangeGroup = {
label: "Added" | "Fixed" | "Improved" | "Security" | "Evidence";
items: string[];
};

type Release = {
version: string;
date: string;
label?: string;
summary: string;
groups: ChangeGroup[];
};

const releases: Release[] = [
{
version: "Unreleased",
date: "Pending release",
label: "In progress",
summary: "Improvements that are tested and ready for the next package release.",
groups: [
{
label: "Fixed",
items: [
"Pretty-printed vendored dependency bundles with a source-map marker no longer escape generated-output detection or rank as a high-confidence edit target."
]
},
{
label: "Evidence",
items: [
"Added a dedicated adversarial fixture for readable compiled dependencies while keeping Chalk's real vendored implementation ranked first.",
"All 420 workspace tests pass; held-out and external accuracy remain unchanged, and the adversarial suite is now 9/9 with zero false-confidence cases."
]
}
]
},
{
version: "0.8.6",
date: "August 2, 2026",
label: "Latest release",
summary: "Cleaner implementation rankings without hiding legitimate UI or generated-artifact work.",
groups: [
{
label: "Fixed",
items: [
"Stylesheets are deprioritized for non-UI implementation tasks, while genuine CSS and layout tasks still rank them normally.",
"Explicitly named generated artifacts remain visible, but a maintained source twin caps their confidence and explains the source relationship."
]
},
{
label: "Evidence",
items: [
"Added counterexample coverage for real CSS tasks and tasks that genuinely target a stale generated artifact.",
"Held-out accuracy remained 7/12 Top-1, 8/12 Top-3, and 9/12 Top-5."
]
}
]
},
{
version: "0.8.5",
date: "August 2, 2026",
summary: "A proper installation path and a much shorter everyday command.",
groups: [
{
label: "Improved",
items: [
"The README and website now lead with a global installation followed by the short fixmap command.",
"Install guidance now explains when npm may prefer an older project-local binary and why the running version printed by Doctor is authoritative."
]
}
]
},
{
version: "0.8.4",
date: "August 2, 2026",
summary: "Doctor can identify an exact-version request that started the wrong installation.",
groups: [
{
label: "Fixed",
items: [
"fixmap doctor reports both the requested and running versions when a local or ancestor installation shadows an exact npm request.",
"The clean verification procedure uses an isolated npm prefix and invokes its shim directly on Windows."
]
}
]
},
{
version: "0.8.3",
date: "August 2, 2026",
summary: "Stricter MCP comparison inputs, with honest failures instead of false success.",
groups: [
{
label: "Fixed",
items: [
"fixmap_compare rejects truncated report-shaped objects while continuing to accept complete reports that legitimately contain zero matches.",
"Optional rank, score, and confidence fields are type-checked when present."
]
}
]
},
{
version: "0.8.2",
date: "August 2, 2026",
summary: "A broad reliability release across Windows, test routing, MCP, the Action, and diagnostics.",
groups: [
{
label: "Added",
items: [
"New diagnostics identify unread content, missing tracked paths, duplicate real paths, generated-path dominance, and missing related tests.",
"MCP explain gained working-tree controls, the product page gained Compare, and the site gained robots.txt."
]
},
{
label: "Fixed",
items: [
"Windows path normalization, BOM and UTF-16 manifests, common GitHub URL forms, failed diff handling, and additional source languages now behave consistently.",
"Workspace test routing, Action exclusions and comments, and stemming were hardened with regression coverage."
]
}
]
},
{
version: "0.8.1",
date: "August 1, 2026",
summary: "The first large dogfooding sweep closed gaps across every FixMap surface.",
groups: [
{
label: "Added",
items: [
"Compare and Doctor MCP tools, working-tree controls, browser-safe exports, and Action inputs for limit, exclude, and untracked files.",
"Release gates now verify the npm latest tag, canonical homepage metadata, internal versions, and a clean installation before publishing."
]
},
{
label: "Fixed",
items: [
"CLI validation, comparison output, exclusions, confidence, risk evidence, JSON ranks, test routing, and Action comment selection."
]
}
]
},
{
version: "0.8.0",
date: "August 1, 2026",
summary: "Plan, focus, compare, and verify became one coherent workflow.",
groups: [
{
label: "Added",
items: [
"Go and Rust test routing, fixmap doctor, plan comparison, exclusions, result limits, working-tree mode, progress phases, pull-request URLs, and Action verify mode.",
"MCP explain lets agents investigate a missing file without shell access."
]
},
{
label: "Fixed",
items: [
"Confidence now reflects real ranking separation instead of labeling a whole result page high.",
"Language detection, diagnostic bounds, file-mention performance, duplicate flags, verify output, and report consistency were corrected."
]
},
{
label: "Security",
items: [
"Unbounded user text no longer flows into JSON reports, CI logs, or pull-request comments."
]
}
]
}
];

const icons = {
Added: Plus,
Fixed: Wrench,
Improved: Sparkle,
Security: ShieldCheck,
Evidence: ChartLineUp
} as const;

const releaseId = (version: string) => `v-${version.toLowerCase().replaceAll(".", "-")}`;

export default function ChangelogPage() {
return (
<main>
<section className="subpage-hero page-shell changelog-hero">
<p className="eyebrow">Product changelog</p>
<h1>Every improvement.<br /><em>Plainly recorded.</em></h1>
<p>New features, important fixes, and the evidence behind each recent FixMap release.</p>
<div className="changelog-hero-meta">
<span><CheckCircle size={19} weight="fill" aria-hidden /> Current package: v{siteStats.version}</span>
<a className="text-link" href={`${repoUrl}/blob/main/CHANGELOG.md`}>Read the complete history <ArrowRight size={17} weight="bold" aria-hidden /></a>
</div>
</section>

<section className="section page-shell changelog-layout">
<aside className="release-index" aria-label="Recent releases">
<strong>Recent releases</strong>
<nav>
{releases.map((release) => (
<a key={release.version} href={`#${releaseId(release.version)}`}>
<span>{release.version === "Unreleased" ? "Next" : `v${release.version}`}</span>
<small>{release.date}</small>
</a>
))}
</nav>
</aside>

<div className="release-list">
{releases.map((release) => (
<article className="release-entry" id={releaseId(release.version)} key={release.version}>
<header className="release-heading">
<div>
<p>{release.date}</p>
<h2>{release.version === "Unreleased" ? "Coming next" : `FixMap v${release.version}`}</h2>
</div>
{release.label ? <span>{release.label}</span> : null}
</header>
<p className="release-summary">{release.summary}</p>
<div className="release-groups">
{release.groups.map((group) => {
const Icon = icons[group.label];
return (
<section className="release-group" key={group.label}>
<h3><Icon size={19} weight="bold" aria-hidden /> {group.label}</h3>
<ul>
{group.items.map((item) => <li key={item}>{item}</li>)}
</ul>
</section>
);
})}
</div>
</article>
))}
</div>
</section>

<section className="section dark-section">
<div className="page-shell changelog-bottom">
<div><p className="eyebrow">Nothing hidden</p><h2>Every release stays inspectable.</h2><p>The repository contains the full history, exact test evidence, and source for every change.</p></div>
<a className="button light" href={`${repoUrl}/releases`}>Browse GitHub releases <ArrowRight size={18} weight="bold" aria-hidden /></a>
</div>
</section>
</main>
);
}
43 changes: 43 additions & 0 deletions apps/web/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,40 @@ h3 { margin-bottom: 10px; font-size: 21px; line-height: 1.25; letter-spacing: -.
.docs-bottom > div:first-child p { color: #c2ccd4; }
.not-found { min-height: 630px; display: flex; flex-direction: column; justify-content: center; align-items: flex-start; }

/* Changelog */
.changelog-hero { padding-bottom: 84px; }
.changelog-hero > p:not(.eyebrow) { max-width: 680px; }
.changelog-hero-meta { margin-top: 34px; display: flex; flex-wrap: wrap; align-items: center; gap: 18px 32px; }
.changelog-hero-meta > span { display: inline-flex; align-items: center; gap: 8px; color: var(--green-dark); font-size: 14px; font-weight: 650; }
.changelog-hero-meta > span svg { color: var(--green); }
.changelog-layout { padding-top: 90px; display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: clamp(60px, 8vw, 120px); align-items: start; }
.release-index { position: sticky; top: 116px; padding: 22px; border: 1px solid var(--line); border-radius: 12px; background: rgba(255,253,248,.72); }
.release-index > strong { color: var(--ink-faint); font: 650 11px var(--font-mono), monospace; text-transform: uppercase; letter-spacing: .1em; }
.release-index nav { margin-top: 15px; display: grid; }
.release-index a { padding: 11px 0; display: grid; gap: 2px; border-top: 1px solid var(--line); color: var(--ink); text-decoration: none; }
.release-index a:hover span { color: var(--green); }
.release-index span { font-size: 14px; font-weight: 650; transition: color .18s ease; }
.release-index small { color: var(--ink-faint); font-size: 11px; }
.release-list { position: relative; }
.release-list::before { content: ""; position: absolute; left: 7px; top: 9px; bottom: 72px; width: 1px; background: var(--line-strong); }
.release-entry { position: relative; padding: 0 0 86px 52px; scroll-margin-top: 120px; }
.release-entry::before { content: ""; position: absolute; left: 0; top: 8px; width: 15px; height: 15px; border: 3px solid var(--paper); border-radius: 50%; background: var(--green); box-shadow: 0 0 0 1px var(--green); }
.release-heading { display: flex; align-items: flex-start; justify-content: space-between; gap: 28px; }
.release-heading p { margin: 0 0 8px; color: var(--ink-faint); font: 600 11px var(--font-mono), monospace; text-transform: uppercase; letter-spacing: .08em; }
.release-heading h2 { font-size: clamp(34px, 4vw, 48px); }
.release-heading > span { flex: 0 0 auto; padding: 7px 10px; border: 1px solid rgba(10,90,67,.18); border-radius: 999px; background: var(--mint-soft); color: var(--green-dark); font: 650 10px var(--font-mono), monospace; text-transform: uppercase; letter-spacing: .06em; }
.release-summary { max-width: 720px; margin-top: 18px; color: var(--ink-soft); font-size: 18px; }
.release-groups { margin-top: 36px; border-bottom: 1px solid var(--line); }
.release-group { padding: 25px 0; display: grid; grid-template-columns: 145px minmax(0, 1fr); gap: 32px; border-top: 1px solid var(--line); }
.release-group h3 { display: flex; align-items: center; gap: 9px; color: var(--green-dark); font-size: 14px; }
.release-group h3 svg { color: var(--green); }
.release-group ul { margin: 0; padding: 0; display: grid; gap: 13px; list-style: none; }
.release-group li { position: relative; padding-left: 19px; color: var(--ink-soft); line-height: 1.65; }
.release-group li::before { content: ""; position: absolute; left: 0; top: .72em; width: 6px; height: 6px; border-radius: 50%; background: var(--mint); }
.changelog-bottom { display: flex; align-items: center; justify-content: space-between; gap: 60px; }
.changelog-bottom > div { max-width: 690px; }
.changelog-bottom > div > p:last-child { color: #b7c5d1; }

/* Footer */
.site-footer { padding: 72px max(32px, calc((100vw - var(--page)) / 2)); background: var(--navy); color: var(--paper-light); }
.footer-main { display: grid; grid-template-columns: 1fr 1.2fr; gap: 100px; }
Expand Down Expand Up @@ -370,6 +404,10 @@ h3 { margin-bottom: 10px; font-size: 21px; line-height: 1.25; letter-spacing: -.
.setup-section { grid-template-columns: minmax(0, 1fr); gap: 34px; }
.docs-layout { grid-template-columns: 1fr; }
.docs-sidebar { display: none; }
.changelog-layout { grid-template-columns: 1fr; gap: 55px; }
.release-index { position: static; }
.release-index nav { grid-template-columns: repeat(4, 1fr); gap: 0 18px; }
.changelog-bottom { align-items: flex-start; flex-direction: column; }
.footer-main { grid-template-columns: 1fr; gap: 54px; }
}

Expand Down Expand Up @@ -417,6 +455,11 @@ h3 { margin-bottom: 10px; font-size: 21px; line-height: 1.25; letter-spacing: -.
.copy-command button { width: 100%; }
.docs-cards { grid-template-columns: 1fr; }
.definition-list > div { grid-template-columns: 1fr; gap: 6px; }
.changelog-hero-meta { align-items: flex-start; flex-direction: column; }
.release-index nav { grid-template-columns: 1fr 1fr; }
.release-entry { padding-left: 32px; }
.release-heading { flex-direction: column; gap: 14px; }
.release-group { grid-template-columns: 1fr; gap: 16px; }
.setup-next { align-items: flex-start; flex-direction: column; }
.footer-links { grid-template-columns: 1fr 1fr; }
.footer-bottom { flex-direction: column; gap: 8px; }
Expand Down
2 changes: 1 addition & 1 deletion apps/web/app/sitemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { MetadataRoute } from "next";
const base = "https://usefixmap.vercel.app";

export default function sitemap(): MetadataRoute.Sitemap {
return ["", "/product", "/demo", "/evidence", "/get-started", "/docs"].map((path) => ({
return ["", "/product", "/demo", "/evidence", "/changelog", "/get-started", "/docs"].map((path) => ({
url: `${base}${path}`,
changeFrequency: path === "" ? "weekly" : "monthly",
priority: path === "" ? 1 : path === "/demo" || path === "/get-started" ? 0.9 : 0.8
Expand Down
9 changes: 5 additions & 4 deletions benchmarks/adversarial/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ A wrong answer costs an agent one wasted file read. A wrong answer delivered wit

| Result | Value |
| --- | ---: |
| Cases | 8 |
| Passed | 8 |
| Cases | 9 |
| Passed | 9 |
| **False-confidence rate** | **0.0** |

Measured 2026-07-26. Per-case output is checked in at [`results.json`](results.json).
Measured 2026-08-02. Per-case output is checked in at [`results.json`](results.json).

## The cases

Expand All @@ -28,8 +28,9 @@ Measured 2026-07-26. Per-case output is checked in at [`results.json`](results.j
| `absent-feature-surface` | chalk | A CLI flag for a package that exposes no CLI |
| `runtime-only-symptom` | pino | A timing-dependent concurrency symptom with no static trace |
| `documentation-term-flood` | webpack | Only broad development vocabulary that instruction and documentation files carry in volume |
| `pretty-printed-vendored-bundle` | Synthetic compiled dependency | A readable development bundle with one source-map marker and no maintained source twin |

Cases reuse the checkouts already pinned by the accuracy suites, so this suite clones nothing new.
External cases reuse the checkouts already pinned by the accuracy suites, so this suite clones nothing new. The generated-output case uses a deterministic temporary fixture and removes it after every run.

## Why this is not only unit tests

Expand Down
8 changes: 8 additions & 0 deletions benchmarks/adversarial/dataset.json
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,14 @@
"descriptive",
"vague"
]
},
{
"id": "pretty-printed-vendored-bundle",
"kind": "generated-output",
"fixture": "pretty-printed-vendored-bundle",
"task": "experimental transition state",
"why": "A readable development bundle under compiled/ contains the task vocabulary and one source-map marker but has no maintained source twin. It must not lead at high confidence.",
"maxConfidence": "low"
}
]
}
Loading