Skip to content
Open
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2,132 changes: 1,812 additions & 320 deletions console-oven-behavior-policy.json → ...ts/oven/console-oven-behavior-policy.json

Large diffs are not rendered by default.

4,160 changes: 3,348 additions & 812 deletions console-oven-behavior.json → audits/oven/console-oven-behavior.json

Large diffs are not rendered by default.

3,156 changes: 2,065 additions & 1,091 deletions terminal-oven-parity-corpus.json → audits/oven/terminal-oven-parity-corpus.json

Large diffs are not rendered by default.

6,585 changes: 5,961 additions & 624 deletions terminal-oven-parity.json → audits/oven/terminal-oven-parity.json

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions bin/burnlist.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const knownSubcommands = new Set([
"install",
"uninstall",
"agent-monitor",
"differential-testing",
"streaming-diff",
"hooks",
Expand Down Expand Up @@ -161,6 +162,7 @@ Usage:
burnlist differential-testing validate-bundle <bundle/current.json>
burnlist differential-testing schema
burnlist differential-testing sdk
burnlist agent-monitor <start|stop|status|run|url> ...
burnlist streaming-diff <ensure-feed|capture|url|hook> ...
burnlist hooks [install|uninstall|status] [--agent codex,claude] [--untracked] (bare defaults to status)
burnlist oven <list|view|use|set|bind|unbind|bindings|event|create|update|adopt|upgrade|fork> ...
Expand Down Expand Up @@ -223,6 +225,8 @@ if (args[0] !== "oven" && (args.includes("--version") || args.includes("-v"))) {

if (args[0] === "oven") {
await import("../src/cli/oven-cli.mjs");
} else if (args[0] === "agent-monitor") {
await import("../src/cli/agent-monitor-cli.mjs");
} else if (args[0] === "streaming-diff") {
await import("../src/cli/streaming-diff-cli.mjs");
} else if (args[0] === "hooks") {
Expand Down
13 changes: 7 additions & 6 deletions dashboard/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import { useMemo, useState } from "react";
import { ListChecks } from "lucide-react";
import { AppHeader, BurnlistTable, ChecklistOvenView, CustomOvenView, DashboardError, DifferentialTestingOvenPage, EmptyState, FILTERS, Filters, LensSwitcher, ModelLabPage, NewOvenPage, OvenCatalog, OvenDefinition, OvenExplainer, PerformanceTracingOvenPage, ProjectGroup, RunBurnPage, StreamingDiff, VisualParityPage } from "@components";
import { AgentMonitor, AppHeader, BurnlistTable, ChecklistOvenView, CustomOvenView, DashboardError, DifferentialTestingOvenPage, EmptyState, FILTERS, Filters, LensSwitcher, ModelLabPage, NewOvenPage, OvenCatalog, OvenDefinition, OvenExplainer, PerformanceTracingOvenPage, ProjectGroup, RunBurnPage, StreamingDiff, VisualParityPage } from "@components";
import { useDashboardData } from "@hooks";
import { checklistOvenRepoKey, currentSection, filterFromUrl, ovenRepoKey, selectedBurnlist } from "@lib";
import { checklistOvenRepoKey, currentSection, customOvenSelection, filterFromUrl, ovenRepoKey, selectedBurnlist } from "@lib";
import type { Filter } from "@lib";
import { Button } from "@layout";

export function App() {
const section = currentSection();
const selected = useMemo(selectedBurnlist, [window.location.pathname, window.location.search]);
const repoKey = ovenRepoKey();
const customOven = section === "custom-oven" ? customOvenSelection() : null;
const [filter, setFilter] = useState(() => filterFromUrl(FILTERS));
const dashboardSection = ["landing", "burnlist", "streaming-diff"].includes(section) || (section === "custom-oven" && selected) ? "burnlists" : section;
const dashboardSection = ["landing", "burnlist", "agent-monitor", "streaming-diff"].includes(section) || (section === "custom-oven" && selected) ? "burnlists" : section;
const { projects, progress, error, loading, stale } = useDashboardData({ section: dashboardSection, selected });
const checklistRepoKey = checklistOvenRepoKey(progress, selected);
const visibleBurnlistCount = projects.reduce((total, project) => total + project.entries.filter((entry) => filter === "all" || entry.status === filter).length, 0);
Expand All @@ -26,13 +27,13 @@ export function App() {
setFilter(nextFilter);
};

const fullLayout = ["differential-testing", "model-lab", "performance-tracing", "streaming-diff", "visual-parity", "custom-oven"].includes(section) || selected;
const fullLayout = ["agent-monitor", "differential-testing", "model-lab", "performance-tracing", "streaming-diff", "visual-parity", "custom-oven"].includes(section) || selected;

return (
<div className="dashboard-app">
<AppHeader detail={progress} section={section} />
<AppHeader detail={progress} ovenId={customOven?.id} section={section} />
<main className="dashboard-main" data-layout={fullLayout ? "full" : "index"} data-section={section}>
{section === "differential-testing" ? <OvenDefinition id="differential-testing" repoKey={repoKey}>{(ir) => <DifferentialTestingOvenPage ir={ir} />}</OvenDefinition> : section === "model-lab" ? <OvenDefinition id="model-lab" repoKey={repoKey}>{(ir) => <ModelLabPage ir={ir} />}</OvenDefinition> : section === "performance-tracing" ? <OvenDefinition id="performance-tracing" repoKey={repoKey}>{(ir) => <PerformanceTracingOvenPage ir={ir} />}</OvenDefinition> : section === "streaming-diff" ? <OvenDefinition id="streaming-diff" repoKey={repoKey}>{(ir) => <StreamingDiff ir={ir} projects={projects} projectsLoading={loading} />}</OvenDefinition> : section === "visual-parity" ? <OvenDefinition id="visual-parity" repoKey={repoKey}>{(ir) => <VisualParityPage ir={ir} />}</OvenDefinition> : section === "custom-oven" ? <CustomOvenView error={error} loading={loading} progress={progress} stale={stale} /> : section === "new-oven" ? <NewOvenPage /> : section === "run-burn" ? <RunBurnPage /> : section === "ovens-catalog" ? <OvenCatalog /> : section === "oven-explainer" ? <OvenExplainer /> : selected ? (
{section === "agent-monitor" ? <OvenDefinition id="agent-monitor" repoKey={repoKey}>{(ir) => <AgentMonitor ir={ir} projects={projects} projectsLoading={loading} />}</OvenDefinition> : section === "differential-testing" ? <OvenDefinition id="differential-testing" repoKey={repoKey}>{(ir) => <DifferentialTestingOvenPage ir={ir} />}</OvenDefinition> : section === "model-lab" ? <OvenDefinition id="model-lab" repoKey={repoKey}>{(ir) => <ModelLabPage ir={ir} />}</OvenDefinition> : section === "performance-tracing" ? <OvenDefinition id="performance-tracing" repoKey={repoKey}>{(ir) => <PerformanceTracingOvenPage ir={ir} />}</OvenDefinition> : section === "streaming-diff" ? <OvenDefinition id="streaming-diff" repoKey={repoKey}>{(ir) => <StreamingDiff ir={ir} projects={projects} projectsLoading={loading} />}</OvenDefinition> : section === "visual-parity" ? <OvenDefinition id="visual-parity" repoKey={repoKey}>{(ir) => <VisualParityPage ir={ir} />}</OvenDefinition> : section === "custom-oven" ? <CustomOvenView error={error} loading={loading} progress={progress} stale={stale} /> : section === "new-oven" ? <NewOvenPage /> : section === "run-burn" ? <RunBurnPage /> : section === "ovens-catalog" ? <OvenCatalog /> : section === "oven-explainer" ? <OvenExplainer /> : selected ? (
loading && !progress ? <EmptyState title="Loading progress" detail="Reading the selected Burnlist." /> : progress ? (
<>{error && <DashboardError message={error} />}<LensSwitcher /><OvenDefinition id="checklist" repoKey={checklistRepoKey}>{(ir) => <ChecklistOvenView data={progress} ir={ir} />}</OvenDefinition></>
) : error ? <DashboardError message={error} /> : <EmptyState title="Choose a Burnlist" detail="Select an item from the list to inspect its progress." icon={ListChecks} />
Expand Down
63 changes: 63 additions & 0 deletions dashboard/src/components/AgentMonitor/AgentMonitor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { useEffect, useMemo } from "react";
import { useAgentMonitorActivation, useAgentMonitorFeeds, useAgentMonitorSnapshot, type ResolvedOvenIr } from "@hooks";
import { FeedList } from "@oven";
import {
agentMonitorAutoOpenHref,
agentMonitorRepositories,
agentMonitorSelection,
agentMonitorSnapshotNotice,
ovenRepoKey,
} from "@lib";
import type { Project } from "@lib";
import { OvenRuntime } from "@/oven/runtime/OvenRuntime";
import "./agent-monitor.css";

export function AgentMonitor({
ir,
projects,
projectsLoading,
}: {
ir: ResolvedOvenIr;
projects: Project[];
projectsLoading: boolean;
}) {
const selection = agentMonitorSelection();
const repoKey = ovenRepoKey();
const repositories = useMemo(
() => repoKey ? [{ repoKey, label: repoKey }] : agentMonitorRepositories(projects),
[projects, repoKey],
);
const activation = useAgentMonitorActivation(repositories);
const feeds = useAgentMonitorFeeds(repositories, projectsLoading || activation.loading, Boolean(selection));
const snapshot = useAgentMonitorSnapshot(selection);
const notice = activation.error
? { kind: "error", text: activation.error }
: agentMonitorSnapshotNotice(snapshot);
const autoOpenHref = agentMonitorAutoOpenHref(feeds.feeds);

useEffect(() => {
if (autoOpenHref) window.location.replace(autoOpenHref);
}, [autoOpenHref]);

if (!selection) {
return <FeedList
{...feeds}
description="Recent Codex threads for this repository, identified by exact session id."
emptyText="No recent Codex thread feeds."
loadingText="Loading recent Codex threads."
showRepository={!repoKey && repositories.length > 1}
title="Agent Monitor"
/>;
}

const backHref = `/r/${encodeURIComponent(selection.repoKey)}/o/agent-monitor`;
return <section className="agent-monitor-selected">
<header className="agent-monitor-heading">
<a className="agent-monitor-back" href={backHref}>Recent threads</a>
<h1>Agent Monitor</h1>
<p>Thread {selection.session}</p>
</header>
{notice && <p className={`agent-monitor-message${notice.kind === "error" ? " is-error" : ""}`}>{notice.text}</p>}
{snapshot.data && <OvenRuntime ir={ir} payload={snapshot.data} />}
</section>;
}
Loading
Loading