Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .changeset/structurer-kind-migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
'@platforma-open/milaboratories.3d-structure-based-liabilities.kind': patch
'@platforma-open/milaboratories.3d-structure-based-liabilities.model': patch
'@platforma-open/milaboratories.3d-structure-based-liabilities.workflow': patch
'@platforma-open/milaboratories.3d-structure-based-liabilities.software': patch
'@platforma-open/milaboratories.3d-structure-based-liabilities.ui': patch
'@platforma-open/milaboratories.3d-structure-based-liabilities': patch
---

Migrate to the latest block template and add the mandatory kind package

Refreshed onto block-tools 2.14.3 via `upgrade-sdk`, and added the `kind/`
package every block must now declare. The kind carries the block's identity
(`{name}@{version}`, read from its own `package.json`) and its init-params
contract. The refresh also reshaped `block/` into the slim facade, which
publishes the whole block from one dependency-free package.

`BlockParams` is the two confidence gates, `frConfThresh` and `cdrConfThresh`.
They decide which residues are trusted enough to score, so they are the only
fields that change what the block computes. Both are optional, so a project
template can seed either one alone and the model's `init` keeps a default
behind each. `.templateParams` projects the same two back, so exporting a block
to a template and initializing one from it are inverses. Everything else is
excluded by construction: `dataset` is an anchor-bound `DatasetSelection` that
cannot travel between projects, `tableState` is view state, and
`customBlockLabel` is a label typed over a derived default.

Author-code fixes the SDK upgrade required:

- `ArrayColumnProvider` is gone from `@platforma-sdk/model`. The scores table
now builds its recipes with `DataColumn.fromColumn`, and passes primary and
enrichment columns through the separate `primaryColumns` / `columns` fields
that `createPlDataTableV3` now takes.
- Column visibility rules match by selector object (`{ name: "..." }`) instead
of by predicate function.
- The test used the facade's old `blockSpec` export, which the slim facade
replaced with a from-pack-v2 `BlockPointer`.
22 changes: 19 additions & 3 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ on:
workflow_dispatch: {}
jobs:
init:
runs-on: ubuntu-latest
runs-on: hz-ubuntu-dind
steps:
- uses: milaboratory/github-ci/actions/context/init@v4
with:
Expand All @@ -22,10 +22,12 @@ jobs:
- init
uses: milaboratory/github-ci/.github/workflows/node-simple-pnpm.yaml@v4
with:
app-name: 'Block: 3d Structure-Based Liabilities'
app-name: 'Block: 3d Structure Based Liabilities'
app-name-slug: 'block-3d-structure-based-liabilities'
node-version: '22.x'
build-script-name: 'build'
gha-runner-label: hz-ubuntu-dind
build-script-name: 'build:dev-local'
build-before-publish-script-name: 'build:release'
pnpm-recursive-build: false

test: true
Expand All @@ -37,6 +39,11 @@ jobs:
package-path: 'block'
create-tag: 'true'

# Require the published `block` package to be bumped by a changeset on
# PRs (empty changeset or the `skip-changelog` label waives it). Needs
# the input to exist on the pinned `@v4` reusable workflow.
require-package-path-bump: true

npmrc-config: |
{
"registries": {
Expand All @@ -56,6 +63,15 @@ jobs:

"AWS_CI_IAM_MONOREPO_SIMPLE_ROLE": ${{ toJSON(secrets.AWS_CI_IAM_MONOREPO_SIMPLE_ROLE) }},
"AWS_CI_TURBOREPO_S3_BUCKET": ${{ toJSON(secrets.AWS_CI_TURBOREPO_S3_BUCKET) }},

"HZ_CI_TURBO_S3_BUCKET": ${{ toJSON(vars.HZ_CI_TURBO_S3_BUCKET) }},
"HZ_CI_TURBO_S3_ENDPOINT": ${{ toJSON(vars.HZ_CI_TURBO_S3_ENDPOINT) }},
"HZ_CI_TURBO_S3_REGION": ${{ toJSON(vars.HZ_CI_TURBO_S3_REGION) }},
"HZ_CI_TURBO_S3_ACCESS_KEY": ${{ toJSON(secrets.HZ_CI_TURBO_S3_ACCESS_KEY) }},
"HZ_CI_TURBO_S3_SECRET_KEY": ${{ toJSON(secrets.HZ_CI_TURBO_S3_SECRET_KEY) }},
"HZ_CI_CACHE_S3_ACCESS_KEY": ${{ toJSON(secrets.HZ_CI_CACHE_S3_ACCESS_KEY) }},
"HZ_CI_CACHE_S3_SECRET_KEY": ${{ toJSON(secrets.HZ_CI_CACHE_S3_SECRET_KEY) }},

"PL_REGISTRY_PLATFORMA_OPEN_UPLOAD_URL": ${{ toJSON(secrets.PL_REGISTRY_PLOPEN_UPLOAD_URL) }},
"QUAY_USERNAME": ${{ toJSON(secrets.QUAY_USERNAME) }},
"QUAY_ROBOT_TOKEN": ${{ toJSON(secrets.QUAY_ROBOT_TOKEN) }} }
Expand Down
2 changes: 1 addition & 1 deletion .structure
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"version":1}
{"version":2}
6 changes: 0 additions & 6 deletions block/index.d.ts

This file was deleted.

8 changes: 0 additions & 8 deletions block/index.js

This file was deleted.

