Skip to content

Migrate repertoire-diversity onto structurer + BlockModelV3#49

Merged
mzueva merged 6 commits into
mainfrom
chore/repertoire-diversity-structurer-v3
Jul 20, 2026
Merged

Migrate repertoire-diversity onto structurer + BlockModelV3#49
mzueva merged 6 commits into
mainfrom
chore/repertoire-diversity-structurer-v3

Conversation

@vadimpiven

@vadimpiven vadimpiven commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Migrates repertoire-diversity onto the block-tools structurer and from V1 to BlockModelV3.

Commits

  1. chore: structurer refresh + SDK upgrade — tool-managed layout (oxlint/oxfmt, ts-builder, regenerated configs across model, ui, workflow, block, software). Full SDK upgrade: model/ui-vue 1.64.0→1.79.14, tengo-builder 2.5.29→4.0.8 (2→4), workflow-tengo→6.6.3, block-tools→2.11.0. Removes orphaned test scaffolding (the structurer drops vitest from model/ui devDeps — canonical structured blocks centralize tests in a test/ package — leaving dangling test: "vitest" scripts + vitest.config.mts files with zero test files behind them).
  2. feat: BlockModelV3 model — see below.
  3. chore: changeset.

V3 model design

V1 field V3 channel Why
abundanceRef args (required) input selection; stales; throws when absent
metrics args via convertMetricsUiToArgs(data.metrics) the workflow's Metric[] is projected from the editable MetricUI[]
metrics (MetricUI[]), tableState, graphState data editable list + view state; not projected
defaultBlockLabel, customBlockLabel data block labels; never read by the workflow
  • data holds the editable MetricUI[] (with id/isExpanded); the args lambda strips it to Metric[]. The debounced ui.metrics → args.metrics sync watcher is deleted — the projection lambda replaces it. Editing view state / labels no longer stales the block; only the abundance input and metric set do.
  • .upgradeLegacy folds V1 args + uiState into unified data, preserving persisted projects.
  • The block-label watchEffect (tolerated SDK exception) stays, repointed to data.

Fixes surfaced by the SDK upgrade

  • Guarded SettingsModal's isEmpty against the now-optional visibleTableHandle (PTableHandle | undefined since model 1.79).

Deliberately not adopted

