MILAB-6648: add the mandatory block kind and migrate column access - #211
Merged
Conversation
Adds the mandatory kind/ sibling and runs structure refresh, which wires the facade's kind devDep, the model's kind dependency, the workspace packages list and the canonical kind configs. Also picks up require-package-path-bump on the published block package. Discovery classifies a package as a kind by its @platforma-sdk/block-kind dependency, but only enumerates workspace modules — so both the packages entry and the catalog entry had to be added by hand before refresh could see it.
BlockParams covers the analysis recipe, input refs, run mode and resources, and display labels — everything in BlockData except tableState, which is view state. Every field is optional on purpose. A block with no input picked is a state the UI reaches, so export has to be able to write it and apply has to take it back; a contract demanding input would stop export and apply being inverses. Runnability stays gated by the model's args lambda. File handles are narrowed to index:// — an upload:// handle names an import local to one machine and resolves nowhere else. The CONTRACT table is checked with satisfies over keyof BlockParams, so adding a field without its guard fails to compile. That matters precisely because every field is optional: a parser that simply forgot one would otherwise return a valid BlockParams and say nothing.
Kind wiring: DataModelBuilder({ kind }), BlockModelV3.create({ dataModel, kind }),
init consuming params with per-field defaults, and the templateParams projection
mirroring the same field set back out.
Column access moves off the removed and deprecated surface:
- ColumnLazy -> DataColumn (removed in the new mechanism)
- resultPool.getSpecByRef(ref) -> Column(ref).getSpec()
- all three getPColumns() call sites -> ColumnsCollection
The collection resolves ids host-side, so clones and pt no longer materialise
specs in the sandbox just to hand them back. rawTsvs drops its ...pCol spread —
the only consumer reads id and data, so the output now fetches no specs at all.
resultPool.getOptions stays: ctx.getOptions is not on RenderCtxBase yet, and it
is the only entry point preserving the Option[] wire shape.
sampleLabels still calls resultPool.getData() — migrating it needs the domain
matching reworked against a discover selector, left for a separate change.
AStaroverov
marked this pull request as draft
August 19, 2026 17:14
AStaroverov
marked this pull request as ready for review
August 20, 2026 12:02
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Brings
mixcr-clonotypingonto the current block structure: it declares the mandatorykind/component, and its model moves off the removed and deprecated column-access surface.The kind
A block kind is a small, separately versioned package carrying the block's identity and its init-params contract — the fields a project template supplies to seed a new instance.
structure checkhard-fails a kind-less block, so this is what unblocks the block on the current structurer.BlockParamscovers the analysis recipe, input refs, run mode and resources, and display labels — everything inBlockDataexcepttableState, which is view state.Two decisions worth reviewing:
inputwould stop export and apply being inverses. Whether a configuration is runnable stays gated by the model'sargslambda.index://handles. Anupload://handle names an import local to one machine, so it cannot survive being written to a template and applied elsewhere. The parser rejects them andtemplateParamsdrops them, rather than writing a reference that resolves nowhere. This applies tolibraryFileand to a file-shapedpreset.The runtime check is a
CONTRACTtable validated withsatisfiesoverkeyof BlockParams, so adding a field without its guard fails to compile — which matters precisely because every field is optional, and a parser that simply forgot one would otherwise return a validBlockParamsand say nothing.Column access
Per
migrations/2026-05-20-new-column-access-mechanism.mdanddocs/column-access-api.md:ColumnLazy/.fromColumnDataColumn, then dropped entirelyresultPool.getSpecByRef(ref)Column(ref)?.getSpec()accessor.getPColumns()ColumnsCollection([accessor])The collection resolves ids host-side, so
clonesandptno longer materialise specs in the sandbox only to hand them straight back.rawTsvsalso drops its...pColspread — its only consumer (ui/src/MainPage.vue) readsidanddataand never touches the spec, so that output now fetches no specs at all.Deliberately unchanged:
resultPool.getOptions(3 sites) — the migration doc says to stay on it:ctx.getOptionsis not onRenderCtxBaseyet, and it is the only entry point preserving theOption[]={ ref, label }wire shape withrefsWithEnrichments.sampleLabelsstill callsresultPool.getData(). This is the real 8 MB anti-pattern and worth fixing, but the axis-domain matching has to be reworked against a discover selector plus agetSpec()post-filter, and the data-reading tail needs narrowing off thePColumnDataUniversalunion. Out of scope here — left for a separate change.Verification
turbo run build— 11/11 green.block-tools structure check—up to date (0 changes), i.e. a fixpoint.pnpm install --frozen-lockfile— in sync.parseInitializationParamsexercised against the builtdist/kind.js: empty params, a template-shaped{ species, preset }, an unknown key (dropped), a wrong-typed field,upload://vsindex://handles, a bad enum, andnull/ array envelopes all behave as intended.No backend run — nothing here changes workflow behavior.
Greptile Summary
The PR adds the mandatory block-kind contract, connects template import/export to model state, and migrates model outputs to the current column-access APIs.
kind/workspace package and connects it to the model and block build.index://file reference; this PR narrows template file parameters to this type instead of retaining localupload://references.getPColumns()calls for clone, QC-table, and raw-TSV outputs.Column(ref)?.getSpec().Confidence Score: 5/5
The PR appears safe to merge because no blocking failure remains.
No blocking failure remains.
Important Files Changed
Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart LR T[Project template] --> P[Kind parameter parser] P --> I[Model init] I --> D[BlockData] D --> A[Runtime args validation] D --> E[Template parameter projection] E -->|portable index handles only| T W[Workflow output trees] --> C[ColumnsCollection / Column] C --> O[Clone frame, QC table, labels, raw TSV outputs]Reviews (2): Last reviewed commit: "update node version to 22.x and bump dep..." | Re-trigger Greptile
Context used: