feat: add internal team-only roadmap page (#2590)

## Summary

- Adds `/roadmap` page with visual flowchart showing codeflash-python
and codeflash-agent planned work
- Gated behind `isTeamMemberCheck` (same auth pattern as
`/observability`)
- Sidebar link visible only to team members
- Status tracking with distinct visual treatments: compact left-accent
for shipped, hero cards with glow for in-progress, dashed wireframe for
planned

## Test plan

- [ ] Visit `/roadmap` as a team member — page renders with status cards
- [ ] Visit `/roadmap` as a non-team member — redirects to `/`
- [ ] Sidebar shows roadmap link only for team members
- [ ] Build passes (`npm run build`)
- [ ] All tests pass (`npm test` — 39/39)
This commit is contained in:
Kevin Turcios 2026-04-09 15:54:43 -05:00 committed by GitHub
parent b43e9ba648
commit e8561b9485
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 736 additions and 25 deletions

View file

@ -0,0 +1,43 @@
---
date: 2026-04-01
branch: main
---
## Accomplished
- Created an internal employee-only `/roadmap` page in cf-webapp (Next.js)
- Gated behind existing `isTeamMemberCheck` in middleware + server-side `isTeamMember()` check
- Added `/roadmap` to `ConditionalLayout` exclusion list so it renders as a standalone page (no sidebar)
- Added "Roadmap" link with Map icon to the sidebar, visible only to team members (same block as Observability)
- Built a visual flowchart UI with amber-themed nodes, dot-grid background, numbered badges linking to detail cards below
- Merged codeflash-python and codeflash-agent planned items into a single unified flow (3 branching nodes feed into 1 node below)
- Wrote a rationale section explaining: original CLI's single-language design + fragile multi-lang bolt-on, the codeflash-python + codeflash-core rewrite, the OptimizationSession API gap (building blocks done, experiment loop stubbed), and the goal of making codeflash-python the autonomous orchestrator
- Added a two-track strategy section: Consumer (codeflash --file / --all unchanged) vs B2B/Enterprise (agentic capabilities)
- Applied avoid-ai-writing skill to clean up language: killed em dash overuse, hollow intensifiers, compulsive triads, indirect phrasing, vague B2B copy
## Current State
- Branch: `main` (behind origin/main by 7 commits)
- Uncommitted changes:
- `js/cf-webapp/src/app/roadmap/page.tsx` (new file - the roadmap page)
- `js/cf-webapp/src/middleware.ts` (added /roadmap to team gate + matcher)
- `js/cf-webapp/src/components/conditional-layout.tsx` (added /roadmap to standalone page list)
- `js/cf-webapp/src/components/dashboard/sidebar.tsx` (added Roadmap link + Map icon import)
- `.tessl/RULES.md` (modified by tessl, not related to our work)
- Tests: not run (TypeScript type-check passes clean via `npx tsc --noEmit`)
## Key Decisions
- Used the same auth pattern as `/observability` (middleware redirect + server-side check) rather than inventing a new gate
- Page renders standalone (no sidebar) via `ConditionalLayout` exclusion, same as observability
- Roadmap data is hardcoded in the component as a TypeScript array, easy to edit manually
- Used amber/gold accent color (not blue) to differentiate planned items and give a forward-looking feel
- Unified all planned items (codeflash-python + codeflash-agent) into one flow rather than separate sections, per user preference
- Rationale text explains the rewrite motivation: original CLI was Python-only, multi-language was bolted on, architecture doesn't support autonomous operation
## Blockers
- None
## Next Steps
1. Create a feature branch and commit all changes (currently on main, user hasn't asked to commit yet)
2. Pull latest from origin/main (7 commits behind) and resolve any conflicts
3. Run the dev server (`npm run dev` in js/cf-webapp) and visually verify the page
4. Consider adding more planned items to the roadmap as they're defined
5. The roadmap data structure supports `FlowRow` with "single" and "branch" types, so new items can be added as rows that connect vertically

2
.tessl/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
tiles/
RULES.md

View file

@ -1,27 +1,3 @@
# Agent Rules
This file is updated when running `tessl install`. If a linked file is missing, make sure to run the command to download any missing tiles from the registry.
## codeflash/codeflash-internal-rules — code-style
@tiles/codeflash/codeflash-internal-rules/rules/code-style.md [code-style](tiles/codeflash/codeflash-internal-rules/rules/code-style.md)
## codeflash/codeflash-internal-rules — architecture
@tiles/codeflash/codeflash-internal-rules/rules/architecture.md [architecture](tiles/codeflash/codeflash-internal-rules/rules/architecture.md)
## codeflash/codeflash-internal-rules — optimization-patterns
@tiles/codeflash/codeflash-internal-rules/rules/optimization-patterns.md [optimization-patterns](tiles/codeflash/codeflash-internal-rules/rules/optimization-patterns.md)
## codeflash/codeflash-internal-rules — git-conventions
@tiles/codeflash/codeflash-internal-rules/rules/git-conventions.md [git-conventions](tiles/codeflash/codeflash-internal-rules/rules/git-conventions.md)
## codeflash/codeflash-internal-rules — testing-rules
@tiles/codeflash/codeflash-internal-rules/rules/testing-rules.md [testing-rules](tiles/codeflash/codeflash-internal-rules/rules/testing-rules.md)
## codeflash/codeflash-internal-rules — multi-language-handlers
@tiles/codeflash/codeflash-internal-rules/rules/multi-language-handlers.md [multi-language-handlers](tiles/codeflash/codeflash-internal-rules/rules/multi-language-handlers.md)

View file

@ -0,0 +1,680 @@
import { isTeamMember } from "@/app/utils/auth"
import { redirect } from "next/navigation"
import {
Repeat,
Wrench,
Zap,
Shield,
Code,
GitPullRequest,
Network,
LayoutDashboard,
Package,
FlaskConical,
RefreshCw,
BookOpen,
Check,
CircleDashed,
type LucideIcon,
} from "lucide-react"
type Status = "shipped" | "in-progress" | "planned"
interface Stage {
name: string
status: Status
icon: LucideIcon
description: string
details?: string[]
children?: Stage[]
downstream?: Stage[]
}
type FlowRow = { type: "single"; stage: Stage } | { type: "branch"; stages: Stage[] }
function countStages(rows: FlowRow[]): Record<Status, number> {
const counts: Record<Status, number> = { shipped: 0, "in-progress": 0, planned: 0 }
function walk(stage: Stage) {
counts[stage.status]++
stage.children?.forEach(walk)
stage.downstream?.forEach(walk)
}
for (const row of rows) {
if (row.type === "single") walk(row.stage)
else row.stages.forEach(walk)
}
return counts
}
const roadmap: FlowRow[] = [
{
type: "branch",
stages: [
{
name: "codeflash-python",
status: "shipped",
icon: Package,
description:
"The rebuilt Python optimization pipeline. All core stages complete \u2014 discovery, context extraction, test generation, benchmarking, verification, and orchestration.",
details: [
"OptimizationSession exposes each pipeline step as a callable method",
"stdlib ast for discovery, Jedi-based context resolution, SQLite-backed reference graph with file-hash invalidation",
"attrs models with to_dict() / from_dict() serialization throughout",
],
children: [
{
name: "JS / Java Pipeline",
status: "planned",
icon: Code,
description:
"Add JavaScript and Java optimization stages using the LanguagePlugin interface in codeflash-core.",
details: [
"LanguagePlugin interface already defines the contract \u2014 each language implements discovery, context extraction, and verification",
],
},
{
name: "Cross-Function Optimization",
status: "planned",
icon: Network,
description: "Optimize call chains together instead of one function at a time.",
details: [
"Reference graph in analysis/ already maps function dependencies",
"Generate candidates that touch multiple related functions in the same call path",
],
},
{
name: "Automated Code Refactoring",
status: "planned",
icon: RefreshCw,
description:
"Rewrite how a codebase uses its dependencies \u2014 tailored to what it actually needs.",
details: [
"Proven on ourselves: replaced libcst with stdlib ast, cached visitor dispatch tables \u2014 7.04s \u2192 1.60s (4.4x faster)",
"Same approach generalizes: profile dependency usage, identify overkill, generate targeted replacements",
],
},
],
downstream: [
{
name: "RL Environment",
status: "planned",
icon: FlaskConical,
description:
"Code optimization evaluation environment in Harbor format for training and evaluating software engineering agents.",
details: [
"Each task: one function to optimize inside a real-world OSS codebase",
"Evaluates correctness (behavioral equivalence), performance (runtime speedup), and quality",
],
},
],
},
{
name: "codeflash-agent",
status: "in-progress",
icon: Zap,
description:
"Fully autonomous optimization agent. Given a repository, it profiles, identifies bottlenecks, implements verified fixes, and ships results \u2014 no human in the loop.",
details: [
"Profiling spans CPU, memory, async, and structure dimensions to catch cross-cutting performance issues",
"Each optimization: profile \u2192 reason \u2192 implement \u2192 test \u2192 benchmark \u2192 keep or discard \u2192 commit",
],
children: [
{
name: "CI Mode",
status: "in-progress",
icon: GitPullRequest,
description:
"Acts like a team member that reviews every PR for performance. Open PRs are automatically profiled and optimized \u2014 like having a performance engineer on the team who never misses a review.",
details: [],
},
{
name: "Adversarial Review",
status: "in-progress",
icon: Shield,
description:
"6-pass independent code review that maps attack surfaces before shipping optimizations.",
details: [
"Correctness, performance, security, maintainability, edge cases, and integration passes",
"Review gate runs automatically before session ends",
],
},
{
name: "Research-Informed Optimization",
status: "planned",
icon: BookOpen,
description:
"Agents with access to research papers apply novel algorithmic improvements \u2014 not just mechanical refactoring.",
details: [
"arxiv access as a tool call \u2014 agents read papers and implement ideas directly",
"Enables optimizations that haven\u2019t been tried publicly before",
],
},
],
},
],
},
{
type: "single",
stage: {
name: "Programmatic API",
status: "in-progress",
icon: Wrench,
description:
"Wire codeflash-python\u2019s OptimizationSession directly into the agent \u2014 replacing CLI shell-outs with programmatic method calls. Expose session methods as MCP tools.",
details: [
"Experiment loop: profile(), build_targets(), measure(), evaluate() \u2014 no LLM needed in the loop",
"MCP tool layer: every method already accepts and returns JSON-serializable types",
"Agent migration: actions become testable and composable \u2014 no more CLI parsing",
],
},
},
{
type: "single",
stage: {
name: "Continuous Optimization",
status: "planned",
icon: Repeat,
description:
"The pipeline runs itself. codeflash-python provides the experiment loop, the agent drives it autonomously \u2014 profile, optimize, verify, ship, repeat across an entire codebase without human intervention.",
details: [
"Combines the programmatic API with autonomous orchestration",
"Iterative: each optimization pass feeds back into the next \u2014 targets are re-ranked by measured impact",
],
},
},
{
type: "single",
stage: {
name: "Enterprise Dashboard",
status: "planned",
icon: LayoutDashboard,
description: "Org-level visibility into optimization results across repos and teams.",
details: [],
},
},
]
/* ─── Shipped: compact, left-accent, details hidden ─── */
function ShippedCard({ stage }: { stage: Stage }) {
const Icon = stage.icon
return (
<div className="group relative flex flex-col gap-1.5 rounded-lg border-l-4 border-emerald-400 dark:border-emerald-500 bg-zinc-50 dark:bg-zinc-800/40 pl-4 pr-5 py-3 w-full transition-all duration-200 hover:bg-zinc-100 dark:hover:bg-zinc-800/60">
<div className="flex items-center gap-2.5">
<div className="flex h-6 w-6 shrink-0 items-center justify-center rounded text-emerald-500 dark:text-emerald-400">
<Check size={14} strokeWidth={3} />
</div>
<span className="text-sm font-semibold text-zinc-600 dark:text-zinc-300 leading-tight">
{stage.name}
</span>
<Icon size={13} className="text-zinc-300 dark:text-zinc-600 ml-auto shrink-0" />
</div>
<p className="text-[11px] leading-relaxed text-zinc-400 dark:text-zinc-500 pl-[34px]">
{stage.description}
</p>
</div>
)
}
/* ─── In-progress: hero card, elevated, glowing ─── */
function InProgressCard({ stage }: { stage: Stage }) {
const Icon = stage.icon
return (
<div className="group relative w-full">
{/* Outer glow */}
<div className="absolute -inset-1 rounded-2xl bg-gradient-to-b from-amber-400/30 via-amber-300/15 to-transparent dark:from-amber-500/25 dark:via-amber-400/10 blur-sm" />
<div className="relative flex flex-col gap-4 rounded-2xl border-2 border-amber-400 dark:border-amber-500/70 bg-gradient-to-b from-white via-white to-amber-50/30 dark:from-zinc-800 dark:via-zinc-800/95 dark:to-amber-950/30 px-7 py-6 shadow-xl shadow-amber-200/40 dark:shadow-amber-900/30 transition-all duration-300 hover:shadow-2xl hover:shadow-amber-300/40 dark:hover:shadow-amber-800/35">
{/* Status indicator */}
<div className="flex items-center gap-2 text-[11px] font-semibold uppercase tracking-widest text-amber-500 dark:text-amber-300">
<span className="relative flex h-2 w-2">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-amber-400 opacity-75" />
<span className="relative inline-flex h-2 w-2 rounded-full bg-amber-500" />
</span>
Building now
</div>
<div className="flex items-center gap-4">
<div className="flex h-12 w-12 shrink-0 items-center justify-center rounded-xl bg-amber-100 dark:bg-amber-800/50 text-amber-600 dark:text-amber-300 ring-2 ring-amber-200/60 dark:ring-amber-600/40">
<Icon size={22} />
</div>
<span className="text-lg font-bold text-zinc-900 dark:text-zinc-50 leading-tight tracking-tight">
{stage.name}
</span>
</div>
<p className="text-sm leading-relaxed text-zinc-700 dark:text-zinc-300">
{stage.description}
</p>
{stage.details && stage.details.length > 0 && (
<ul className="space-y-2 border-t border-amber-200/40 dark:border-amber-700/30 pt-4">
{stage.details.map((detail, i) => (
<li
key={i}
className="flex items-start gap-2.5 text-xs text-zinc-700 dark:text-zinc-300"
>
<span className="mt-[5px] h-1.5 w-1.5 rounded-full bg-amber-400 dark:bg-amber-500 shrink-0" />
{detail}
</li>
))}
</ul>
)}
</div>
</div>
)
}
/* ─── Planned: wireframe, dashed, ghosted ─── */
function PlannedCard({ stage }: { stage: Stage }) {
const Icon = stage.icon
return (
<div className="group relative flex flex-col gap-2.5 rounded-xl border border-dashed border-zinc-300 dark:border-zinc-700 bg-transparent px-5 py-4 w-full transition-all duration-200 hover:bg-zinc-50/50 dark:hover:bg-zinc-800/20 hover:border-zinc-400 dark:hover:border-zinc-600">
<div className="flex items-center gap-3">
<div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg border border-dashed border-zinc-300 dark:border-zinc-700 text-zinc-400 dark:text-zinc-600">
<Icon size={15} />
</div>
<span className="text-sm font-medium text-zinc-400 dark:text-zinc-500 leading-tight">
{stage.name}
</span>
</div>
<p className="text-xs leading-relaxed text-zinc-400 dark:text-zinc-600 pl-11">
{stage.description}
</p>
{stage.details && stage.details.length > 0 && (
<ul className="space-y-1 pl-11">
{stage.details.map((detail, i) => (
<li
key={i}
className="flex items-start gap-2 text-[11px] text-zinc-300 dark:text-zinc-600"
>
<CircleDashed size={8} className="mt-[3px] shrink-0" />
{detail}
</li>
))}
</ul>
)}
</div>
)
}
function StageCard({ stage }: { stage: Stage }) {
if (stage.status === "shipped") return <ShippedCard stage={stage} />
if (stage.status === "in-progress") return <InProgressCard stage={stage} />
return <PlannedCard stage={stage} />
}
function Connector({ to }: { to?: Status }) {
if (to === "planned") {
return (
<div className="flex justify-center py-1">
<div className="w-px h-6 border-l border-dashed border-zinc-300 dark:border-zinc-700" />
</div>
)
}
return (
<div className="flex justify-center py-1">
<div className="w-px h-6 bg-zinc-200 dark:bg-zinc-700" />
</div>
)
}
function StageNode({ stage }: { stage: Stage }) {
return (
<div className="flex flex-col items-center w-full">
<StageCard stage={stage} />
{stage.children && stage.children.length > 0 && (
<>
<Connector to={stage.children[0]?.status} />
{stage.children.length === 1 ? (
<StageCard stage={stage.children[0]} />
) : (
<div className="relative w-full">
<div className="grid grid-cols-2 gap-3">
{stage.children.map((child, j) => {
const isLastOdd =
j === stage.children!.length - 1 && stage.children!.length % 2 !== 0
return (
<div
key={j}
className={`flex flex-col items-center ${isLastOdd ? "col-span-2" : ""}`}
>
<div
className={`flex flex-col items-center w-full ${isLastOdd ? "max-w-[calc(50%-6px)] mx-auto" : ""}`}
>
<Connector to={child.status} />
<StageCard stage={child} />
</div>
</div>
)
})}
</div>
</div>
)}
</>
)}
{stage.downstream && stage.downstream.length > 0 && (
<>
<Connector to={stage.downstream[0]?.status} />
<div className="w-full max-w-md">
{stage.downstream.map((ds, j) => (
<StageCard key={j} stage={ds} />
))}
</div>
</>
)}
</div>
)
}
function FlowChart({ rows }: { rows: FlowRow[] }) {
return (
<div className="relative rounded-2xl border border-zinc-200/60 dark:border-zinc-700/40 bg-white/80 dark:bg-zinc-900/50 p-10 lg:p-12 overflow-hidden">
{/* Subtle grid background */}
<div
className="absolute inset-0 opacity-[0.03] dark:opacity-[0.05]"
style={{
backgroundImage:
"linear-gradient(to right, currentColor 1px, transparent 1px), linear-gradient(to bottom, currentColor 1px, transparent 1px)",
backgroundSize: "48px 48px",
}}
/>
<div className="relative flex flex-col items-center">
{rows.map((row, rowIdx) => (
<div key={rowIdx} className="flex flex-col items-center w-full">
{rowIdx > 0 && (
<div className="flex justify-center py-1">
<div className="w-px h-8 bg-zinc-200 dark:bg-zinc-700" />
</div>
)}
{row.type === "single" && (
<div className="w-full max-w-2xl">
<StageNode stage={row.stage} />
</div>
)}
{row.type === "branch" && (
<div className="relative w-full max-w-full">
<div
className="absolute top-0 h-px bg-zinc-200 dark:bg-zinc-700"
style={{
left: `${100 / (2 * row.stages.length)}%`,
right: `${100 / (2 * row.stages.length)}%`,
}}
/>
<div
className="grid"
style={{
gridTemplateColumns: `repeat(${row.stages.length}, 1fr)`,
}}
>
{row.stages.map((stage, j) => (
<div key={j} className="flex flex-col items-center px-3">
<Connector />
<StageNode stage={stage} />
</div>
))}
</div>
</div>
)}
</div>
))}
</div>
</div>
)
}
function Metrics() {
const counts = countStages(roadmap)
const total = counts.shipped + counts["in-progress"] + counts.planned
const shippedPct = (counts.shipped / total) * 100
const inProgressPct = (counts["in-progress"] / total) * 100
return (
<div className="space-y-4">
{/* Counters */}
<div className="flex items-baseline gap-8">
<div className="flex items-baseline gap-2">
<span className="text-3xl font-mono font-bold text-emerald-500 dark:text-emerald-400 tabular-nums">
{counts.shipped}
</span>
<span className="text-xs font-medium text-zinc-400 dark:text-zinc-500 uppercase tracking-wider">
shipped
</span>
</div>
<div className="flex items-baseline gap-2">
<span className="text-3xl font-mono font-bold text-amber-500 dark:text-amber-400 tabular-nums">
{counts["in-progress"]}
</span>
<span className="text-xs font-medium text-zinc-400 dark:text-zinc-500 uppercase tracking-wider">
active
</span>
</div>
<div className="flex items-baseline gap-2">
<span className="text-3xl font-mono font-bold text-zinc-300 dark:text-zinc-600 tabular-nums">
{counts.planned}
</span>
<span className="text-xs font-medium text-zinc-300 dark:text-zinc-600 uppercase tracking-wider">
planned
</span>
</div>
<span className="ml-auto text-sm font-mono text-zinc-400 dark:text-zinc-500 tabular-nums">
{Math.round(shippedPct)}%
</span>
</div>
{/* Segmented bar */}
<div className="h-1.5 w-full rounded-full bg-zinc-100 dark:bg-zinc-800 overflow-hidden flex">
<div
className="h-full bg-emerald-400 dark:bg-emerald-500 rounded-l-full"
style={{ width: `${shippedPct}%` }}
/>
<div
className="h-full bg-amber-400 dark:bg-amber-500"
style={{ width: `${inProgressPct}%` }}
/>
</div>
</div>
)
}
export default async function RoadmapPage() {
const teamMember = await isTeamMember()
if (!teamMember) {
redirect("/")
}
return (
<div className="min-h-screen bg-zinc-50 dark:bg-zinc-900">
<div className="border-b border-zinc-200 dark:border-zinc-700 bg-white dark:bg-zinc-800">
<div className="max-w-[1600px] mx-auto px-8 py-8 space-y-6">
<h1 className="text-2xl font-bold tracking-tight text-zinc-900 dark:text-zinc-50">
Roadmap
</h1>
<Metrics />
</div>
</div>
<div className="max-w-[1600px] mx-auto px-8 py-10">
{/* Rationale */}
<div className="mb-12 space-y-6">
<h2 className="text-base font-mono font-semibold text-zinc-800 dark:text-zinc-200 tracking-tight">
Why
</h2>
<div className="space-y-4 text-sm leading-relaxed text-zinc-600 dark:text-zinc-400">
<p>
The original codeflash CLI was designed for Python only. When multi-language support
was added, it was bolted on in a way that doesn&apos;t extend well. Discovery, context
extraction, AI calls, verification, and PR creation are all coupled together across
181 files. It works. But you can&apos;t run pieces on their own, call them from code,
or have the pipeline run itself.
</p>
<p>
We rebuilt the pipeline as two packages in a{" "}
<span className="font-mono text-zinc-800 dark:text-zinc-200">uv</span> workspace. The
original CLI packed everything into one class (
<span className="font-mono text-zinc-800 dark:text-zinc-200">FunctionOptimizer</span>
). The rewrite decomposes it into focused modules. Code was ported from the original
where possible, not rewritten from scratch, and we optimized the hot paths: stdlib{" "}
<span className="font-mono text-xs">ast</span> for discovery instead of libcst,
class-level visitor dispatch caching, type-identity fast-paths in the comparator, Jedi
refs caching with RO/TESTGEN deduplication in context extraction, SQLite-backed
reference graph with file-hash invalidation, and single CST parse reused across all
four context types. All models use{" "}
<span className="font-mono text-zinc-800 dark:text-zinc-200">attrs</span> with{" "}
<span className="font-mono text-xs">to_dict()</span> /{" "}
<span className="font-mono text-xs">from_dict()</span> for serialization.
</p>
<div className="mt-4 space-y-3">
<div className="rounded-lg border border-zinc-200/60 dark:border-zinc-700/40 bg-white/60 dark:bg-zinc-800/40 px-5 py-4">
<div className="flex items-center gap-2 mb-2.5">
<span className="font-mono text-sm font-semibold text-zinc-800 dark:text-zinc-200">
codeflash-core
</span>
<span className="text-[10px] font-medium px-1.5 py-0.5 rounded bg-zinc-100 dark:bg-zinc-700 text-zinc-500 dark:text-zinc-400">
language-agnostic
</span>
</div>
<ul className="grid grid-cols-2 gap-x-6 gap-y-1.5">
{(
[
["AIClient", "AI service communication"],
["Models", "shared types (Candidate, OptimizationRequest, etc.)"],
["Git", "repository operations"],
["Telemetry", "PostHog instrumentation"],
["Platform", "CodeFlash API client"],
["Pipeline", "candidate tree and ranking"],
["Plugin", "LanguagePlugin interface"],
] as const
).map(([name, desc], i) => (
<li
key={i}
className="flex items-start gap-2 text-xs text-zinc-500 dark:text-zinc-400"
>
<span className="mt-[5px] h-1 w-1 rounded-full bg-zinc-400/50 shrink-0" />
<span>
<span className="font-mono text-zinc-700 dark:text-zinc-300">{name}</span>
{" \u2014 "}
{desc}
</span>
</li>
))}
</ul>
</div>
<div className="rounded-lg border border-zinc-200/60 dark:border-zinc-700/40 bg-white/60 dark:bg-zinc-800/40 px-5 py-4">
<div className="flex items-center gap-2 mb-2.5">
<span className="font-mono text-sm font-semibold text-zinc-800 dark:text-zinc-200">
codeflash-python
</span>
<span className="text-[10px] font-medium px-1.5 py-0.5 rounded-full bg-emerald-500 text-white flex items-center gap-0.5">
<Check size={8} strokeWidth={3} />
shipped
</span>
</div>
<ul className="grid grid-cols-2 gap-x-6 gap-y-1.5">
{(
[
[
"analysis/",
"discovery, extraction, ranking, coverage, reference graph, call graph",
],
["context/", "dependency resolution, import mapping, enrichment, pruning"],
["test_discovery/", "pytest/unittest discovery, filtering, linking"],
[
"testing/",
"instrumentation, generation, pytest plugin, concolic validation",
],
["benchmarking/", "profiling, tracing, result parsing, comparison"],
[
"verification/",
"baseline, comparator, critic, ranking, candidate evaluation",
],
["codegen/", "code replacement, PR generation"],
["ai/", "refinement, repair, adaptive optimization"],
[
"pipeline/",
"orchestration (module prep \u2192 function optimizer \u2192 end-to-end)",
],
["api/", "OptimizationSession programmatic interface"],
] as const
).map(([dir, desc], i) => (
<li
key={i}
className="flex items-start gap-2 text-xs text-zinc-500 dark:text-zinc-400"
>
<span className="mt-[5px] h-1 w-1 rounded-full bg-zinc-400/50 shrink-0" />
<span>
<span className="font-mono text-zinc-700 dark:text-zinc-300">{dir}</span>{" "}
{desc}
</span>
</li>
))}
</ul>
</div>
<div className="rounded-lg border border-zinc-200/60 dark:border-zinc-700/40 bg-white/60 dark:bg-zinc-800/40 px-5 py-4">
<div className="flex items-center gap-2 mb-2.5">
<span className="font-mono text-sm font-semibold text-zinc-800 dark:text-zinc-200">
codeflash-agent
</span>
<span className="text-[10px] font-medium px-1.5 py-0.5 rounded-full bg-amber-500 text-white flex items-center gap-0.5">
in progress
</span>
</div>
<p className="text-xs leading-relaxed text-zinc-500 dark:text-zinc-400 mb-3">
A Claude Code plugin that autonomously optimizes an entire codebase. Given a
repository, it profiles across CPU, memory, async, and structure dimensions,
identifies performance bottlenecks, implements and verifies fixes, and ships
results &mdash; no human in the loop. Includes CI mode for automatic optimization
on PRs and adversarial review before shipping. Currently invokes the CLI for
pipeline steps &mdash; the Programmatic API replaces this with direct
OptimizationSession calls.
</p>
</div>
</div>
</div>
</div>
<FlowChart rows={roadmap} />
{/* Two-track strategy */}
<div className="mt-12 space-y-6">
<h2 className="text-base font-mono font-semibold text-zinc-800 dark:text-zinc-200 tracking-tight">
Two tracks
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="rounded-xl border border-zinc-200/80 dark:border-zinc-700/50 bg-white dark:bg-zinc-800/60 p-5">
<div className="flex items-center gap-2 mb-2">
<span className="text-xs font-mono font-semibold uppercase tracking-wider text-zinc-500 dark:text-zinc-400">
Consumer
</span>
<span className="text-[10px] font-medium px-1.5 py-0.5 rounded bg-zinc-100 dark:bg-zinc-700 text-zinc-600 dark:text-zinc-300">
unchanged
</span>
</div>
<p className="text-sm text-zinc-600 dark:text-zinc-400 leading-relaxed">
The existing{" "}
<span className="font-mono text-zinc-800 dark:text-zinc-200">codeflash --file</span>{" "}
/{" "}
<span className="font-mono text-zinc-800 dark:text-zinc-200">codeflash --all</span>{" "}
workflow stays as-is. Single-function and whole-project optimization continues to
run the same pipeline it does today.
</p>
</div>
<div className="rounded-xl border border-amber-300/40 dark:border-amber-500/20 bg-gradient-to-b from-amber-50/50 to-white dark:from-amber-950/20 dark:to-zinc-800/60 p-5">
<div className="flex items-center gap-2 mb-2">
<span className="text-xs font-mono font-semibold uppercase tracking-wider text-amber-600 dark:text-amber-400">
B2B / Enterprise
</span>
<span className="text-[10px] font-medium px-1.5 py-0.5 rounded bg-amber-100 dark:bg-amber-900/40 text-amber-700 dark:text-amber-300">
new
</span>
</div>
<p className="text-sm text-zinc-600 dark:text-zinc-400 leading-relaxed">
The autonomous experiment loop and agentic capabilities target B2B and enterprise
contracts. Multi-domain profiling, cross-cutting optimization, and iterative
measurement across an entire codebase, without a human driving each step.
</p>
</div>
</div>
</div>
</div>
</div>
)
}

View file

@ -26,6 +26,7 @@ import {
Loader2,
Zap,
BarChart3,
Map,
} from "lucide-react"
import type { User as UserProfile } from "@auth0/nextjs-auth0/types"
import { SignOut } from "../ui/SignOut"
@ -320,6 +321,15 @@ export function Sidebar({ className, user, isLoading, error }: SidebarProps): JS
Observability
</Button>
</Link>
<Link href="/roadmap" className="block mb-1">
<Button
variant={currentRoute?.startsWith("/roadmap") ? "secondary" : "ghost"}
className="flex items-center justify-start w-full"
>
<Map size={16} className="mr-2 h-4 w-4 shrink-0" />
Roadmap
</Button>
</Link>
</>
)}