35 changes: 25 additions & 10 deletions block/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,39 @@
"name": "@platforma-open/milaboratories.3d-structure-based-liabilities",
"version": "1.3.0",
"files": [
"index.d.ts",
"index.js"
"dist",
"block-pack"
],
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"sources": "./src/index.ts",
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"scripts": {
"build": "shx rm -rf ./block-pack && block-tools pack",
"build": "ts-builder build --target block-facade && block-tools pack",
"prepublishOnly": "block-tools publish -r s3://milab-euce1-prod-pkgs-s3-block-registry/pub/releases/?region=eu-central-1 --registry-serve-url https://blocks.pl-open.science",
"do-pack": "shx rm -f *.tgz && block-tools pack && pnpm pack && shx mv *.tgz package.tgz",
"mark-stable": "block-tools mark-stable -r 's3://milab-euce1-prod-pkgs-s3-block-registry/pub/releases/?region=eu-central-1'"
"do-pack": "shx rm -f package.tgz && pnpm pack && shx mv *.tgz package.tgz",
"mark-stable": "block-tools mark-stable -r 's3://milab-euce1-prod-pkgs-s3-block-registry/pub/releases/?region=eu-central-1'",
"check": "ts-builder type-check --target block-facade"
},
"dependencies": {
"dependencies": {},
"devDependencies": {
"@milaboratories/ts-builder": "catalog:",
"@milaboratories/ts-configs": "catalog:",
"@platforma-open/milaboratories.3d-structure-based-liabilities.kind": "workspace:*",
"@platforma-open/milaboratories.3d-structure-based-liabilities.model": "workspace:*",
"@platforma-open/milaboratories.3d-structure-based-liabilities.ui": "workspace:*",
"@platforma-open/milaboratories.3d-structure-based-liabilities.workflow": "workspace:*",
"@platforma-sdk/model": "catalog:"
},
"devDependencies": {
"@platforma-sdk/block-tools": "catalog:",
"shx": "catalog:"
"@platforma-sdk/model": "catalog:",
"shx": "catalog:",
"typescript": "catalog:"
},
"packageManager": "pnpm@9.12.0",
"block": {
Expand Down
5 changes: 5 additions & 0 deletions block/src/AGENTS.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// This file is managed by `block-tools structure`. Do not edit by hand.
// Narrow MCP / AI surface.

export type { BlockContract, BlockOutputs, BlockData } from "./index";
export * from "./agents-extra";
8 changes: 8 additions & 0 deletions block/src/agents-extra.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Author-owned. `block-tools structure` does not modify this file.
// MCP / AI extension surface. Add types and functions the agent
// surface should expose.
//
// In the future this file will host JS functions the MCP runtime
// can execute. The `.d.ts` declarations stay visible to the agent;
// the JS bodies execute in the MCP code-execution context (the
// agent sees the types but not the implementation).
9 changes: 9 additions & 0 deletions block/src/block-extra.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Author-owned. `block-tools structure` does not modify this file.
// Add block-specific helper types or values the consumer surface
// should expose. Anything you `export` here flows out via the
// main entry (./index re-exports this file).
//
// Do NOT redefine: BlockContract, BlockOutputs, BlockData,
// BlockPointer, platforma, or the block-named <PascalName>Block*
// aliases — those names come from ./index and `export *` from this
// file would shadow them.
55 changes: 55 additions & 0 deletions block/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// This file is managed by `block-tools structure`. Do not edit by hand.
// Author content lives in ./block-extra.ts.

import { platforma } from "@platforma-open/milaboratories.3d-structure-based-liabilities.model";
import {
InferOutputsType,
InferDataType,
InferHrefType,
} from "@platforma-sdk/model";

export { platforma };

export type BlockContract = {
outputs: InferOutputsType<typeof platforma>;
data: InferDataType<typeof platforma>;
href: InferHrefType<typeof platforma>;
};

export type BlockOutputs = BlockContract["outputs"];
export type BlockData = BlockContract["data"];

// import.meta.url is a file: URL (always forward-slash, even on Windows:
// file:///C:/…). We expose URLs, NOT paths — the facade stays dependency-free
// and loadable in minimal engines (e.g. QuickJS), and each consumer converts
// at its own edge with the right tool (fileURLToPath in Node), where Windows
// drive letters / %-encoding / UNC are handled correctly. The bundled entry
// sits one dir under the package root (dist/index.js, or src/index.ts in dev),
// so the root is two URL segments up. The structurer owns this layout —
// consumers read these URLs, they never reconstruct <root>/block-pack.
//
// TypeScript ships `ImportMeta.url` only in the `dom`/`webworker` libs; the
// facade tsconfig is lib-minimal (no `dom`, no `@types/node`) by design. We
// type the one ESM-standard member we use with a local cast rather than a
// `declare global` — a global augmentation would leak into the published
// `dist/index.d.ts` and clash with `@types/node`'s `ImportMeta` in full-Node
// consumers (test packages, the Middle Layer).
const selfUrl = (import.meta as ImportMeta & { url: string }).url;
const dirUrl = selfUrl.slice(0, selfUrl.lastIndexOf("/"));
const rootUrl = dirUrl.slice(0, dirUrl.lastIndexOf("/"));

export const BlockPointer = {
type: "from-pack-v2" as const,
packUrl: rootUrl + "/block-pack",
rootUrl,
} as const;

// Block-named aliases for readable cross-block imports in tests and
// consumer code. Same types / same runtime value as the universal
// names above; the aliases avoid `as`-renames at the import site.
export type _3dStructureBasedLiabilitiesBlockContract = BlockContract;
export type _3dStructureBasedLiabilitiesBlockOutputs = BlockOutputs;
export type _3dStructureBasedLiabilitiesBlockData = BlockData;
export const _3dStructureBasedLiabilitiesBlockPointer = BlockPointer;

export * from "./block-extra";
4 changes: 4 additions & 0 deletions block/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "@milaboratories/ts-configs/block/facade",
"include": ["src/**/*"]
}
4 changes: 4 additions & 0 deletions kind/.oxfmtrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": ["node_modules/@milaboratories/ts-builder/configs/oxfmt.json"],
"ignorePatterns": ["dist", "coverage", "CHANGELOG.md"]
}
3 changes: 3 additions & 0 deletions kind/.oxlintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": ["node_modules/@milaboratories/ts-builder/dist/configs/oxlint-node.json"]
}
36 changes: 36 additions & 0 deletions kind/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "@platforma-open/milaboratories.3d-structure-based-liabilities.kind",
"version": "1.0.0",
"private": true,
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"sources": "./src/index.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs",
"default": "./dist/index.js"
}
},
"scripts": {
"fmt": "ts-builder format",
"watch": "ts-builder build --target block-kind --watch",
"build": "ts-builder build --target block-kind && block-tools build-kind-manifest",
"check": "ts-builder check --target block-kind"
},
"dependencies": {
"@platforma-sdk/block-kind": "catalog:"
},
"devDependencies": {
"@milaboratories/ts-builder": "catalog:",
"@milaboratories/ts-configs": "catalog:",
"@platforma-sdk/block-tools": "catalog:"
},
"peerDependencies": {
"@types/node": "*",
"typescript": "*"
}
}
75 changes: 75 additions & 0 deletions kind/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { assertParamsObject, defineBlockKind } from "@platforma-sdk/block-kind";
import { name, version } from "../package.json" with { type: "json" };

/**
* This block's init-params contract — what a project template supplies to seed a
* new instance.
*
* The two confidence gates are the only settings that change what the block
* computes: they decide which residues are trusted enough to score, so they are
* real configuration. Everything else in `BlockData` is deliberately absent.
* `dataset` is a `DatasetSelection`, an anchor-bound reference whose meaning
* depends on the anchor map of the project that made it, so it cannot travel in
* a template. `tableState` is view state, and `customBlockLabel` is a label the
* user types over a derived default — neither is configuration.
*
* Both fields are optional so a template can seed either one alone; the model's
* `init` keeps a default behind each.
*/
export type BlockParams = {
/** Framework-region confidence gate, in ångström. */
frConfThresh?: number;
/** CDR confidence gate, in ångström. */
cdrConfThresh?: number;
};

/**
* Reject a value that is not a finite number.
*
* Both gates are plain numbers, so there is no SDK guard to reach for. The check
* stops at "finite number" on purpose. The UI offers a bounded range, but
* encoding that range here would make the kind refuse a file this block itself
* exported the day the range changes. A range is meaning; the kind checks the
* envelope.
*/
function finiteNumber(key: string, value: unknown): number {
if (typeof value !== "number" || !Number.isFinite(value)) {
throw new Error(`'${key}' must be a finite number. Got: ${JSON.stringify(value)}`);
}
return value;
}

/**
* The same contract at runtime, for params arriving from a template file rather
* than from typed code — the only point that can catch a hand-written entry
* being wrong.
*
* Each field is checked only when present, because both are optional. Keys the
* contract does not name are dropped by not being read; refusing them would mean
* holding a list of field names as strings that nothing keeps in step with the
* type.
*/
function parseInitializationParams(value: unknown): BlockParams {
assertParamsObject(value);

const params: BlockParams = {};

if (value.frConfThresh !== undefined) {
params.frConfThresh = finiteNumber("frConfThresh", value.frConfThresh);
}

if (value.cdrConfThresh !== undefined) {
params.cdrConfThresh = finiteNumber("cdrConfThresh", value.cdrConfThresh);
}

return params;
}

// Identity (`name`/`version`) comes from this package's own `package.json`, so
// the on-wire `{name}@{version}` reference can never drift from what npm
// publishes; the bundler inlines the JSON import.
export const kind = defineBlockKind<BlockParams>({
name,
version,
parseInitializationParams,
});
10 changes: 10 additions & 0 deletions kind/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "@milaboratories/ts-configs/block/facade",
"compilerOptions": {
"outDir": "./dist",
"rootDir": ".",
"resolveJsonModule": true
},
"include": ["src/**/*", "package.json"],
"exclude": ["dist", "node_modules"]
}
2 changes: 2 additions & 0 deletions model/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "@platforma-open/milaboratories.3d-structure-based-liabilities.model",
"version": "1.3.0",
"private": true,
"description": "Block model",
"type": "module",
"main": "dist/index.cjs",
Expand All @@ -23,6 +24,7 @@
"dependencies": {
"@milaboratories/graph-maker": "catalog:",
"@milaboratories/helpers": "catalog:",
"@platforma-open/milaboratories.3d-structure-based-liabilities.kind": "workspace:*",
"@platforma-sdk/model": "catalog:"
},
"devDependencies": {
Expand Down
Loading
Loading