Repository navigation
feat(W15-A14): Autopilot tab — planner queue, agent activity, freeze/thaw - #210
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (7)
📒 Files selected for processing (7)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (6)
📝 WalkthroughWalkthroughThis PR adds three new Autopilot control panels—PlannerQueue, AgentActivityFeed, and FreezeThawControls—with polling and backend freeze/thaw wiring, integrates them into a responsive two-column Autopilot tab, updates the completion ledger, and adds Playwright scripts for screenshots and freeze/thaw verification. ChangesAutopilot UI Components & Tab Integration
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Code Review
This pull request implements the 'Primary Tabs A' functionality, specifically enhancing the Autopilot tab with new live-data components: AgentActivityFeed, PlannerQueue, and FreezeThawControls. These components are integrated into the UI and wired to backend endpoints for real-time monitoring and control. Feedback suggests improving the portability of the new test scripts by removing hardcoded absolute paths, centralizing duplicated configuration logic for backend URLs, and abstracting direct fetch calls into the existing adapters layer for better architectural consistency.
| // Wave 15 A14 — confirm freeze/thaw element is present in autopilot DOM. | ||
| import { chromium } from "@playwright/test"; | ||
| const BASE = process.env.W15_PREVIEW_URL || "http://127.0.0.1:4173"; | ||
| const browser = await chromium.launch(); | ||
| try { | ||
| const page = await browser.newPage({ viewport: { width: 1536, height: 1024 } }); | ||
| page.on("console", (msg) => { if (msg.type() === "error") console.error(`[err] ${msg.text()}`); }); | ||
| await page.goto(`${BASE}/#autopilot`, { waitUntil: "networkidle", timeout: 30_000 }); | ||
| await page.waitForTimeout(1500); | ||
| const present = { | ||
| planner: await page.locator('[data-testid="autopilot-planner-queue"]').count(), | ||
| agents: await page.locator('[data-testid="autopilot-agent-activity"]').count(), | ||
| freezeThaw: await page.locator('[data-testid="autopilot-freeze-thaw"]').count(), | ||
| freezeBtn: await page.locator('[data-testid="autopilot-freeze-button"]').count(), | ||
| thawBtn: await page.locator('[data-testid="autopilot-thaw-button"]').count(), | ||
| }; | ||
| console.log("DOM presence:", JSON.stringify(present, null, 2)); | ||
| // Scroll the freeze/thaw into view and capture. | ||
| const el = page.locator('[data-testid="autopilot-freeze-thaw"]').first(); | ||
| await el.scrollIntoViewIfNeeded({ timeout: 5000 }).catch(() => {}); | ||
| await page.screenshot({ path: "G:/Github/Hermes3D/03_implementation/proof/screenshots/w15-a14/autopilot-freeze-thaw-detail.png", clip: await el.boundingBox().then((b) => ({ x: Math.max(b.x - 12, 0), y: Math.max(b.y - 12, 0), width: Math.min(b.width + 24, 1536), height: Math.min(b.height + 24, 1024) })) }).catch(async (e) => { | ||
| console.error("bbox screenshot failed:", e.message); | ||
| await page.screenshot({ path: "G:/Github/Hermes3D/03_implementation/proof/screenshots/w15-a14/autopilot-after-scroll.png" }); | ||
| }); | ||
| } finally { | ||
| await browser.close(); | ||
| } |
There was a problem hiding this comment.
The script uses hardcoded absolute Windows paths for saving screenshots (e.g., G:/Github/Hermes3D/...), which will cause it to fail on other systems or in CI. It also lacks necessary imports for path manipulation. I've updated the script to use relative paths and proper path utilities, consistent with w15-a14-capture.mjs.
// Wave 15 A14 — confirm freeze/thaw element is present in autopilot DOM.
import { chromium } from "@playwright/test";
import path from "node:path";
import url from "node:url";
const HERE = path.dirname(url.fileURLToPath(import.meta.url));
const REPO_ROOT = path.resolve(HERE, "../../../../");
const OUT_DIR = path.join(REPO_ROOT, "03_implementation/proof/screenshots/w15-a14");
const BASE = process.env.W15_PREVIEW_URL || "http://127.0.0.1:4173";
const browser = await chromium.launch();
try {
const page = await browser.newPage({ viewport: { width: 1536, height: 1024 } });
page.on("console", (msg) => { if (msg.type() === "error") console.error(`[err] ${msg.text()}`); });
await page.goto(`${BASE}/#autopilot`, { waitUntil: "networkidle", timeout: 30_000 });
await page.waitForTimeout(1500);
const present = {
planner: await page.locator('[data-testid="autopilot-planner-queue"]').count(),
agents: await page.locator('[data-testid="autopilot-agent-activity"]').count(),
freezeThaw: await page.locator('[data-testid="autopilot-freeze-thaw"]').count(),
freezeBtn: await page.locator('[data-testid="autopilot-freeze-button"]').count(),
thawBtn: await page.locator('[data-testid="autopilot-thaw-button"]').count(),
};
console.log("DOM presence:", JSON.stringify(present, null, 2));
// Scroll the freeze/thaw into view and capture.
const el = page.locator('[data-testid="autopilot-freeze-thaw"]').first();
await el.scrollIntoViewIfNeeded({ timeout: 5000 }).catch(() => {});
const outPath = path.join(OUT_DIR, "autopilot-freeze-thaw-detail.png");
await page.screenshot({ path: outPath, clip: await el.boundingBox().then((b) => ({ x: Math.max(b.x - 12, 0), y: Math.max(b.y - 12, 0), width: Math.min(b.width + 24, 1536), height: Math.min(b.height + 24, 1024) })) }).catch(async (e) => {
console.error("bbox screenshot failed:", e.message);
const fallbackPath = path.join(OUT_DIR, "autopilot-after-scroll.png");
await page.screenshot({ path: fallbackPath });
});
} finally {
await browser.close();
}| type HermesImportMeta = ImportMeta & { | ||
| env: { | ||
| VITE_HERMES3D_BRIDGE_PORT?: string; | ||
| }; | ||
| }; | ||
|
|
||
| const DEFAULT_BRIDGE_PORT = "8765"; | ||
| const LIVE_BRIDGE_PORT = (import.meta as HermesImportMeta).env.VITE_HERMES3D_BRIDGE_PORT ?? DEFAULT_BRIDGE_PORT; | ||
| const LIVE_BASE_URL = `http://127.0.0.1:${LIVE_BRIDGE_PORT}`; |
There was a problem hiding this comment.
The HermesImportMeta type definition and the LIVE_BASE_URL construction logic are duplicated from Autopilot.tsx. This duplication makes the configuration fragile and harder to maintain. Consider centralizing this logic in a shared constants file or within the adapters layer to ensure consistency across the application.
| const response = await fetch(`${LIVE_BASE_URL}/api/autopilot/${path}`, { | ||
| method: "POST", | ||
| headers: { Accept: "application/json", "Content-Type": "application/json" }, | ||
| body: JSON.stringify({ source: "autopilot.freeze_thaw_controls" }), | ||
| cache: "no-store", | ||
| }); |
There was a problem hiding this comment.
This component uses fetch directly to interact with the backend API. Following the project's established pattern, these network calls should be abstracted into the adapters layer. This improves maintainability, allows for easier mocking in tests, and centralizes error handling and base URL management.
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@03_implementation/docs/handoffs/GUI_VISUAL_E2E_COMPLETION_LEDGER_2026-05-10.md`:
- Line 37: Update the screenshot count in the "Primary Tabs A
(Autopilot/Design/Gen3D/Jobs)" entry in
GUI_VISUAL_E2E_COMPLETION_LEDGER_2026-05-10.md: change the phrase "4 screenshots
in `proof/screenshots/w15-a14/`" to "6 screenshots in
`proof/screenshots/w15-a14/`" so it matches the six files listed later; ensure
the updated sentence remains in the same entry that starts with "Primary Tabs A
(Autopilot/Design/Gen3D/Jobs)".
In `@03_implementation/ui/src/components/autopilot/PlannerQueue.tsx`:
- Around line 100-101: The UI assumes workflow.stages is non-empty and
workflow.active_stage is in-range, causing outputs like "1/0" when stages is []
or active_stage is invalid; in PlannerQueue (the JSX that renders "stage
{workflow.active_stage + 1}/{workflow.stages.length}"), guard rendering by
checking workflow.stages && workflow.stages.length > 0 and that
workflow.active_stage is a number within [0, workflow.stages.length - 1];
compute a safe displayActive and totalStages (or render a fallback like "—" or
"0/0") before interpolation and use those safe values in place of the current
expression so out-of-range or empty stage arrays don't produce invalid UI.
In `@03_implementation/ui/tests/screenshots/w15-a14-verify-freeze-thaw.mjs`:
- Around line 10-17: The current DOM presence check only logs counts (present
object) and can silently pass; replace these logs with hard assertions that fail
the test when required elements are missing by asserting the locator counts for
freezeThaw, freezeBtn, thawBtn (and optionally planner and agents) are > 0; use
Playwright's expect/assert (e.g., expect(await
page.locator(...).count()).toBeGreaterThan(0)) or your test framework's
equivalent and import expect if not already present so the test fails when
selectors are absent.
- Around line 21-23: The screenshots use hardcoded absolute Windows paths in the
page.screenshot calls (see page.screenshot and the fallback screenshot) which
will fail on other machines; update both calls to build repo-relative output
paths instead (use process.cwd() or __dirname with path.join/path.resolve) and
ensure the target directory is created before calling page.screenshot; modify
the path arguments in the page.screenshot invocations and any related error
handler so they reference the repo-relative
"03_implementation/proof/screenshots/w15-a14" location rather than "G:/...".
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: ff790e0f-9ec5-4499-8799-7df26b664f66
⛔ Files ignored due to path filters (7)
03_implementation/proof/screenshots/w15-a14/autopilot-1536x1400.pngis excluded by!**/*.png03_implementation/proof/screenshots/w15-a14/autopilot-freeze-thaw-detail.pngis excluded by!**/*.png03_implementation/proof/screenshots/w15-a14/autopilot-fullpage.pngis excluded by!**/*.png03_implementation/proof/screenshots/w15-a14/autopilot.pngis excluded by!**/*.png03_implementation/proof/screenshots/w15-a14/design.pngis excluded by!**/*.png03_implementation/proof/screenshots/w15-a14/gen3d.pngis excluded by!**/*.png03_implementation/proof/screenshots/w15-a14/jobs.pngis excluded by!**/*.png
📒 Files selected for processing (7)
03_implementation/docs/handoffs/GUI_VISUAL_E2E_COMPLETION_LEDGER_2026-05-10.md03_implementation/ui/src/components/autopilot/AgentActivityFeed.tsx03_implementation/ui/src/components/autopilot/FreezeThawControls.tsx03_implementation/ui/src/components/autopilot/PlannerQueue.tsx03_implementation/ui/src/tabs/Autopilot.tsx03_implementation/ui/tests/screenshots/w15-a14-capture.mjs03_implementation/ui/tests/screenshots/w15-a14-verify-freeze-thaw.mjs
| | 12 | Dashboard Modes | _pending_ | | ||
| | 13 | Source OS + 60 Apps | _pending_ | | ||
| | 14 | Primary Tabs A (Autopilot/Design/Gen3D/Jobs) | _pending_ | | ||
| | 14 | Primary Tabs A (Autopilot/Design/Gen3D/Jobs) | claude/w15-a14-tabs-a — Autopilot: +PlannerQueue/+AgentActivityFeed/+FreezeThawControls components wired to live `/api/workflows/active`, `/api/agents`, freeze/thaw endpoints (blocked-honest when not implemented). Design/Gen3D/Jobs already FULLY_WIRED per W15-A3 audit; verified no fake fallback + tsc/build PASS. 4 screenshots in `proof/screenshots/w15-a14/`. | |
There was a problem hiding this comment.
Update screenshot count to match recorded artifacts.
Line 37 says “4 screenshots,” but Line 60 lists 6 files. Keeping this consistent avoids confusion in proof tracking.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@03_implementation/docs/handoffs/GUI_VISUAL_E2E_COMPLETION_LEDGER_2026-05-10.md`
at line 37, Update the screenshot count in the "Primary Tabs A
(Autopilot/Design/Gen3D/Jobs)" entry in
GUI_VISUAL_E2E_COMPLETION_LEDGER_2026-05-10.md: change the phrase "4 screenshots
in `proof/screenshots/w15-a14/`" to "6 screenshots in
`proof/screenshots/w15-a14/`" so it matches the six files listed later; ensure
the updated sentence remains in the same entry that starts with "Primary Tabs A
(Autopilot/Design/Gen3D/Jobs)".
| stage {workflow.active_stage + 1}/{workflow.stages.length} · started{" "} | ||
| {workflow.started_utc ? new Date(workflow.started_utc).toLocaleTimeString() : "—"} |
There was a problem hiding this comment.
Guard stage progress rendering against empty/out-of-range stage data.
Line 100 assumes workflow.stages.length > 0 and a valid active_stage. If the backend returns stages: [] or an out-of-bounds index, the UI can show invalid progress like 1/0.
Proposed fix
- stage {workflow.active_stage + 1}/{workflow.stages.length} · started{" "}
+ {(() => {
+ const total = workflow.stages.length;
+ const current =
+ total > 0
+ ? Math.min(Math.max(workflow.active_stage, 0), total - 1) + 1
+ : 0;
+ return `stage ${current}/${total}`;
+ })()} · started{" "}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| stage {workflow.active_stage + 1}/{workflow.stages.length} · started{" "} | |
| {workflow.started_utc ? new Date(workflow.started_utc).toLocaleTimeString() : "—"} | |
| {(() => { | |
| const total = workflow.stages.length; | |
| const current = | |
| total > 0 | |
| ? Math.min(Math.max(workflow.active_stage, 0), total - 1) + 1 | |
| : 0; | |
| return `stage ${current}/${total}`; | |
| })()} · started{" "} | |
| {workflow.started_utc ? new Date(workflow.started_utc).toLocaleTimeString() : "—"} |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@03_implementation/ui/src/components/autopilot/PlannerQueue.tsx` around lines
100 - 101, The UI assumes workflow.stages is non-empty and workflow.active_stage
is in-range, causing outputs like "1/0" when stages is [] or active_stage is
invalid; in PlannerQueue (the JSX that renders "stage {workflow.active_stage +
1}/{workflow.stages.length}"), guard rendering by checking workflow.stages &&
workflow.stages.length > 0 and that workflow.active_stage is a number within [0,
workflow.stages.length - 1]; compute a safe displayActive and totalStages (or
render a fallback like "—" or "0/0") before interpolation and use those safe
values in place of the current expression so out-of-range or empty stage arrays
don't produce invalid UI.
| const present = { | ||
| planner: await page.locator('[data-testid="autopilot-planner-queue"]').count(), | ||
| agents: await page.locator('[data-testid="autopilot-agent-activity"]').count(), | ||
| freezeThaw: await page.locator('[data-testid="autopilot-freeze-thaw"]').count(), | ||
| freezeBtn: await page.locator('[data-testid="autopilot-freeze-button"]').count(), | ||
| thawBtn: await page.locator('[data-testid="autopilot-thaw-button"]').count(), | ||
| }; | ||
| console.log("DOM presence:", JSON.stringify(present, null, 2)); |
There was a problem hiding this comment.
Turn presence logging into hard assertions.
Right now the script only logs counts and can exit successfully even if freeze/thaw UI is missing. A verification script should fail when required selectors are absent.
Proposed fix
const present = {
planner: await page.locator('[data-testid="autopilot-planner-queue"]').count(),
agents: await page.locator('[data-testid="autopilot-agent-activity"]').count(),
freezeThaw: await page.locator('[data-testid="autopilot-freeze-thaw"]').count(),
freezeBtn: await page.locator('[data-testid="autopilot-freeze-button"]').count(),
thawBtn: await page.locator('[data-testid="autopilot-thaw-button"]').count(),
};
console.log("DOM presence:", JSON.stringify(present, null, 2));
+ for (const [key, count] of Object.entries(present)) {
+ if (count < 1) {
+ throw new Error(`Missing required element: ${key}`);
+ }
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const present = { | |
| planner: await page.locator('[data-testid="autopilot-planner-queue"]').count(), | |
| agents: await page.locator('[data-testid="autopilot-agent-activity"]').count(), | |
| freezeThaw: await page.locator('[data-testid="autopilot-freeze-thaw"]').count(), | |
| freezeBtn: await page.locator('[data-testid="autopilot-freeze-button"]').count(), | |
| thawBtn: await page.locator('[data-testid="autopilot-thaw-button"]').count(), | |
| }; | |
| console.log("DOM presence:", JSON.stringify(present, null, 2)); | |
| const present = { | |
| planner: await page.locator('[data-testid="autopilot-planner-queue"]').count(), | |
| agents: await page.locator('[data-testid="autopilot-agent-activity"]').count(), | |
| freezeThaw: await page.locator('[data-testid="autopilot-freeze-thaw"]').count(), | |
| freezeBtn: await page.locator('[data-testid="autopilot-freeze-button"]').count(), | |
| thawBtn: await page.locator('[data-testid="autopilot-thaw-button"]').count(), | |
| }; | |
| console.log("DOM presence:", JSON.stringify(present, null, 2)); | |
| for (const [key, count] of Object.entries(present)) { | |
| if (count < 1) { | |
| throw new Error(`Missing required element: ${key}`); | |
| } | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@03_implementation/ui/tests/screenshots/w15-a14-verify-freeze-thaw.mjs` around
lines 10 - 17, The current DOM presence check only logs counts (present object)
and can silently pass; replace these logs with hard assertions that fail the
test when required elements are missing by asserting the locator counts for
freezeThaw, freezeBtn, thawBtn (and optionally planner and agents) are > 0; use
Playwright's expect/assert (e.g., expect(await
page.locator(...).count()).toBeGreaterThan(0)) or your test framework's
equivalent and import expect if not already present so the test fails when
selectors are absent.
| await page.screenshot({ path: "G:/Github/Hermes3D/03_implementation/proof/screenshots/w15-a14/autopilot-freeze-thaw-detail.png", clip: await el.boundingBox().then((b) => ({ x: Math.max(b.x - 12, 0), y: Math.max(b.y - 12, 0), width: Math.min(b.width + 24, 1536), height: Math.min(b.height + 24, 1024) })) }).catch(async (e) => { | ||
| console.error("bbox screenshot failed:", e.message); | ||
| await page.screenshot({ path: "G:/Github/Hermes3D/03_implementation/proof/screenshots/w15-a14/autopilot-after-scroll.png" }); |
There was a problem hiding this comment.
Replace hardcoded Windows screenshot paths with repo-relative output paths.
Lines 21–23 use machine-specific absolute paths (G:/...), which breaks on other environments and contributors’ machines.
Proposed fix
+import fs from "node:fs";
+import path from "node:path";
+import url from "node:url";
+
+const HERE = path.dirname(url.fileURLToPath(import.meta.url));
+const REPO_ROOT = path.resolve(HERE, "../../../..");
+const OUT_DIR = path.join(REPO_ROOT, "03_implementation/proof/screenshots/w15-a14");
+fs.mkdirSync(OUT_DIR, { recursive: true });
...
- await page.screenshot({ path: "G:/Github/Hermes3D/03_implementation/proof/screenshots/w15-a14/autopilot-freeze-thaw-detail.png", clip: await el.boundingBox().then((b) => ({ x: Math.max(b.x - 12, 0), y: Math.max(b.y - 12, 0), width: Math.min(b.width + 24, 1536), height: Math.min(b.height + 24, 1024) })) }).catch(async (e) => {
+ await page.screenshot({ path: path.join(OUT_DIR, "autopilot-freeze-thaw-detail.png"), clip: await el.boundingBox().then((b) => ({ x: Math.max(b.x - 12, 0), y: Math.max(b.y - 12, 0), width: Math.min(b.width + 24, 1536), height: Math.min(b.height + 24, 1024) })) }).catch(async (e) => {
console.error("bbox screenshot failed:", e.message);
- await page.screenshot({ path: "G:/Github/Hermes3D/03_implementation/proof/screenshots/w15-a14/autopilot-after-scroll.png" });
+ await page.screenshot({ path: path.join(OUT_DIR, "autopilot-after-scroll.png") });
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| await page.screenshot({ path: "G:/Github/Hermes3D/03_implementation/proof/screenshots/w15-a14/autopilot-freeze-thaw-detail.png", clip: await el.boundingBox().then((b) => ({ x: Math.max(b.x - 12, 0), y: Math.max(b.y - 12, 0), width: Math.min(b.width + 24, 1536), height: Math.min(b.height + 24, 1024) })) }).catch(async (e) => { | |
| console.error("bbox screenshot failed:", e.message); | |
| await page.screenshot({ path: "G:/Github/Hermes3D/03_implementation/proof/screenshots/w15-a14/autopilot-after-scroll.png" }); | |
| import fs from "node:fs"; | |
| import path from "node:path"; | |
| import url from "node:url"; | |
| const HERE = path.dirname(url.fileURLToPath(import.meta.url)); | |
| const REPO_ROOT = path.resolve(HERE, "../../../.."); | |
| const OUT_DIR = path.join(REPO_ROOT, "03_implementation/proof/screenshots/w15-a14"); | |
| fs.mkdirSync(OUT_DIR, { recursive: true }); | |
| await page.screenshot({ path: path.join(OUT_DIR, "autopilot-freeze-thaw-detail.png"), clip: await el.boundingBox().then((b) => ({ x: Math.max(b.x - 12, 0), y: Math.max(b.y - 12, 0), width: Math.min(b.width + 24, 1536), height: Math.min(b.height + 24, 1024) })) }).catch(async (e) => { | |
| console.error("bbox screenshot failed:", e.message); | |
| await page.screenshot({ path: path.join(OUT_DIR, "autopilot-after-scroll.png") }); | |
| }); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@03_implementation/ui/tests/screenshots/w15-a14-verify-freeze-thaw.mjs` around
lines 21 - 23, The screenshots use hardcoded absolute Windows paths in the
page.screenshot calls (see page.screenshot and the fallback screenshot) which
will fail on other machines; update both calls to build repo-relative output
paths instead (use process.cwd() or __dirname with path.join/path.resolve) and
ensure the target directory is created before calling page.screenshot; modify
the path arguments in the page.screenshot invocations and any related error
handler so they reference the repo-relative
"03_implementation/proof/screenshots/w15-a14" location rather than "G:/...".
2daf04b to
7271056
Compare
…/thaw Wave 15 — Agent 14 (Primary Tabs A). Adds three new components for the Autopilot tab matching the Images-GUI reference for `02-primary-pages/primary-tabs-autopilot-design-gen3d-jobs.png`: - `components/autopilot/PlannerQueue.tsx` — read-only feed of active workflows from `adapters.getActiveWorkflows()` (live `/api/workflows/active`). Empty/error states are explicit, no fake fallback data; auto-refresh every 15s. - `components/autopilot/AgentActivityFeed.tsx` — live agent roster from `adapters.getAgents()` (live `/api/agents`); sorts active first, shows task count + model provider + last activity. 20s refresh. - `components/autopilot/FreezeThawControls.tsx` — POSTs to `/api/autopilot/freeze` and `/api/autopilot/thaw`. The current backend has not implemented these endpoints (verified against `src/hermes3d/api/routes/autopilot.py` 2026-05-10); a 404/405 surfaces an explicit "Blocked: /api/autopilot/<path> is not implemented on this backend (W15 A20 owns the endpoint)." No fake "frozen" state ever; W15 A20 owns the backend route work. Autopilot tab layout switches from a single column of three sections to a 12-column grid: left col (lg:col-span-7) keeps READINESS / SAFE ACTIONS / GUARDRAILS; new right col (lg:col-span-5) stacks PLANNER QUEUE / AGENT ACTIVITY / FREEZE-THAW. Design / Gen3D / Jobs tabs already FULLY_WIRED per W15_A3 audit — unchanged here, verified by re-running tsc + build + capturing 4 screenshots at 1536x1024 (`proof/screenshots/w15-a14/`). Self-audit - `npx tsc --noEmit` PASS - `npm run build` PASS (vite 1.14s) - 4 PNG screenshots captured per tab (autopilot, design, gen3d, jobs) plus autopilot-1536x1400 and autopilot-freeze-thaw-detail for the full Autopilot view including freeze/thaw card. - Honest "blocked" / "loading" / "unreachable" empty states for every data path; no MOCK_PRINTERS/MOCK_JOBS imports introduced. Sources cited - Official React composition: small read-only components with their own `useEffect` polling, similar to the existing AutopilotConsole + AutopilotTab pattern in this repo. - Cross-project: GitHub Actions runs UI — table-with-status-pill pattern used in `AgentActivityFeed` (one row per agent, status dot, sortable by status). Refs: W15 24-agent loop, A14 Primary Tabs A; Images-GUI ref `02-primary-pages/primary-tabs-autopilot-design-gen3d-jobs.png`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
7271056 to
adc2ec0
Compare
Wave 15 — Agent 14 · Primary Tabs A
Brings the Autopilot tab in line with the Wave 15 brief
(
planner queue + agent activity feed + freeze/thaw controls) whileleaving the already-FULLY_WIRED Design / Gen3D / Jobs tabs untouched.
What changed
components/autopilot/PlannerQueue.tsx— readsgetActiveWorkflows()(live/api/workflows/active).components/autopilot/AgentActivityFeed.tsx— readsgetAgents()(live/api/agents).components/autopilot/FreezeThawControls.tsx— POSTs to/api/autopilot/freeze&/thaw; renders explicit "Blocked: endpoint not implemented" when 404/405 (W15 A20 owns the backend route).tabs/Autopilot.tsx— wraps existing READINESS/SAFE ACTIONS/GUARDRAILS in a 7-col left pane; new components go into a 5-col right pane.Disjoint scope respected
Only Autopilot.tsx + new autopilot/* components touched. Design / Gen3D / Jobs unchanged.
No-fake policy
mode=unknown; only flips tofrozen/thawedafter a real HTTP 2xx; surfaces 404/405 as explicit "Blocked: /api/autopilot/ is not implemented on this backend (W15 A20 owns the endpoint)."4 tabs status
#autopilot/api/autopilot/*/api/workflows/active/api/agentslive; freeze/thaw 404-blocked-honest#design/api/design/*live#gen3d/api/gen3d/*+/api/generation/runlive#jobs/api/jobs/*(9 paths) liveSelf-audit (all PASS)
npx tsc --noEmit— EXIT 0npm run build—built in 1.14s, all chunks emitted127.0.0.1:8765ConnectionRefused since no backend is running locally — the UI surfaces these as honest empty/blocked states)03_implementation/proof/screenshots/w15-a14/:autopilot.png,design.png,gen3d.png,jobs.png(1536×1024)autopilot-1536x1400.pngshowing all 6 sections in one frameautopilot-freeze-thaw-detail.pngshowing the new freeze/thaw cardSources cited
useEffectpolling (matches existingAutopilotConsole+Autopilot.tsxpatterns in this repo).AgentActivityFeed(status dot + role + meta + last-activity time, sorted active → idle → error).Hermes lock
claude-w15-a14-tabs-a03_implementation/ui/src/tabs/{Autopilot,Design,Gen3D,Jobs}.tsxW15-A14-TABS-A-2026-05-10Ledger
03_implementation/docs/handoffs/GUI_VISUAL_E2E_COMPLETION_LEDGER_2026-05-10.mdupdated under the Wave 15 Phase 3 — Agent 14 row.Test plan
npm run buildlocally#autopilotagainst a live backend; planner queue + agent activity show real rows; freeze/thaw shows "Blocked: not implemented" until W15 A20 lands the endpoint🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Tests
Documentation