From 571513f5f9f3e5a1c3e316cefe4fd2eb10b6c0a1 Mon Sep 17 00:00:00 2001 From: huangrt01 Date: Sun, 28 Jun 2026 03:49:27 +0800 Subject: [PATCH] Add auto-research frontstage board --- .../dashboard/smoke/frontstage-route-smoke.ts | 57 ++ apps/dashboard/src/router.tsx | 14 +- .../views/frontstage-auto-research-page.tsx | 538 ++++++++++++++++++ ...auto-research-frontstage-board.public.json | 258 +++++++++ 4 files changed, 866 insertions(+), 1 deletion(-) create mode 100644 apps/dashboard/src/views/frontstage-auto-research-page.tsx create mode 100644 docs/product/auto-research-frontstage-board.public.json diff --git a/apps/dashboard/smoke/frontstage-route-smoke.ts b/apps/dashboard/smoke/frontstage-route-smoke.ts index ca95bfd2..4a7f8bf5 100644 --- a/apps/dashboard/smoke/frontstage-route-smoke.ts +++ b/apps/dashboard/smoke/frontstage-route-smoke.ts @@ -24,6 +24,7 @@ function sourceBetween(source: string, start: string, end: string, label: string const routerSource = readFileSync("src/router.tsx", "utf8"); const mainSource = readFileSync("src/main.tsx", "utf8"); +const frontstageAutoResearchSource = readFileSync("src/views/frontstage-auto-research-page.tsx", "utf8"); const frontstageDeveloperSource = readFileSync("src/views/frontstage-developer-page.tsx", "utf8"); const frontstageSource = readFileSync("src/views/frontstage-page.tsx", "utf8"); const stylesSource = readFileSync("src/styles.css", "utf8"); @@ -31,6 +32,7 @@ const dataSource = readFileSync("src/data/goal-channel-frontstage.ts", "utf8"); const localStatusQuerySource = readFileSync("src/data/local-status-query.ts", "utf8"); const statusSource = readFileSync("src/data/status.ts", "utf8"); const catalogSource = readFileSync("../../docs/showcases/showcase-catalog.json", "utf8"); +const autoResearchBoardSource = readFileSync("../../docs/product/auto-research-frontstage-board.public.json", "utf8"); const rolloutProjectionFixtureSource = readFileSync("../../examples/fixtures/frontstage-rollout-projections.public.json", "utf8"); const privateTrapFixtureSource = readFileSync("../../examples/fixtures/frontstage-private-status-trap.public.json", "utf8"); const readmeSource = readFileSync("README.md", "utf8"); @@ -42,6 +44,9 @@ includes(routerSource, "component: FrontstagePage", "frontstage route component" includes(routerSource, 'path: "/frontstage/developer"', "frontstage developer route path"); includes(routerSource, "component: FrontstageDeveloperPage", "frontstage developer route component"); includes(routerSource, "frontstageDeveloperRoute", "frontstage developer route export"); +includes(routerSource, 'path: "/frontstage/auto-research"', "frontstage auto-research route path"); +includes(routerSource, "component: FrontstageAutoResearchPage", "frontstage auto-research route component"); +includes(routerSource, "frontstageAutoResearchRoute", "frontstage auto-research route export"); includes(routerSource, "frontstageSearchSchema", "frontstage search schema"); includes(routerSource, 'mode: z.enum(["showcase", "developer", "ops"]).optional().default("showcase")', "frontstage mode gate"); includes(routerSource, 'todoLane: z.enum(["all", "user", "agent"]).optional().default("all")', "frontstage todo lane filter search param"); @@ -55,6 +60,40 @@ includes(privateTrapFixtureSource, "GH_FAKE_LIVE_STATUS_FEED_BETA", "fake-privat includes(privateTrapFixtureSource, "GH_FAKE_PRIVATE_TODO_GAMMA", "fake-private todo trap marker"); includes(packageSource, '"@tanstack/react-query"', "TanStack Query dependency"); +const autoResearchBoard = JSON.parse(autoResearchBoardSource); +assert( + autoResearchBoard.schema_version === "auto_research_frontstage_board_v0", + "auto-research board schema version", +); +assert(autoResearchBoard.surface.stage === "experimental", "auto-research board remains experimental"); +assert(autoResearchBoard.lane_contract.topology === "decentralized", "auto-research decentralized topology"); +assert(autoResearchBoard.value_metrics.length >= 4, "auto-research board must expose user-value metrics"); +assert( + autoResearchBoard.evidence_graph.best_holdout_metric > autoResearchBoard.evidence_graph.metric.baseline, + "auto-research board must surface held-out improvement", +); +assert( + autoResearchBoard.decision_candidates.promotion_candidates.length >= 1, + "auto-research board promotion candidate", +); +assert( + autoResearchBoard.decision_candidates.retirement_candidates.length >= 1, + "auto-research board retirement candidate", +); +for (const forbidden of [ + "/Users/", + "/private/", + "/tmp/", + "lark" + "office", + "byte" + "dance", + "Bearer ", + "api_key", + "password", + "secret", +]) { + excludes(autoResearchBoardSource, forbidden, `auto-research board private marker ${forbidden}`); +} + includes(mainSource, "QueryClientProvider", "TanStack Query provider"); includes(mainSource, "new QueryClient", "query client construction"); includes(mainSource, "refetchOnWindowFocus: false", "query focus refetch policy"); @@ -377,6 +416,24 @@ includes(readmeSource, "write authority", "README write authority boundary"); includes(selectionSource, "Multica", "Multica benchmark note"); includes(selectionSource, "agent board", "agent board benchmark note"); +includes(frontstageAutoResearchSource, 'data-testid="frontstage-auto-research-board"', "auto-research board route test id"); +includes(frontstageAutoResearchSource, "autoResearchBoardData", "auto-research board JSON import"); +includes(frontstageAutoResearchSource, "auto-research-frontstage-board.public.json", "auto-research board public fixture"); +includes(frontstageAutoResearchSource, 'data-testid="auto-research-value-metrics"', "auto-research value metrics"); +includes(frontstageAutoResearchSource, 'data-testid="auto-research-contract-commands"', "auto-research runnable command strip"); +includes(frontstageAutoResearchSource, 'data-testid="auto-research-lane-contract"', "auto-research lane contract"); +includes(frontstageAutoResearchSource, 'data-testid="auto-research-frontier"', "auto-research per-agent frontier"); +includes(frontstageAutoResearchSource, 'data-testid="auto-research-evidence-graph"', "auto-research evidence graph"); +includes(frontstageAutoResearchSource, 'data-testid="auto-research-decision-candidates"', "auto-research decision candidates"); +includes(frontstageAutoResearchSource, 'data-testid="auto-research-showcase-projection"', "auto-research showcase projection"); +includes(autoResearchBoardSource, "single leader agent owns the whole hypothesis tree", "auto-research hidden leader anti-pattern"); +includes(autoResearchBoardSource, "Public fixture and protected-evaluator outputs only", "auto-research public boundary"); +includes(frontstageAutoResearchSource, "BoardPanel", "auto-research board panel component"); +excludes(frontstageAutoResearchSource, " rootRoute, + path: "/frontstage/auto-research", + component: FrontstageAutoResearchPage, +}); + +const routeTree = rootRoute.addChildren([ + dashboardRoute, + frontstageRoute, + frontstageDeveloperRoute, + frontstageAutoResearchRoute, +]); function routerBasepathFromViteBase(baseUrl: string) { if (!baseUrl || baseUrl === "/" || baseUrl === "./") { diff --git a/apps/dashboard/src/views/frontstage-auto-research-page.tsx b/apps/dashboard/src/views/frontstage-auto-research-page.tsx new file mode 100644 index 00000000..b8395845 --- /dev/null +++ b/apps/dashboard/src/views/frontstage-auto-research-page.tsx @@ -0,0 +1,538 @@ +import { + ArrowRight, + Bot, + CheckCircle2, + GitBranch, + LayoutDashboard, + Network, + ShieldCheck, + Sparkles, + Target, + Trophy, +} from "lucide-react"; + +import autoResearchBoardData from "../../../../docs/product/auto-research-frontstage-board.public.json"; +import { Badge } from "../components/ui/badge"; + +type BoardTone = "neutral" | "success" | "warning" | "info" | "danger"; + +type BoardCommand = { + label: string; + command: string; +}; + +type BoardMetric = { + label: string; + value: string; + baseline: string; + interpretation: string; + source: string; +}; + +type BoardLane = { + role_id: string; + display_name: string; + agent_id: string; + responsibility: string; + produces: string[]; + does_not_own: string; +}; + +type BoardFrontierItem = { + hypothesis_id: string; + todo_id: string; + mechanism_family: string; + next_action?: string; + allowed_action?: string; + status?: string; + why_selected?: string; + blocked_by?: string; + operator_value?: string; +}; + +type BoardEvidenceNode = { + hypothesis_id: string; + status: string; + summary: string; + best_dev_metric: number | null; + best_holdout_metric: number | null; + evidence_boundary: string; +}; + +type BoardEvidenceEdge = { + from: string; + to: string; + label: string; +}; + +type BoardDecisionCandidate = { + hypothesis_id: string; + todo_id: string; + decision: string; + dev_metric?: string; + holdout_metric?: string; + requires?: string[]; + reason?: string; + user_value?: string; +}; + +type AutoResearchBoard = { + schema_version: "auto_research_frontstage_board_v0"; + generated_at: string; + surface: { + id: string; + title: string; + subtitle: string; + stage: string; + positioning: string; + public_boundary: string; + }; + research_contract: { + goal_id: string; + objective: string; + editable_scope: string[]; + protected_scope: string[]; + metric: { + name: string; + direction: string; + baseline: string; + }; + promotion_policy: string; + commands: BoardCommand[]; + }; + value_metrics: BoardMetric[]; + lane_contract: { + topology: string; + anti_pattern: string; + lanes: BoardLane[]; + }; + frontier: { + agent_id: string; + selected: BoardFrontierItem; + runnable: BoardFrontierItem[]; + blocked: BoardFrontierItem[]; + }; + evidence_graph: { + schema_version: string; + goal_id: string; + metric: { + name: string; + direction: string; + baseline: number; + }; + best_dev_metric: number; + best_holdout_metric: number; + holdout_improved: boolean; + source_kind: string; + nodes: BoardEvidenceNode[]; + edges: BoardEvidenceEdge[]; + }; + decision_candidates: { + promotion_candidates: BoardDecisionCandidate[]; + retry_candidates: BoardDecisionCandidate[]; + retirement_candidates: BoardDecisionCandidate[]; + }; + showcase_projection: { + schema_version: string; + title: string; + primary_claim: string; + audience_takeaway: string; + public_demo_path: string; + next_product_step: string; + }; + quality_gates: string[]; +}; + +const board = autoResearchBoardData as AutoResearchBoard; + +function statusTone(status: string): BoardTone { + if (["supported", "promote_after_boundary_scan"].includes(status)) { + return "success"; + } + if (["active", "retry_with_executor_lane"].includes(status)) { + return "info"; + } + if (["contradicted", "retire_until_exactness_proof"].includes(status)) { + return "warning"; + } + return "neutral"; +} + +function metricValue(value: number | null) { + return value === null ? "not scored" : `${value.toFixed(1)}x`; +} + +function BoardPanel({ + children, + eyebrow, + title, +}: { + children: React.ReactNode; + eyebrow?: string; + title: string; +}) { + return ( +
+
+ {eyebrow ? ( +
{eyebrow}
+ ) : null} +

{title}

+
+
{children}
+
+ ); +} + +function ValueMetrics() { + return ( +
+ {board.value_metrics.map((metric) => ( +
+
+
{metric.label}
+ +
+
{metric.value}
+
{metric.baseline}
+

{metric.interpretation}

+
{metric.source}
+
+ ))} +
+ ); +} + +function ResearchContractPanel() { + return ( + +
+
+

{board.research_contract.objective}

+
+
+
Metric
+
{board.research_contract.metric.name}
+
+ {board.research_contract.metric.direction} from {board.research_contract.metric.baseline} +
+
+
+
Editable
+
+ {board.research_contract.editable_scope.map((item) => ( + {item} + ))} +
+
+
+
Protected
+
+ {board.research_contract.protected_scope.map((item) => ( + {item} + ))} +
+
+
+
+ Promotion policy: + {board.research_contract.promotion_policy} +
+
+
+ {board.research_contract.commands.map((command) => ( +
+
+ + {command.label} +
+ + {command.command} + +
+ ))} +
+
+
+ ); +} + +function LaneContractPanel() { + return ( + +
+ Avoid: + {board.lane_contract.anti_pattern} +
+
+ {board.lane_contract.lanes.map((lane) => ( +
+
+ {lane.role_id} + +
+

{lane.display_name}

+
{lane.agent_id}
+

{lane.responsibility}

+
+ {lane.produces.map((item) => ( + {item} + ))} +
+

+ Does not own: + {lane.does_not_own} +

+
+ ))} +
+
+ ); +} + +function FrontierCard({ item, tone }: { item: BoardFrontierItem; tone: BoardTone }) { + return ( +
+
+ {item.hypothesis_id} + {item.todo_id} +
+
{item.mechanism_family}
+

+ {item.why_selected ?? item.next_action ?? item.operator_value ?? item.allowed_action ?? item.blocked_by} +

+ {item.blocked_by ? ( +
blocked_by={item.blocked_by}
+ ) : null} +
+ ); +} + +function FrontierPanel() { + return ( + +
+
+
+ + Selected +
+ +
+
+
+ + Runnable +
+
+ {board.frontier.runnable.map((item) => ( + + ))} +
+
+
+
+ + Blocked Or Claimed Elsewhere +
+
+ {board.frontier.blocked.map((item) => ( + + ))} +
+
+
+
+ ); +} + +function EvidenceGraphPanel() { + return ( + +
+
+
Best dev
+
{metricValue(board.evidence_graph.best_dev_metric)}
+
+
+
Best holdout
+
+ {metricValue(board.evidence_graph.best_holdout_metric)} +
+
+
+
Source kind
+
{board.evidence_graph.source_kind}
+
+
+
+ {board.evidence_graph.nodes.map((node) => ( +
+
+ {node.status} + {node.hypothesis_id} +
+

{node.summary}

+
+
+
dev
+
{metricValue(node.best_dev_metric)}
+
+
+
holdout
+
{metricValue(node.best_holdout_metric)}
+
+
+

{node.evidence_boundary}

+
+ ))} +
+
+ {board.evidence_graph.edges.map((edge) => ( +
+ +
+ {edge.from} + + {edge.to} +
{edge.label}
+
+
+ ))} +
+
+ ); +} + +function DecisionColumn({ + candidates, + title, +}: { + candidates: BoardDecisionCandidate[]; + title: string; +}) { + return ( +
+
{title}
+ {candidates.map((candidate) => ( +
+
+ {candidate.decision} + {candidate.hypothesis_id} +
+
{candidate.todo_id}
+ {candidate.dev_metric || candidate.holdout_metric ? ( +
+
+
dev
+
{candidate.dev_metric ?? "not scored"}
+
+
+
holdout
+
{candidate.holdout_metric ?? "not scored"}
+
+
+ ) : null} +

{candidate.user_value ?? candidate.reason}

+ {candidate.requires ? ( +
+ {candidate.requires.map((item) => ( + {item} + ))} +
+ ) : null} +
+ ))} +
+ ); +} + +function DecisionCandidatesPanel() { + return ( + +
+ + + +
+
+ ); +} + +function ShowcaseProjectionPanel() { + return ( + +
+
+

{board.showcase_projection.primary_claim}

+

{board.showcase_projection.audience_takeaway}

+
+ Demo path: + {board.showcase_projection.public_demo_path} +
+
+
+
+ + Quality Gates +
+
    + {board.quality_gates.map((gate) => ( +
  • + + {gate} +
  • + ))} +
+
+ Next: + {board.showcase_projection.next_product_step} +
+
+
+
+ ); +} + +export function FrontstageAutoResearchPage() { + return ( +
+
+
+
+ {board.surface.stage} + {board.schema_version} + public-safe projection +
+
+
+
+ + Auto Research Frontstage +
+

+ {board.surface.title} +

+

{board.surface.positioning}

+
+
+
+ + Boundary +
+ {board.surface.public_boundary} +
+
+
+ + + + + + + + +
+
+ ); +} diff --git a/docs/product/auto-research-frontstage-board.public.json b/docs/product/auto-research-frontstage-board.public.json new file mode 100644 index 00000000..c05a7334 --- /dev/null +++ b/docs/product/auto-research-frontstage-board.public.json @@ -0,0 +1,258 @@ +{ + "schema_version": "auto_research_frontstage_board_v0", + "generated_at": "2026-06-28T00:00:00Z", + "surface": { + "id": "loopx_auto_research_knn_board", + "title": "Auto Research Product Board", + "subtitle": "A public-safe Frontstage board for decentralized k-NN research.", + "stage": "experimental", + "positioning": "LoopX keeps autonomous research decentralized: every agent sees a claim-compatible frontier, while hypotheses, evidence, retries, and promotion decisions stay in the shared control plane.", + "public_boundary": "Public fixture and protected-evaluator outputs only; no raw logs, non-public source docs, credentials, local paths, or hidden leader transcript." + }, + "research_contract": { + "goal_id": "loopx-auto-research-knn", + "objective": "Improve exact k-nearest-neighbor inference speed while preserving exact neighbor identity.", + "editable_scope": ["solution_candidate.py"], + "protected_scope": ["protected_eval.py", "solution_baseline.py", "generated dev/holdout data"], + "metric": { + "name": "deterministic_speedup", + "direction": "maximize", + "baseline": "1.0x" + }, + "promotion_policy": "Promote only after dev and holdout improvement, exact output, clean protected boundary, and no-upload evidence.", + "commands": [ + { + "label": "dev evidence", + "command": "python3 examples/auto_research_knn_pack/protected_eval.py --solution examples/auto_research_knn_pack/solution_candidate.py --split dev" + }, + { + "label": "holdout evidence", + "command": "python3 examples/auto_research_knn_pack/protected_eval.py --solution examples/auto_research_knn_pack/solution_candidate.py --split holdout" + } + ] + }, + "value_metrics": [ + { + "label": "Held-out speedup", + "value": "4.5x", + "baseline": "1.0x baseline", + "interpretation": "The candidate still improves on the protected holdout split, so the result is not only a dev-set artifact.", + "source": "auto_research_knn_eval_result_v0:holdout" + }, + { + "label": "Dev to holdout transfer", + "value": "4.0x -> 4.5x", + "baseline": "dev result before promotion", + "interpretation": "The promotion candidate improves across both splits under the same protected metric.", + "source": "auto_research_knn_eval_result_v0:dev+holdout" + }, + { + "label": "Correctness preserved", + "value": "exact neighbors", + "baseline": "oracle identity check", + "interpretation": "The speedup is only accepted because every query keeps exact nearest-neighbor identity.", + "source": "protected_eval.py exactness gate" + }, + { + "label": "Protected boundary", + "value": "clean", + "baseline": "no protected edits, no upload", + "interpretation": "The executor can optimize the candidate while the evaluator, data, oracle, and promotion gate stay protected.", + "source": "promotion_gate.requires" + } + ], + "lane_contract": { + "topology": "decentralized", + "anti_pattern": "single leader agent owns the whole hypothesis tree", + "lanes": [ + { + "role_id": "curator", + "display_name": "Curator", + "agent_id": "codex-product-capability", + "responsibility": "Keep the research contract, protected scope, and public boundary clear.", + "produces": ["research_contract_v0", "scope boundary notes"], + "does_not_own": "Experiment execution or promotion by persuasion." + }, + { + "role_id": "hypothesis_proposer", + "display_name": "Hypothesis proposer", + "agent_id": "codex-side-bypass", + "responsibility": "Propose todo-linked hypotheses and parent-child refinements.", + "produces": ["research_hypothesis_v0", "grounding refs"], + "does_not_own": "Novelty claims from the same material used for ideation." + }, + { + "role_id": "research_executor", + "display_name": "Research executor", + "agent_id": "codex-side-bypass", + "responsibility": "Run one claimed hypothesis in an isolated worktree and emit split-aware evidence.", + "produces": ["auto_research_evidence_packet_v0", "branch refs"], + "does_not_own": "Protected files, evaluator behavior, or promotion gates." + }, + { + "role_id": "evaluator_promoter", + "display_name": "Evaluator / promoter", + "agent_id": "codex-product-capability", + "responsibility": "Classify scored attempts into promote, retry, or retire using dev and holdout evidence.", + "produces": ["promotion candidates", "retirement candidates", "gate todos"], + "does_not_own": "Dev-only promotion or hidden bypass of user gates." + }, + { + "role_id": "product_narrator", + "display_name": "Product narrator", + "agent_id": "codex-side-bypass", + "responsibility": "Turn the evidence graph into a public showcase without leaking private material.", + "produces": ["research_showcase_projection_v0", "Frontstage board"], + "does_not_own": "Changing public first screens without owner review." + } + ] + }, + "frontier": { + "agent_id": "codex-side-bypass", + "selected": { + "hypothesis_id": "hyp_002", + "todo_id": "todo_auto_research_002", + "status": "active", + "mechanism_family": "partial_selection", + "allowed_action": "run_dev_attempt", + "why_selected": "Claim-compatible, unblocked, and directly tied to the current exact k-NN speedup objective." + }, + "runnable": [ + { + "hypothesis_id": "hyp_002", + "todo_id": "todo_auto_research_002", + "mechanism_family": "partial_selection", + "next_action": "Run dev evidence, then require holdout before promotion." + } + ], + "blocked": [ + { + "hypothesis_id": "hyp_003", + "todo_id": "todo_auto_research_003", + "mechanism_family": "batch_query_path", + "blocked_by": "claimed_by:codex-product-capability", + "operator_value": "Shows other-lane work without letting this agent silently steal it." + }, + { + "hypothesis_id": "hyp_004", + "todo_id": "todo_auto_research_004", + "mechanism_family": "approximate_search_guardrail", + "blocked_by": "correctness_guardrail_failed", + "operator_value": "Keeps a useful negative direction visible so the next agent does not rediscover it." + } + ] + }, + "evidence_graph": { + "schema_version": "research_evidence_graph_v0", + "goal_id": "loopx-auto-research-knn", + "metric": { + "name": "deterministic_speedup", + "direction": "maximize", + "baseline": 1.0 + }, + "best_dev_metric": 4.0, + "best_holdout_metric": 4.5, + "holdout_improved": true, + "source_kind": "public_pack_plus_public_fixture", + "nodes": [ + { + "hypothesis_id": "hyp_001", + "status": "supported", + "summary": "Vectorize exact distance work as the broad mechanism family.", + "best_dev_metric": 4.8, + "best_holdout_metric": 4.3, + "evidence_boundary": "Fixture evidence only; retained as a shape example." + }, + { + "hypothesis_id": "hyp_002", + "status": "active", + "summary": "Use exact partial selection to avoid full distance sorting.", + "best_dev_metric": 4.0, + "best_holdout_metric": 4.5, + "evidence_boundary": "Runnable public pack evidence from protected_eval.py." + }, + { + "hypothesis_id": "hyp_003", + "status": "active", + "summary": "Batch query work so shared array layout setup can be reused.", + "best_dev_metric": null, + "best_holdout_metric": null, + "evidence_boundary": "Claimed future lane; not promoted without split evidence." + }, + { + "hypothesis_id": "hyp_004", + "status": "contradicted", + "summary": "Approximate search is rejected unless exact identity can be preserved.", + "best_dev_metric": null, + "best_holdout_metric": null, + "evidence_boundary": "Negative evidence because correctness guardrail failed." + } + ], + "edges": [ + { + "from": "research_contract", + "to": "hyp_001", + "label": "opens mechanism family" + }, + { + "from": "hyp_001", + "to": "hyp_002", + "label": "narrows to exact selection" + }, + { + "from": "hyp_002", + "to": "hyp_003", + "label": "future batching refinement" + }, + { + "from": "hyp_003", + "to": "hyp_004", + "label": "negative-control branch" + } + ] + }, + "decision_candidates": { + "promotion_candidates": [ + { + "hypothesis_id": "hyp_002", + "todo_id": "todo_auto_research_002", + "decision": "promote_after_boundary_scan", + "dev_metric": "4.0x", + "holdout_metric": "4.5x", + "requires": ["boundary_scan", "exact_neighbor_identity", "protected_scope_clean", "no_upload"], + "user_value": "A reproducible speedup that survived the protected holdout gate." + } + ], + "retry_candidates": [ + { + "hypothesis_id": "hyp_003", + "todo_id": "todo_auto_research_003", + "decision": "retry_with_executor_lane", + "reason": "Potential product value, but no dev or holdout score yet." + } + ], + "retirement_candidates": [ + { + "hypothesis_id": "hyp_004", + "todo_id": "todo_auto_research_004", + "decision": "retire_until_exactness_proof", + "reason": "Approximate search conflicts with exact output unless a later proof changes the boundary." + } + ] + }, + "showcase_projection": { + "schema_version": "research_showcase_projection_v0", + "title": "Decentralized Auto Research: k-NN Speedup", + "primary_claim": "LoopX can present an Arbor-style research tree while keeping execution decentralized through todo claims, evidence events, and promotion gates.", + "audience_takeaway": "A user can inspect what is runnable now, what is blocked by another lane, what is promotable, and what has been retired without trusting a hidden leader chat.", + "public_demo_path": "Run the k-NN pack, emit evidence, append rollout events, then render this board from the evidence graph.", + "next_product_step": "Replace fixture-only nodes with live rollout-event projections for every auto-research run." + }, + "quality_gates": [ + "All promoted work needs dev and holdout evidence.", + "Protected scope edits fail the promotion gate.", + "Every hypothesis stays todo-linked and agent-scoped.", + "Negative evidence remains visible as reusable research memory.", + "Public boards render projections, not raw logs or private planning text." + ] +}