The structurer rewrote the CI workflows with unrelated changes — app-name 'Repertoire Diversity''Repertoire Diversity 2', test:falsetrue (no tests), a turborepo S3-bucket secret rename, Slack reordering. Both .github/workflows/*.yaml are left identical to main.

Verification

pnpm build:dev + check (tsc + oxlint + oxfmt) + pnpm test all green (turbo 8/8). Changeset validated.

Not done: runtime legacy-upgrade check against a saved V1 project (needs a backend) — recommended before merge.

Greptile Summary

This PR migrates repertoire-diversity from BlockModel V1 to BlockModelV3, replacing the separate args/uiState channels with a unified data model, and upgrades the full SDK stack (model/ui-vue 1.64.0→1.79.14, tengo-builder 2.5.29→4.0.8, workflow-tengo 5.23.0→6.6.3, block-tools 2.7.25→2.11.0). A .upgradeLegacy path folds the V1 on-disk args+uiState into the new data shape to preserve persisted projects.

  • BlockModelV3 + DataModelBuilder: BlockArgs is now projected from BlockData via an args lambda (convertMetricsUiToArgs), removing the debounced ui.metrics → args.metrics watcher; editing labels or view state no longer stales the block, only abundanceRef and metrics do.
  • SettingsModal guard: visibleTableHandle is now checked for undefined before being passed to pFrameDriver.getShape, fixing a crash on the SDK-1.79 API change where the handle became optional.
  • CI/Turbo rework: lint/type-check tasks replaced by fmt/check; pl-tengo check split into its own check script; the CI workflow files are intentionally left unchanged from main.

Confidence Score: 4/5

Safe to merge with awareness that the runtime legacy-upgrade path has not been validated against a real saved V1 project.

The structural migration is clean and the build/check/test pipeline is reportedly green. The main open item called out by the author themselves — a runtime check against a persisted V1 project — is still pending. The upgradeLegacy silently discards args.metrics when uiState is absent, which could reset a user's metric configuration on first open. The pre-existing getIndex(-1) crash in the graph view is also left unguarded. Neither is a showstopper for most scenarios, but the legacy-upgrade gap is worth confirming before shipping to users with saved V1 projects.

model/src/dataModel.ts (upgradeLegacy path) and ui/src/pages/DiversityGraph.vue (unchecked array access) deserve a second look before shipping to users with existing V1 projects.

Important Files Changed

Filename Overview
model/src/index.ts Core model rewritten with BlockModelV3; args lambda replaces argsValid+debounced watcher; ctx.uiState references updated to ctx.data
model/src/dataModel.ts New file: DataModelBuilder wires up BlockData v1 schema, upgradeLegacy mapping, and init defaults
model/src/types.ts New file: defines BlockData (unified data), BlockArgs (workflow-facing), and legacy V1 shapes; well-documented
model/src/converters.ts Unchanged logic; imports Metric/MetricUI from ./index instead of the more direct ./types, creating a circular import chain
ui/src/app.ts Migrated to defineAppV3; debounced metrics sync watcher removed; syncDefaultBlockLabel now writes to data instead of args
ui/src/pages/SettingsModal.vue isEmpty now guards against undefined visibleTableHandle (required by model 1.79 SDK upgrade)
ui/src/pages/DiversityGraph.vue Binding migrated from ui.graphState to data.graphState; pre-existing unchecked getIndex(-1) crash retained
ui/src/pages/MainPage.vue tableState binding migrated from uiState to data; no functional changes

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    subgraph data["BlockData (persisted)"]
        AR[abundanceRef]
        ME["metrics: MetricUI[]"]
        DBL[defaultBlockLabel]
        CBL[customBlockLabel]
        TS[tableState]
        GS[graphState]
    end

    subgraph argsLambda["args lambda (BlockModelV3)"]
        CHECK{abundanceRef\ndefined?}
        CONV[convertMetricsUiToArgs]
        THROW[throw Error]
    end

    subgraph args["BlockArgs → Workflow"]
        WF_AR["abundanceRef: PlRef"]
        WF_ME["metrics: Metric[]"]
    end

    subgraph outputs["Model Outputs"]
        OPT[abundanceOptions]
        PT["pt: PTable"]
        PF["pf: PFrame"]
    end

    subgraph uiwatcher["UI watchEffect"]
        WE[syncDefaultBlockLabel]
    end

    AR --> CHECK
    ME --> CONV
    CHECK -- undefined --> THROW
    CHECK -- present --> WF_AR
    CONV --> WF_ME

    OPT --> WE
    WE -->|writes| DBL

    TS -->|v-model| PT
    GS -->|v-model| PF

    style THROW fill:#f88,color:#000
    style data fill:#e8f4fd,color:#000
    style args fill:#d4edda,color:#000
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    subgraph data["BlockData (persisted)"]
        AR[abundanceRef]
        ME["metrics: MetricUI[]"]
        DBL[defaultBlockLabel]
        CBL[customBlockLabel]
        TS[tableState]
        GS[graphState]
    end

    subgraph argsLambda["args lambda (BlockModelV3)"]
        CHECK{abundanceRef\ndefined?}
        CONV[convertMetricsUiToArgs]
        THROW[throw Error]
    end

    subgraph args["BlockArgs → Workflow"]
        WF_AR["abundanceRef: PlRef"]
        WF_ME["metrics: Metric[]"]
    end

    subgraph outputs["Model Outputs"]
        OPT[abundanceOptions]
        PT["pt: PTable"]
        PF["pf: PFrame"]
    end

    subgraph uiwatcher["UI watchEffect"]
        WE[syncDefaultBlockLabel]
    end

    AR --> CHECK
    ME --> CONV
    CHECK -- undefined --> THROW
    CHECK -- present --> WF_AR
    CONV --> WF_ME

    OPT --> WE
    WE -->|writes| DBL

    TS -->|v-model| PT
    GS -->|v-model| PF

    style THROW fill:#f88,color:#000
    style data fill:#e8f4fd,color:#000
    style args fill:#d4edda,color:#000
Loading

Fix All in Claude Code

Prompt To Fix All With AI
Fix the following 3 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 3
model/src/converters.ts:1
Circular import: `converters.ts` imports from `./index`, while `index.ts` re-exports from `./converters`. `Metric` and `MetricUI` are now defined in `./types`, so importing directly there removes the cycle and avoids the risk of bundler ordering surprises.

```suggestion
import type { Metric, MetricUI } from "./types";
```

### Issue 2 of 3
model/src/dataModel.ts:49-56
**Legacy metric config silently dropped when uiState is absent**

`upgradeLegacy` recovers metrics exclusively from `uiState?.metrics` and falls back to `defaultMetrics()` if `uiState` is absent. V1 `args.metrics: Metric[]` (the workflow-projected list) is never consulted. If a V1 project was saved before `uiState` existed — or if the `uiState` record is missing for any reason — the user's configured metric set is silently replaced with the five hardcoded defaults. While the PR notes that a runtime legacy-upgrade check is still pending, this edge case is worth either documenting explicitly or adding a best-effort conversion (e.g. assign generated IDs to `args.metrics` entries and fall back to that when `uiState` is absent).

### Issue 3 of 3
ui/src/pages/DiversityGraph.vue:22-29
**Potential crash when `pl7.app/diversity` column is absent**

`getIndex("pl7.app/diversity", pcols)` returns `-1` when no matching column exists. `pcols[-1]` evaluates to `undefined` in JavaScript (not the last element), so `.spec.axesSpec[0]` immediately throws a `TypeError`. This guard was absent before this PR and is unchanged here, but the reformatting makes the unsafe array access more visible. Adding an early-return when `getIndex` returns `-1` would prevent a visible crash in the graph view if `pcols` is populated by columns that don't include a diversity column.

Reviews (1): Last reviewed commit: "chore: add changeset for structurer + V3..." | Re-trigger Greptile

Greptile also left 3 inline comments on this PR.

Context used:

  • Context used - Terms is a types in codebase. Provide the list of ... (source)

… upgrade

Adopt the tool-managed block layout (oxlint/oxfmt, ts-builder, regenerated
tsconfig/turbo/index/package.json across model, ui, workflow, block, software)
and the forced full SDK upgrade: model/ui-vue 1.64.0 -> 1.79.14, tengo-builder
2.5.29 -> 4.0.8 (2->4), workflow-tengo -> 6.6.3, block-tools -> 2.11.0.

Remove orphaned test scaffolding: the structurer drops vitest from model/ui
devDeps (canonical structured blocks centralize tests in a test/ package),
leaving the model/ui 'test': 'vitest' scripts and vitest.config.mts files
dangling — the block has zero test files. Drop the dead scripts and configs.

CI workflows left unchanged from main (structurer drift — app-name
'Repertoire Diversity' -> 'Repertoire Diversity 2', test:false->true, a
turborepo S3 bucket secret rename, Slack reordering — is unrelated).
Replace the V1 model (BlockModel + withArgs/withUiState/argsValid) with
BlockModelV3 + a DataModelBuilder:

- model/src/types.ts: unified BlockData (abundanceRef, MetricUI[] metrics, block
  labels, table/graph view state), workflow-facing BlockArgs (abundanceRef +
  stripped Metric[]), and legacy V1 on-disk shapes.
- model/src/dataModel.ts: .upgradeLegacy folds V1 args (refData + metrics +
  labels) and uiState (MetricUI[] + table/graph state) into unified data;
  .init seeds the five default metrics for fresh projects.
- index.ts: .args projects abundanceRef + convertMetricsUiToArgs(data.metrics)
  and throws on missing input / untyped metric (replaces argsValid + .done(2)).
  ctx.uiState/ctx.args reads -> ctx.data. abundanceRef is required in BlockArgs.
- UI: defineApp -> defineAppV3; app.model.args/ui.* -> app.model.data.*. Delete
  the debounced ui.metrics -> args.metrics sync watcher (the args lambda does the
  projection now). The block-label watchEffect stays (tolerated exception),
  repointed to data.

SDK-upgrade fallout fix: guard SettingsModal's isEmpty against the now-optional
visibleTableHandle (PTableHandle | undefined since model 1.79).

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request migrates the repository to the BlockModelV3 and block-tools structurer, upgrading the SDK packages and moving UI bindings to app.model.data. It also reorganizes the workspace configuration, updates build and linting scripts to use ts-builder and oxlint/oxfmt, and simplifies state synchronization. Feedback on the changes highlights two potential runtime errors: a possible crash in DiversityGraph.vue if the diversity column is not found in pcols, and a potential TypeError in SettingsModal.vue if app.model.outputs.pt.value is undefined when accessing visibleTableHandle.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread ui/src/pages/DiversityGraph.vue
Comment thread ui/src/pages/SettingsModal.vue
Comment thread model/src/converters.ts Outdated
Comment thread model/src/dataModel.ts
Comment thread ui/src/pages/DiversityGraph.vue
vadimpiven and others added 3 commits June 22, 2026 10:59
… metric loss

- converters.ts imports Metric/MetricUI from ./types (not ./index), removing the
  type-only import cycle now that the types live in ./types.
- upgradeLegacy: if a V1 project's uiState.metrics is absent, recover the metric
  set from args.metrics (with generated ids) instead of silently dropping to the
  hardcoded defaults; defaults only when neither source exists.
@mzueva
mzueva added this pull request to the merge queue Jul 20, 2026
Merged via the queue into main with commit 0d212eb Jul 20, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants