v0.0.78 — Branch Focus, scorecard polish, Migration Cockpit
Released: 2026-05-18. Twelve commits.
Three tracks: the Branch Focus drilldown closes the demo loop (priority table → click row → see that branch in detail), the G22 scorecard heatmap gets sort / search / CSV / drilldown drawer, and the Honeyframe Catalog Phase 1 scaffold lands with 5 lineage-source adapters covering a typical enterprise migration stack.
Webapp — Branch Focus page + clickable rows
A new single-entity drilldown page pattern for webapps: pick any branch from a single-select dropdown and a set of cards re-execute against that branch — KPI snapshot vs target, utilization, Δ vs network average, ranking in a composite.
This closes the demo loop: a priority table and scorecard surface problem branches; the drilldown lets the user drill into any one of them for full context.
Architecture changes
AppPageSpec.filters— page-level filter override.Webapp.tsxmerges page filters on top of webapp-level filters so one page can declare single-select branch while the rest keeps multi-select.BranchFilter.spec.emptyValue— publishes that value when no selection is made, instead of always emitting null. Lets cards with:branch_codebinds render before any interaction.- Card SQL uses
COALESCE(:branch_code, '<default>')as defense-in-depth in case a future caller forgetsemptyValue.
Clickable rows — row_action DSL
New card_config DSL — row_action: { type: 'navigate', url_template: '/apps/.../?branch_code={Kode}', target: '_self' | '_blank' }. {ColumnHeader} placeholders interpolate from row data and URL-encode.
TableChartrows become buttons (cursor-pointer, keyboard-accessible via Enter/Space,role=button).ScorecardHeatmapChartdrawer footer shows Open detail → whenrow_actionis set; drawer still opens on row click as before.BranchFilterreads URL query param matchingspec.paramon first mount. Multi-mode supports comma-separated values. The destination page arrives with the right branch preselected.
Priority-table and scorecard cards can be wired with row_action pointing to a /apps/<key>/branch-focus drilldown page.
G22 + Table polish
Scorecard — extracted component + drill-down drawer
The scorecard_heatmap renderer moves into its own component (ScorecardHeatmapChart) so it can own React state for a self-contained drawer. Click any row → slides in from the right with all metrics expanded as vertical cards (label, status badge, value, attainment, threshold band text). Closes on backdrop click or Esc. Works in both the PaaS editor (where onDrillDown is wired) AND the SaaS webapp viewer (where CardRef doesn't pass onDrillDown).
Sort + search
Click any column header (entity or metric) → cycles desc → asc → off. Sort comparator uses the same column the cell color is derived from (basis=attainment → attainment_column, basis_column → that column, else value_column) so sort order matches the visible RAG ranking. Search input filters rows by entity label or subtitle (case-insensitive). Row count badge shows "N total" or "M / N" when filtered. Reset clears both in one click. Empty-state row when filter matches nothing.
CSV export — symmetric across table and scorecard_heatmap
ScorecardHeatmapChart ↓ CSV button exports displayRows (post-search + post-sort) with headers built from entityLabel + subtitle + each metric's columns. The regular table card type gets a small ↓ CSV button floating top-right that exports all rows. Both use Blob + URL.createObjectURL + a hidden anchor — no library dep. RFC-4180 quoting for fields with commas / quotes / newlines.
Table extracted + symmetric interactions
The G22 polish wave (drilldown drawer / sort+search / CSV) is now symmetric with the regular table card type — both are extracted components with the same interaction layer. Card config DSL preserved 1:1 (table_rules, column_thresholds, badge_columns, display_options.{striped,compact,show_row_numbers}).
Executive Overview — YoY summary card
A network-monthly fact table can carry prior-year columns, and a card pivots the latest month into a multi-row comparison (current / prior year / Δ YoY). column_thresholds on the "Δ YoY" column colors green for ≥0, red for <0.
Slotted into an executive layout below the priority table on the right rail, so a viewer sees both "who needs intervention" and "are we trending up YoY" in one view.
Honeyframe Catalog — Phase 1 scaffold
New paas/backend/routers/catalog/ with the Migration Cockpit Phase 1 scaffold. Five endpoints register; five adapters self-register on import. Stubs only — real extraction comes next. Frontend (MigrationCockpitPage) NOT yet built.
Adapters cover a typical enterprise lineage stack: Dataiku, dbt, Kafka, SSIS, Informatica. Adding a new source = drop a new module + register, no changes to router or scoring.
OGG adapter stub
Oracle GoldenGate is a common CDC layer. Without an adapter the unified lineage graph misses the source-DB → trail-file → target-DB replicate edges. .prm parsing approach matches the rest of the file/API ingestion policy (no source DB queries, no prod load). Lineage source count: 5 → 6.
Excel + db_metadata adapters
Two lightweight inventory adapters complete the catalog's coverage of a typical migration stack:
excel— ingests a master spreadsheet (~100 source systems / ~6K datafeeds). Zero query load on any source DB — pure file read. The primary inventory mechanism for a human-curated source inventory workflow.db_metadata— generic multi-dialect adapter (oracle/mssql/mysql/mariadb/postgres/saphana/teradata/bigquery/snowflake/redshift/db2). Metadata-only (INFORMATION_SCHEMA/ALL_TABLES). Refuses prod by default — requires explicitreplica_dsnorallow_prod=Trueopt-in. Single bounded query per refresh, configurable cadence + safety caps.
Catalog adapter count: 6 → 8. Split: inventory (excel, db_metadata) lists "what exists"; lineage (dataiku, dbt, kafka, ogg, ssis, informatica) adds "how things connect". Both produce the same CatalogAsset shape so the cockpit can show them together.
Webapp — Wave 2 fact tables
Extends the v0.0.77 recipe (cards SELECT from per-tenant upload tables instead of inline VALUES) to the remaining demo cards. With every demo card table-backed, swapping to real data is a single xlsx upload + materialize once upstream connectors land — no card SQL changes.
Pilot deploy docs
docs/deploy/ gains a pilot deploy section capturing the operational gotchas learned during the v0.0.70 → v0.0.77 pilot upgrade so the next on-site visit doesn't re-learn them: adm-app SSH + password auth (sshpass -e), scp not rsync (Rocky 9.4 minimal lacks rsync), sudo /usr/local/bin/honeyframe absolute path, tier-not-applicable WARNs are expected, DB name remains dataintel_db (pre-rebrand, intentional).