* feat(flow): pipelineLayout supports highlightJobId option
Add an optional `highlightJobId` to PipelineLayoutOptions. When set, the
matching FlowNode is emitted with `highlighted = true`, which the new
FlowPage canvas renders with a thicker accent-coloured border + glow.
Used by JobDetail's embedded Flow tab to draw the operator's eye to the
parent job on first paint. Pure flag — no layout change.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(flow): FloatingLogPane (25vw slide-in) + StatusStrip components
Two new presentational components for the v3 Flow surface:
FloatingLogPane (products/.../components/FloatingLogPane.tsx):
- Slide-in 25vw log viewer that overlays the right edge of the canvas.
- Reuses the canonical <ExecutionLogs /> body — no rebuild.
- Closes on X click, Escape key, or canvas-background click (handled
by the FlowPage parent).
- Renders an empty-state branch when executionId is falsy (pending
jobs without an execution row).
StatusStrip (products/.../components/StatusStrip.tsx):
- Top contextual strip mirroring provision-mockup.html's geometry:
breadcrumb / provisioning pill (animated pulse) / progress bar /
optional Jobs↔Batches mode toggle.
- Mode toggle is URL-driven via a parent-supplied onChange callback.
- All colours bind to existing theme tokens; light/dark theme stays
intact (no new CSS variables).
Per docs/INVIOLABLE-PRINCIPLES.md #4 (never hardcode), every dimension /
status / count is a prop. Per #2 (no compromise), no graph library and
no Mantine — pure CSS-token-bound styles.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(flow): FlowPage canvas at /flow with scope + mode + click semantics
New per-deployment flow canvas served at:
/sovereign/provision/$deploymentId/flow
Routing contract:
- ?scope=all → render every job in the deployment
- ?scope=batch:<id> → filter to a single batch
- ?view=jobs|batches → mode toggle (default = jobs)
Mode contract:
- Jobs mode: every job rendered as a bubble; node border colour by
status. Single-click bubble → opens FloatingLogPane (right 25vw).
Double-click bubble → navigates to /jobs/$jobId. Click empty
canvas → closes the floating pane.
- Batches mode: each batch as a single supernode. Single-click →
highlights it (no log pane — batches have no execution logs).
Double-click → drills into Jobs mode scoped to that batch
(URL becomes ?scope=batch:<id>).
Embedded variant (`embedded` prop) — used by JobDetail's Flow tab:
- Reduces canvas height to ~50vh.
- Hides the StatusStrip (JobDetail's header already shows job-level
breadcrumb + status badge).
- `highlightJobId` prop pre-emphasises the parent job (thicker
accent border + glow rect overlay).
- `deploymentIdOverride` prop bypasses TanStack Router's strict
useParams(from:'/flow'), since JobDetail mounts FlowPage from a
different route.
Single-vs-double-click: SVG `onClick` fires on every click in a double-
click, so we debounce the single-click handler 220ms — if a second click
arrives first, cancel the timer and fire the double-click handler
instead. Matches OS double-click threshold.
Per docs/INVIOLABLE-PRINCIPLES.md #1 (waterfall) — full target shape
in this PR: route, mode toggle, log pane, double-click drill, embedded
variant. Per #2 (no compromise) — pure SVG + computed bezier; reuses
the existing Sugiyama core in pipelineLayout.ts. Per #4 (never
hardcode) — every CSS token comes from --color-*; the 25vw width
binds to the spec verbatim.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(routing): /flow route + JobsPage drops Tab strip + batch chip → /flow
Routing restructure (founder rejected PR #242 Tab-on-JobsPage pattern):
router.tsx:
- Register the new /provision/$deploymentId/flow route with FlowPage.
- Drop the validateSearch{ view: table|flow } wiring on /jobs — the
Tab strip is gone, search params no longer drive view selection.
- Add validateSearch{ scope, view } on /flow so deep links survive
unknown values.
JobsPage.tsx:
- Remove the entire jobs-view-tabs strip (JOBS_VIEW_TABS, setView,
resolveJobsView). The Flow surface now lives at /flow.
- Add a "Show as Flow" button in the page header that navigates to
/flow?scope=all. Founder spec: "[Show as Flow] button in JobsPage
header → /flow?scope=all".
- Drop the JobsFlowView import + the activeView render switch.
JobsPage.test.tsx:
- Replace the BatchDetail-link assertion with a /flow?scope=batch:<id>
assertion (the v3 routing model).
- Add anti-regression guards for the retired Tab strip + new Show-as-
Flow button.
JobsTable.tsx:
- Batch chip in each row now Links to /flow?scope=batch:<batchId>
(was previously a Link to the BatchDetail page). Founder spec:
"JobsTable batch chip click navigates to /flow?scope=batch:<id>".
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(job-detail): consolidate to 2 tabs (Flow + Exec Log)
v3 founder spec: JobDetail tab strip is now exactly two tabs.
- Tab 1 (default): "Flow" — embedded FlowPage canvas scoped to the
parent batch with this job pre-highlighted (thicker accent border
+ glow rect). The canvas IS the dependency view.
- Tab 2: "Exec Log" — existing GitLab-CI-runner-style log viewer.
Retired from v2:
- Dependencies tab — replaced by the Flow tab. The Flow canvas is a
superior dependency surface (pure Sugiyama with cross-batch edges,
scope filter, batch supernodes).
- Apps tab — collapsed into the header chip + each Flow bubble's
appId display.
JobDetail.test.tsx (new file):
- Locks in EXACTLY 2 tabs labeled Flow + Exec Log.
- Flow tab is default-active.
- Asserts Dependencies + Apps tabs are gone (anti-regression for v3).
- Asserts the Flow tab panel mounts the embedded FlowPage canvas
(testid=flow-page-embedded).
- Tab swap fires correctly.
Per docs/INVIOLABLE-PRINCIPLES.md #1 (waterfall) — full target shape
in this PR; the previous 3-tab vocabulary is gone, not feature-flagged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(flow): retire JobsFlowView + JobApps + JobDependencies
These four files are no longer rendered by any caller after the v3
routing model lands:
- JobsFlowView.tsx + JobsFlowView.test.tsx — the in-page Flow tab
was rejected by the founder (PR #242). The /flow route + FlowPage
component supersede it.
- JobDependencies.tsx — JobDetail v3 has no Dependencies tab. The
Flow canvas (scoped to the parent batch with the focal job
highlighted) is the dependency view now.
- JobApps.tsx — JobDetail v3 has no Apps tab. The header chip + each
Flow bubble's appId display cover the same surface.
Note: depsLayout (shared/lib) is KEPT — it's still used by
JobDependenciesGraph (a different widget under widgets/job-deps-graph
that may surface in other future surfaces).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test(cosmetic-guards): replace v2 Flow-tab guards with v3 Flow-route guards
Tests #5-#8 in cosmetic-guards.spec.ts asserted the v2 Tab-on-JobsPage
shape that the founder rejected (jobs-view-tabs / jobs-view-tab-table /
jobs-view-tab-flow / jobs-flow-svg / ?view=flow URL). This commit
replaces them with v3 founder spec assertions:
5. JobsPage has NO tab strip, exposes a "Show as Flow" button →
/flow?scope=all (anti-regression for the retired Tab strip).
6. /flow?scope=all renders the canvas SVG with ≥ 1 batch + bubble.
7. Single-click on a job bubble opens the FloatingLogPane and the
inline width is 25vw verbatim.
8. StatusStrip mode toggle (Jobs ↔ Batches) updates the URL ?view=
parameter, so the choice is bookmarkable.
Plus 2 NEW guards:
- "JobDetail v3 (Flow + Exec Log only)" — locks in EXACTLY 2 tabs
labeled Flow + Exec Log, with Flow aria-selected by default; asserts
Dependencies + Apps tabs are GONE.
- "JobsTable batch chip → /flow link" — the chip is an <a> linking
to /flow?scope=batch:<id> (was previously a no-op chip / BatchDetail
link).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: hatiyildiz <hatice.yildiz@openova.io>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>