From e9c1714c139ae24128cb3b4b0b2083492817c1da Mon Sep 17 00:00:00 2001 From: saravanakumardb1 Date: Sun, 31 May 2026 06:28:28 -0700 Subject: [PATCH] feat(tracker-web): factory dropdown routes job to the selected factory's product New Job form: pick a Factory (2 hardcoded for this machine) -> the job is submitted to that factory's product (submitJob productId override) and the dashboard view switches to it so the job is visible. Confirmation shows factory + product. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../src/app/dashboard/fleet/jobs/page.tsx | 65 ++++++++++++++----- .../tracker-web/src/lib/fleet-client.ts | 11 +++- 2 files changed, 57 insertions(+), 19 deletions(-) diff --git a/dashboards/tracker-web/src/app/dashboard/fleet/jobs/page.tsx b/dashboards/tracker-web/src/app/dashboard/fleet/jobs/page.tsx index 633423c3..cac0350f 100644 --- a/dashboards/tracker-web/src/app/dashboard/fleet/jobs/page.tsx +++ b/dashboards/tracker-web/src/app/dashboard/fleet/jobs/page.tsx @@ -48,6 +48,13 @@ const FLEET_REPOS = [ ]; const FLEET_BASE_BRANCH = 'main'; +// Factories set up on this machine. Selecting one routes the job to that factory's +// product (the factory polling that product claims it). +const FLEET_FACTORIES = [ + { id: 'mac-1', label: 'mac-1 — LysnrAI (autoship + PR)', productId: 'lysnrai' }, + { id: 'mac-2', label: 'mac-2 — ChronoMind (human gate + PR)', productId: 'chronomind' }, +]; + export default function FleetJobsPage() { const { token } = useAuth(); const [jobs, setJobs] = useState([]); @@ -56,6 +63,7 @@ export default function FleetJobsPage() { // New-job form state const [showForm, setShowForm] = useState(false); + const [factoryId, setFactoryId] = useState(FLEET_FACTORIES[0].id); const [body, setBody] = useState(''); const [priority, setPriority] = useState<'critical' | 'high' | 'medium' | 'low'>('high'); const [caps, setCaps] = useState('build'); @@ -97,24 +105,32 @@ export default function FleetJobsPage() { .split(',') .map(c => c.trim()) .filter(Boolean); - const { job } = await submitJob({ - idempotencyKey: `ui-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`, - bodyMd: body.trim(), - priority, - capabilities, - ...(repo - ? { - repo, - baseBranch: FLEET_BASE_BRANCH, - ...(verifyCmd.trim() ? { verify: verifyCmd.trim() } : {}), - ...(autoMerge ? { autoMerge: true } : {}), - } - : {}), - }); + const factory = FLEET_FACTORIES.find(f => f.id === factoryId) ?? FLEET_FACTORIES[0]; + const { job } = await submitJob( + { + idempotencyKey: `ui-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`, + bodyMd: body.trim(), + priority, + capabilities, + ...(repo + ? { + repo, + baseBranch: FLEET_BASE_BRANCH, + ...(verifyCmd.trim() ? { verify: verifyCmd.trim() } : {}), + ...(autoMerge ? { autoMerge: true } : {}), + } + : {}), + }, + factory.productId + ); + // Route the dashboard view to the factory's product so the job is visible. + if (typeof window !== 'undefined') { + localStorage.setItem('tracker_selected_product', factory.productId); + } setSubmitMsg({ ok: true, text: - `Submitted ${job.id} (stage: ${job.stage})` + + `Submitted ${job.id} to ${factory.id} (${factory.productId}, stage: ${job.stage})` + (repo ? ` — PR mode: ${repo}@${FLEET_BASE_BRANCH}${verifyCmd.trim() ? ' +verify' : ''}${autoMerge ? ' +auto-merge' : ''}` : ' — no PR (plain job)') + @@ -128,7 +144,7 @@ export default function FleetJobsPage() { } finally { setSubmitting(false); } - }, [body, caps, priority, repo, verifyCmd, autoMerge, refresh]); + }, [body, caps, priority, repo, verifyCmd, autoMerge, factoryId, refresh]); return (
@@ -147,6 +163,23 @@ export default function FleetJobsPage() { {showForm && (
+
+ + +