@platforma-sdk/block-tools 2.12.13 → 2.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +12 -12
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +804 -720
- package/dist/cli.mjs.map +1 -1
- package/dist/cmd/build-kind-manifest.d.ts +7 -0
- package/dist/config-CtXMWNgm.js +3 -0
- package/dist/config-CtXMWNgm.js.map +1 -0
- package/dist/{config-CiC347sB.mjs → config-Dx45aFJ_.mjs} +792 -456
- package/dist/config-Dx45aFJ_.mjs.map +1 -0
- package/dist/index.js +1 -1
- package/dist/index.mjs +15 -15
- package/dist/structure/engine/api.d.ts +1 -1
- package/dist/structure/rules/kind-package-json.d.ts +3 -0
- package/dist/structure/rules/kind.d.ts +1 -0
- package/dist/v2/build_kind_dist.d.ts +25 -0
- package/dist/v2/index.d.ts +4 -0
- package/dist/v2/kind/resolve-refs.d.ts +63 -0
- package/dist/v2/kind/version-match.d.ts +23 -0
- package/dist/v2/model/block_description.d.ts +8 -1
- package/dist/v2/publish-block.d.ts +23 -0
- package/dist/v2/registry/index.d.ts +2 -0
- package/dist/v2/registry/kind_resolver.d.ts +121 -0
- package/dist/v2/registry/registry.d.ts +23 -0
- package/dist/v2/registry/registry_reader.d.ts +34 -1
- package/dist/v2/registry/schema_kinds.d.ts +632 -0
- package/dist/v2/registry/schema_public.d.ts +72 -0
- package/package.json +9 -9
- package/src/cli.test.ts +2 -1
- package/src/cli.ts +2 -0
- package/src/cmd/build-kind-manifest.ts +41 -0
- package/src/cmd/publish.ts +10 -1
- package/src/cmd/software/build.ts +17 -1
- package/src/structure/__tests__/model-package-json.snapshot.test.ts +1 -0
- package/src/structure/engine/api.ts +1 -1
- package/src/structure/engine/ctx.ts +1 -0
- package/src/structure/engine/discovery.ts +16 -2
- package/src/structure/rules/block-package-json.ts +18 -0
- package/src/structure/rules/kind-package-json.ts +117 -0
- package/src/structure/rules/kind.ts +29 -0
- package/src/structure/rules/model-package-json.ts +8 -0
- package/src/structure/rules/model.ts +15 -13
- package/src/structure/rules/shared/pascal-case.ts +1 -1
- package/src/structure/structure-definition.ts +2 -0
- package/src/structure/templates/static/kind/.oxfmtrc.json +4 -0
- package/src/structure/templates/static/kind/.oxlintrc.json +3 -0
- package/src/structure/templates/static/kind/src/index.ts +49 -0
- package/src/structure/templates/static/kind/tsconfig.json +10 -0
- package/src/structure/templates/text/model/src/index.tpl.ts +18 -0
- package/src/v2/build_dist.ts +35 -0
- package/src/v2/build_kind_dist.ts +104 -0
- package/src/v2/from_pack_v2.test.ts +2 -2
- package/src/v2/index.ts +4 -0
- package/src/v2/kind/resolve-refs.ts +150 -0
- package/src/v2/kind/version-match.test.ts +60 -0
- package/src/v2/kind/version-match.ts +55 -0
- package/src/v2/model/block_description.ts +15 -4
- package/src/v2/publish-block.ts +60 -0
- package/src/v2/registry/index.ts +2 -0
- package/src/v2/registry/kind_resolver.test.ts +123 -0
- package/src/v2/registry/kind_resolver.ts +190 -0
- package/src/v2/registry/registry.test.ts +247 -1
- package/src/v2/registry/registry.ts +227 -4
- package/src/v2/registry/registry_reader.ts +68 -0
- package/src/v2/registry/schema_kinds.test.ts +65 -0
- package/src/v2/registry/schema_kinds.ts +169 -0
- package/dist/config-BmJWc8sR.js +0 -3
- package/dist/config-BmJWc8sR.js.map +0 -1
- package/dist/config-CiC347sB.mjs.map +0 -1
- package/src/structure/templates/static/model/src/index.ts +0 -13
package/dist/cli.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.mjs","names":[],"sources":["../src/cmd/build-meta.ts","../src/cmd/build-model.ts","../src/cmd/pack.ts","../src/cmd/publish.ts","../src/cmd/refresh-registry.ts","../src/cmd/mark-stable.ts","../src/structure/engine/fs/node.ts","../src/structure/engine/templates.ts","../src/structure/engine/flatten.ts","../src/structure/engine/glob.ts","../src/structure/engine/builders.ts","../src/structure/engine/parsers/json.ts","../src/structure/engine/parsers/lines.ts","../src/structure/engine/content-rules.ts","../src/structure/engine/parsers/yaml.ts","../src/structure/engine/version.ts","../src/structure/engine/runner.ts","../src/structure/engine/discovery.ts","../src/structure/engine/ctx.ts","../src/structure/engine/discovery-fs.ts","../src/structure/rules/shared/key-order.ts","../src/structure/rules/root-package-json.ts","../src/structure/rules/root-turbo-json.ts","../src/structure/engine/registry-client.ts","../src/structure/rules/shared/retired-deps.ts","../src/structure/rules/root-pnpm-workspace.ts","../src/structure/rules/root-gitignore.ts","../src/structure/rules/root.ts","../src/structure/rules/root-ci.ts","../src/structure/rules/block-package-json.ts","../src/structure/rules/shared/pascal-case.ts","../src/structure/rules/block.ts","../src/structure/rules/shared/colocated-tests.ts","../src/structure/rules/model-package-json.ts","../src/structure/rules/model.ts","../src/structure/rules/ui-package-json.ts","../src/structure/rules/ui.ts","../src/structure/rules/workflow-package-json.ts","../src/structure/rules/workflow.ts","../src/structure/rules/test-package-json.ts","../src/structure/rules/test.ts","../src/structure/rules/software-package-json.ts","../src/structure/rules/software.ts","../src/structure/rules/migrations.ts","../src/structure/rules/root-catalog-bump.ts","../src/structure/structure-definition.ts","../src/structure/cli/run-structure.ts","../src/cmd/structure/refresh.ts","../src/cmd/update-deps.ts","../src/cmd/list-overview-snapshots.ts","../src/cmd/restore-overview-from-snapshot.ts","../src/registry_v1/flags.ts","../src/cmd/upload-package-v1.ts","../src/cmd/structure/check.ts","../src/structure/init-block-constructor.ts","../src/cmd/structure/init.ts","../src/cmd/software/knobs.ts","../src/cmd/software/ecr-login.ts","../src/cmd/software/run-build.ts","../src/cmd/software/env.ts","../src/cmd/software/build.ts","../src/cmd/software/index.ts","../src/cli.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport path from \"node:path\";\nimport fs from \"node:fs\";\nimport { loadPackDescriptionRaw } from \"../v2\";\nimport { embedBlockPackMetaAbsoluteBase64, resolveBlockPackMeta } from \"../v2/model/block_meta\";\n\nexport function buildMetaCommand(): Command {\n const cmd = new Command(\"build-meta\").description(\n \"Extracts meta information from blocks package.json and outputs meta.json with embedded binary \" +\n \"and textual information linked from the meta section.\",\n );\n\n cmd.option(\"-i, --modulePath <path>\", \"input module path\", \".\");\n cmd.requiredOption(\"-o, --destination <path>\", \"output meta.json file\");\n\n cmd.action(async (flags) => {\n const modulePath = path.resolve(flags.modulePath);\n const descriptionRaw = await loadPackDescriptionRaw(modulePath);\n const metaEmbedded = await embedBlockPackMetaAbsoluteBase64(\n await resolveBlockPackMeta(descriptionRaw.meta, modulePath),\n );\n\n await fs.promises.writeFile(path.resolve(flags.destination), JSON.stringify(metaEmbedded));\n });\n\n return cmd;\n}\n","import { Command } from \"commander\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nasync function getFileContent(path: string) {\n try {\n return await fs.promises.readFile(path, \"utf8\");\n } catch (error: unknown) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n return undefined;\n }\n throw error;\n }\n}\n\nexport function buildModelCommand(): Command {\n const cmd = new Command(\"build-model\").description(\n \"Extracts and outputs block model JSON from pre-built block model module\",\n );\n\n cmd.option(\"-i, --modulePath <path>\", \"input module path\", \".\");\n cmd.option(\n \"-b, --sourceBundle <path>\",\n \"bundled model code to embed into the model for callback-based rendering to work\",\n \"./dist/bundle.js\",\n );\n cmd.option(\"-o, --destination <path>\", \"output model file\", \"./dist/model.json\");\n\n cmd.action(async (flags) => {\n const modulePath = path.resolve(flags.modulePath); // i.e. folder with package.json file\n let { model, platforma } = require(modulePath);\n\n if (!model) model = platforma;\n if (!model) throw new Error('\"model\" export not found');\n\n const { config } = model;\n\n if (!config)\n throw new Error(\n 'Malformed \"model\" object, check it is created with \"BlockModel\" ' +\n 'and \".done()\" is executed as the call in the chain.',\n );\n\n if (!(\"outputs\" in config) || !(\"sections\" in config))\n throw new Error('\"config\" has unexpected structure');\n\n const code = await getFileContent(flags.sourceBundle);\n if (code !== undefined) {\n config.code = {\n type: \"plain\",\n content: code,\n };\n }\n\n await fs.promises.writeFile(path.resolve(flags.destination), JSON.stringify(config));\n });\n\n return cmd;\n}\n","import { Command } from \"commander\";\nimport { loadPackDescription } from \"../v2/source_package\";\nimport path from \"node:path\";\nimport { buildBlockPackDist } from \"../v2/build_dist\";\n\nexport function packCommand(): Command {\n const cmd = new Command(\"pack\").description(\n \"Builds block pack and outputs a block pack manifest consolidating all \" +\n \"references assets into a single folder\",\n );\n\n cmd.option(\"-i, --modulePath <path>\", \"input module path\", \".\");\n cmd.option(\"-o, --destinationPath <path>\", \"output folder\", \"./block-pack\");\n\n cmd.action(async (flags) => {\n const description = await loadPackDescription(path.resolve(flags.modulePath));\n await buildBlockPackDist(description, path.resolve(flags.destinationPath));\n });\n\n return cmd;\n}\n","import { Command, Option } from \"commander\";\nimport fs from \"node:fs\";\nimport { ConsoleLoggerAdapter } from \"@milaboratories/ts-helpers\";\nimport { ManifestFileName } from \"../v2/registry/schema_public\";\nimport {\n BlockPackManifest,\n overrideManifestVersion,\n StableChannel,\n} from \"@milaboratories/pl-model-middle-layer\";\nimport { storageByUrl } from \"../io/storage\";\nimport { BlockRegistryV2 } from \"../v2/registry/registry\";\nimport { buildPublishedCoords, writePublishedCoords } from \"../v2/resolve_to_registry\";\nimport path from \"node:path\";\n\nfunction simpleDeepMerge<T extends Record<string, unknown>>(\n target: Record<string, unknown>,\n source: T,\n): T {\n const result = { ...target };\n\n for (const key in source) {\n if (source[key] && typeof source[key] === \"object\" && !Array.isArray(source[key])) {\n if (result[key] && typeof result[key] === \"object\" && !Array.isArray(result[key])) {\n result[key] = simpleDeepMerge(\n result[key] as Record<string, unknown>,\n source[key] as Record<string, unknown>,\n );\n } else {\n result[key] = source[key];\n }\n } else {\n result[key] = source[key];\n }\n }\n\n return result as T;\n}\n\nexport function publishCommand(): Command {\n const cmd = new Command(\"publish\").description(\n \"Publishes the block package and refreshes the registry (for v2 block-pack schema)\",\n );\n\n cmd.addOption(\n new Option(\"-r, --registry <address>\", \"full address of the registry\")\n .env(\"PL_REGISTRY\")\n .makeOptionMandatory(),\n );\n cmd.addOption(\n new Option(\n \"--registry-serve-url <url>\",\n \"CDN serve URL written into block-pack/published.json (npm-consumed blocks)\",\n )\n .env(\"PL_REGISTRY_SERVE_URL\")\n .makeOptionMandatory(),\n );\n cmd.option(\"-m, --manifest <path>\", \"manifest file path\", `./block-pack/${ManifestFileName}`);\n cmd.option(\"-v, --version-override <path>\", \"override package version\");\n cmd.addOption(\n new Option(\"--refresh\", \"refresh repository after adding the package\")\n .default(true)\n .env(\"PL_REGISTRY_REFRESH\"),\n );\n cmd.option(\"--no-refresh\", \"do not refresh repository after adding the package\");\n cmd.addOption(\n new Option(\"--unstable\", \"do not add the published package to stable channel\")\n .default(false)\n .env(\"PL_PUBLISH_UNSTABLE\"),\n );\n\n cmd.action(async (flags) => {\n const logger = new ConsoleLoggerAdapter();\n\n const manifestPath = path.resolve(flags.manifest);\n const rawManifest = JSON.parse(\n await fs.promises.readFile(manifestPath, { encoding: \"utf-8\" }),\n ) as Record<string, unknown>;\n let manifest = BlockPackManifest.parse(rawManifest);\n // To keep extra fields from the manifest and keep coerced fields\n manifest = simpleDeepMerge(\n rawManifest,\n manifest as BlockPackManifest & Record<string, unknown>,\n );\n const manifestRoot = path.dirname(manifestPath);\n\n logger.info(`Manifest root = ${manifestRoot}`);\n\n if (flags.versionOverride) manifest = overrideManifestVersion(manifest, flags.versionOverride);\n\n const storage = storageByUrl(flags.registry);\n const registry = new BlockRegistryV2(storage, logger);\n\n await registry.publishPackage(manifest, async (file) =>\n Buffer.from(await fs.promises.readFile(path.resolve(manifestRoot, file))),\n );\n\n if (!flags.unstable) {\n logger.info(`Adding package to ${StableChannel} channel...`);\n await registry.addPackageToChannel(manifest.description.id, StableChannel);\n }\n\n // Write registry coordinates next to the manifest so npm consumers can\n // resolve the published block via `resolveToRegistry`. Written before\n // returning so `npm publish`'s tarball generation (after prepublishOnly)\n // picks it up.\n const coords = buildPublishedCoords({\n registryUrl: flags.registryServeUrl,\n id: manifest.description.id,\n });\n await writePublishedCoords(manifestRoot, coords);\n logger.info(`Wrote published coordinates to ${path.resolve(manifestRoot, \"published.json\")}`);\n\n if (flags.refresh) await registry.updateIfNeeded();\n });\n\n return cmd;\n}\n","import { Command, Option } from \"commander\";\nimport { BlockRegistryV2 } from \"../v2\";\nimport { storageByUrl } from \"../io\";\nimport { ConsoleLoggerAdapter } from \"@milaboratories/ts-helpers\";\n\nexport function refreshRegistryCommand(): Command {\n const cmd = new Command(\"refresh-registry\").description(\n \"Refresh overview files based on published but not proecessed artefacts\",\n );\n\n cmd.addOption(\n new Option(\"-r, --registry <address>\", \"full address of the registry\")\n .env(\"PL_REGISTRY\")\n .makeOptionMandatory(),\n );\n cmd.addOption(\n new Option(\"-m, --mode <mode>\", 'refresh mode (allowed valiues: \"force\", \"normal\", \"dry-run\")')\n .choices([\"force\", \"normal\", \"dry-run\"])\n .env(\"PL_REGISTRY_REFRESH_DRY_RUN\")\n .default(\"normal\"),\n );\n\n cmd.action(async (flags) => {\n const storage = storageByUrl(flags.registry);\n const registry = new BlockRegistryV2(storage, new ConsoleLoggerAdapter());\n await registry.updateIfNeeded(flags.mode as \"force\" | \"normal\" | \"dry-run\");\n });\n\n return cmd;\n}\n","import { Command, Option } from \"commander\";\nimport { BlockRegistryV2, loadPackDescriptionRaw } from \"../v2\";\nimport path from \"node:path\";\nimport { overrideDescriptionVersion, StableChannel } from \"@milaboratories/pl-model-middle-layer\";\nimport { storageByUrl } from \"../io\";\nimport { ConsoleLoggerAdapter } from \"@milaboratories/ts-helpers\";\n\nexport function markStableCommand(): Command {\n const cmd = new Command(\"mark-stable\").description(\"Mark target block stable\");\n\n cmd.option(\"-i, --modulePath <path>\", \"input module path\", \".\");\n cmd.addOption(\n new Option(\"-c, --channel <channel name>\", \"custom channel\").default(StableChannel).hideHelp(),\n );\n cmd.option(\"-v, --version-override <path>\", \"override package version\");\n cmd.addOption(\n new Option(\"-r, --registry <address>\", \"full address of the registry\")\n .env(\"PL_REGISTRY\")\n .makeOptionMandatory(),\n );\n cmd.addOption(\n new Option(\"--refresh\", \"refresh repository after adding the package\")\n .default(true)\n .env(\"PL_REGISTRY_REFRESH\"),\n );\n cmd.option(\"--no-refresh\", \"do not refresh repository after adding the package\");\n cmd.option(\n \"--unmark\",\n 'reverses meaning of this command, flag can be used to remove \"stable\" flag from the package',\n false,\n );\n\n cmd.action(async (flags) => {\n let description = await loadPackDescriptionRaw(path.resolve(flags.modulePath));\n if (flags.versionOverride)\n description = overrideDescriptionVersion(description, flags.versionOverride);\n const storage = storageByUrl(flags.registry);\n const registry = new BlockRegistryV2(storage, new ConsoleLoggerAdapter());\n\n if (flags.unmark) await registry.removePackageFromChannel(description.id, flags.channel);\n else await registry.addPackageToChannel(description.id, flags.channel);\n\n if (flags.refresh) await registry.updateIfNeeded();\n });\n\n return cmd;\n}\n","// node:fs-backed implementation (synchronous). Anchored at a configured\n// `root`. All FileSystem methods take block-relative paths; this wrapper\n// joins them against root before touching disk.\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { DirEntry, FileSystem } from \"./api\";\n\nexport class NodeFileSystem implements FileSystem {\n constructor(private root: string) {}\n\n private abs(p: string): string {\n return path.resolve(this.root, p);\n }\n\n read(p: string): string {\n return fs.readFileSync(this.abs(p), \"utf-8\");\n }\n\n write(p: string, content: string): void {\n const a = this.abs(p);\n fs.mkdirSync(path.dirname(a), { recursive: true });\n fs.writeFileSync(a, content, \"utf-8\");\n }\n\n writeBinary(p: string, content: Uint8Array): void {\n const a = this.abs(p);\n fs.mkdirSync(path.dirname(a), { recursive: true });\n fs.writeFileSync(a, content);\n }\n\n exists(p: string): boolean {\n try {\n fs.statSync(this.abs(p));\n return true;\n } catch {\n return false;\n }\n }\n\n list(dir: string): string[] {\n const a = this.abs(dir);\n try {\n const stat = fs.statSync(a);\n if (!stat.isDirectory()) return [];\n } catch {\n return [];\n }\n const out: string[] = [];\n function walk(rel: string, absDir: string): void {\n const entries = fs.readdirSync(absDir, { withFileTypes: true });\n for (const e of entries) {\n const childRel = rel ? `${rel}/${e.name}` : e.name;\n const childAbs = path.join(absDir, e.name);\n if (e.isDirectory()) {\n walk(childRel, childAbs);\n } else if (e.isFile()) {\n out.push(childRel);\n }\n }\n }\n walk(dir === \"\" || dir === \".\" ? \"\" : dir, a);\n return out.sort();\n }\n\n listDir(dir: string): DirEntry[] {\n const a = this.abs(dir);\n let entries;\n try {\n entries = fs.readdirSync(a, { withFileTypes: true });\n } catch {\n return [];\n }\n return entries\n .map((e) => ({ name: e.name, isDirectory: e.isDirectory() }))\n .sort((x, y) => x.name.localeCompare(y.name));\n }\n\n move(from: string, to: string): void {\n const fromA = this.abs(from);\n const toA = this.abs(to);\n fs.mkdirSync(path.dirname(toA), { recursive: true });\n fs.renameSync(fromA, toA);\n }\n\n delete(p: string): void {\n fs.rmSync(this.abs(p), { recursive: true, force: true });\n }\n}\n","// Template-content provider for the runner.\n//\n// `file(path)` and `tpl(path, vars)` content forms resolve through this\n// provider. Static templates live at `<root>/static/`; templated text\n// lives at `<root>/text/`. The runner accepts a TemplateProvider via\n// `RunOptions.templates`; the production CLI wires a NodeTemplateProvider\n// rooted at the bundled `templates/` directory, and tests can use\n// `MemoryTemplateProvider` or point at the on-disk templates directory\n// during the Layer-2 zero-diff invariant.\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport interface TemplateProvider {\n /** Read a static template file (under `<root>/static/`). */\n staticRead(p: string): string;\n /** Read a static template file as raw bytes (under `<root>/static/`).\n * For binary assets (logos, images) that must not be utf-8 decoded. */\n staticReadBinary(p: string): Uint8Array;\n /** Read a text template file (under `<root>/text/`). */\n textRead(p: string): string;\n}\n\n/** Provider backed by an on-disk template tree. Reads are synchronous\n * so the runner can stay sync inside content-form resolution. */\nexport class NodeTemplateProvider implements TemplateProvider {\n constructor(private root: string) {}\n\n staticRead(p: string): string {\n return fs.readFileSync(path.resolve(this.root, \"static\", p), \"utf-8\");\n }\n\n staticReadBinary(p: string): Uint8Array {\n return fs.readFileSync(path.resolve(this.root, \"static\", p));\n }\n\n textRead(p: string): string {\n return fs.readFileSync(path.resolve(this.root, \"text\", p), \"utf-8\");\n }\n}\n\n/** In-memory provider for tests. Keyed by the same `static/...` /\n * `text/...` shape as on disk. */\nexport class MemoryTemplateProvider implements TemplateProvider {\n constructor(private files: Record<string, string>) {}\n\n staticRead(p: string): string {\n const k = `static/${p}`;\n const v = this.files[k];\n if (v === undefined) throw new Error(`MemoryTemplateProvider: missing '${k}'`);\n return v;\n }\n\n staticReadBinary(p: string): Uint8Array {\n // In-memory templates are stored as strings; expose their bytes. Real\n // binary assets are exercised through NodeTemplateProvider on disk.\n return new TextEncoder().encode(this.staticRead(p));\n }\n\n textRead(p: string): string {\n const k = `text/${p}`;\n const v = this.files[k];\n if (v === undefined) throw new Error(`MemoryTemplateProvider: missing '${k}'`);\n return v;\n }\n}\n\n/** Shell-style `${name}` substitution. Unknown names left as-is so\n * template authors notice. Backslash escape is not supported. */\nexport function substituteVars(text: string, vars: Record<string, string>): string {\n return text.replace(/\\$\\{([A-Za-z_][A-Za-z0-9_]*)\\}/g, (_m, name: string) => {\n return vars[name] ?? `\\${${name}}`;\n });\n}\n","// Flatten: DFS over the tree IR; fan out each scope frame once per\n// matching module in `ctx.modules`. Compose enclosing `when` triggers\n// (AND of all on the path from root). Track which run modes the leaf\n// fires in (its enclosing mode frame, or the `[\"default\", \"init\"]`\n// default) and emit that as `modes` on the FlatItem. No execution here —\n// execution lives in `runner.ts`.\n\nimport type { Module, RunContext, Scope } from \"./api\";\nimport type { FlatItem, LeafItem, RunMode, Structure, TreeNode, TriggerFn } from \"./ir\";\n\n/** Modes a leaf fires in when it sits outside any mode frame: default\n * refresh/check plus init. (`onUpdateDeps` / `onInitOrUpdate` frames\n * override this for their children.) */\nconst DEFAULT_MODES: RunMode[] = [\"default\", \"init\"];\n\nfunction resolveRelative(modulePath: string, fileRel: string): string {\n if (!modulePath) return fileRel;\n if (!fileRel) return modulePath;\n // Strip trailing slash on modulePath, leading slash on fileRel.\n const m = modulePath.endsWith(\"/\") ? modulePath.slice(0, -1) : modulePath;\n const f = fileRel.startsWith(\"/\") ? fileRel.slice(1) : fileRel;\n return f ? `${m}/${f}` : m;\n}\n\n/**\n * Lexicographic sort of modules by `path`.\n * Used for deterministic fan-out order.\n */\nfunction modulesByScope(modules: Module[], scope: Scope): Module[] {\n return modules\n .filter((m) => m.scope === scope)\n .slice()\n .sort((a, b) => a.path.localeCompare(b.path));\n}\n\nexport function flatten(structure: Structure, ctx: RunContext): FlatItem[] {\n const out: FlatItem[] = [];\n\n function visit(\n node: TreeNode,\n boundScope: Scope | undefined,\n boundModulePath: string | undefined,\n triggers: TriggerFn[],\n modes: RunMode[],\n ): void {\n if (node.kind === \"scope\") {\n const matches = modulesByScope(ctx.modules, node.scope);\n for (const m of matches) {\n for (const child of node.children) {\n visit(child, node.scope, m.path, triggers, modes);\n }\n }\n return;\n }\n if (node.kind === \"when\") {\n const nextTriggers = triggers.concat(node.trigger);\n for (const child of node.children) {\n visit(child, boundScope, boundModulePath, nextTriggers, modes);\n }\n return;\n }\n if (node.kind === \"mode\") {\n for (const child of node.children) {\n visit(child, boundScope, boundModulePath, triggers, node.modes);\n }\n return;\n }\n // Leaf.\n if (boundScope === undefined || boundModulePath === undefined) {\n throw new Error(`flatten: leaf '${describeLeaf(node)}' is not inside a scope() frame`);\n }\n if (node.kind === \"rename\") {\n out.push({\n leaf: node,\n scope: boundScope,\n modulePath: boundModulePath,\n resolvedPath: resolveRelative(boundModulePath, node.from),\n resolvedTo: resolveRelative(boundModulePath, node.to),\n triggers,\n modes,\n });\n return;\n }\n out.push({\n leaf: node,\n scope: boundScope,\n modulePath: boundModulePath,\n resolvedPath: resolveRelative(boundModulePath, leafPath(node)),\n triggers,\n modes,\n });\n }\n\n for (const node of structure.children) {\n visit(node, undefined, undefined, [], DEFAULT_MODES);\n }\n\n return out;\n}\n\nfunction leafPath(leaf: LeafItem): string {\n switch (leaf.kind) {\n case \"fixed\":\n case \"managed\":\n case \"scaffold\":\n case \"seed\":\n case \"remove\":\n return leaf.path;\n case \"rename\":\n return leaf.from;\n }\n}\n\nfunction describeLeaf(leaf: LeafItem): string {\n if (leaf.kind === \"rename\") return `rename ${leaf.from} -> ${leaf.to}`;\n return `${leaf.kind} ${leaf.path}`;\n}\n","// Minimal glob matcher for the structurer's file-existence triggers.\n//\n// Supports `**` (any number of path segments, including none), `*` (any\n// run of chars except `/`), and `?` (a single non-`/` char); every other\n// character is matched literally. No brace expansion / char classes — the\n// patterns we match are deliberately simple (e.g. `src/**/*.test.ts`).\n// Paths are matched whole (anchored at both ends).\n\nconst REGEXP_SPECIALS = /[.+^${}()|[\\]\\\\]/g;\n\n/** Compile a glob to an anchored RegExp. */\nexport function globToRegExp(glob: string): RegExp {\n let re = \"\";\n for (let i = 0; i < glob.length; i++) {\n const c = glob[i]!;\n if (c === \"*\") {\n if (glob[i + 1] === \"*\") {\n // `**`: any path segments. Absorb a following `/` so `**/x` also\n // matches `x` at depth 0 (zero segments).\n i++;\n if (glob[i + 1] === \"/\") {\n i++;\n re += \"(?:.*/)?\";\n } else {\n re += \".*\";\n }\n } else {\n re += \"[^/]*\";\n }\n } else if (c === \"?\") {\n re += \"[^/]\";\n } else {\n re += c.replace(REGEXP_SPECIALS, \"\\\\$&\");\n }\n }\n return new RegExp(`^${re}$`);\n}\n\n/** True if `path` matches `glob` (whole-path, anchored). */\nexport function matchesGlob(glob: string, path: string): boolean {\n return globToRegExp(glob).test(path);\n}\n","// `defineStructure` + the module-global builder set.\n//\n// Active context is a module-level mutable: `defineStructure` pushes a\n// fresh tree state, invokes the zero-arg lambda, pops, returns. Each\n// builder reads the active state and appends to the current children\n// list. Calling a builder outside `defineStructure` throws with a\n// clear message. Re-entering `defineStructure` from inside another\n// `defineStructure` lambda is rejected.\n\nimport type { Scope, RunContext, BlockVars, ContentForm } from \"./api\";\nimport type {\n ManagedBody,\n Structure,\n TriggerFn,\n TreeNode,\n ScopeFrame,\n WhenFrame,\n ModeFrame,\n RunMode,\n} from \"./ir\";\n\ntype TreeState = {\n root: TreeNode[];\n /** Stack of children-lists; top is where new nodes append. */\n stack: TreeNode[][];\n inScope: boolean;\n};\n\nlet activeTree: TreeState | undefined;\nlet activeRunContext: RunContext | undefined;\n\nfunction requireActiveTree(builder: string): TreeState {\n if (!activeTree) {\n throw new Error(\n `${builder}() called outside defineStructure(). ` +\n `Builders must run inside the lambda passed to defineStructure(...).`,\n );\n }\n return activeTree;\n}\n\nfunction appendNode(builder: string, node: TreeNode): void {\n const t = requireActiveTree(builder);\n t.stack[t.stack.length - 1]!.push(node);\n}\n\n/** Engine-internal: scope `blockVars()` lookups during a run. The body is\n * synchronous, so the module-global `activeRunContext` cannot be observed\n * by an interleaved run — a sync call stack runs to completion before any\n * other `run()` can start. The try/finally restores the previous context\n * (supporting the nested-run case the post-run recheck used to imply). */\nexport function withRunContext<T>(ctx: RunContext, fn: () => T): T {\n const prev = activeRunContext;\n activeRunContext = ctx;\n try {\n return fn();\n } finally {\n activeRunContext = prev;\n }\n}\n\n/** Engine-internal: content-rule builders that need `ctx.modules` look\n * up the active context through this accessor. Returns `undefined`\n * outside a run. */\nexport function tryGetActiveRunContext(): RunContext | undefined {\n return activeRunContext;\n}\n\n/** Get-or-die counterpart of `tryGetActiveRunContext`. Generators run\n * only inside `engine.run()`; an absent context is framework misuse, not\n * a valid state, so throw rather than emit degenerate (empty) output.\n * Mirrors `blockVars()`. */\nexport function getActiveRunContext(): RunContext {\n if (!activeRunContext) {\n throw new Error(\n \"getActiveRunContext() called outside engine.run(). \" +\n \"Generators only see the run context during a run.\",\n );\n }\n return activeRunContext;\n}\n\n/** The single entry point: build a {@link Structure} from `fn`, which calls\n * the scaffold-DSL builders (`scope`, `fixed`, `managed`, `seed`, …). Throws\n * if called nested, or if `fn` leaves an unclosed group frame. */\nexport function defineStructure(fn: () => void): Structure {\n if (activeTree) {\n throw new Error(\"defineStructure() cannot be called from inside another defineStructure().\");\n }\n const root: TreeNode[] = [];\n const state: TreeState = { root, stack: [root], inScope: false };\n activeTree = state;\n try {\n fn();\n if (state.stack.length !== 1) {\n throw new Error(\n `defineStructure: builder body left ${state.stack.length - 1} unclosed group frame(s)`,\n );\n }\n const structure: Structure = { children: root };\n // Validation: a path may not appear as both `seed` and any\n // engine-managed primitive (`fixed` / `managed` / `scaffold`) within\n // the same scope. The two contracts (write-once-and-ignore vs\n // rewrite-on-every-refresh) are mutually exclusive. Detect at\n // tree-build time.\n validateSeedDisjointness(structure);\n return structure;\n } finally {\n activeTree = undefined;\n }\n}\n\nfunction validateSeedDisjointness(structure: Structure): void {\n // (scope) → (path) → set of leaf kinds present at that path.\n const perScope = new Map<string, Map<string, Set<string>>>();\n\n function visit(node: TreeNode, scopeName: string): void {\n if (node.kind === \"scope\") {\n for (const c of node.children) visit(c, node.scope);\n return;\n }\n if (node.kind === \"when\" || node.kind === \"mode\") {\n for (const c of node.children) visit(c, scopeName);\n return;\n }\n if (node.kind === \"rename\") return; // rename works on paths; not a content leaf\n let scopeMap = perScope.get(scopeName);\n if (!scopeMap) {\n scopeMap = new Map();\n perScope.set(scopeName, scopeMap);\n }\n let kinds = scopeMap.get(node.path);\n if (!kinds) {\n kinds = new Set();\n scopeMap.set(node.path, kinds);\n }\n kinds.add(node.kind);\n }\n\n for (const n of structure.children) visit(n, \"(top-level)\");\n\n for (const [scopeName, paths] of perScope) {\n for (const [path, kinds] of paths) {\n if (\n kinds.has(\"seed\") &&\n (kinds.has(\"managed\") || kinds.has(\"fixed\") || kinds.has(\"scaffold\"))\n ) {\n const others = [...kinds]\n .filter((k) => k !== \"seed\")\n .sort()\n .join(\", \");\n throw new Error(\n `defineStructure validation: path '${path}' under scope '${scopeName}' ` +\n `is declared as both seed and ${others}. Seeds are block-author territory ` +\n `(written once at init, untouched thereafter); engine-managed primitives ` +\n `(fixed/managed/scaffold) rewrite on every refresh. The two contracts cannot ` +\n `coexist on the same path.`,\n );\n }\n }\n }\n}\n\n/** Open a scope (`root` / `block` / `model` / `ui` / `workflow` / `test` /\n * `software`); builders called inside `body` attach to it. Cannot nest. */\nexport function scope(name: Scope, body: () => void): void {\n const t = requireActiveTree(\"scope\");\n if (t.inScope) {\n throw new Error(\"scope() cannot nest. Already inside a scope.\");\n }\n const frame: ScopeFrame = { kind: \"scope\", scope: name, children: [] };\n t.stack[t.stack.length - 1]!.push(frame);\n t.stack.push(frame.children);\n t.inScope = true;\n try {\n body();\n } finally {\n t.stack.pop();\n t.inScope = false;\n }\n}\n\n/** Inner-mode `when` handler. Registered by `content-rules.ts` at\n * load time. Returns true if the call was dispatched (an inner active\n * state was present); false otherwise. Avoids a circular import. */\ntype InnerWhenHandler = (trigger: TriggerFn, body: () => void) => boolean;\nlet innerWhenHandler: InnerWhenHandler | undefined;\n\n/** Engine-internal: register the inner-mode `when` handler (set by\n * `content-rules.ts` at load time to avoid a circular import). */\nexport function registerInnerWhenHandler(h: InnerWhenHandler): void {\n innerWhenHandler = h;\n}\n\n/**\n * Conditionally run `body`, with an optional `elseBody`. One `when` symbol for\n * both layers — `dispatchWhen` picks the timing:\n * - inside `defineStructure(...)` → register a `WhenFrame`; its trigger fires\n * later, per module, at runner time.\n * - inside a `managed(...)` body → evaluate the trigger against the live block\n * now and run/skip synchronously.\n *\n * `else` is just the negated trigger dispatched the same way, so exactly one\n * branch applies (in either layer).\n */\nexport function when(trigger: TriggerFn, body: () => void, elseBody?: () => void): void {\n dispatchWhen(trigger, body);\n if (elseBody) dispatchWhen((tctx) => !trigger(tctx), elseBody);\n}\n\n/** Single-branch dispatch shared by both `when` branches. In a managed body the\n * handler runs `body` iff its trigger holds and returns whether a managed-body\n * context existed; no context — and not tree-build either — means `when()` was\n * called outside both layers, a misuse. */\nfunction dispatchWhen(trigger: TriggerFn, body: () => void): void {\n if (activeTree) {\n pushWhenFrame(trigger, body);\n return;\n }\n const handled = innerWhenHandler?.(trigger, body) ?? false;\n if (!handled) {\n throw new Error(\n \"when() called outside defineStructure() and outside any managed(...) body. \" +\n \"Place this call inside one of the two.\",\n );\n }\n}\n\nfunction pushWhenFrame(trigger: TriggerFn, body: () => void): void {\n const t = activeTree!;\n const frame: WhenFrame = { kind: \"when\", trigger, children: [] };\n t.stack[t.stack.length - 1]!.push(frame);\n t.stack.push(frame.children);\n try {\n body();\n } finally {\n t.stack.pop();\n }\n}\n\n/** Trigger factory: true when at least one file in the leaf's module\n * matches `glob` (module-relative — see `TriggerContext.filesMatch`). Use\n * to gate a rule on the presence of co-located files, e.g. add a vitest\n * `test` script only when `src/**\\/*.test.ts` exists. Pairs with `when`:\n * `when(whenFilesExist(\"src/**\\/*.test.ts\"), () => { ... })`. */\nexport function whenFilesExist(glob: string): TriggerFn {\n return (tctx) => tctx.filesMatch(glob);\n}\n\nfunction pushModeFrame(builder: string, modes: RunMode[], body: () => void): void {\n const t = requireActiveTree(builder);\n const frame: ModeFrame = { kind: \"mode\", modes, children: [] };\n t.stack[t.stack.length - 1]!.push(frame);\n t.stack.push(frame.children);\n try {\n body();\n } finally {\n t.stack.pop();\n }\n}\n\n/** Leaves inside fire ONLY under `--update-deps-only` (mode\n * `\"updateDeps\"`); they are skipped on default refresh/check and init. */\nexport function onUpdateDeps(body: () => void): void {\n pushModeFrame(\"onUpdateDeps\", [\"updateDeps\"], body);\n}\n\n/** Leaves inside fire on `init` AND `--update-deps-only`, but NOT on\n * default refresh/check. The frame for rules that resolve/write current\n * versions: both init and update-deps mean \"fetch and write latest\",\n * while a plain refresh leaves them as the author/lockfile has them. */\nexport function onInitOrUpdate(body: () => void): void {\n pushModeFrame(\"onInitOrUpdate\", [\"init\", \"updateDeps\"], body);\n}\n\n/** Engine-OWNED file: (re)written verbatim from `content` on every refresh —\n * author edits are overwritten. */\nexport function fixed(path: string, content: ContentForm): void {\n appendNode(\"fixed\", { kind: \"fixed\", path, content });\n}\n\n/** Engine-RECONCILED file: parsed from disk (or `initial` when absent),\n * mutated by `body` (the JSON/YAML/lines builders), then re-serialised.\n * Content the body does not touch is preserved. */\nexport function managed(path: string, initial: ContentForm, body: ManagedBody): void {\n appendNode(\"managed\", { kind: \"managed\", path, initial, body });\n}\n\n/** Write-once file: created from `initial` if absent (on init AND refresh),\n * never overwritten once present. For files the author subsequently owns. */\nexport function scaffold(path: string, initial: ContentForm): void {\n appendNode(\"scaffold\", { kind: \"scaffold\", path, initial });\n}\n\n/** Author-owned starter file: written from `initial` only on `init`, and only\n * if absent; `refresh` / `check` never touch it. */\nexport function seed(path: string, initial: ContentForm): void {\n appendNode(\"seed\", { kind: \"seed\", path, initial });\n}\n\n/** Delete `path` if present, on every refresh. */\nexport function remove(path: string): void {\n appendNode(\"remove\", { kind: \"remove\", path });\n}\n\n/** Rename file `from` → `to` on refresh (migrating a renamed scaffold file). */\nexport function rename(from: string, to: string): void {\n appendNode(\"rename\", { kind: \"rename\", from, to });\n}\n\n/** Content form: a UTF-8 static template read from the structurer's static\n * templates. Use inside `fixed` / `managed` / `scaffold` / `seed`. */\nexport function file(path: string): ContentForm {\n return { kind: \"file\", path };\n}\n\n/** A binary static asset (e.g. a logo) read verbatim from `<root>/static/`.\n * Unlike `file()`, the bytes are never decoded to a string — use for\n * images / archives. Only valid inside `seed()` / `scaffold()`. */\nexport function binaryFile(path: string): ContentForm {\n return { kind: \"binary\", path };\n}\n\n/** Content form: an inline literal string. */\nexport function text(value: string): ContentForm {\n return { kind: \"text\", value };\n}\n\n/** Content form: a text template (the structurer's `text/` templates) with\n * `${var}` placeholders substituted from `vars`. When `vars` is a function it\n * receives the active {@link RunContext} at resolve time. */\nexport function tpl(\n path: string,\n vars: Record<string, string> | ((ctx: RunContext) => Record<string, string>),\n): ContentForm {\n return { kind: \"tpl\", path, vars };\n}\n\n/** Content form: content computed at run time from the active\n * {@link RunContext}. The return value is serialised as JSON / YAML by the\n * target file's extension, or used verbatim if it is already a string. */\nexport function generate(fn: (ctx: RunContext) => unknown): ContentForm {\n return { kind: \"generate\", fn };\n}\n\n/** The active run's {@link BlockVars} (block name parts + software platform).\n * Valid only during a run (inside a generator or managed body); throws\n * otherwise. */\nexport function blockVars(): BlockVars {\n if (!activeRunContext) {\n throw new Error(\n \"blockVars() called outside engine.run(). \" +\n \"Generators and managed bodies only see BlockVars during a run.\",\n );\n }\n return activeRunContext.blockVars;\n}\n","// JSON parser + serialiser + jsonPath helpers + top-level key reorder.\n//\n// `parseJson`/`stringifyJson` are the canonical round-trip primitives the\n// managed pass uses. The dot-notation helpers (`getAtPath`, `setAtPath`,\n// `hasAtPath`, `deleteAtPath`) back the content-rule builders. `reorderTopLevel`\n// implements the \"known keys in declared order, unknown keys stay adjacent to\n// preceding known key\" projection.\n\nexport type JsonValue = string | number | boolean | null | JsonValue[] | { [k: string]: JsonValue };\n\nexport type JsonObject = { [k: string]: unknown };\n\n/** Parse JSON; throws on invalid input. */\nexport function parseJson(raw: string): unknown {\n return JSON.parse(raw);\n}\n\n// oxfmt formats JSON two ways, keyed on filename:\n// - package.json: every array/object fully expanded, one element per line,\n// regardless of width (what `JSON.stringify(…, 2)` already produces).\n// - any other .json (e.g. tsconfig.json): oxfmt's generic shape —\n// * objects: always expanded, one property per line (oxfmt preserves\n// the brace newline, so the expanded form is a fixpoint);\n// * arrays: collapsed onto one line when that line — its indent, the\n// `\"key\": ` prefix, the flat array, and a trailing comma if a sibling\n// follows — fits `PRINT_WIDTH` (oxfmt's default 100), else broken one\n// element per line.\n// This is exactly the form `oxfmt` itself produces, verified against\n// oxfmt 0.35 at the array boundary (≤100 collapses, 101 breaks; a\n// trailing comma counts) and across all in-mono blocks. The single-\n// element `include` array was the regression: `JSON.stringify` expanded\n// it while oxfmt collapses it.\n// `stringifyJson` defaults to the expanded form; callers serialising a\n// generic .json pass `{ collapse: true }` so the output is oxfmt-clean by\n// construction (no prior `pnpm fmt` needed for `check` — the same\n// emit-clean-by-design contract as the canonical key/dependency ordering).\nconst PRINT_WIDTH = 100;\nconst INDENT = 2;\n\n/** One-line rendering of an array, matching oxfmt's flat spacing: `[a, b]`\n * (no inner padding), nested objects inline as `{ \"k\": v }`, empty `[]`.\n * Only arrays collapse, so this is the array-fits primitive. */\nfunction flatArray(value: unknown[]): string {\n if (value.length === 0) return \"[]\";\n return \"[\" + value.map(flatValue).join(\", \") + \"]\";\n}\n\n/** One-line rendering of any value (used inside a collapsed array, where\n * contained objects render inline). */\nfunction flatValue(value: unknown): string {\n if (Array.isArray(value)) return flatArray(value);\n if (isObject(value)) {\n const entries = Object.entries(value);\n if (entries.length === 0) return \"{}\";\n return (\n \"{ \" + entries.map(([k, v]) => `${JSON.stringify(k)}: ${flatValue(v)}`).join(\", \") + \" }\"\n );\n }\n return JSON.stringify(value);\n}\n\n/** Print `value` starting at `column`. Objects always break (one property per\n * line); arrays collapse when their flat line — `column` + the flat array +\n * `reserved` (1 for a trailing comma when a sibling follows) — fits\n * `PRINT_WIDTH`, else break. `indent` is the leading-space width of the line\n * the container opens on. */\nfunction printValue(value: unknown, indent: number, column: number, reserved: number): string {\n const inner = indent + INDENT;\n const pad = \" \".repeat(inner);\n if (Array.isArray(value)) {\n const flat = flatArray(value);\n if (column + flat.length + reserved <= PRINT_WIDTH) return flat;\n const last = value.length - 1;\n const lines = value.map((item, i) => pad + printValue(item, inner, inner, i === last ? 0 : 1));\n return \"[\\n\" + lines.join(\",\\n\") + \"\\n\" + \" \".repeat(indent) + \"]\";\n }\n if (isObject(value)) {\n const entries = Object.entries(value);\n if (entries.length === 0) return \"{}\";\n const last = entries.length - 1;\n const lines = entries.map(([k, v], i) => {\n const prefix = `${pad}${JSON.stringify(k)}: `;\n return prefix + printValue(v, inner, prefix.length, i === last ? 0 : 1);\n });\n return \"{\\n\" + lines.join(\",\\n\") + \"\\n\" + \" \".repeat(indent) + \"}\";\n }\n return JSON.stringify(value);\n}\n\n/** Canonical serialiser: 2-space indent, trailing newline.\n * Default — every container expanded (the package.json shape, byte-identical\n * to `JSON.stringify(…, 2)`).\n * `{ collapse: true }` — oxfmt's generic-.json shape: containers that fit\n * `PRINT_WIDTH` collapse onto one line. Used for tsconfig.json and any other\n * non-package.json the engine emits, so `oxfmt --check` passes without a\n * prior format pass. */\nexport function stringifyJson(value: unknown, opts?: { collapse?: boolean }): string {\n if (!opts?.collapse) return JSON.stringify(value, null, 2) + \"\\n\";\n // Normalise through a round-trip so non-JSON inputs (undefined values,\n // functions) are dropped exactly as `JSON.stringify` would.\n const normalized = JSON.parse(JSON.stringify(value ?? null));\n return printValue(normalized, 0, 0, 0) + \"\\n\";\n}\n\nfunction splitPath(jsonPath: string): string[] {\n if (jsonPath === \"\" || jsonPath === undefined) return [];\n return jsonPath.split(\".\");\n}\n\nfunction isObject(v: unknown): v is JsonObject {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\n/** Get the value at `jsonPath`. Returns `undefined` if any segment is\n * missing or not an object. */\nexport function getAtPath(obj: JsonObject, jsonPath: string): unknown {\n const parts = splitPath(jsonPath);\n let cur: unknown = obj;\n for (const p of parts) {\n if (!isObject(cur)) return undefined;\n cur = cur[p];\n }\n return cur;\n}\n\n/** True if `jsonPath` resolves to a defined value (including `null`). */\nexport function hasAtPath(obj: JsonObject, jsonPath: string): boolean {\n const parts = splitPath(jsonPath);\n if (parts.length === 0) return true;\n let cur: unknown = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n if (!isObject(cur)) return false;\n cur = cur[parts[i]!];\n }\n if (!isObject(cur)) return false;\n return parts[parts.length - 1]! in cur;\n}\n\n/** Set `value` at `jsonPath`. Auto-creates intermediate objects. Throws\n * if a non-object value is on the path (would be silently overwritten\n * otherwise — caller bug). */\nexport function setAtPath(obj: JsonObject, jsonPath: string, value: unknown): void {\n const parts = splitPath(jsonPath);\n if (parts.length === 0) {\n throw new Error(\"setAtPath: jsonPath must be non-empty\");\n }\n let cur: JsonObject = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n const k = parts[i]!;\n const next = cur[k];\n if (next === undefined) {\n const fresh: JsonObject = {};\n cur[k] = fresh;\n cur = fresh;\n } else if (isObject(next)) {\n cur = next;\n } else {\n throw new Error(\n `setAtPath: cannot descend into non-object at '${parts.slice(0, i + 1).join(\".\")}'`,\n );\n }\n }\n cur[parts[parts.length - 1]!] = value;\n}\n\n/** Delete the value at `jsonPath`. No-op if any segment is missing. */\nexport function deleteAtPath(obj: JsonObject, jsonPath: string): void {\n const parts = splitPath(jsonPath);\n if (parts.length === 0) {\n throw new Error(\"deleteAtPath: jsonPath must be non-empty\");\n }\n let cur: unknown = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n if (!isObject(cur)) return;\n cur = cur[parts[i]!];\n }\n if (!isObject(cur)) return;\n delete cur[parts[parts.length - 1]!];\n}\n\n/**\n * Reorder top-level keys of `obj`:\n * - Known keys (those listed in `order`) appear in declared order.\n * - Unknown keys (not in `order`) stay adjacent to the preceding known\n * key they followed in the source. Unknown keys appearing before any\n * known key go first, in source order.\n */\nexport function reorderTopLevel(obj: JsonObject, order: readonly string[]): JsonObject {\n const known = new Set(order);\n const sourceKeys = Object.keys(obj);\n\n const adjacents = new Map<string, string[]>();\n adjacents.set(\"\", []);\n let anchor = \"\";\n for (const k of sourceKeys) {\n if (known.has(k)) {\n anchor = k;\n adjacents.set(anchor, []);\n } else {\n adjacents.get(anchor)!.push(k);\n }\n }\n\n const out: JsonObject = {};\n for (const k of adjacents.get(\"\")!) out[k] = obj[k];\n for (const k of order) {\n if (!(k in obj)) continue;\n out[k] = obj[k];\n for (const u of adjacents.get(k) ?? []) out[u] = obj[u];\n }\n return out;\n}\n","// .gitignore-style line list parser/serialiser.\n//\n// `parseLines` keeps the file verbatim as an array of lines (one per\n// \"\\n\"). `serializeLines` joins them with \"\\n\" and guarantees a trailing\n// newline. `normaliseLine` strips comments and surrounding whitespace —\n// used by the `ensureGitignoreEntries` family to compare an existing\n// line to a required entry without being fooled by inline `#` comments\n// or extra indentation.\n\nexport function parseLines(raw: string): string[] {\n // Drop the synthetic empty entry caused by a trailing newline so a\n // serialise-then-parse round-trip is stable.\n const lines = raw.split(\"\\n\");\n if (lines.length > 0 && lines[lines.length - 1] === \"\") lines.pop();\n return lines;\n}\n\nexport function serializeLines(lines: readonly string[]): string {\n return lines.join(\"\\n\") + \"\\n\";\n}\n\n/** Strip leading/trailing whitespace and trailing inline `# ...` comments.\n * Returns empty string for blank / comment-only lines. */\nexport function normaliseLine(line: string): string {\n const noComment = line.replace(/(^|\\s)#.*$/, \"$1\");\n return noComment.trim();\n}\n\n/** True if `line` (after normalisation) equals `entry` (after trim). */\nexport function lineEqualsEntry(line: string, entry: string): boolean {\n const n = normaliseLine(line);\n if (n === \"\") return false;\n return n === entry.trim();\n}\n\n/** True if any line in `lines` normalises to `entry`. */\nexport function containsEntry(lines: readonly string[], entry: string): boolean {\n for (const line of lines) {\n if (lineEqualsEntry(line, entry)) return true;\n }\n return false;\n}\n","// Content-rules DSL — builders that mutate the parsed representation\n// of a `managed(path, initial, body)` file.\n//\n// Three active-state kinds correspond to three file flavours:\n// - JSON object (package.json) → withManagedBody(obj, body)\n// - YAML Document (pnpm-workspace.yaml) → withManagedYaml(doc, body)\n// - line list (.gitignore) → withManagedLines(lines, body)\n//\n// Each builder verifies it is invoked under the matching active state\n// and throws otherwise. The full inventory: JSON\n// ensure*/remove*/require*/prune/enforce*/transform; YAML catalog\n// management + workspace module paths; gitignore line management.\n\nimport { registerInnerWhenHandler, tryGetActiveRunContext } from \"./builders\";\nimport type { RunContext, Scope } from \"./api\";\nimport type { ManagedBody, TriggerContext, TriggerFn } from \"./ir\";\nimport {\n deleteAtPath,\n getAtPath,\n hasAtPath,\n reorderTopLevel,\n setAtPath,\n type JsonObject,\n} from \"./parsers/json\";\nimport { containsEntry, normaliseLine } from \"./parsers/lines\";\nimport type { YamlDocument } from \"./parsers/yaml\";\n\nexport type { JsonObject };\n\n/** Allowed dep version strings. Specific versions live in the catalog.\n * `\"sdk:\"` is an authoring abstraction, not an on-disk value: the engine\n * resolves it at write time (`workspace:*` when `ctx.isSdkInternal`, else\n * `\"catalog:\"`) and the resolved literal is what serializes. Use it for\n * every dep that is a member of the platforma monorepo's pnpm workspace\n * (the `@platforma-sdk/*` packages + `@milaboratories/ts-builder` /\n * `ts-configs`). */\nexport type DepVersion = \"catalog:\" | \"sdk:\" | `workspace:${string}` | \"*\";\n\n/** Resolve the `\"sdk:\"` sentinel to its on-disk literal. All other\n * `DepVersion` forms pass through unchanged — `\"sdk:\"` never serializes. */\nexport function resolveDepVersion(\n version: DepVersion,\n isSdkInternal: boolean,\n): Exclude<DepVersion, \"sdk:\"> {\n if (version === \"sdk:\") return isSdkInternal ? \"workspace:*\" : \"catalog:\";\n return version;\n}\n\nconst DEP_SECTION_KEYS = [\n \"dependencies\",\n \"devDependencies\",\n \"peerDependencies\",\n \"optionalDependencies\",\n] as const;\n\n/** Resolve any `\"sdk:\"` sentinels in the dep sections of a generated\n * package.json object, in place. Mirrors `resolveDepVersion` for the\n * generator (`initial` content) path — the runner calls this on every\n * `generate()`-produced `.json` value so the sentinel never reaches disk\n * via a generator. */\nexport function resolveSdkSentinelsInJson(value: unknown, isSdkInternal: boolean): void {\n if (!isObject(value)) return;\n for (const section of DEP_SECTION_KEYS) {\n const sec = value[section];\n if (!isObject(sec)) continue;\n for (const k of Object.keys(sec)) {\n if (sec[k] === \"sdk:\") sec[k] = isSdkInternal ? \"workspace:*\" : \"catalog:\";\n }\n }\n}\n\ntype JsonState = {\n kind: \"json\";\n obj: JsonObject;\n ctx?: RunContext;\n triggerContext?: TriggerContext;\n};\n\ntype YamlState = {\n kind: \"yaml\";\n doc: YamlDocument;\n ctx?: RunContext;\n triggerContext?: TriggerContext;\n /** Synchronous accessor for prefetched npm latest versions. */\n getLatestVersion?: (packageName: string) => string | undefined;\n /** Synchronous accessor for prefetched derived catalog pins\n * (`catalogEntry → exact version`); see `pinCatalogToDependencyOf`. */\n getDerivedDependencyPin?: (catalogEntry: string) => string | undefined;\n};\n\ntype LinesState = {\n kind: \"lines\";\n lines: string[];\n ctx?: RunContext;\n triggerContext?: TriggerContext;\n};\n\ntype ActiveState = JsonState | YamlState | LinesState;\n\nlet active: ActiveState | undefined;\n\nfunction requireActive(builder: string): ActiveState {\n if (!active) {\n throw new Error(\n `${builder}() only valid inside a managed(...) body. ` +\n `Move this call inside managed(path, initial, () => {...}).`,\n );\n }\n return active;\n}\n\nfunction requireJson(builder: string): JsonState {\n const a = requireActive(builder);\n if (a.kind !== \"json\") {\n throw new Error(`${builder}() requires a JSON-managed body; got '${a.kind}'.`);\n }\n return a;\n}\n\nfunction requireYaml(builder: string): YamlState {\n const a = requireActive(builder);\n if (a.kind !== \"yaml\") {\n throw new Error(`${builder}() requires a YAML-managed body; got '${a.kind}'.`);\n }\n return a;\n}\n\nfunction requireLines(builder: string): LinesState {\n const a = requireActive(builder);\n if (a.kind !== \"lines\") {\n throw new Error(`${builder}() requires a lines-managed body; got '${a.kind}'.`);\n }\n return a;\n}\n\nfunction ctxOrThrow(state: ActiveState, builder: string): RunContext {\n const c = state.ctx ?? tryGetActiveRunContext();\n if (!c) {\n throw new Error(\n `${builder}() needs a RunContext but none is active. ` +\n `Pass { ctx } via the with-managed-* helper or run inside engine.run(...).`,\n );\n }\n return c;\n}\n\nfunction isObject(v: unknown): v is JsonObject {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\n// --- Active-context wrappers (used by the runner + Layer-1 helpers) ---\n\nexport type WithManagedOpts = {\n ctx?: RunContext;\n /** Trigger context for `when(...)` calls inside the body. The runner\n * builds this from the post-structural-pass FS snapshot + run ctx.\n * Without it, `when(...)` inside the body throws. */\n triggerContext?: TriggerContext;\n};\n\n/** Engine-internal: run `body` with `obj` as the active JSON state so the\n * JSON builders mutate it; returns the mutated object. Exported for tests —\n * the runner calls this for managed `.json` files. */\nexport function withManagedBody(\n obj: JsonObject,\n body: ManagedBody,\n opts: WithManagedOpts = {},\n): JsonObject {\n if (active) throw new Error(\"Nested managed(...) body — engine bug.\");\n active = { kind: \"json\", obj, ctx: opts.ctx, triggerContext: opts.triggerContext };\n try {\n body((opts.ctx ?? opts.triggerContext?.ctx) as RunContext);\n return obj;\n } finally {\n active = undefined;\n }\n}\n\nexport type WithManagedYamlOpts = WithManagedOpts & {\n /** Sync accessor for prefetched latest versions. Required for\n * `ensureCatalogLatest` to take effect. */\n getLatestVersion?: (packageName: string) => string | undefined;\n /** Sync accessor for prefetched derived catalog pins. Required for\n * `pinCatalogToDependencyOf` to take effect. */\n getDerivedDependencyPin?: (catalogEntry: string) => string | undefined;\n};\n\n/** Engine-internal: run `body` with `doc` as the active YAML state (for\n * `pnpm-workspace.yaml`); returns the mutated document. Exported for tests. */\nexport function withManagedYaml(\n doc: YamlDocument,\n body: ManagedBody,\n opts: WithManagedYamlOpts = {},\n): YamlDocument {\n if (active) throw new Error(\"Nested managed(...) body — engine bug.\");\n active = {\n kind: \"yaml\",\n doc,\n ctx: opts.ctx,\n triggerContext: opts.triggerContext,\n getLatestVersion: opts.getLatestVersion,\n getDerivedDependencyPin: opts.getDerivedDependencyPin,\n };\n try {\n body((opts.ctx ?? opts.triggerContext?.ctx) as RunContext);\n return doc;\n } finally {\n active = undefined;\n }\n}\n\n/** Engine-internal: run `body` with `lines` as the active line-based state\n * (for `.gitignore`); returns the mutated lines. Exported for tests. */\nexport function withManagedLines(\n lines: string[],\n body: ManagedBody,\n opts: WithManagedOpts = {},\n): string[] {\n if (active) throw new Error(\"Nested managed(...) body — engine bug.\");\n active = {\n kind: \"lines\",\n lines,\n ctx: opts.ctx,\n triggerContext: opts.triggerContext,\n };\n try {\n body((opts.ctx ?? opts.triggerContext?.ctx) as RunContext);\n return lines;\n } finally {\n active = undefined;\n }\n}\n\n// --- Inner-when handler registration ---\n//\n// `when(...)` is exported from `builders.ts`. When the active tree is\n// absent (we are inside a managed body, not inside `defineStructure`),\n// it delegates here. The handler returns true iff there is an inner\n// active state to dispatch against; the caller in `builders.ts` then\n// treats the call as handled. Outer/inner dispatch lives in one\n// exported `when` symbol — no separate inner-when builder.\n\nregisterInnerWhenHandler((trigger: TriggerFn, body: () => void): boolean => {\n if (!active) return false;\n const tctx = active.triggerContext;\n if (!tctx) {\n throw new Error(\n \"when() inside a managed(...) body requires a triggerContext. \" +\n \"The runner supplies it via the `triggerContext` opt to with-managed-*; \" +\n \"ensure your test/test helper passes one.\",\n );\n }\n if (trigger(tctx)) body();\n return true;\n});\n\n// ============================================================\n// JSON builders — `package.json` (and other JSON managed files)\n// ============================================================\n\n/** Set the value at `jsonPath` in the active managed JSON object. */\nexport function ensureField(jsonPath: string, value: unknown): void {\n setAtPath(requireJson(\"ensureField\").obj, jsonPath, value);\n}\n\n/** Remove the field at `jsonPath`. With `predicate`, only removes when\n * the predicate returns true against the current value. */\nexport function removeField(\n jsonPath: string,\n predicate?: (currentValue: unknown) => boolean,\n): void {\n const obj = requireJson(\"removeField\").obj;\n if (!hasAtPath(obj, jsonPath)) return;\n if (predicate) {\n const current = getAtPath(obj, jsonPath);\n if (!predicate(current)) return;\n }\n deleteAtPath(obj, jsonPath);\n}\n\n/** Assert a field exists; throw if absent. No mutation. */\nexport function requireField(jsonPath: string, message?: string): void {\n const obj = requireJson(\"requireField\").obj;\n if (!hasAtPath(obj, jsonPath)) {\n throw new Error(message ?? `requireField: missing field '${jsonPath}'`);\n }\n}\n\n/** Merge `entries` into the object at `jsonPath`. Auto-creates the\n * object if missing. Existing other entries preserved. */\nexport function ensureFieldEntries(jsonPath: string, entries: Record<string, unknown>): void {\n const obj = requireJson(\"ensureFieldEntries\").obj;\n const current = hasAtPath(obj, jsonPath) ? getAtPath(obj, jsonPath) : undefined;\n const base: JsonObject = isObject(current) ? current : {};\n for (const [k, v] of Object.entries(entries)) base[k] = v;\n if (!isObject(current)) setAtPath(obj, jsonPath, base);\n}\n\n/** Set `scripts.<name>` to `command`. */\nexport function ensureScript(name: string, command: string): void {\n ensureField(`scripts.${name}`, command);\n}\n\n/** Remove `scripts.<name>` if present. */\nexport function removeScript(name: string): void {\n removeField(`scripts.${name}`);\n}\n\n// --- Dependency builders ---\n\nconst DEP_SECTIONS = [\n \"dependencies\",\n \"devDependencies\",\n \"peerDependencies\",\n \"optionalDependencies\",\n] as const;\ntype DepSection = (typeof DEP_SECTIONS)[number];\n\nfunction ensureInSection(\n builder: string,\n name: string,\n version: DepVersion,\n section: DepSection,\n): void {\n const state = requireJson(builder);\n const obj = state.obj;\n // Resolve the `sdk:` sentinel against the run mode before writing — it\n // must never reach disk.\n const resolved =\n version === \"sdk:\"\n ? resolveDepVersion(version, ctxOrThrow(state, builder).isSdkInternal)\n : version;\n // Single-section invariant: remove from any other section first.\n for (const s of DEP_SECTIONS) {\n if (s === section) continue;\n const sec = obj[s];\n if (isObject(sec) && name in sec) delete sec[name];\n }\n const existing = obj[section];\n const target: JsonObject = isObject(existing) ? existing : {};\n target[name] = resolved;\n if (!isObject(existing)) obj[section] = target;\n}\n\n/** Pin `name` to `version` in `dependencies`. Enforces the single-section\n * invariant — `name` may live in only one dependency section, so it is\n * removed from the others first. A `sdk:` sentinel version is resolved\n * against the run's `--sdk-internal` flag before it reaches disk. */\nexport function ensureDep(name: string, version: DepVersion): void {\n ensureInSection(\"ensureDep\", name, version, \"dependencies\");\n}\n\n/** Pin `name` to `version` in `devDependencies` (see {@link ensureDep} for the\n * single-section + `sdk:` semantics). */\nexport function ensureDevDep(name: string, version: DepVersion): void {\n ensureInSection(\"ensureDevDep\", name, version, \"devDependencies\");\n}\n\n/** Pin `name` to `version` in `peerDependencies` (see {@link ensureDep}). */\nexport function ensurePeerDep(name: string, version: DepVersion): void {\n ensureInSection(\"ensurePeerDep\", name, version, \"peerDependencies\");\n}\n\n/** Pin `name` to `version` in `optionalDependencies` (see {@link ensureDep}). */\nexport function ensureOptionalDep(name: string, version: DepVersion): void {\n ensureInSection(\"ensureOptionalDep\", name, version, \"optionalDependencies\");\n}\n\n/** Remove `name` from every dependency section. */\nexport function removeDep(name: string): void {\n const obj = requireJson(\"removeDep\").obj;\n for (const s of DEP_SECTIONS) {\n const sec = obj[s];\n if (isObject(sec) && name in sec) delete sec[name];\n }\n}\n\n/** Bulk {@link ensureDep} for each `name → version` entry. */\nexport function ensureDeps(entries: Record<string, DepVersion>): void {\n for (const [n, v] of Object.entries(entries)) ensureDep(n, v);\n}\n\n/** Bulk {@link ensureDevDep} for each `name → version` entry. */\nexport function ensureDevDeps(entries: Record<string, DepVersion>): void {\n for (const [n, v] of Object.entries(entries)) ensureDevDep(n, v);\n}\n\n/** Bulk {@link ensurePeerDep} for each `name → version` entry. */\nexport function ensurePeerDeps(entries: Record<string, DepVersion>): void {\n for (const [n, v] of Object.entries(entries)) ensurePeerDep(n, v);\n}\n\n/** Bulk {@link ensureOptionalDep} for each `name → version` entry. */\nexport function ensureOptionalDeps(entries: Record<string, DepVersion>): void {\n for (const [n, v] of Object.entries(entries)) ensureOptionalDep(n, v);\n}\n\nfunction ensureWorkspaceScopeIn(builder: string, scope: Scope, section: DepSection): void {\n const state = requireJson(builder);\n const ctx = ctxOrThrow(state, builder);\n for (const m of ctx.modules) {\n if (m.scope === scope) {\n ensureInSection(builder, m.name, \"workspace:*\", section);\n }\n }\n}\n\n/** Add every discovered module of `scope` as a `workspace:*` entry in\n * `dependencies` — wires a block's intra-workspace links (e.g. the test\n * scope depending on the other scopes). Single-section invariant per\n * {@link ensureDep}. */\nexport function ensureWorkspaceScopeDeps(scope: Scope): void {\n ensureWorkspaceScopeIn(\"ensureWorkspaceScopeDeps\", scope, \"dependencies\");\n}\n\n/** Like {@link ensureWorkspaceScopeDeps}, into `devDependencies`. */\nexport function ensureWorkspaceScopeDevDeps(scope: Scope): void {\n ensureWorkspaceScopeIn(\"ensureWorkspaceScopeDevDeps\", scope, \"devDependencies\");\n}\n\n/** Like {@link ensureWorkspaceScopeDeps}, into `peerDependencies`. */\nexport function ensureWorkspaceScopePeerDeps(scope: Scope): void {\n ensureWorkspaceScopeIn(\"ensureWorkspaceScopePeerDeps\", scope, \"peerDependencies\");\n}\n\n// --- Prune ---\n\n/** Delete every top-level key for which `predicate(key, value)` is true. */\nexport function pruneKeysMatching(predicate: (key: string, value: unknown) => boolean): void {\n const obj = requireJson(\"pruneKeysMatching\").obj;\n for (const k of Object.keys(obj)) {\n if (predicate(k, obj[k])) delete obj[k];\n }\n}\n\n/** Delete every key of the object at `jsonPath` for which\n * `predicate(key, value)` is true. No-op if the path is not an object. */\nexport function pruneKeysMatchingAt(\n jsonPath: string,\n predicate: (key: string, value: unknown) => boolean,\n): void {\n const obj = requireJson(\"pruneKeysMatchingAt\").obj;\n const sub = getAtPath(obj, jsonPath);\n if (!isObject(sub)) return;\n for (const k of Object.keys(sub)) {\n if (predicate(k, sub[k])) delete sub[k];\n }\n}\n\n// --- Field order ---\n\nfunction applyOrderInPlace(o: JsonObject, order: readonly string[]): void {\n const reordered = reorderTopLevel(o, order);\n for (const k of Object.keys(o)) delete o[k];\n for (const k of Object.keys(reordered)) o[k] = reordered[k];\n}\n\n/** Reorder top-level keys to `orderedKeys`; keys not listed keep their\n * position relative to the preceding listed key. Typically the LAST call in\n * a managed body, projecting the canonical field order. */\nexport function enforceFieldOrder(orderedKeys: string[]): void {\n applyOrderInPlace(requireJson(\"enforceFieldOrder\").obj, orderedKeys);\n}\n\n/** Like {@link enforceFieldOrder}, applied to the object at `jsonPath`. No-op\n * if the path is not an object. */\nexport function enforceFieldOrderAt(jsonPath: string, orderedKeys: string[]): void {\n const obj = requireJson(\"enforceFieldOrderAt\").obj;\n const sub = getAtPath(obj, jsonPath);\n if (!isObject(sub)) return;\n applyOrderInPlace(sub, orderedKeys);\n}\n\nfunction sortAlphabeticalInPlace(o: JsonObject, recursive: boolean): void {\n const sorted = Object.keys(o).sort();\n const buf: JsonObject = {};\n for (const k of sorted) buf[k] = o[k];\n for (const k of Object.keys(o)) delete o[k];\n for (const k of sorted) {\n o[k] = buf[k];\n if (recursive && isObject(o[k])) sortAlphabeticalInPlace(o[k] as JsonObject, true);\n }\n}\n\n/** Sort keys alphabetically. Called with no args it is a deliberate no-op\n * (guards against accidental whole-file sorts); pass a `jsonPath` to sort one\n * object, or `{ recursive: true }` to sort the whole tree. Matches oxfmt's\n * dependency-section ordering. */\nexport function enforceAlphabeticalOrder(\n jsonPath: string = \"\",\n opts: { recursive?: boolean } = {},\n): void {\n const recursive = opts.recursive ?? false;\n // Default jsonPath=\"\" with recursive:false is a no-op (prevents accidents).\n if (jsonPath === \"\" && !recursive) return;\n const obj = requireJson(\"enforceAlphabeticalOrder\").obj;\n if (jsonPath === \"\") {\n sortAlphabeticalInPlace(obj, true);\n return;\n }\n const sub = getAtPath(obj, jsonPath);\n if (!isObject(sub)) return;\n sortAlphabeticalInPlace(sub, recursive);\n}\n\n// --- Generic transform escape hatch ---\n\n/** Escape hatch: replace the value at `jsonPath` with `transform(current)`,\n * for shapes the typed builders above do not cover. */\nexport function transformAt<T = unknown>(jsonPath: string, transform: (current: T) => T): void {\n const obj = requireJson(\"transformAt\").obj;\n const current = getAtPath(obj, jsonPath) as T;\n const next = transform(current);\n setAtPath(obj, jsonPath, next);\n}\n\n// ============================================================\n// YAML builders — `pnpm-workspace.yaml`\n// ============================================================\n\n/** Set the workspace `packages:` list to all discovered NON-root module\n * paths (sorted lex). The block root (\"\") is discovered implicitly\n * and is NEVER written to `packages:` — listing \".\" there breaks turbo's\n * task graph. Equality-guarded — skips the rewrite when the existing\n * list already matches, so a YAML round-trip on an already-canonical\n * file produces zero churn. */\nexport function ensureWorkspaceModulePaths(): void {\n const state = requireYaml(\"ensureWorkspaceModulePaths\");\n const ctx = ctxOrThrow(state, \"ensureWorkspaceModulePaths\");\n const paths = ctx.modules\n .filter((m) => m.path !== \"\")\n .map((m) => m.path)\n .sort();\n const json = state.doc.toJSON() as { packages?: unknown } | null;\n const cur = json?.packages;\n if (Array.isArray(cur) && cur.length === paths.length && cur.every((v, i) => v === paths[i])) {\n return;\n }\n state.doc.setIn([\"packages\"], paths);\n}\n\nfunction readCatalogString(state: YamlState, name: string): string | undefined {\n const node = state.doc.getIn([\"catalog\", name]);\n return typeof node === \"string\" ? node : undefined;\n}\n\n/** Add `catalog.<name>` at `version` ONLY if the key is absent. An entry\n * the block already carries is left untouched — no overwrite, no\n * downgrade. This is the seeding primitive for curated fixed versions\n * (`INFRA_CATALOG_FLOOR`, the python runenv pin): on\n * `refresh --update-deps-only` a missing standard catalog key is added,\n * while a key the block already pins keeps its own version. To force a\n * specific version regardless of what is present, use `pinCatalogTo`. */\nexport function ensureCatalogVersion(name: string, version: string): void {\n const state = requireYaml(\"ensureCatalogVersion\");\n if (readCatalogString(state, name) !== undefined) return;\n state.doc.setIn([\"catalog\", name], version);\n}\n\n/** Set `catalog.<name>` to `version` EXACTLY — creates the entry if\n * missing, overwrites it (including a downgrade) if present. Use to force\n * a specific version; with top-to-bottom declaration order a later\n * `pinCatalogTo` overrides an earlier `ensureCatalogLatest`. Distinct\n * from `ensureCatalogVersion`, which never touches a present key. */\nexport function pinCatalogTo(name: string, version: string): void {\n const state = requireYaml(\"pinCatalogTo\");\n if (readCatalogString(state, name) === version) return;\n state.doc.setIn([\"catalog\", name], version);\n}\n\n/** Resolve `catalog.<name>` to npm \"latest\" from the active state's\n * prefetched `getLatestVersion` accessor (the caller pre-resolves; no\n * network here), creating the key if absent. No-op when no latest is\n * available — default refresh passes no lookup, and a name that was not\n * prefetched resolves to `undefined`; in both cases any existing entry is\n * left untouched. This is the SDK-family resolver: on\n * `refresh --update-deps-only` it both SEEDS a missing standard SDK key\n * and refreshes a present one, and on `init` it overwrites the\n * placeholder with the real latest. */\nexport function ensureCatalogLatest(name: string): void {\n const state = requireYaml(\"ensureCatalogLatest\");\n if (!state.getLatestVersion) return;\n const latest = state.getLatestVersion(name);\n if (latest === undefined) return;\n if (readCatalogString(state, name) === latest) return;\n state.doc.setIn([\"catalog\", name], latest);\n}\n\n/** Pin `catalog.<catalogEntry>` to the EXACT version that package `opts.of`\n * declares for `catalogEntry` in its own manifest (read at npm latest, or at\n * `opts.ofVersion` if given). The value is resolved by the runner's\n * prefetched `getDerivedDependencyPin` accessor (the caller pre-resolves and\n * validates — exact-version-only — at prefetch time; no network here).\n * OVERWRITES like `pinCatalogTo` (not add-if-absent): a pre-existing loose\n * entry (`vue: ^3.5.24`) is tightened to the exact derived version. No-op\n * when no derived-pin lookup is available — default refresh/check pass none,\n * leaving the entry exactly as the lockfile has it; the resolution leaves\n * live in the `onInitOrUpdate` frame. */\nexport function pinCatalogToDependencyOf(\n catalogEntry: string,\n _opts: { of: string; ofVersion?: string },\n): void {\n const state = requireYaml(\"pinCatalogToDependencyOf\");\n if (!state.getDerivedDependencyPin) return;\n const version = state.getDerivedDependencyPin(catalogEntry);\n if (version === undefined) return;\n if (readCatalogString(state, catalogEntry) === version) return;\n state.doc.setIn([\"catalog\", catalogEntry], version);\n}\n\n/** Remove `catalog.<name>` if present; no-op when absent. */\nexport function ensureCatalogAbsent(name: string): void {\n const state = requireYaml(\"ensureCatalogAbsent\");\n if (!state.doc.hasIn([\"catalog\", name])) return;\n state.doc.deleteIn([\"catalog\", name]);\n}\n\n// ============================================================\n// Lines builders — `.gitignore`\n// ============================================================\n\n/** Append each `entry` if not already present (comment-aware equality). */\nexport function ensureGitignoreEntries(entries: string[]): void {\n const state = requireLines(\"ensureGitignoreEntries\");\n for (const e of entries) {\n if (containsEntry(state.lines, e)) continue;\n state.lines.push(e);\n }\n}\n\n/** Drop any line whose normalised form matches any of `patterns`. */\nexport function removeGitignoreEntries(patterns: RegExp[]): void {\n const state = requireLines(\"removeGitignoreEntries\");\n const kept: string[] = [];\n for (const line of state.lines) {\n const n = normaliseLine(line);\n if (n === \"\") {\n kept.push(line);\n continue;\n }\n if (patterns.some((p) => p.test(n))) continue;\n kept.push(line);\n }\n state.lines.splice(0, state.lines.length, ...kept);\n}\n","// YAML parser + serialiser, comment-preserving via the `yaml` lib's\n// Document API (CST-preserving). Wraps `parseDocument` + `Document.toString`.\n// Helpers (`yamlGet`, `yamlSet`, `yamlHas`, `yamlDelete`) operate on the\n// Document by jsonPath-style addresses, matching the JSON parser's API.\n// Comments attached to map entries survive set/delete operations as long\n// as the affected nodes are mutated in place (not reassigned wholesale).\n\nimport {\n Document,\n isMap,\n isPair,\n isSeq,\n parseDocument,\n YAMLMap,\n YAMLSeq,\n Scalar,\n Node,\n} from \"yaml\";\n\nexport type YamlDocument = Document.Parsed;\n\n/** Parse YAML into a CST-preserving Document. */\nexport function parseYaml(raw: string): YamlDocument {\n return parseDocument(raw);\n}\n\n/** Serialise back to string. Preserves comments + ordering of unchanged\n * nodes per the `yaml` library's contract. */\nexport function stringifyYaml(doc: YamlDocument): string {\n return doc.toString();\n}\n\nfunction splitPath(jsonPath: string): string[] {\n if (jsonPath === \"\" || jsonPath === undefined) return [];\n return jsonPath.split(\".\");\n}\n\n/** Get the JS value at the given jsonPath in the document. */\nexport function yamlGet(doc: YamlDocument, jsonPath: string): unknown {\n const parts = splitPath(jsonPath);\n if (parts.length === 0) return doc.toJS();\n return doc.getIn(parts, false) as unknown;\n}\n\nexport function yamlHas(doc: YamlDocument, jsonPath: string): boolean {\n const parts = splitPath(jsonPath);\n if (parts.length === 0) return true;\n return doc.hasIn(parts);\n}\n\n/** Set a value at jsonPath. Auto-creates intermediate maps. Existing\n * comments on parent map entries are preserved by the yaml library. */\nexport function yamlSet(doc: YamlDocument, jsonPath: string, value: unknown): void {\n const parts = splitPath(jsonPath);\n if (parts.length === 0) {\n throw new Error(\"yamlSet: jsonPath must be non-empty\");\n }\n doc.setIn(parts, value);\n}\n\n/** Delete a value at jsonPath. No-op if missing. */\nexport function yamlDelete(doc: YamlDocument, jsonPath: string): void {\n const parts = splitPath(jsonPath);\n if (parts.length === 0) {\n throw new Error(\"yamlDelete: jsonPath must be non-empty\");\n }\n doc.deleteIn(parts);\n}\n\n/** Re-export selected `yaml` lib types for downstream content-rule builders. */\nexport { isMap, isPair, isSeq, YAMLMap, YAMLSeq, Scalar };\nexport type { Node };\n","// `.structure` metadata file — read/write + floor check.\n//\n// Single JSON file at the block root holding the layout-version\n// integer and (in future) any other structurer metadata. Two\n// constants govern lifecycle gates:\n// - STRUCTURE_VERSION : latest known. v2 = software-build layout.\n// - STRUCTURE_MIN_SUPPORTED : floor. Initial value 0.\n// Both are bumped by structurer releases; rule predicates may consult\n// `ctx.version` for one-shot version-gated transitions.\n\nimport type { FileSystem } from \"./fs/api\";\n\nexport const STRUCTURE_VERSION = 2;\nexport const STRUCTURE_MIN_SUPPORTED = 0;\n/** Block-relative path of the structurer metadata file. */\nexport const STRUCTURE_META_FILE = \".structure\";\n\nexport type StructureMeta = { version: number };\n\n/** Read `.structure`. Missing file or invalid payload → version 0. */\nexport function readStructureMeta(fs: FileSystem): StructureMeta {\n if (!fs.exists(STRUCTURE_META_FILE)) return { version: 0 };\n try {\n const parsed = JSON.parse(fs.read(STRUCTURE_META_FILE)) as Partial<StructureMeta>;\n return { version: typeof parsed?.version === \"number\" ? parsed.version : 0 };\n } catch {\n return { version: 0 };\n }\n}\n\n/** Throw if version is below floor. */\nexport function assertVersionAboveFloor(\n version: number,\n floor: number = STRUCTURE_MIN_SUPPORTED,\n): void {\n if (version < floor) {\n throw new StructureVersionFloorError(version, floor);\n }\n}\n\nexport class StructureVersionFloorError extends Error {\n constructor(\n public readonly version: number,\n public readonly floor: number,\n ) {\n super(\n `Block .structure version is ${version}, below floor ${floor}. ` +\n `Bootstrap via the legacy-migration skill, then re-run.`,\n );\n this.name = \"StructureVersionFloorError\";\n }\n}\n\n/** Write `.structure`. Writes a fresh payload rather than merging. */\nexport function writeStructureMeta(fs: FileSystem, meta: StructureMeta): void {\n // Compact, single-line — this is a tiny machine file, no pretty-print.\n fs.write(STRUCTURE_META_FILE, JSON.stringify(meta));\n}\n","// Engine runner — structural pass, managed pass, post-run recheck.\n//\n// `run(structure, fs, ctx, opts)` drives one block through the structural\n// pass, managed pass, and post-run recheck (DISCOVERY happens in the\n// caller, which constructs `ctx.modules`). The function is shared by\n// `check`, `refresh`,\n// `refresh --update-deps-only`, and `init`. The mode (see `currentMode`)\n// selects which leaves fire — a leaf fires iff its `modes` include the\n// current one:\n// - dryRun=true → check, mode \"default\" (no\n// writes)\n// - dryRun=false, updateDepsOnly=false → refresh, mode \"default\"\n// (writes + .structure bump +\n// post-run recheck)\n// - dryRun=false, updateDepsOnly=true → refresh --update-deps-only,\n// mode \"updateDeps\" (only\n// onUpdateDeps/onInitOrUpdate\n// leaves fire; no version\n// bump; no recheck)\n// - dryRun=false, opts.initMode=true → init, mode \"init\" (default\n// + onInitOrUpdate leaves +\n// seeds; no recheck — the\n// init→check test runs an\n// explicit dry-run afterwards)\n//\n// Idempotency invariant is enforced by the post-run recheck: after a\n// successful refresh, the runner reruns the lifecycle in dry-run mode (fresh\n// rediscover when supplied) and throws `RecheckError` on any non-empty\n// change list. The error carries the failing item's\n// (scope, path, primitive, action) tuple for diagnostics.\n\nimport { stringify as yamlStringify } from \"yaml\";\nimport type { ContentForm, FlatItem, RunMode, Structure, TriggerContext, ManagedBody } from \"./ir\";\nimport type { RunContext, Scope } from \"./api\";\nimport type { FileSystem } from \"./fs/api\";\nimport type { TemplateProvider } from \"./templates\";\nimport { substituteVars } from \"./templates\";\nimport { flatten } from \"./flatten\";\nimport { matchesGlob } from \"./glob\";\nimport { withRunContext } from \"./builders\";\nimport {\n withManagedBody,\n withManagedYaml,\n withManagedLines,\n resolveSdkSentinelsInJson,\n} from \"./content-rules\";\nimport { parseJson, stringifyJson } from \"./parsers/json\";\nimport type { JsonObject } from \"./parsers/json\";\nimport { parseYaml, stringifyYaml } from \"./parsers/yaml\";\nimport { parseLines, serializeLines } from \"./parsers/lines\";\nimport { writeStructureMeta, STRUCTURE_VERSION, STRUCTURE_META_FILE } from \"./version\";\n\nexport type ChangeAction = \"create\" | \"update\" | \"delete\" | \"rename\" | \"noop\";\n\nexport type Change = {\n scope: Scope;\n /** Resolved (block-relative) path. For rename, the source path. */\n path: string;\n /** \"fixed\" | \"managed\" | \"scaffold\" | \"seed\" | \"remove\" | \"rename\" */\n primitive: string;\n action: ChangeAction;\n};\n\nexport type RunResult = {\n changes: Change[];\n};\n\nexport type RunOptions = {\n /** Called before the post-run recheck to obtain a fresh RunContext\n * reflecting the just-written FS state (re-reads `pnpm-workspace.yaml`).\n * If absent, recheck reuses the original ctx with `dryRun: true`. */\n rediscover?: (fs: FileSystem) => RunContext;\n /** Template provider used by `file(...)` and `tpl(...)` content forms.\n * Required whenever the structure references such forms. */\n templates?: TemplateProvider;\n /** Init mode: write seed leaves (only-if-missing semantics) and skip\n * the post-run recheck. The caller is expected to follow with an\n * explicit dry-run check (Layer-2 invariant). */\n initMode?: boolean;\n /** Sync accessor for prefetched npm \"latest\" versions, consumed by\n * `ensureCatalogLatest` inside `onUpdateDeps` managed bodies. The CLI\n * prefetches the catalog's package versions before the run (network)\n * and passes the resulting sync map here; unit tests pass a mock.\n * Absent → `ensureCatalogLatest` is a no-op (default refresh). */\n registryLookup?: (packageName: string) => string | undefined;\n /** Sync accessor for prefetched derived catalog pins\n * (`catalogEntry → exact version`), consumed by `pinCatalogToDependencyOf`\n * inside `onInitOrUpdate` managed bodies. The CLI / init constructor\n * prefetches + validates these before the run (network). Absent →\n * `pinCatalogToDependencyOf` is a no-op (default refresh). */\n derivedPinLookup?: (catalogEntry: string) => string | undefined;\n};\n\nexport class RecheckError extends Error {\n constructor(public readonly failing: Change) {\n super(\n `Post-run recheck: rule set not idempotent. ` +\n `Failing item: ${failing.primitive} '${failing.path}' ` +\n `(scope=${failing.scope}, action=${failing.action}). Engine bug.`,\n );\n this.name = \"RecheckError\";\n }\n}\n\n/** Resolve a `ContentForm` to its on-disk string for the given file\n * path. `file` / `tpl` resolution goes through the configured\n * `TemplateProvider`; `generate` returns parsed structure → JSON/YAML\n * or a string. */\nfunction resolveContent(\n form: ContentForm,\n filePath: string,\n templates: TemplateProvider | undefined,\n ctx: RunContext,\n): string {\n switch (form.kind) {\n case \"text\":\n return form.value;\n case \"file\": {\n if (!templates) {\n throw new Error(\n `file('${form.path}'): no TemplateProvider configured. ` +\n `Pass opts.templates to engine.run(...).`,\n );\n }\n return templates.staticRead(form.path);\n }\n case \"tpl\": {\n if (!templates) {\n throw new Error(\n `tpl('${form.path}'): no TemplateProvider configured. ` +\n `Pass opts.templates to engine.run(...).`,\n );\n }\n const raw = templates.textRead(form.path);\n const vars = typeof form.vars === \"function\" ? form.vars(ctx) : form.vars;\n return substituteVars(raw, vars);\n }\n case \"generate\": {\n const value = form.fn(ctx);\n if (filePath.endsWith(\".json\")) {\n // Resolve `sdk:` sentinels in the generated dep sections so the\n // initial content matches what the body rules re-assert.\n resolveSdkSentinelsInJson(value, ctx.isSdkInternal);\n // package.json stays fully expanded (oxfmt's package.json shape);\n // every other .json collapses to oxfmt's generic-file shape.\n return stringifyJson(value, { collapse: !filePath.endsWith(\"package.json\") });\n }\n if (filePath.endsWith(\".yaml\") || filePath.endsWith(\".yml\")) {\n return yamlStringify(value);\n }\n if (typeof value !== \"string\") {\n throw new Error(\n `generate() for '${filePath}' must return a string for non-JSON/YAML files; got ${typeof value}`,\n );\n }\n return value;\n }\n case \"binary\":\n throw new Error(\n `binary('${form.path}') cannot be resolved to a string; it is only valid ` +\n `inside seed()/scaffold(), which copy it verbatim via fs.writeBinary.`,\n );\n }\n}\n\n/** Write a leaf's content to disk, dispatching binary assets (copied\n * verbatim, never utf-8 decoded) from string content. */\nfunction writeLeafContent(\n fs: FileSystem,\n resolvedPath: string,\n form: ContentForm,\n templates: TemplateProvider | undefined,\n ctx: RunContext,\n): void {\n if (form.kind === \"binary\") {\n if (!templates) {\n throw new Error(\n `binary('${form.path}'): no TemplateProvider configured. ` +\n `Pass opts.templates to engine.run(...).`,\n );\n }\n fs.writeBinary(resolvedPath, templates.staticReadBinary(form.path));\n return;\n }\n fs.write(resolvedPath, resolveContent(form, resolvedPath, templates, ctx));\n}\n\n/** Dispatch managed-body parse → mutate → serialize by file extension /\n * basename. JSON, YAML, and lines all share the same `(initial, body,\n * triggerContext) → newRaw` shape via the active-state wrappers in\n * `content-rules.ts`. */\nfunction runManagedBody(\n path: string,\n raw: string,\n body: ManagedBody,\n tctx: TriggerContext,\n registryLookup: ((packageName: string) => string | undefined) | undefined,\n derivedPinLookup: ((catalogEntry: string) => string | undefined) | undefined,\n): string {\n const base = path.split(\"/\").pop() ?? path;\n if (path.endsWith(\".json\")) {\n const parsed = parseJson(raw) as JsonObject;\n if (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new Error(`managed: parsed value at '${path}' is not a JSON object`);\n }\n withManagedBody(parsed, body, { triggerContext: tctx });\n // package.json stays fully expanded; other .json (tsconfig, …) collapses\n // to oxfmt's generic-file shape.\n return stringifyJson(parsed, { collapse: base !== \"package.json\" });\n }\n if (path.endsWith(\".yaml\") || path.endsWith(\".yml\")) {\n const doc = parseYaml(raw);\n withManagedYaml(doc, body, {\n triggerContext: tctx,\n getLatestVersion: registryLookup,\n getDerivedDependencyPin: derivedPinLookup,\n });\n return stringifyYaml(doc);\n }\n if (base === \".gitignore\" || base.endsWith(\".gitignore\")) {\n const lines = parseLines(raw);\n withManagedLines(lines, body, { triggerContext: tctx });\n return serializeLines(lines);\n }\n throw new Error(\n `managed('${path}'): unsupported file kind. Only .json, .yaml, .yml, .gitignore are dispatched.`,\n );\n}\n\nfunction buildSnapshot(fs: FileSystem): Set<string> {\n const files = fs.list(\"\");\n const out = new Set<string>();\n for (const f of files) {\n out.add(f);\n const parts = f.split(\"/\");\n for (let i = 1; i < parts.length; i++) {\n out.add(parts.slice(0, i).join(\"/\"));\n }\n }\n return out;\n}\n\nfunction snapshotHas(snap: Set<string>, p: string): boolean {\n const n = p === \"\" ? p : p.endsWith(\"/\") ? p.slice(0, -1) : p;\n return snap.has(n);\n}\n\n/** Build the trigger context for one leaf. `pathExists`/`pathMissing` are\n * block-relative; `filesMatch` resolves its glob MODULE-RELATIVE to\n * `modulePath` so the same predicate (`whenFilesExist(\"src/*.test.ts\")`)\n * reads the right module when a scope fans out. The snapshot is shared\n * across leaves; only the resolution prefix differs per item. */\nfunction buildTriggerCtx(snap: Set<string>, ctx: RunContext, modulePath: string): TriggerContext {\n return {\n ctx,\n version: ctx.version,\n pathExists: (p: string) => snapshotHas(snap, p),\n pathMissing: (p: string) => !snapshotHas(snap, p),\n filesMatch: (glob: string) => {\n const resolved = modulePath ? `${modulePath}/${glob}` : glob;\n for (const entry of snap) {\n if (matchesGlob(resolved, entry)) return true;\n }\n return false;\n },\n };\n}\n\nfunction passesTriggers(item: FlatItem, tctx: TriggerContext): boolean {\n for (const t of item.triggers) {\n if (!t(tctx)) return false;\n }\n return true;\n}\n\n/** Derive the active run mode from the context + init flag. `check`\n * (dryRun) and `refresh` share `\"default\"` — same leaves, the `dryRun`\n * flag alone decides whether writes land. */\nfunction currentMode(ctx: RunContext, initMode: boolean): RunMode {\n if (initMode) return \"init\";\n if (ctx.updateDepsOnly) return \"updateDeps\";\n return \"default\";\n}\n\nfunction filterByMode(items: FlatItem[], mode: RunMode): FlatItem[] {\n return items.filter((i) => i.modes.includes(mode));\n}\n\nfunction applyStructural(\n item: FlatItem,\n fs: FileSystem,\n dryRun: boolean,\n templates: TemplateProvider | undefined,\n initMode: boolean,\n ctx: RunContext,\n): Change | undefined {\n const leaf = item.leaf;\n if (leaf.kind === \"fixed\") {\n const desired = resolveContent(leaf.content, item.resolvedPath, templates, ctx);\n const exists = fs.exists(item.resolvedPath);\n if (!exists) {\n if (!dryRun) fs.write(item.resolvedPath, desired);\n return {\n scope: item.scope,\n path: item.resolvedPath,\n primitive: \"fixed\",\n action: \"create\",\n };\n }\n const current = fs.read(item.resolvedPath);\n if (current === desired) return undefined;\n if (!dryRun) fs.write(item.resolvedPath, desired);\n return {\n scope: item.scope,\n path: item.resolvedPath,\n primitive: \"fixed\",\n action: \"update\",\n };\n }\n if (leaf.kind === \"scaffold\") {\n if (fs.exists(item.resolvedPath)) return undefined;\n if (!dryRun) {\n writeLeafContent(fs, item.resolvedPath, leaf.initial, templates, ctx);\n }\n return {\n scope: item.scope,\n path: item.resolvedPath,\n primitive: \"scaffold\",\n action: \"create\",\n };\n }\n if (leaf.kind === \"seed\") {\n // Init mode: write seeds once if missing (same shape as scaffold).\n // Refresh / check: seeds are off-limits to the engine — they belong\n // to the block author. Layer-2 init→check parity relies on the\n // init action depositing canonical seed content, then the check\n // pass simply skipping seeds (vacuously fine).\n if (!initMode) return undefined;\n if (fs.exists(item.resolvedPath)) return undefined;\n if (!dryRun) {\n writeLeafContent(fs, item.resolvedPath, leaf.initial, templates, ctx);\n }\n return {\n scope: item.scope,\n path: item.resolvedPath,\n primitive: \"seed\",\n action: \"create\",\n };\n }\n if (leaf.kind === \"remove\") {\n if (!fs.exists(item.resolvedPath)) return undefined;\n if (!dryRun) fs.delete(item.resolvedPath);\n return {\n scope: item.scope,\n path: item.resolvedPath,\n primitive: \"remove\",\n action: \"delete\",\n };\n }\n if (leaf.kind === \"rename\") {\n if (!fs.exists(item.resolvedPath)) return undefined;\n const to = item.resolvedTo!;\n if (fs.exists(to)) {\n // dest exists — treat as already-renamed; no change.\n return undefined;\n }\n if (!dryRun) fs.move(item.resolvedPath, to);\n return {\n scope: item.scope,\n path: item.resolvedPath,\n primitive: \"rename\",\n action: \"rename\",\n };\n }\n return undefined;\n}\n\nfunction applyManaged(\n item: FlatItem,\n fs: FileSystem,\n dryRun: boolean,\n tctx: TriggerContext,\n templates: TemplateProvider | undefined,\n registryLookup: ((packageName: string) => string | undefined) | undefined,\n derivedPinLookup: ((catalogEntry: string) => string | undefined) | undefined,\n ctx: RunContext,\n): Change | undefined {\n if (item.leaf.kind !== \"managed\") return undefined;\n const leaf = item.leaf;\n const path = item.resolvedPath;\n const exists = fs.exists(path);\n\n let beforeRaw: string;\n let created = false;\n\n if (!exists) {\n beforeRaw = resolveContent(leaf.initial, path, templates, ctx);\n created = true;\n } else {\n beforeRaw = fs.read(path);\n }\n\n const after = runManagedBody(path, beforeRaw, leaf.body, tctx, registryLookup, derivedPinLookup);\n\n if (created) {\n if (!dryRun) fs.write(path, after);\n return {\n scope: item.scope,\n path,\n primitive: \"managed\",\n action: \"create\",\n };\n }\n if (after === beforeRaw) return undefined;\n if (!dryRun) fs.write(path, after);\n return {\n scope: item.scope,\n path,\n primitive: \"managed\",\n action: \"update\",\n };\n}\n\n/** Execute one pass over the flattened items: structural items first\n * (declaration order), then managed items. Returns the change list. */\nfunction executePass(\n flat: FlatItem[],\n fs: FileSystem,\n ctx: RunContext,\n dryRun: boolean,\n templates: TemplateProvider | undefined,\n initMode: boolean,\n registryLookup: ((packageName: string) => string | undefined) | undefined,\n derivedPinLookup: ((catalogEntry: string) => string | undefined) | undefined,\n): Change[] {\n const items = filterByMode(flat, currentMode(ctx, initMode));\n const changes: Change[] = [];\n\n // Structural pass. The trigger context is per-item: `filesMatch` resolves\n // module-relative, so it must carry the leaf's bound module path.\n const snap1 = buildSnapshot(fs);\n for (const item of items) {\n if (item.leaf.kind === \"managed\") continue;\n const tctx1 = buildTriggerCtx(snap1, ctx, item.modulePath);\n if (!passesTriggers(item, tctx1)) continue;\n const change = applyStructural(item, fs, dryRun, templates, initMode, ctx);\n if (change) changes.push(change);\n }\n\n // Re-snapshot after structural pass — managed-body triggers see the\n // post-rename / post-delete world.\n const snap2 = buildSnapshot(fs);\n for (const item of items) {\n if (item.leaf.kind !== \"managed\") continue;\n const tctx2 = buildTriggerCtx(snap2, ctx, item.modulePath);\n if (!passesTriggers(item, tctx2)) continue;\n const change = applyManaged(\n item,\n fs,\n dryRun,\n tctx2,\n templates,\n registryLookup,\n derivedPinLookup,\n ctx,\n );\n if (change) changes.push(change);\n }\n\n return changes;\n}\n\n/**\n * Run the structurer engine end-to-end. See module header for mode\n * semantics. Throws `RecheckError` if the post-run dry-run finds any\n * leftover diff after a successful refresh.\n */\nexport function run(\n structure: Structure,\n fs: FileSystem,\n ctx: RunContext,\n opts: RunOptions = {},\n): RunResult {\n return withRunContext(ctx, () => {\n const flat = flatten(structure, ctx);\n const initMode = !!opts.initMode;\n const changes = executePass(\n flat,\n fs,\n ctx,\n ctx.dryRun,\n opts.templates,\n initMode,\n opts.registryLookup,\n opts.derivedPinLookup,\n );\n\n const isRefreshDefault = !ctx.dryRun && !ctx.updateDepsOnly && !initMode;\n\n if (isRefreshDefault) {\n // version bump\n writeStructureMeta(fs, { version: STRUCTURE_VERSION });\n\n // post-run recheck. Fresh discovery → fresh flatten →\n // dry-run. Any change list emits RecheckError on the first item.\n const recheckCtxBase = opts.rediscover ? opts.rediscover(fs) : ctx;\n const recheckCtx: RunContext = { ...recheckCtxBase, dryRun: true };\n const recheckFlat = flatten(structure, recheckCtx);\n const recheckChanges = executePass(\n recheckFlat,\n fs,\n recheckCtx,\n true,\n opts.templates,\n false,\n opts.registryLookup,\n opts.derivedPinLookup,\n );\n // Ignore .structure self-write (already up to date after\n // writeStructureMeta above).\n const filtered = recheckChanges.filter((c) => c.path !== STRUCTURE_META_FILE);\n if (filtered.length > 0) {\n throw new RecheckError(filtered[0]!);\n }\n }\n\n // Init mode: write .structure so the resulting tree carries the\n // current version (matches what `init` ships to disk).\n if (initMode && !ctx.dryRun) {\n writeStructureMeta(fs, { version: STRUCTURE_VERSION });\n }\n\n return { changes };\n });\n}\n","// Workspace-package classification — the seven scope detection rules.\n//\n// Input: the parsed package.json of every workspace member, plus its\n// block-relative path. Output: `Module[]` (scope + name + path).\n// First-match wins on the detection rules; an explicit `block-scope`\n// override on package.json skips detection.\n\nimport type { Module, Scope } from \"./api\";\n\nexport const ALL_SCOPES: Scope[] = [\"root\", \"block\", \"model\", \"ui\", \"workflow\", \"test\", \"software\"];\n\nexport type WorkspacePackage = {\n /** Block-relative path of the package — \"\" or \".\" means the\n * workspace root. */\n path: string;\n /** Parsed package.json. */\n pkg: PackageJsonLike;\n};\n\nexport type PackageJsonLike = {\n name?: string;\n main?: string;\n files?: string[];\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n optionalDependencies?: Record<string, string>;\n // Top-level `block` field — the unambiguous facade marker.\n block?: unknown;\n // Override field — value MUST be one of the seven scopes.\n \"block-scope\"?: string;\n \"block-software\"?: unknown;\n};\n\nexport class DiscoveryError extends Error {\n constructor(\n msg: string,\n public readonly path?: string,\n ) {\n super(msg);\n this.name = \"DiscoveryError\";\n }\n}\n\nfunction depKeys(pkg: PackageJsonLike): Set<string> {\n const all = new Set<string>();\n for (const section of [\n pkg.dependencies,\n pkg.devDependencies,\n pkg.peerDependencies,\n pkg.optionalDependencies,\n ]) {\n if (section) for (const k of Object.keys(section)) all.add(k);\n }\n return all;\n}\n\nfunction isRoot(p: string): boolean {\n return p === \"\" || p === \".\";\n}\n\n/**\n * Classify one package.\n *\n * @param wp The workspace package.\n * @returns Scope or `undefined` if unclassified.\n */\nexport function classifyOne(wp: WorkspacePackage): Scope | undefined {\n const override = wp.pkg[\"block-scope\"];\n if (typeof override === \"string\") {\n if (!(ALL_SCOPES as string[]).includes(override)) {\n throw new DiscoveryError(\n `package.json \"block-scope\" must be one of ${ALL_SCOPES.join(\", \")}, got '${override}'`,\n wp.path,\n );\n }\n return override as Scope;\n }\n\n // Standalone implicit root: the package at path \"\" is present\n // because pnpm-workspace.yaml lives there, so it IS the workspace root —\n // classify it as `root` unconditionally, BEFORE any detection rule. A\n // nameless root carrying legacy facade cruft (`files: [\"index.d.ts\",\n // \"index.js\"]` + block-tools, e.g. sequence-properties) must NOT fall\n // through to the rule-4 block fallback and become a nameless second\n // `block` module — root-as-facade is a forbidden anti-pattern.\n // SDK-internal enumeration never produces a path-\"\" package (it scans\n // sub-package dirs), so this only ever fires in standalone mode.\n if (isRoot(wp.path)) return \"root\";\n\n // block (facade) — a top-level `block` field is the unambiguous facade\n // marker; no non-facade workspace package carries one. MUST precede the model\n // rule: a migrated facade carries `@platforma-sdk/model` as a devDep plus\n // `main`, which would otherwise match model.\n if (wp.pkg.block !== undefined) return \"block\";\n\n const deps = depKeys(wp.pkg);\n\n // 1. software — top-level `block-software` field OR\n // (package-builder AND any @platforma-open/*runenv* dep).\n if (wp.pkg[\"block-software\"] !== undefined) return \"software\";\n if (deps.has(\"@platforma-sdk/package-builder\")) {\n for (const d of deps) {\n if (/^@platforma-open\\/.*runenv/.test(d)) return \"software\";\n }\n }\n\n // 2. workflow — @platforma-sdk/workflow-tengo in deps.\n if (deps.has(\"@platforma-sdk/workflow-tengo\")) return \"workflow\";\n\n // 3. ui — (ui-vue OR vue) AND main is not set.\n if ((deps.has(\"@platforma-sdk/ui-vue\") || deps.has(\"vue\")) && !wp.pkg.main) {\n return \"ui\";\n }\n\n // 4. model — @platforma-sdk/model in deps AND main is set.\n if (deps.has(\"@platforma-sdk/model\") && wp.pkg.main) return \"model\";\n\n // 5. test — @platforma-sdk/test in deps.\n if (deps.has(\"@platforma-sdk/test\")) return \"test\";\n\n // (root — the workspace root, path \"\", is classified above, before the\n // detection rules, so it can never reach this fallthrough.)\n return undefined;\n}\n\n/**\n * Classify a whole workspace. Throws on the first unclassified package\n * with a message that directs the operator to add `block-scope` to its\n * package.json.\n */\nexport function discoverModules(packages: WorkspacePackage[]): Module[] {\n const out: Module[] = [];\n for (const p of packages) {\n const scope = classifyOne(p);\n if (!scope) {\n throw new DiscoveryError(\n `Unclassified workspace package at '${p.path}'. ` +\n `Add a top-level \"block-scope\" string to its package.json.`,\n p.path,\n );\n }\n out.push({\n scope,\n name: p.pkg.name ?? p.path,\n path: isRoot(p.path) ? \"\" : p.path,\n });\n }\n return out;\n}\n","// RunContext assembly helpers + module-lookup helpers. The full\n// `RunContext` type lives in `api.ts` (rule authors see it via\n// `({ ctx }) => ...` trigger predicates). This file provides convenience\n// constructors and the scope-lookup helpers generators use.\n\nimport type { BlockVars, Module, RunContext, Scope } from \"./api\";\n\n/** All modules of `scope` (zero or more). Never throws. Use when \"zero or\n * more\" is the right intent (e.g. software). */\nexport function findModules(ctx: RunContext, scope: Scope): Module[] {\n return ctx.modules.filter((m) => m.scope === scope);\n}\n\n/** The single module of `scope`. Throws if absent OR if more than one\n * exists. Use when exactly one is required (model / ui / workflow). */\nexport function findModule(ctx: RunContext, scope: Scope): Module {\n const ms = findModules(ctx, scope);\n if (ms.length === 0) {\n throw new Error(`findModule: expected one '${scope}' module, found none`);\n }\n if (ms.length > 1) {\n throw new Error(`findModule: expected exactly one '${scope}' module, found ${ms.length}`);\n }\n return ms[0]!;\n}\n\n/** Workspace dep map `{ name: \"workspace:*\" }` for the single module of\n * `scope`. Throws if absent (via `findModule`) — guarantees the dep. */\nexport function scopeDepMap(ctx: RunContext, scope: Scope): Record<string, string> {\n return { [findModule(ctx, scope).name]: \"workspace:*\" };\n}\n\n/** Workspace dep map for ALL modules of `scope` (zero or more). Never\n * throws — use where multiple modules are legitimate (e.g. software). */\nexport function scopeDepMaps(ctx: RunContext, scope: Scope): Record<string, string> {\n const out: Record<string, string> = {};\n for (const m of findModules(ctx, scope)) out[m.name] = \"workspace:*\";\n return out;\n}\n\n/**\n * Module set produced by `init` for the given BlockVars: one module per\n * base scope (root/block/model/ui/workflow/test) plus, when a platform\n * was selected, one `software` module. `--platform` is single-valued, so\n * `init` produces at most one software module; multi-software shapes only\n * arise via DISCOVERY on existing blocks.\n *\n * Single source of truth shared by the real `init` constructor and the\n * `simulateInit` test helper — keeping them in lockstep is what makes the\n * init→check zero-diff invariant meaningful.\n */\nexport function modulesForInit(vars: BlockVars): Module[] {\n const facade = vars.facadeName;\n const mods: Module[] = [\n { scope: \"root\", name: facade, path: \"\" },\n { scope: \"block\", name: `${facade}.block`, path: \"block\" },\n { scope: \"model\", name: `${facade}.model`, path: \"model\" },\n { scope: \"ui\", name: `${facade}.ui`, path: \"ui\" },\n { scope: \"workflow\", name: `${facade}.workflow`, path: \"workflow\" },\n { scope: \"test\", name: `${facade}.test`, path: \"test\" },\n ];\n if (vars.softwarePlatform) {\n // Single software module lives at the flat `software/` dir with name\n // `${facade}.software` — matches the boilerplate and every real\n // single-software block. Multi-software blocks arise only via\n // DISCOVERY on existing workspaces, never from `init`.\n mods.push({\n scope: \"software\",\n name: `${facade}.software`,\n path: \"software\",\n });\n }\n return mods;\n}\n\nexport type CreateRunContextInput = {\n isSdkInternal?: boolean;\n updateDepsOnly?: boolean;\n modules: Module[];\n blockVars: BlockVars;\n version?: number;\n dryRun?: boolean;\n};\n\nexport function createRunContext(input: CreateRunContextInput): RunContext {\n return {\n isSdkInternal: input.isSdkInternal ?? false,\n updateDepsOnly: input.updateDepsOnly ?? false,\n modules: input.modules,\n blockVars: input.blockVars,\n version: input.version ?? 0,\n dryRun: input.dryRun ?? false,\n };\n}\n","// Filesystem-backed DISCOVERY.\n//\n// The engine runner consumes a fully-assembled `RunContext` (modules,\n// version, blockVars). This module is the \"caller\" that builds it from a\n// block directory, working through the engine's `FileSystem` abstraction\n// — so the same code path serves the CLI (NodeFileSystem) and the\n// in-memory init→check round-trip (MemoryFileSystem), which re-discovers\n// from the just-written FS instead of reusing init's module set, so a\n// discovery/classification regression surfaces in the parity invariant.\n//\n// Two enumeration modes:\n//\n// - Standalone (default): read the block-root `pnpm-workspace.yaml`,\n// read each `packages:` member's `package.json` (literal paths only —\n// globs are a hard error), classify via `discoverModules`. This is the\n// canonical path.\n//\n// - SDK-internal (`--sdk-internal`): in-monorepo blocks (e.g.\n// `etc/blocks/*`) have NO block-local `pnpm-workspace.yaml` — they\n// are members of the parent monorepo's workspace. The block's\n// modules are therefore enumerated by scanning the block directory\n// for sub-package `package.json` files (depth-limited, skipping\n// `node_modules`).\n//\n// `.structure` version is read (missing → 0) and floor-checked. BlockVars\n// are parsed from the block-scope module's `package.json` `name` (the\n// facade name), or — for the root-as-block shape — from the root package.\n\nimport { parse as parseYamlText } from \"yaml\";\nimport type { BlockVars, Module, RunContext } from \"./api\";\nimport type { FileSystem } from \"./fs/api\";\nimport { discoverModules, type WorkspacePackage, type PackageJsonLike } from \"./discovery\";\nimport { createRunContext } from \"./ctx\";\nimport { STRUCTURE_MIN_SUPPORTED, assertVersionAboveFloor, readStructureMeta } from \"./version\";\n\nexport class StructureCliError extends Error {\n constructor(msg: string) {\n super(msg);\n this.name = \"StructureCliError\";\n }\n}\n\n/** Join two block-relative path segments (\"\" = root). */\nfunction joinRel(a: string, b: string): string {\n return a === \"\" ? b : `${a}/${b}`;\n}\n\nfunction readJsonIfExists(fs: FileSystem, rel: string): PackageJsonLike | undefined {\n try {\n return JSON.parse(fs.read(rel)) as PackageJsonLike;\n } catch {\n return undefined;\n }\n}\n\n/** Resolve a single pnpm-workspace `packages:` entry to a block-relative\n * directory path. Entries are literal paths only — the structurer does\n * not expand globs: no real block uses them, and a globbing surface\n * with no caller is dead complexity. A `*` anywhere is a hard error. */\nfunction resolvePackagePath(pattern: string): string {\n if (pattern.includes(\"*\")) {\n throw new StructureCliError(\n `pnpm-workspace.yaml 'packages:' entry '${pattern}' contains a glob. ` +\n `The structurer requires literal package paths — replace the glob ` +\n `with one entry per package directory.`,\n );\n }\n const p = pattern.replace(/^\\.\\//, \"\").replace(/\\/$/, \"\");\n return p === \".\" ? \"\" : p;\n}\n\nfunction enumerateStandalone(fs: FileSystem): WorkspacePackage[] {\n let wsRaw: string;\n try {\n wsRaw = fs.read(\"pnpm-workspace.yaml\");\n } catch {\n throw new StructureCliError(\n `No pnpm-workspace.yaml found. This directory is empty or ` +\n `unrecognisable as a block — run 'block-tools structure init' instead, ` +\n `or pass --sdk-internal for an in-monorepo block.`,\n );\n }\n const ws = (parseYamlText(wsRaw) ?? {}) as { packages?: string[] };\n const patterns = Array.isArray(ws.packages) ? ws.packages : [];\n // The block root (\"\") is ALWAYS a member, discovered implicitly.\n // pnpm treats the directory holding pnpm-workspace.yaml as the implicit\n // workspace root, so the structurer reads the root package.json directly\n // — no real block lists \".\" in `packages:` (it would break turbo's task\n // graph), and the structurer never requires or writes it. The Set\n // dedupes if a workspace did list \".\".\n const dirs = new Set<string>([\"\"]);\n for (const pat of patterns) {\n const d = resolvePackagePath(pat);\n if (d === \"\" || fs.exists(d)) dirs.add(d);\n }\n const out: WorkspacePackage[] = [];\n for (const d of dirs) {\n const pkg = readJsonIfExists(fs, joinRel(d, \"package.json\"));\n if (pkg) out.push({ path: d, pkg });\n }\n return out;\n}\n\n/** SDK-internal enumeration: scan the block directory for sub-package\n * `package.json` files. Depth-limited to two levels (covers `block/`,\n * `model/`, … and `software/<name>/`), skipping `node_modules`. */\nfunction enumerateSdkInternal(fs: FileSystem): WorkspacePackage[] {\n const out: WorkspacePackage[] = [];\n const SKIP = new Set([\"node_modules\", \".turbo\", \"dist\", \".git\", \"block-pack\"]);\n\n function scan(rel: string, depth: number): void {\n const entries = fs.listDir(rel);\n for (const e of entries) {\n if (!e.isDirectory || SKIP.has(e.name)) continue;\n const childRel = joinRel(rel, e.name);\n const pkg = readJsonIfExists(fs, joinRel(childRel, \"package.json\"));\n if (pkg) out.push({ path: childRel, pkg });\n if (depth < 2) scan(childRel, depth + 1);\n }\n }\n scan(\"\", 1);\n return out;\n}\n\n/** Parse a facade package name `@npmOrg/orgScope.shortName` into BlockVars. */\nexport function parseBlockVars(facadeName: string): BlockVars {\n const slash = facadeName.indexOf(\"/\");\n if (!facadeName.startsWith(\"@\") || slash < 0) {\n throw new StructureCliError(\n `Cannot parse block name '${facadeName}': expected '@npm-org/org-scope.short-name'.`,\n );\n }\n const npmOrg = facadeName.slice(0, slash);\n const baseName = facadeName.slice(slash + 1);\n const dot = baseName.indexOf(\".\");\n if (dot < 0) {\n throw new StructureCliError(\n `Cannot parse block name '${facadeName}': base name '${baseName}' has no '.' separating org-scope from short-name.`,\n );\n }\n return {\n facadeName,\n baseName,\n npmOrg,\n orgScope: baseName.slice(0, dot),\n shortName: baseName.slice(dot + 1),\n };\n}\n\nexport type DiscoverInput = {\n /** Block-rooted filesystem (NodeFileSystem for the CLI, MemoryFileSystem\n * for the Layer-2 round-trip). */\n fs: FileSystem;\n isSdkInternal: boolean;\n updateDepsOnly?: boolean;\n dryRun?: boolean;\n};\n\n/**\n * Run DISCOVERY against a block filesystem and return a fully-assembled\n * `RunContext`, ready for `engine.run`. Throws `StructureCliError` /\n * `DiscoveryError` / `StructureVersionFloorError` on a non-block dir,\n * an unclassified package, or a below-floor version.\n */\nexport function discoverRunContext(input: DiscoverInput): RunContext {\n const { fs, isSdkInternal } = input;\n\n const packages = isSdkInternal ? enumerateSdkInternal(fs) : enumerateStandalone(fs);\n\n if (packages.length === 0) {\n throw new StructureCliError(\n `No workspace packages found. ` + `Run 'block-tools structure init' to scaffold a block.`,\n );\n }\n\n const modules: Module[] = discoverModules(packages);\n\n const meta = readStructureMeta(fs);\n assertVersionAboveFloor(meta.version, STRUCTURE_MIN_SUPPORTED);\n\n // BlockVars from the block-scope module's name (facade). Fall back to\n // the root module if a block has the root-as-block shape.\n const blockMod =\n modules.find((m) => m.scope === \"block\") ?? modules.find((m) => m.scope === \"root\");\n if (!blockMod) {\n throw new StructureCliError(\n `Could not find a 'block' (or root-as-block) package to derive BlockVars from.`,\n );\n }\n // This structurer names the block package `<facade>.block`\n // (block-package-json.ts). The root package carries no `name`, so DISCOVERY\n // derives BlockVars from the block module — whose `.block` suffix would\n // otherwise leak into `shortName` on refresh/check (but not init, which is\n // fed the facade directly). Strip it so `shortName` is the real short name\n // everywhere. No-op for legacy blocks whose block package IS the bare facade\n // and for the root-as-block fallback.\n const facadeName = blockMod.name.replace(/\\.block$/, \"\");\n const blockVars = parseBlockVars(facadeName);\n\n return createRunContext({\n isSdkInternal,\n updateDepsOnly: input.updateDepsOnly ?? false,\n modules,\n blockVars,\n version: meta.version,\n dryRun: input.dryRun ?? false,\n });\n}\n","// Canonical top-level key order for `package.json` files.\n// Used by `enforceFieldOrder(canonicalPackageJsonOrder)` at the end of\n// every `*-package-json.ts` body.\n// Per-block extensions: rules call\n// `enforceFieldOrder([...canonicalPackageJsonOrder, \"customKey\"])`.\n//\n// This order is derived EMPIRICALLY from oxfmt (the canonical formatter run\n// by `ts-builder check`): a freshly-refreshed package.json must pass\n// `oxfmt --check` so `pnpm check` is green without a prior `pnpm fmt`. oxfmt\n// also alphabetises the dependency sections — the `*-package-json.ts` bodies\n// call `enforceAlphabeticalOrder` on each dep section to match (scripts and\n// `exports` keep source order; oxfmt does not reorder them).\nexport const canonicalPackageJsonOrder = [\n \"name\",\n \"version\",\n \"private\",\n \"description\",\n \"keywords\",\n \"files\",\n \"type\",\n \"main\",\n \"module\",\n \"types\",\n \"exports\",\n \"scripts\",\n \"dependencies\",\n \"devDependencies\",\n \"peerDependencies\",\n \"optionalDependencies\",\n \"packageManager\",\n \"pnpm\",\n \"block\",\n \"block-software\",\n] as const;\n","// Root `package.json`: the initial generator and the drift-correcting body\n// rules, co-located. The body re-asserts the canonical scripts, devDeps,\n// peerDeps, and the final field-order projection (enforceFieldOrder is the\n// LAST call).\n\nimport {\n ensureField,\n ensureScript,\n ensureDevDeps,\n ensurePeerDeps,\n removeScript,\n removeField,\n pruneKeysMatching,\n enforceAlphabeticalOrder,\n enforceFieldOrder,\n} from \"../engine/api\";\nimport { canonicalPackageJsonOrder } from \"./shared/key-order\";\n\n// `variant=all` builds every variant the software declares — docker-vs-binary is not a per-script\n// choice. `no-software` builds placeholder software for validators.\n\nconst BUILD_SCRIPTS: Record<string, string> = {\n \"build:dev-local\":\n \"env PL_BUILD_CHANNEL=dev PL_BUILD_VARIANT=all PL_BUILD_LOCATION=local turbo run build\",\n \"build:dev-remote\":\n \"env PL_BUILD_CHANNEL=dev PL_BUILD_VARIANT=all PL_BUILD_LOCATION=remote turbo run build\",\n \"build:dev-no-software\": \"env PL_BUILD_CHANNEL=dev PL_BUILD_VARIANT=none turbo run build\",\n \"build:dev-binary-existing\":\n \"env PL_BUILD_CHANNEL=dev PL_BUILD_USE_PUBLISHED=true turbo run build\",\n \"build:release\":\n \"env PL_BUILD_CHANNEL=release PL_BUILD_VARIANT=all PL_BUILD_LOCATION=remote turbo run build\",\n};\n\n// `test` / `test:dry-run` run the build-then-test DAG in the dev-binary-local target; the live\n// backend's env reaches the integration tests via the turbo `test` task's passThroughEnv.\nconst TEST_SCRIPTS: Record<string, string> = {\n test: `env PL_BUILD_CHANNEL=dev PL_BUILD_VARIANT=binary PL_BUILD_LOCATION=local turbo run test --concurrency 1`,\n \"test:dry-run\": `env PL_BUILD_CHANNEL=dev PL_BUILD_VARIANT=binary PL_BUILD_LOCATION=local turbo run test --dry-run=json`,\n};\n\nexport function rootPackageJsonInitial(): Record<string, unknown> {\n // No `name`: the root is never published. Body rules re-assert\n // (removeField(\"name\")) as a drift-corrector.\n return {\n version: \"1.0.0\",\n private: true,\n scripts: {\n fmt: \"turbo run fmt\",\n check: \"turbo run check\",\n ...BUILD_SCRIPTS,\n ...TEST_SCRIPTS,\n \"mark-stable\": \"turbo run mark-stable\",\n \"do-pack\": \"turbo run do-pack\",\n watch: \"turbo watch build\",\n changeset: \"changeset\",\n \"version-packages\": \"changeset version\",\n // Deprecated alias of `upgrade-sdk`; kept for compatibility.\n \"update-sdk\": \"block-tools structure refresh --update-deps-only\",\n \"upgrade-sdk\":\n \"block-tools structure refresh --update-deps-only && pnpm i && block-tools structure refresh && pnpm i && pnpm fmt\",\n },\n peerDependencies: {\n oxlint: \"*\",\n oxfmt: \"*\",\n },\n devDependencies: {\n \"@changesets/cli\": \"catalog:\",\n \"@milaboratories/ts-builder\": \"sdk:\",\n \"@platforma-sdk/block-tools\": \"sdk:\",\n shx: \"catalog:\",\n turbo: \"catalog:\",\n },\n packageManager: \"pnpm@9.12.0\",\n };\n}\n\nexport function rootPackageJsonRules(): void {\n ensureField(\"packageManager\", \"pnpm@9.12.0\");\n\n // Root is never published — it carries no `name`; delete any stray one.\n removeField(\"name\");\n\n // Canonical lifecycle script set. The live backend's env reaches the\n // integration tests via the turbo `test` task's passThroughEnv (no\n // --env-mode=loose needed).\n ensureScript(\"fmt\", \"turbo run fmt\");\n ensureScript(\"check\", \"turbo run check\");\n for (const [name, command] of Object.entries(BUILD_SCRIPTS)) {\n ensureScript(name, command);\n }\n for (const [name, command] of Object.entries(TEST_SCRIPTS)) {\n ensureScript(name, command);\n }\n // No bare `build` — a developer must pick a scenario (`build:dev-local`, `build:release`,\n // …). Drop the legacy plain `build` and the old single `build:dev` so migrated blocks converge.\n removeScript(\"build\");\n removeScript(\"build:dev\");\n ensureScript(\"mark-stable\", \"turbo run mark-stable\");\n ensureScript(\"do-pack\", \"turbo run do-pack\");\n ensureScript(\"watch\", \"turbo watch build\");\n ensureScript(\"changeset\", \"changeset\");\n ensureScript(\"version-packages\", \"changeset version\");\n // `update-sdk` is a deprecated alias of `upgrade-sdk`, kept for compatibility;\n // `update` is the pre-rename name — drop it so refreshed blocks converge.\n ensureScript(\"update-sdk\", \"block-tools structure refresh --update-deps-only\");\n removeScript(\"update\");\n // Full SDK-upgrade flow: bump catalog (deps-only) → install → re-apply\n // structure against the freshly-pulled deps → install AGAIN (the structural\n // pass can add new devDeps — e.g. ts-builder/oxlint/oxfmt on a first\n // migration — that `pnpm fmt` then needs on PATH) → format. Wrapped as one\n // script. `pnpm fmt` (turbo run fmt) leaves the tree oxfmt-clean after the\n // structural rewrite so a follow-up `pnpm check` passes.\n ensureScript(\n \"upgrade-sdk\",\n \"block-tools structure refresh --update-deps-only && pnpm i && block-tools structure refresh && pnpm i && pnpm fmt\",\n );\n\n ensureDevDeps({\n \"@changesets/cli\": \"catalog:\",\n \"@milaboratories/ts-builder\": \"sdk:\",\n \"@platforma-sdk/block-tools\": \"sdk:\",\n shx: \"catalog:\",\n turbo: \"catalog:\",\n });\n\n ensurePeerDeps({\n oxlint: \"*\",\n oxfmt: \"*\",\n });\n\n // Strip committed dev-machine override clutter: keys like \"//pnpm\",\n // \"///pnpm\", \"--\" carrying a pnpm/overrides sub-object (often absolute\n // local paths). Left in place these are unknown top-level keys that oxfmt\n // shoves past the canonical sections, breaking `oxfmt --check`.\n pruneKeysMatching((key, value): boolean => {\n if (!/^(\\/\\/|--)/.test(key)) return false;\n if (typeof value !== \"object\" || value === null) return false;\n const v = value as { pnpm?: unknown; overrides?: unknown };\n return v.pnpm !== undefined || v.overrides !== undefined;\n });\n\n enforceAlphabeticalOrder(\"dependencies\");\n enforceAlphabeticalOrder(\"devDependencies\");\n enforceAlphabeticalOrder(\"peerDependencies\");\n enforceAlphabeticalOrder(\"optionalDependencies\");\n enforceFieldOrder([...canonicalPackageJsonOrder]);\n}\n","// Root `turbo.json`: the initial generator and the drift-correcting body\n// rules, co-located. Managed (not fixed) so the engine OWNS its own task\n// graph but LEAVES author-added tasks alone — `ensureFieldEntries(\"tasks\", …)`\n// merges the canonical engine tasks over whatever is there, preserving any\n// other key under `tasks`.\n//\n// Why this matters: blocks with a Python software package carry a\n// `software:reqs` task (a `requirements-sync` CI job runs `turbo run\n// software:reqs`). When turbo.json was `fixed`, every `upgrade-sdk` wiped that\n// task and CI failed with \"Could not find task software:reqs\". `software:reqs`\n// is deliberately NOT in the engine-owned set below — it (and any custom task)\n// is author-owned and survives refresh via the merge.\n\nimport { ensureField, ensureFieldEntries, removeField, enforceFieldOrder } from \"../engine/api\";\n\nconst SCHEMA = \"https://turbo.build/schema.json\";\nconst GLOBAL_DEPENDENCIES = [\"tsconfig.json\"];\n\n// The tasks the engine owns. Re-asserted on every refresh; author tasks\n// (e.g. `software:reqs`) are merged around these, never clobbered.\nconst ENGINE_TASKS: Record<string, unknown> = {\n fmt: { cache: false },\n check: { dependsOn: [\"^build\"], outputs: [] },\n build: {\n dependsOn: [\"^build\", \"check\"],\n inputs: [\"$TURBO_DEFAULT$\"],\n env: [\n \"PL_DOCKER_REGISTRY_PUSH_TO\",\n \"PL_BUILD_CHANNEL\",\n \"PL_BUILD_VARIANT\",\n \"PL_BUILD_LOCATION\",\n \"PL_BUILD_USE_PUBLISHED\",\n \"PL_DEV_DOCKER_PUSH_URL\",\n \"PL_DEV_DOCKER_PULL_URL\",\n \"PL_DEV_BINARY_UPLOAD_URL\",\n \"PL_RELEASE_DOCKER_PUSH_URL\",\n \"PL_RELEASE_DOCKER_PULL_URL\",\n \"PL_RELEASE_BINARY_UPLOAD_URL\",\n \"PL_REGISTRY_PLATFORMA_OPEN_UPLOAD_URL\",\n ],\n passThroughEnv: [\"AWS_*\", \"PL_AWS_*\"],\n outputs: [\"./dist/**\", \"./block-pack/**\", \"./pkg-*.tgz\"],\n },\n \"do-pack\": { dependsOn: [\"build\"], outputs: [\"package.tgz\"] },\n test: {\n dependsOn: [\"build\", \"check\"],\n passThroughEnv: [\"PL_ADDRESS\", \"PL_TEST_PASSWORD\", \"PL_TEST_USER\", \"PL_TEST_PROXY\", \"DEBUG\"],\n },\n \"mark-stable\": { passThroughEnv: [\"PL_REGISTRY\", \"AWS_*\"], cache: false },\n};\n\nexport function rootTurboJsonInitial(): Record<string, unknown> {\n return {\n $schema: SCHEMA,\n globalDependencies: GLOBAL_DEPENDENCIES,\n tasks: { ...ENGINE_TASKS },\n };\n}\n\nexport function rootTurboJsonRules(): void {\n ensureField(\"$schema\", SCHEMA);\n ensureField(\"globalDependencies\", GLOBAL_DEPENDENCIES);\n // Merge the engine tasks, preserving any author task (software:reqs, …).\n ensureFieldEntries(\"tasks\", ENGINE_TASKS);\n // Legacy single-dev-build task, superseded by the env-parameterised `build`\n // task + `build:dev-*` package scripts (software-build spec). The\n // root package.json rule likewise drops the `build:dev` script; drop the\n // matching turbo task so migrated blocks converge.\n removeField(\"tasks.build:dev\");\n enforceFieldOrder([\"$schema\", \"globalDependencies\", \"tasks\"]);\n}\n","// npm registry client used by the catalog ensure-family (`ensureCatalogLatest`).\n//\n// The content-rule builder is synchronous; the runner pre-resolves\n// \"latest\" versions via this client and passes a sync lookup function\n// to `withManagedYaml(..., { getLatestVersion })`. The real impl talks\n// to https://registry.npmjs.org with retry + Retry-After handling\n// ported from `tools/blocks-deps-updater/src/updater.ts`. The mock\n// impl wraps an in-memory map and is the only client used in unit\n// tests.\n\nimport { setTimeout as sleep } from \"node:timers/promises\";\n\nexport interface RegistryClient {\n getLatestVersion(packageName: string): Promise<string>;\n /** Read the version `packageName@version` declares for `depName` in its\n * published manifest. `version` may be \"latest\" (resolved via the\n * dist-tags). Looks in `dependencies` first, then `peerDependencies`.\n * Returns `undefined` when the dep is declared in neither section. */\n getDeclaredDependency(\n packageName: string,\n version: string,\n depName: string,\n ): Promise<string | undefined>;\n}\n\nconst RETRY_COUNT = 2;\nconst RETRY_BASE_MS = 500;\nconst TIMEOUT_MS = 30_000;\n\n/** Parse the HTTP Retry-After header (RFC 9110): either a delay in\n * seconds or an absolute HTTP-date. Returns the delay in ms, or null\n * if the header is missing / unparseable. */\nexport function parseRetryAfter(header: string | null): number | null {\n if (!header) return null;\n const seconds = Number(header);\n if (Number.isFinite(seconds) && seconds > 0) return seconds * 1000;\n const date = Date.parse(header);\n if (!Number.isNaN(date)) return Math.max(0, date - Date.now());\n return null;\n}\n\nasync function fetchWithRetry(url: string): Promise<Response> {\n for (let attempt = 1; ; attempt++) {\n let res: Response;\n // Only the network call is retry-eligible: a transport error\n // (timeout, DNS, reset) is transient. HTTP-status handling sits\n // OUTSIDE this catch so a non-retryable status (404/403) throws\n // immediately instead of being swallowed and retried.\n try {\n res = await fetch(url, { signal: AbortSignal.timeout(TIMEOUT_MS) });\n } catch (err) {\n if (attempt > RETRY_COUNT) throw err;\n const delay = RETRY_BASE_MS * 2 ** (attempt - 1) * (0.8 + 0.4 * Math.random());\n await sleep(delay);\n continue;\n }\n if (res.ok) return res;\n const retryable = res.status === 429 || res.status >= 500;\n if (!retryable || attempt > RETRY_COUNT) {\n throw new Error(`registry returned HTTP ${res.status}`);\n }\n const retryAfterMs = parseRetryAfter(res.headers.get(\"retry-after\"));\n if (retryAfterMs != null) {\n await sleep(retryAfterMs);\n continue;\n }\n const delay = RETRY_BASE_MS * 2 ** (attempt - 1) * (0.8 + 0.4 * Math.random());\n await sleep(delay);\n }\n}\n\n/** Shape of the per-version manifest doc fetched from\n * `https://registry.npmjs.org/<pkg>/<version>` (only the dep sections are\n * read). */\ntype PackageManifest = {\n dependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n};\n\n/** Live npm registry client. Hits the network on each call. */\nexport function createRealRegistryClient(): RegistryClient {\n return {\n async getLatestVersion(packageName: string): Promise<string> {\n const res = await fetchWithRetry(\n `https://registry.npmjs.org/-/package/${packageName}/dist-tags`,\n );\n const tags = (await res.json()) as Record<string, string>;\n const latest = tags.latest;\n if (!latest) {\n throw new Error(\"no 'latest' dist-tag in registry response\");\n }\n return latest;\n },\n async getDeclaredDependency(\n packageName: string,\n version: string,\n depName: string,\n ): Promise<string | undefined> {\n const res = await fetchWithRetry(`https://registry.npmjs.org/${packageName}/${version}`);\n const manifest = (await res.json()) as PackageManifest;\n return manifest.dependencies?.[depName] ?? manifest.peerDependencies?.[depName];\n },\n };\n}\n\n/** In-memory client backed by a fixed `name → version` map. The optional\n * `manifests` map (`pkg@version` → declared deps) backs\n * `getDeclaredDependency`; \"latest\" keys resolve via the `versions` map. */\nexport function createMockRegistryClient(\n versions: Record<string, string>,\n manifests: Record<string, Record<string, string>> = {},\n): RegistryClient {\n function resolveVersion(packageName: string, version: string): string {\n if (version !== \"latest\") return version;\n const v = versions[packageName];\n if (v === undefined) {\n throw new Error(`mock registry: no version configured for '${packageName}'`);\n }\n return v;\n }\n return {\n async getLatestVersion(packageName: string): Promise<string> {\n const v = versions[packageName];\n if (v === undefined) {\n throw new Error(`mock registry: no version configured for '${packageName}'`);\n }\n return v;\n },\n async getDeclaredDependency(\n packageName: string,\n version: string,\n depName: string,\n ): Promise<string | undefined> {\n const resolved = resolveVersion(packageName, version);\n const deps = manifests[`${packageName}@${resolved}`];\n if (deps === undefined) {\n throw new Error(`mock registry: no manifest configured for '${packageName}@${resolved}'`);\n }\n return deps[depName];\n },\n };\n}\n\n/** Resolve a batch of `name → latest` entries in parallel. */\nexport async function prefetchLatestVersions(\n client: RegistryClient,\n packageNames: readonly string[],\n): Promise<Map<string, string>> {\n const entries = await Promise.all(\n packageNames.map(async (n) => [n, await client.getLatestVersion(n)] as const),\n );\n return new Map(entries);\n}\n\n/** Build a sync lookup function (the shape `withManagedYaml` consumes)\n * from a prefetched map. Returns undefined for unknown names. */\nexport function makeSyncLookup(\n resolved: Map<string, string>,\n): (packageName: string) => string | undefined {\n return (name) => resolved.get(name);\n}\n\n/** Catalog package-name patterns the version-resolution rules\n * (`ensureCatalogLatest`) match against — the `@platforma-sdk/*` and\n * `@milaboratories/*` SDK families. Infra/runtime entries (turbo, shx,\n * …) are deliberately NOT here: they stay a curated floor, not auto-latest.\n * Shared so `init` (names from the SDK pin map) and `refresh\n * --update-deps-only` (names from the on-disk catalog) select the same\n * set. */\nexport const CATALOG_BUMP_PATTERNS: readonly RegExp[] = [/^@platforma-sdk\\//, /^@milaboratories\\//];\n\n/** True if `name` is a version-resolved SDK package (matches any bump\n * pattern). */\nexport function matchesBumpPattern(name: string): boolean {\n return CATALOG_BUMP_PATTERNS.some((p) => p.test(name));\n}\n\n/** Prefetch npm \"latest\" for `names` and return the sync lookup the\n * runner passes to the catalog ensure-family (`ensureCatalogLatest`).\n * Empty list → a lookup that\n * resolves nothing (no network). A network/registry failure REJECTS\n * (callers that require the network — `init` — let it propagate).\n * `client` defaults to the live npm client; tests inject a mock. */\nexport async function buildRegistryLookupForNames(\n names: readonly string[],\n client: RegistryClient = createRealRegistryClient(),\n): Promise<(packageName: string) => string | undefined> {\n if (names.length === 0) return () => undefined;\n const resolved = await prefetchLatestVersions(client, names);\n return makeSyncLookup(resolved);\n}\n\n/** A catalog entry whose version is DERIVED from the version another\n * package declares for it. `entry` is the catalog key (== the dep name in\n * the source manifest); `of` is the package whose manifest is read; the\n * optional `ofVersion` pins which release of `of` to read (default: npm\n * latest, the same release the catalog bump pins `of` to). Consumed by\n * `pinCatalogToDependencyOf`. */\nexport type DerivedCatalogPin = {\n entry: string;\n of: string;\n ofVersion?: string;\n};\n\n/** True iff `version` is a bare exact `x.y.z(-prerelease)?` — no range\n * modifier (`^`, `~`, `>=`, `*`, `||`, ` - `, `x`, workspace:, etc.). */\nfunction isExactVersion(version: string): boolean {\n return /^\\d+\\.\\d+\\.\\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(version);\n}\n\n/** Prefetch every derived pin and build the sync lookup the runner passes\n * to `pinCatalogToDependencyOf` (`entry → exact version`). Reads\n * `pin.of`'s manifest (at `pin.ofVersion`, default npm latest) and the\n * version it declares for `pin.entry`. Policy (b): THROWS at prefetch time\n * if the source declares the dep as a non-exact (ranged) version or does\n * not declare it at all — a derived pin must resolve to an exact version\n * or it is a configuration error. Empty list → a lookup that resolves\n * nothing (no network). A registry failure REJECTS. `client` defaults to\n * the live npm client; tests inject a mock. */\nexport async function buildDerivedPinLookupForPins(\n pins: readonly DerivedCatalogPin[],\n client: RegistryClient = createRealRegistryClient(),\n): Promise<(entry: string) => string | undefined> {\n if (pins.length === 0) return () => undefined;\n const entries = await Promise.all(\n pins.map(async (pin) => {\n const declared = await client.getDeclaredDependency(\n pin.of,\n pin.ofVersion ?? \"latest\",\n pin.entry,\n );\n if (declared === undefined) {\n throw new Error(\n `derived catalog pin '${pin.entry}': package '${pin.of}'` +\n `${pin.ofVersion ? `@${pin.ofVersion}` : \" (latest)\"} declares no ` +\n `dependency '${pin.entry}'. A derived pin requires the source to ` +\n `declare the dep as an exact version.`,\n );\n }\n if (!isExactVersion(declared)) {\n throw new Error(\n `derived catalog pin '${pin.entry}': package '${pin.of}'` +\n `${pin.ofVersion ? `@${pin.ofVersion}` : \" (latest)\"} declares ` +\n `'${pin.entry}: ${declared}', which is not an exact version. ` +\n `A derived pin requires an exact ('x.y.z') source dependency so ` +\n `the catalog can pin to it precisely.`,\n );\n }\n return [pin.entry, declared] as const;\n }),\n );\n const resolved = new Map(entries);\n return (entry) => resolved.get(entry);\n}\n","// Retired toolchain dependencies — a SINGLE source of truth.\n//\n// These packages are superseded by the canonical toolchain (ts-builder owns\n// the build, vue-tsc, and the vite plugins; oxlint/oxfmt replace eslint) and\n// must be shed from a migrated block in BOTH places at once:\n// - the root catalog → `ensureCatalogAbsent` (root-pnpm-workspace)\n// - every package.json scope → `removeDep` (via removeRetiredToolchainDeps)\n//\n// Removing from only one side is a latent bug: a catalog entry dropped while a\n// package still references `<dep>: \"catalog:\"` leaves a dangling reference that\n// breaks `pnpm install`. Driving both from this one list makes that impossible\n// — add (or un-retire) a dependency HERE, once.\n//\n// Per-entry rationale:\n// vite / tsup — bundling now goes through ts-builder + rolldown.\n// vue-tsc — ts-builder runs vue-tsc internally for `block-ui`; a\n// direct dep resolves a different version than the\n// toolchain pins, causing type clashes in main.ts.\n// @vitejs/plugin-vue — bundled by ts-builder's internal vite config.\n// vite-plugin-dts — .d.ts emit is handled by ts-builder.\n// @platforma-sdk/eslint-config — eslint is retired; linting runs via oxlint\n// inside `ts-builder check`.\n\nimport { removeDep } from \"../../engine/api\";\n\nexport const RETIRED_TOOLCHAIN_DEPS: readonly string[] = [\n \"vite\",\n \"tsup\",\n \"vue-tsc\",\n \"@vitejs/plugin-vue\",\n \"vite-plugin-dts\",\n \"@platforma-sdk/eslint-config\",\n];\n\n/** Drop every retired toolchain dep from the current package.json scope.\n * Idempotent (a `removeDep` on an absent key is a no-op), so it is safe to\n * call uniformly from every package.json rules body regardless of which deps\n * a given scope ever carried. Pairs with the catalog-side removal in\n * `rootPnpmWorkspaceRules`. */\nexport function removeRetiredToolchainDeps(): void {\n for (const name of RETIRED_TOOLCHAIN_DEPS) removeDep(name);\n}\n","// Root `pnpm-workspace.yaml`: the catalog membership, the initial generator,\n// and the drift-correcting body rules, co-located.\n//\n// The catalog is split in two:\n// - SDK packages: `SDK_CATALOG_PACKAGES` is a list of package NAMES (catalog\n// membership only — no versions). On init the `onInitOrUpdate` frame fetches\n// npm latest for each (init requires network) and writes it; the keys must\n// exist in the catalog first for that in-place bump to land, so the initial\n// generator seeds them with an obviously-invalid placeholder that the bump\n// always overwrites. No version is stored here and there is no fallback.\n// - infra / tooling: a `~`-floored set we control deliberately. No rule\n// ever fetches these — refresh leaves them untouched and update-deps\n// does not match them. Bump the floor here when authoring the scaffold.\n//\n// Default refresh is purely structural: it verifies the workspace\n// `packages:` list matches the discovered modules and leaves every catalog\n// version exactly as the author/lockfile has it. Version resolution (writing\n// npm-latest for the SDK families) lives in the separate `onInitOrUpdate`\n// frame (`rootCatalogBumpRules`), which fires on init + update-deps only.\n\nimport { ensureWorkspaceModulePaths, ensureCatalogAbsent, type RunContext } from \"../engine/api\";\nimport { matchesBumpPattern, type DerivedCatalogPin } from \"../engine/registry-client\";\nimport { RETIRED_TOOLCHAIN_DEPS } from \"./shared/retired-deps\";\n\n/** SDK packages that live in the catalog (membership only — no versions).\n * Init fetches npm latest for each; refresh leaves them as the lockfile has\n * them. */\nexport const SDK_CATALOG_PACKAGES: readonly string[] = [\n \"@platforma-sdk/model\",\n \"@platforma-sdk/ui-vue\",\n \"@platforma-sdk/workflow-tengo\",\n \"@platforma-sdk/test\",\n \"@platforma-sdk/block-tools\",\n \"@platforma-sdk/tengo-builder\",\n \"@platforma-sdk/package-builder\",\n \"@milaboratories/ts-builder\",\n \"@milaboratories/ts-configs\",\n];\n\n/** Init-only catalog seed for every SDK package: an obviously-invalid version\n * the `onInitOrUpdate` bump always overwrites with npm latest. It exists only\n * so the catalog key is present for that in-place bump. It is never a\n * fallback — a real init requires network and overwrites it; were it ever to\n * reach a lockfile, `pnpm install` fails loudly on the unresolvable version. */\nconst SDK_CATALOG_INIT_PLACEHOLDER = \"0.0.0-init-must-fetch\";\n\n// Invariant: every SDK package must be fetched on init (match a bump pattern),\n// or its placeholder would ship un-resolved. Caught at load time.\nfor (const name of SDK_CATALOG_PACKAGES) {\n if (!matchesBumpPattern(name)) {\n throw new Error(\n `SDK_CATALOG_PACKAGES entry '${name}' matches no catalog bump pattern; ` +\n `its placeholder would never be resolved to npm latest on init. ` +\n `Add it to CATALOG_BUMP_PATTERNS or move it to the infra floor.`,\n );\n }\n}\n\n/** Infra / tooling — a `~`-floored curated set. Not exact-pinned on refresh\n * and not bumped by update-deps. */\nexport const INFRA_CATALOG_FLOOR: Record<string, string> = {\n turbo: \"~2.8.11\",\n shx: \"~0.4.0\",\n \"@changesets/cli\": \"~2.29.8\",\n vitest: \"~4.0.18\",\n};\n\n/** Catalog entries whose exact version is DERIVED from the version another\n * package declares for them (see `pinCatalogToDependencyOf`). Resolved on\n * init + update-deps and OVERWRITES the on-disk entry.\n *\n * `vue`: the seeded ui depends on `vue` (catalog:). `@platforma-sdk/ui-vue`\n * pins vue as an EXACT regular dependency (not a peer), so the block must\n * pin the SAME exact version — a floated `~` lets the ui resolve a newer\n * 3.5.x than ui-vue's, yielding two vue instances and a SdkPluginV3-vs-Plugin\n * type clash in `main.ts`. Deriving the pin from ui-vue's declared dep keeps\n * the block in lockstep with whatever vue ui-vue's npm-latest pins, with no\n * hand-maintained version here.\n *\n * `@milaboratories/helpers`: the block's model/ui depend on it (catalog:) and\n * `@platforma-sdk/model` pins it as an EXACT regular dependency. A hand-pinned\n * floor that lags a model bump yields two helpers instances — the model's\n * inferred `platforma` type then references the SDK's copy, not the block's,\n * failing `tsc` with TS2742. Deriving from model keeps them in lockstep. */\nexport const DERIVED_CATALOG_PINS: readonly DerivedCatalogPin[] = [\n { entry: \"vue\", of: \"@platforma-sdk/ui-vue\" },\n { entry: \"@milaboratories/helpers\", of: \"@platforma-sdk/model\" },\n];\n\n/** Catalog name of the python runenv. Added to a block's catalog only when\n * the block carries a software module. Pinned to an EXACT version — updating\n * the python runenv is an explicit author decision, never automatic. */\nexport const RUNENV_PYTHON = \"@platforma-open/milaboratories.runenv-python-3\";\nexport const RUNENV_PYTHON_VERSION = \"1.8.2\";\n\nexport function rootPnpmWorkspaceInitial(ctx: RunContext): Record<string, unknown> {\n // Non-root module paths only. The block root (\"\") is discovered\n // implicitly and must never be written as a \".\" entry — listing it breaks\n // turbo's task graph. Root stays in ctx.modules for rule fan-out.\n const paths = ctx.modules\n .filter((m) => m.path !== \"\")\n .map((m) => m.path)\n .sort();\n // SDK packages first (placeholder, overwritten by the init bump), then the\n // infra floor — matching the order the catalog is written.\n const catalog: Record<string, string> = {};\n for (const name of SDK_CATALOG_PACKAGES) catalog[name] = SDK_CATALOG_INIT_PLACEHOLDER;\n Object.assign(catalog, INFRA_CATALOG_FLOOR);\n if (ctx.modules.some((m) => m.scope === \"software\")) {\n catalog[RUNENV_PYTHON] = RUNENV_PYTHON_VERSION;\n }\n return {\n packages: paths,\n catalog,\n };\n}\n\nexport function rootPnpmWorkspaceRules(): void {\n ensureWorkspaceModulePaths();\n // Catalog side of the retired-dep cleanup — the per-package side sheds the\n // matching `catalog:` references.\n for (const name of RETIRED_TOOLCHAIN_DEPS) ensureCatalogAbsent(name);\n}\n","// Root `.gitignore` content rules.\n// The static template under templates/static/root/.gitignore carries the\n// canonical line set; the body re-asserts the same set via\n// `ensureGitignoreEntries` so any future edit that drops a required line\n// is restored.\n\nimport { ensureGitignoreEntries } from \"../engine/api\";\n\nexport const GITIGNORE_REQUIRED_LINES = [\n \".test_auth.json\",\n \"node_modules/\",\n \"dist/\",\n \"block-pack/\",\n \"dev/\",\n \"work/\",\n \"log/\",\n \".turbo\",\n \"vite.config.*.timestamp-*\",\n \"software/**/*.tgz\",\n \".DS_Store\",\n \".vscode/sftp.json\",\n \"test-dry-run.json\",\n];\n\nexport function rootGitignoreRules(): void {\n ensureGitignoreEntries(GITIGNORE_REQUIRED_LINES);\n}\n","// Root-scope rules — apply only to the standalone block layout (the\n// pnpm workspace + tooling around the block). `--sdk-internal` blocks\n// skip this whole scope: the parent monorepo owns root files. Hence the\n// `when(({ ctx }) => !ctx.isSdkInternal, ...)` wrapper.\n\nimport { scope, when, fixed, managed, file, generate } from \"../engine/api\";\nimport { rootPackageJsonInitial, rootPackageJsonRules } from \"./root-package-json\";\nimport { rootTurboJsonInitial, rootTurboJsonRules } from \"./root-turbo-json\";\nimport { rootPnpmWorkspaceInitial, rootPnpmWorkspaceRules } from \"./root-pnpm-workspace\";\nimport { rootGitignoreRules } from \"./root-gitignore\";\n\nexport function rootRules(): void {\n scope(\"root\", () => {\n when(\n ({ ctx }) => !ctx.isSdkInternal,\n () => {\n managed(\n \"turbo.json\",\n generate(() => rootTurboJsonInitial()),\n () => {\n rootTurboJsonRules();\n },\n );\n fixed(\".vscode/settings.json\", file(\"root/.vscode/settings.json\"));\n\n managed(\n \"package.json\",\n generate(() => rootPackageJsonInitial()),\n () => {\n rootPackageJsonRules();\n },\n );\n\n managed(\n \"pnpm-workspace.yaml\",\n generate((ctx) => rootPnpmWorkspaceInitial(ctx)),\n () => {\n rootPnpmWorkspaceRules();\n },\n );\n\n managed(\".gitignore\", file(\"root/.gitignore\"), () => {\n rootGitignoreRules();\n });\n },\n );\n });\n}\n","// Root-scope CI workflows — the block's GitHub Actions `build.yaml` and\n// `mark-stable.yaml`. Engine-OWNED (`fixed`): rewritten verbatim on every\n// refresh, generated from the block's identity (short name); everything else\n// is a constant baked into the templates.\n//\n// Why fixed, not managed: previously each block carried a hand-copied\n// workflow pinning the shared reusable workflow at `@v4` (a moving branch),\n// so a breaking shared-CI change was absorbed silently and per-block edits\n// drifted. Engine-owning the file makes the pin + job wiring centrally\n// refreshable; the only per-block bits are derived (app-name, slug), so\n// nothing author-tunable is clobbered.\n//\n// Standalone blocks only — `--sdk-internal` blocks (`etc/blocks/*`) carry no\n// per-block workflow (the monorepo owns their CI), hence the\n// `when(!isSdkInternal)` guard, matching the rest of the root scope.\n\nimport { scope, when, fixed, tpl } from \"../engine/api\";\n\n/** Readable default CI label from a short name (`mixcr-clonotyping-2` →\n * `Mixcr Clonotyping 2`). Dash/underscore words, title-cased. Human-curated\n * casing (e.g. `MiXCR`) is not recoverable from the slug — this is a\n * generated label, not the marketing name. */\nfunction humanizeShortName(shortName: string): string {\n return shortName\n .split(/[-_]+/)\n .filter((w) => w.length > 0)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(\" \");\n}\n\nexport function rootCiRules(): void {\n scope(\"root\", () => {\n when(\n ({ ctx }) => !ctx.isSdkInternal,\n () => {\n fixed(\n \".github/workflows/build.yaml\",\n tpl(\"workflows/build.tpl.yaml\", (ctx) => {\n const shortName = ctx.blockVars.shortName;\n return {\n appName: `Block: ${humanizeShortName(shortName)}`,\n appNameSlug: `block-${shortName}`,\n };\n }),\n );\n fixed(\n \".github/workflows/mark-stable.yaml\",\n tpl(\"workflows/mark-stable.tpl.yaml\", (ctx) => ({\n appName: `Block: ${humanizeShortName(ctx.blockVars.shortName)} - Mark Stable`,\n })),\n );\n },\n );\n });\n}\n","// Facade `package.json`: the initial generator and the drift-correcting body\n// rules, co-located. The facade is the only sibling of a block that publishes,\n// and it ships SLIM: `dependencies` is empty (the consumer's install pulls zero\n// `@platforma-sdk/*` transitive runtime deps), siblings are build-time\n// `workspace:*` devDeps, and the built `dist/` + `block-pack/` carry everything\n// the loader needs.\n\nimport {\n ensureField,\n ensureScript,\n ensureDevDep,\n ensureWorkspaceScopeDevDeps,\n requireField,\n removeScript,\n enforceAlphabeticalOrder,\n enforceFieldOrder,\n type RunContext,\n} from \"../engine/api\";\nimport { findModules, scopeDepMaps } from \"../engine/ctx\";\nimport { canonicalPackageJsonOrder } from \"./shared/key-order\";\n\n/** Per-org publish coordinates: the S3 upload bucket and the public registry\n * serve URL the facade's `prepublishOnly` script passes to `block-tools\n * publish`. One block-registry bucket serves both orgs; only the public read\n * hostname differs by org. Safe for the never-published `etc/blocks` test\n * blocks — the script never runs for them. Extend the map per new org. */\nconst ORG_PUBLISH_TARGETS: Record<string, { s3: string; serveUrl: string }> = {\n \"@platforma-open\": {\n s3: \"s3://milab-euce1-prod-pkgs-s3-block-registry/pub/releases/?region=eu-central-1\",\n serveUrl: \"https://blocks.pl-open.science\",\n },\n \"@milaboratories\": {\n s3: \"s3://milab-euce1-prod-pkgs-s3-block-registry/pub/releases/?region=eu-central-1\",\n serveUrl: \"https://block.registry.platforma.bio/releases\",\n },\n};\n\n/** Fallback for an org not in the table — keeps the generated script valid\n * (and inert until published) rather than throwing during a refresh. */\nconst FALLBACK_PUBLISH_TARGET = {\n s3: \"s3://milab-euce1-prod-pkgs-s3-block-registry/pub/releases/?region=eu-central-1\",\n serveUrl: \"https://blocks.pl-open.science\",\n};\n\n/** Where the in-SDK blocks (`etc/blocks/*`) publish: the aux/dev registry, not\n * production `pub/releases/`. These are the monorepo's test/example blocks, so\n * one target regardless of org — their `@milaboratories` scope must NOT route\n * them to the real catalog alongside standalone blocks. */\nconst SDK_INTERNAL_PUBLISH_TARGET = {\n s3: \"s3://milab-euce1-prod-pkgs-s3-block-registry/aux/dev/?region=eu-central-1\",\n serveUrl: \"https://aux-blocks.pl-open.science\",\n};\n\nfunction prepublishScript(npmOrg: string, isSdkInternal: boolean): string {\n const t = isSdkInternal\n ? SDK_INTERNAL_PUBLISH_TARGET\n : (ORG_PUBLISH_TARGETS[npmOrg] ?? FALLBACK_PUBLISH_TARGET);\n return `block-tools publish -r ${t.s3} --registry-serve-url ${t.serveUrl}`;\n}\n\n/** The facade's `block.components` map: the dist artifact each module build\n * emits, keyed by role. Fully determined by the discovered modules — the body\n * rule re-asserts this exact value, so it is engine-managed (NOT an author\n * seed). Mirrors the artifact paths produced by each scope's build:\n * workflow → pl-tengo, model → build-model, ui → ts-builder. */\nexport function blockComponents(ctx: RunContext): Record<string, string> {\n const components: Record<string, string> = {};\n for (const m of findModules(ctx, \"workflow\"))\n components.workflow = `${m.name}/dist/tengo/tpl/main.plj.gz`;\n for (const m of findModules(ctx, \"model\")) components.model = `${m.name}/dist/model.json`;\n for (const m of findModules(ctx, \"ui\")) components.ui = `${m.name}/dist`;\n return components;\n}\n\n/** The slim facade's canonical scripts (build / check / prepublishOnly /\n * do-pack). Shared by the initial generator and the body rule so they cannot\n * drift apart. `prepublishOnly` routes by block kind: in-SDK blocks publish to\n * the aux/dev registry, standalone blocks to their per-org production target. */\nfunction blockScripts(npmOrg: string, isSdkInternal: boolean): Record<string, string> {\n return {\n build: \"ts-builder build --target block-facade && block-tools pack\",\n check: \"ts-builder type-check --target block-facade\",\n prepublishOnly: prepublishScript(npmOrg, isSdkInternal),\n \"do-pack\": \"shx rm -f package.tgz && pnpm pack && shx mv *.tgz package.tgz\",\n };\n}\n\n/** The facade's build/publish devDependencies (the workspace `model`/`ui`/\n * `workflow` siblings are added separately, from discovery). `sdk:` resolves\n * to `workspace:*` for in-monorepo blocks and `catalog:` for standalone — the\n * body rule re-asserts the same set. */\nconst FACADE_DEV_DEPS = {\n \"@milaboratories/ts-builder\": \"sdk:\",\n \"@milaboratories/ts-configs\": \"sdk:\",\n \"@platforma-sdk/block-tools\": \"sdk:\",\n \"@platforma-sdk/model\": \"sdk:\",\n shx: \"catalog:\",\n typescript: \"catalog:\",\n} as const;\n\n/** The facade's `exports` map: a single `.` entry. `sources` keeps monorepo IDE\n * go-to-definition pointing at `src/` (external consumers don't enable it);\n * `types`/`default` carry the bundled `.d.ts` / `.js` from `dist/`. No\n * `./AGENTS` subpath — that surface ships as a registry-side component. */\nconst FACADE_EXPORTS = {\n \".\": {\n sources: \"./src/index.ts\",\n types: \"./dist/index.d.ts\",\n default: \"./dist/index.js\",\n },\n};\n\n/** Fail loudly if any required `block.*` field is empty — a missing\n * title / description / logo / organization or empty components map would\n * otherwise produce an init block that `block-tools pack` rejects only\n * later. Asserted at generation time so the failure is immediate. */\nfunction assertBlockFieldsFilled(block: {\n components: Record<string, string>;\n meta: Record<string, unknown>;\n}): void {\n if (Object.keys(block.components).length === 0) {\n throw new Error(\"block.components is empty — no workflow/model/ui module was discovered\");\n }\n const meta = block.meta as {\n title?: unknown;\n description?: unknown;\n logo?: unknown;\n organization?: { name?: unknown; url?: unknown; logo?: unknown };\n };\n const required: [string, unknown][] = [\n [\"block.meta.title\", meta.title],\n [\"block.meta.description\", meta.description],\n [\"block.meta.logo\", meta.logo],\n [\"block.meta.organization.name\", meta.organization?.name],\n [\"block.meta.organization.url\", meta.organization?.url],\n [\"block.meta.organization.logo\", meta.organization?.logo],\n ];\n for (const [path, value] of required) {\n if (typeof value !== \"string\" || value === \"\") {\n throw new Error(`required block field '${path}' is empty`);\n }\n }\n}\n\nexport function blockPackageJsonInitial(ctx: RunContext): Record<string, unknown> {\n const v = ctx.blockVars;\n // The facade's siblings are build-time devDeps, never runtime deps — the\n // facade ships its content bundled inside dist/ + block-pack/, so the\n // consumer needs no runtime resolution into siblings. Software/test are\n // excluded (the workflow owns software; a test→facade dep would be a cycle).\n const devDeps: Record<string, string> = {\n ...FACADE_DEV_DEPS,\n ...scopeDepMaps(ctx, \"model\"),\n ...scopeDepMaps(ctx, \"ui\"),\n ...scopeDepMaps(ctx, \"workflow\"),\n };\n // `block-tools pack` requires both `block.components` and `block.meta`. The\n // author edits the placeholder meta before publishing.\n const block = {\n components: blockComponents(ctx),\n meta: {\n title: v.shortName,\n description: `${v.shortName} block`,\n logo: \"file:logos/block-logo.png\",\n organization: {\n name: v.orgScope,\n url: \"https://example.com\",\n logo: \"file:logos/organization-logo.png\",\n },\n },\n };\n assertBlockFieldsFilled(block);\n return {\n name: `${v.facadeName}.block`,\n version: \"1.0.0\",\n // Facade is ESM: rolldown-plugin-dts requires it, and the BlockPointer's\n // `import.meta.url` path math needs it.\n type: \"module\",\n // Drives the npm tarball: only the built outputs ship; sources, tsconfig,\n // and node_modules stay out.\n files: [\"dist\", \"block-pack\"],\n main: \"./dist/index.js\",\n module: \"./dist/index.js\",\n types: \"./dist/index.d.ts\",\n exports: FACADE_EXPORTS,\n scripts: blockScripts(v.npmOrg, ctx.isSdkInternal),\n // Slim invariant: zero runtime deps reach the consumer.\n dependencies: {},\n devDependencies: devDeps,\n block,\n };\n}\n\nexport function blockPackageJsonRules(ctx: RunContext): void {\n const v = ctx.blockVars;\n\n ensureField(\"type\", \"module\");\n ensureField(\"files\", [\"dist\", \"block-pack\"]);\n ensureField(\"main\", \"./dist/index.js\");\n ensureField(\"module\", \"./dist/index.js\");\n ensureField(\"types\", \"./dist/index.d.ts\");\n ensureField(\"exports\", FACADE_EXPORTS);\n\n const scripts = blockScripts(v.npmOrg, ctx.isSdkInternal);\n for (const [name, command] of Object.entries(scripts)) ensureScript(name, command);\n removeScript(\"mark-stable\");\n\n // Slim invariant: the facade carries ZERO runtime dependencies. The siblings\n // and the SDK build/publish deps are all devDeps, so `dependencies` ends\n // empty. Software/test are excluded (the workflow owns software; a\n // test→facade dep would be a cycle).\n ensureWorkspaceScopeDevDeps(\"model\");\n ensureWorkspaceScopeDevDeps(\"ui\");\n ensureWorkspaceScopeDevDeps(\"workflow\");\n ensureDevDep(\"@milaboratories/ts-builder\", \"sdk:\");\n ensureDevDep(\"@milaboratories/ts-configs\", \"sdk:\");\n ensureDevDep(\"@platforma-sdk/block-tools\", \"sdk:\");\n ensureDevDep(\"@platforma-sdk/model\", \"sdk:\");\n ensureDevDep(\"shx\", \"catalog:\");\n ensureDevDep(\"typescript\", \"catalog:\");\n\n // `block.components` is fully determined by the discovered modules — keep it\n // in sync on refresh. `block.meta` is deliberately NOT touched: it is an\n // author-owned seed (set once in the init package.json), so refresh must\n // never overwrite the author's title / description / logo.\n ensureField(\"block.components\", blockComponents(ctx));\n\n // The author owns `name` and `version`; `version` MUST be present (the\n // facade publishes).\n requireField(\"version\", \"facade package.json must carry a 'version' (the facade publishes)\");\n\n enforceAlphabeticalOrder(\"dependencies\");\n enforceAlphabeticalOrder(\"devDependencies\");\n enforceAlphabeticalOrder(\"peerDependencies\");\n enforceAlphabeticalOrder(\"optionalDependencies\");\n enforceFieldOrder([...canonicalPackageJsonOrder]);\n}\n","// `pascalCase(shortName)` → the block-named alias prefix the facade entry\n// template emits (`<PascalName>BlockContract`, …). Splits on any run of\n// non-alphanumeric characters and capitalises each segment's first char:\n// test-sum-numbers-v3 → TestSumNumbersV3\n// mixcr-clonotyping-2 → MixcrClonotyping2\n// samples-and-data → SamplesAndData\nexport function pascalCase(s: string): string {\n const joined = s\n .split(/[^A-Za-z0-9]+/)\n .filter((seg) => seg.length > 0)\n .map((seg) => seg.charAt(0).toUpperCase() + seg.slice(1))\n .join(\"\");\n // A leading digit (e.g. `3d-viewer` → `3dViewer`) is not a valid identifier\n // start — the prefix becomes `const 3dViewerBlockPointer = …`. Prepend `_`.\n return /^[0-9]/.test(joined) ? `_${joined}` : joined;\n}\n","// Block-scope rules — the facade package at `block/`. The facade is the\n// only sibling of a block that publishes: a slim 4-file `src/` surface\n// (engine-owned `index.ts` + `AGENTS.ts`, author-owned `block-extra.ts` +\n// `agents-extra.ts`), a facade `tsconfig.json`, and a slim publishable\n// `package.json`. Workspace-scope deps in the body resolve from ctx.modules.\n\nimport {\n scope,\n fixed,\n scaffold,\n managed,\n seed,\n remove,\n file,\n tpl,\n binaryFile,\n generate,\n} from \"../engine/api\";\nimport { blockPackageJsonInitial, blockPackageJsonRules } from \"./block-package-json\";\nimport { pascalCase } from \"./shared/pascal-case\";\n\nexport function blockRules(): void {\n scope(\"block\", () => {\n // `remove` is idempotent (absent file → no-op), so this is safe on a block\n // that has no such entry files.\n remove(\"index.js\");\n remove(\"index.d.ts\");\n\n // Four-file source surface. `index.ts` is engine-owned and per-block\n // (model import path + `<PascalName>` aliases) → text-templated. `AGENTS.ts`\n // is engine-owned and identical for every block → static. The two `*-extra`\n // files are author scaffolds (`scaffold`: create-if-missing on every refresh,\n // never overwritten).\n fixed(\n \"src/index.ts\",\n tpl(\"block/src/index.tpl.ts\", (ctx) => ({\n facadeName: ctx.blockVars.facadeName,\n pascalName: pascalCase(ctx.blockVars.shortName),\n })),\n );\n fixed(\"src/AGENTS.ts\", file(\"block/src/AGENTS.ts\"));\n scaffold(\"src/block-extra.ts\", file(\"block/src/block-extra.ts\"));\n scaffold(\"src/agents-extra.ts\", file(\"block/src/agents-extra.ts\"));\n\n fixed(\"tsconfig.json\", file(\"block/tsconfig.json\"));\n\n // Placeholder logos referenced by `block.meta` (logo + organization.logo).\n // Binary seeds: written once at init, author-owned thereafter — refresh\n // never overwrites them, so a custom logo survives. `block-tools pack`\n // embeds these into the block pack; without them pack would fail on the\n // `file:logos/...` meta references.\n seed(\"logos/block-logo.png\", binaryFile(\"block/logos/block-logo.png\"));\n seed(\"logos/organization-logo.png\", binaryFile(\"block/logos/organization-logo.png\"));\n\n managed(\n \"package.json\",\n generate((ctx) => blockPackageJsonInitial(ctx)),\n (ctx) => {\n blockPackageJsonRules(ctx);\n },\n );\n });\n}\n","// Shared definition for co-located unit-test handling.\n//\n// A block's model / ui / workflow scope MAY carry co-located vitest unit\n// tests (`src/**/*.test.ts`, including nested `src/test/*.test.ts`). The\n// structurer wires the vitest `test` script and (for ui/model) node ambient\n// types into a scope ONLY when such files are present — so a test-less scope\n// stays free of a `test` script it would never run, and a freshly-init'd\n// (test-less) block remains a refresh fixpoint.\n\n/** Glob (module-relative) for co-located unit tests in a scope's `src/`. */\nexport const COLOCATED_TEST_GLOB = \"src/**/*.test.ts\";\n","// Model `package.json`: the initial generator and the drift-correcting body\n// rules, co-located. Identity (name/version) stays untouched; the body\n// enforces type/main/types/exports + canonical scripts + canonical dep sets,\n// then projects canonical field / dependency order.\n//\n// Authored oxfmt-clean: the model is one of the two scopes `ts-builder\n// check` runs oxfmt on, so neither half enforces field / dependency ordering\n// beyond what oxfmt itself produces — the enforce* calls match oxfmt's order\n// exactly, so refreshing a legacy block yields oxfmt-clean output and the\n// build→check gate (oxfmt --check) passes without a prior `pnpm fmt`.\n\nimport {\n ensureField,\n ensureScript,\n ensureDep,\n ensureDevDep,\n ensureDevDeps,\n removeDep,\n removeScript,\n removeField,\n ensurePeerDeps,\n enforceAlphabeticalOrder,\n enforceFieldOrder,\n when,\n whenFilesExist,\n type RunContext,\n} from \"../engine/api\";\nimport { canonicalPackageJsonOrder } from \"./shared/key-order\";\nimport { COLOCATED_TEST_GLOB } from \"./shared/colocated-tests\";\nimport { removeRetiredToolchainDeps } from \"./shared/retired-deps\";\n\nexport function modelPackageJsonInitial(ctx: RunContext): Record<string, unknown> {\n const v = ctx.blockVars;\n return {\n name: `${v.facadeName}.model`,\n private: true,\n type: \"module\",\n // The block-model build emits both index.cjs and index.js. `main` is\n // the CommonJS entry (require fallback); `module` the ESM entry.\n main: \"dist/index.cjs\",\n module: \"dist/index.js\",\n types: \"dist/index.d.ts\",\n exports: {\n \".\": {\n types: \"./dist/index.d.ts\",\n sources: \"./src/index.ts\",\n import: \"./dist/index.js\",\n },\n \"./dist/*\": \"./dist/*\",\n },\n scripts: {\n fmt: \"ts-builder format\",\n watch: \"ts-builder build --target block-model --watch\",\n build: \"ts-builder build --target block-model && block-tools build-model\",\n check: \"ts-builder check --target block-model\",\n },\n dependencies: {\n \"@platforma-sdk/model\": \"sdk:\",\n },\n devDependencies: {\n \"@milaboratories/ts-builder\": \"sdk:\",\n \"@milaboratories/ts-configs\": \"sdk:\",\n \"@platforma-sdk/block-tools\": \"sdk:\",\n },\n peerDependencies: {\n \"@types/node\": \"*\",\n typescript: \"*\",\n },\n };\n}\n\nexport function modelPackageJsonRules(): void {\n // Controlled sibling — workspace-only, never published. `private: true` makes\n // npm refuse to publish it; the `version` is kept (changesets-owned) so the\n // packed template's lib carries a version.\n ensureField(\"private\", true);\n\n ensureField(\"type\", \"module\");\n // build emits both; main = CJS entry, module = ESM entry (prod convention).\n ensureField(\"main\", \"dist/index.cjs\");\n ensureField(\"module\", \"dist/index.js\");\n ensureField(\"types\", \"dist/index.d.ts\");\n ensureField(\"exports\", {\n \".\": {\n types: \"./dist/index.d.ts\",\n sources: \"./src/index.ts\",\n import: \"./dist/index.js\",\n },\n \"./dist/*\": \"./dist/*\",\n });\n\n ensureScript(\"fmt\", \"ts-builder format\");\n ensureScript(\"watch\", \"ts-builder build --target block-model --watch\");\n ensureScript(\"build\", \"ts-builder build --target block-model && block-tools build-model\");\n ensureScript(\"check\", \"ts-builder check --target block-model\");\n\n ensureDep(\"@platforma-sdk/model\", \"sdk:\");\n\n ensureDevDeps({\n \"@milaboratories/ts-builder\": \"sdk:\",\n \"@milaboratories/ts-configs\": \"sdk:\",\n \"@platforma-sdk/block-tools\": \"sdk:\",\n });\n\n ensurePeerDeps({\n \"@types/node\": \"*\",\n typescript: \"*\",\n });\n\n // The vitest `test` script, the `vitest` devDep, and node ambient types are\n // wired ONLY when the model carries co-located unit tests (`src/**/*.test.ts`).\n // A test-less model gets none — turbo simply has no `test` task for it, and\n // the scope stays a refresh fixpoint. When tests ARE present, `@types/node`\n // is promoted from peer to a devDep (the single-section invariant drops the\n // peer) so the tests' `node:*` imports resolve under the `types: [\"node\"]`\n // that model/tsconfig adds under the same predicate. Runs AFTER ensurePeerDeps\n // so the promotion is not reverted.\n //\n // Skipped entirely for sdk-internal (in-monorepo) blocks: those live inside\n // the platforma monorepo's own test infrastructure (build-configs, shared\n // catalog, coverage providers) and own their test wiring — the structurer\n // must not impose or strip standalone-block test conventions on them.\n when(\n ({ ctx }) => !ctx.isSdkInternal,\n () =>\n when(\n whenFilesExist(COLOCATED_TEST_GLOB),\n () => {\n ensureScript(\"test\", \"vitest run --passWithNoTests\");\n ensureDevDep(\"vitest\", \"catalog:\");\n ensureDevDep(\"@types/node\", \"*\");\n },\n () => removeDep(\"vitest\"),\n ),\n );\n\n removeRetiredToolchainDeps();\n removeField(\"tsup\");\n removeScript(\"lint\");\n\n enforceAlphabeticalOrder(\"dependencies\");\n enforceAlphabeticalOrder(\"devDependencies\");\n enforceAlphabeticalOrder(\"peerDependencies\");\n enforceAlphabeticalOrder(\"optionalDependencies\");\n enforceFieldOrder([...canonicalPackageJsonOrder]);\n}\n","// Model-scope rules. Static config files + managed package.json; the\n// `src/index.ts` seed is dropped by `init` and never touched again\n// (block author owns it).\n\nimport { scope, fixed, managed, seed, file, generate, when, whenFilesExist } from \"../engine/api\";\nimport { modelPackageJsonInitial, modelPackageJsonRules } from \"./model-package-json\";\nimport { COLOCATED_TEST_GLOB } from \"./shared/colocated-tests\";\n\nexport function modelRules(): void {\n scope(\"model\", () => {\n // Two static end states by co-located-test presence: a test-bearing model\n // gets node ambient types (`.node.json`) so the tests type-check —\n // `@types/node` is wired alongside by the package.json rule; a test-less\n // model stays bare. `fixed` (engine-owned, whole-file overwrite) not\n // `managed`, so refresh is idempotent by construction — no key-order drift.\n when(\n whenFilesExist(COLOCATED_TEST_GLOB),\n () => fixed(\"tsconfig.json\", file(\"model/tsconfig.node.json\")),\n () => fixed(\"tsconfig.json\", file(\"model/tsconfig.json\")),\n );\n fixed(\".oxlintrc.json\", file(\"model/.oxlintrc.json\"));\n fixed(\".oxfmtrc.json\", file(\"model/.oxfmtrc.json\"));\n\n // A minimal-but-REAL BlockModelV3: `build-model` rejects a non-model\n // export (\"Malformed model object\"), and a bare `.create(dataModel)`\n // still errors (\"Args rendering function not set\"). This seed is the\n // smallest chain that produces a valid `dist/model.json` — empty data\n // model, identity args, a single \"Main\" section. The block author owns\n // and extends it after init.\n seed(\"src/index.ts\", file(\"model/src/index.ts\"));\n\n managed(\n \"package.json\",\n generate((ctx) => modelPackageJsonInitial(ctx)),\n () => {\n modelPackageJsonRules();\n },\n );\n });\n}\n","// UI `package.json`: the initial generator and the drift-correcting body\n// rules, co-located.\n//\n// Authored oxfmt-clean: the ui is one of the two scopes `ts-builder check`\n// runs oxfmt on, so neither half enforces ordering beyond what oxfmt\n// produces — the enforce* calls match oxfmt's order exactly, so refreshing a\n// legacy block yields oxfmt-clean output and the build→check gate (oxfmt\n// --check) passes without a prior `pnpm fmt`.\n\nimport {\n ensureField,\n ensureScript,\n ensureDep,\n ensureDevDep,\n ensureDevDeps,\n ensurePeerDeps,\n ensureWorkspaceScopeDeps,\n removeDep,\n removeScript,\n enforceAlphabeticalOrder,\n enforceFieldOrder,\n when,\n whenFilesExist,\n type RunContext,\n} from \"../engine/api\";\nimport { scopeDepMap } from \"../engine/ctx\";\nimport { canonicalPackageJsonOrder } from \"./shared/key-order\";\nimport { COLOCATED_TEST_GLOB } from \"./shared/colocated-tests\";\nimport { removeRetiredToolchainDeps } from \"./shared/retired-deps\";\n\nexport function uiPackageJsonInitial(ctx: RunContext): Record<string, unknown> {\n const v = ctx.blockVars;\n return {\n name: `${v.facadeName}.ui`,\n private: true,\n type: \"module\",\n scripts: {\n fmt: \"ts-builder format\",\n dev: \"ts-builder serve --target block-ui\",\n watch: \"ts-builder build --target block-ui --watch\",\n build: \"ts-builder build --target block-ui\",\n check: \"ts-builder check --target block-ui\",\n },\n dependencies: {\n \"@platforma-sdk/ui-vue\": \"sdk:\",\n vue: \"catalog:\",\n // The seeded ui (app.ts) imports the block's model package; depend on\n // it — mirrors the body rule's `ensureWorkspaceScopeDeps(\"model\")`.\n ...scopeDepMap(ctx, \"model\"),\n },\n devDependencies: {\n \"@milaboratories/ts-builder\": \"sdk:\",\n \"@milaboratories/ts-configs\": \"sdk:\",\n },\n peerDependencies: {\n \"@types/node\": \"*\",\n typescript: \"*\",\n },\n };\n}\n\nexport function uiPackageJsonRules(): void {\n // Controlled sibling — workspace-only, never published, but kept versioned\n // (changesets-owned) so the packed template's lib carries a version.\n ensureField(\"private\", true);\n\n ensureField(\"type\", \"module\");\n\n ensureScript(\"fmt\", \"ts-builder format\");\n ensureScript(\"dev\", \"ts-builder serve --target block-ui\");\n ensureScript(\"watch\", \"ts-builder build --target block-ui --watch\");\n ensureScript(\"build\", \"ts-builder build --target block-ui\");\n ensureScript(\"check\", \"ts-builder check --target block-ui\");\n\n ensureDep(\"@platforma-sdk/ui-vue\", \"sdk:\");\n // The seeded ui (main.ts) imports `createApp` from vue.\n ensureDep(\"vue\", \"catalog:\");\n // The seeded ui (app.ts) imports the block's model package.\n ensureWorkspaceScopeDeps(\"model\");\n\n ensureDevDeps({\n \"@milaboratories/ts-builder\": \"sdk:\",\n \"@milaboratories/ts-configs\": \"sdk:\",\n });\n\n removeRetiredToolchainDeps();\n removeScript(\"preview\");\n removeScript(\"lint\");\n\n // `@types/node` is declared as a peer by default — mirrors the model scope\n // (the block author resolves it from the workspace root). The ui builds with\n // `--target block-ui` (types: []), so it pulls no node ambient types into the\n // build; the peer only satisfies IDE / type resolution, alongside `typescript`.\n ensurePeerDeps({\n \"@types/node\": \"*\",\n typescript: \"*\",\n });\n\n // A ui WITH co-located unit tests (`src/**/*.test.ts`) needs the vitest\n // `test` script, the `vitest` devDep, AND node ambient types promoted from\n // peer to a devDep (the single-section invariant drops the peer) so that\n // `types: [\"node\"]` in ui/tsconfig — wired under the same predicate —\n // resolves the tests' `node:*` imports. A test-less ui keeps `@types/node`\n // as a peer and carries no vitest, staying a refresh fixpoint.\n //\n // Skipped entirely for sdk-internal (in-monorepo) blocks: they own their test\n // wiring under the monorepo's shared infrastructure — see model-package-json.\n when(\n ({ ctx }) => !ctx.isSdkInternal,\n () =>\n when(\n whenFilesExist(COLOCATED_TEST_GLOB),\n () => {\n ensureScript(\"test\", \"vitest run --passWithNoTests\");\n ensureDevDep(\"vitest\", \"catalog:\");\n ensureDevDep(\"@types/node\", \"*\");\n },\n () => removeDep(\"vitest\"),\n ),\n );\n\n enforceAlphabeticalOrder(\"dependencies\");\n enforceAlphabeticalOrder(\"devDependencies\");\n enforceAlphabeticalOrder(\"peerDependencies\");\n enforceAlphabeticalOrder(\"optionalDependencies\");\n enforceFieldOrder([...canonicalPackageJsonOrder]);\n}\n","// UI-scope rules. Author owns src/main.ts and components; static config\n// files are engine-managed.\n\nimport {\n scope,\n fixed,\n managed,\n scaffold,\n seed,\n file,\n tpl,\n generate,\n when,\n whenFilesExist,\n} from \"../engine/api\";\nimport { uiPackageJsonInitial, uiPackageJsonRules } from \"./ui-package-json\";\nimport { COLOCATED_TEST_GLOB } from \"./shared/colocated-tests\";\n\nexport function uiRules(): void {\n scope(\"ui\", () => {\n // Two static end states by co-located-test presence: a test-bearing ui gets\n // node ambient types (`.node.json`) so tests' `node:*` imports type-check\n // under vue-tsc — `@types/node` is wired alongside by the package.json rule;\n // a test-less ui stays bare. `fixed` (engine-owned, whole-file overwrite)\n // not `managed`, so refresh is idempotent by construction — no key-order drift.\n when(\n whenFilesExist(COLOCATED_TEST_GLOB),\n () => fixed(\"tsconfig.json\", file(\"ui/tsconfig.node.json\")),\n () => fixed(\"tsconfig.json\", file(\"ui/tsconfig.json\")),\n );\n fixed(\".oxlintrc.json\", file(\"ui/.oxlintrc.json\"));\n // Block-local oxfmt config — the ui is oxfmt-checked (`ts-builder check\n // --target block-ui`).\n fixed(\".oxfmtrc.json\", file(\"ui/.oxfmtrc.json\"));\n // scaffold (not fixed): index.html carries a block-specific CSP. Write\n // the canonical default only when absent; never overwrite an author's.\n scaffold(\"index.html\", file(\"ui/index.html\"));\n\n // A minimal-but-real UI: mount (main.ts), app wiring the block model\n // (app.ts), and a landing page (MainPage.vue). An empty main.ts would\n // trip oxlint `unicorn(no-empty-file)`. Author-owned seeds: written once\n // at init, untouched on refresh.\n seed(\"src/main.ts\", file(\"ui/src/main.ts\"));\n seed(\n \"src/app.ts\",\n tpl(\"ui/src/app.tpl.ts\", (ctx) => ({ modelPkg: `${ctx.blockVars.facadeName}.model` })),\n );\n seed(\n \"src/MainPage.vue\",\n tpl(\"ui/src/MainPage.tpl.vue\", (ctx) => ({ shortName: ctx.blockVars.shortName })),\n );\n\n managed(\n \"package.json\",\n generate((ctx) => uiPackageJsonInitial(ctx)),\n () => {\n uiPackageJsonRules();\n },\n );\n });\n}\n","// Workflow `package.json`: the initial generator and the drift-correcting\n// body rules, co-located. Workflow packages reference software modules at\n// workspace level when the block has any; the generator fills them from the\n// discovered modules and the body rule re-asserts them.\n\nimport {\n ensureField,\n ensureScript,\n ensureDep,\n ensureDevDeps,\n removeDep,\n ensureWorkspaceScopeDeps,\n enforceAlphabeticalOrder,\n enforceFieldOrder,\n when,\n whenFilesExist,\n type RunContext,\n} from \"../engine/api\";\nimport { scopeDepMaps } from \"../engine/ctx\";\nimport { canonicalPackageJsonOrder } from \"./shared/key-order\";\nimport { COLOCATED_TEST_GLOB } from \"./shared/colocated-tests\";\nimport { removeRetiredToolchainDeps } from \"./shared/retired-deps\";\n\nexport function workflowPackageJsonInitial(ctx: RunContext): Record<string, unknown> {\n const v = ctx.blockVars;\n return {\n name: `${v.facadeName}.workflow`,\n private: true,\n type: \"module\",\n scripts: {\n // No `fmt`: the workflow is Tengo, not TS — nothing for oxlint/oxfmt\n // to process. Tengo is built and checked by pl-tengo.\n build: \"shx rm -rf dist && pl-tengo build\",\n check: \"pl-tengo check\",\n // No `test`: the vitest `test` script is wired by the body rule ONLY\n // when co-located test files exist (a freshly-init'd workflow has none).\n // Tengo source formatter (emacs batch). Falls back to a notice when\n // emacs is absent, so the script never hard-fails the environment.\n format: \"/usr/bin/env emacs --script ./format.el || echo 'No emacs.'\",\n },\n dependencies: {\n \"@platforma-sdk/workflow-tengo\": \"sdk:\",\n // Every block-local software module as a workspace dep (zero or more).\n ...scopeDepMaps(ctx, \"software\"),\n },\n devDependencies: {\n \"@platforma-sdk/tengo-builder\": \"sdk:\",\n \"@platforma-sdk/test\": \"sdk:\",\n // `vitest` is NOT seeded here — it's wired by the body rule only when the\n // workflow carries co-located tests (a freshly-init'd workflow has none).\n shx: \"catalog:\",\n },\n };\n}\n\nexport function workflowPackageJsonRules(): void {\n // Controlled sibling — workspace-only, never published, but kept versioned\n // (changesets-owned) so the packed template's lib carries a version.\n ensureField(\"private\", true);\n\n ensureField(\"type\", \"module\");\n\n // No `fmt` script: the workflow is Tengo, not TS — build + check run via\n // pl-tengo; `format` runs the emacs-batch Tengo formatter (no-op when absent).\n ensureScript(\"build\", \"shx rm -rf dist && pl-tengo build\");\n ensureScript(\"check\", \"pl-tengo check\");\n ensureScript(\"format\", \"/usr/bin/env emacs --script ./format.el || echo 'No emacs.'\");\n // The vitest `test` script AND the `vitest` devDep are wired ONLY when the\n // workflow carries co-located integration tests (`src/**/*.test.ts`, incl.\n // `src/test/`). A test-less workflow gets neither — no `test` task, no\n // vitest dep — and stays a refresh fixpoint. (Workflow tests type-check via\n // the standalone workflow/tsconfig with `types: []` — they pull their types\n // from `@platforma-sdk/test` — so no node-types wiring is needed here,\n // unlike model/ui.)\n //\n // Skipped entirely for sdk-internal (in-monorepo) blocks: they own their test\n // wiring under the monorepo's shared infrastructure — see model-package-json.\n when(\n ({ ctx }) => !ctx.isSdkInternal,\n () =>\n when(\n whenFilesExist(COLOCATED_TEST_GLOB),\n () => {\n ensureScript(\"test\", \"vitest run --passWithNoTests\");\n ensureDevDeps({ vitest: \"catalog:\" });\n },\n () => removeDep(\"vitest\"),\n ),\n );\n\n ensureDep(\"@platforma-sdk/workflow-tengo\", \"sdk:\");\n\n // Pulls in every block-local software module as a workspace dep so the\n // workflow can reference the produced runenv assets.\n ensureWorkspaceScopeDeps(\"software\");\n\n // @platforma-sdk/test: workflow integration tests (e.g. mixcr's\n // workflow/src/test/columns.test.ts) import it.\n ensureDevDeps({\n \"@platforma-sdk/tengo-builder\": \"sdk:\",\n \"@platforma-sdk/test\": \"sdk:\",\n shx: \"catalog:\",\n });\n\n // No-op for a canonical Tengo workflow; called uniformly across every scope\n // for safety.\n removeRetiredToolchainDeps();\n\n enforceAlphabeticalOrder(\"dependencies\");\n enforceAlphabeticalOrder(\"devDependencies\");\n enforceAlphabeticalOrder(\"peerDependencies\");\n enforceAlphabeticalOrder(\"optionalDependencies\");\n enforceFieldOrder([...canonicalPackageJsonOrder]);\n}\n","// Workflow-scope rules. The Tengo entry point is a templated seed\n// (substitutes ${shortName}); other config files are static.\n\nimport {\n scope,\n managed,\n fixed,\n scaffold,\n seed,\n file,\n tpl,\n generate,\n remove,\n when,\n whenFilesExist,\n} from \"../engine/api\";\nimport { workflowPackageJsonInitial, workflowPackageJsonRules } from \"./workflow-package-json\";\nimport { COLOCATED_TEST_GLOB } from \"./shared/colocated-tests\";\n\nexport function workflowRules(): void {\n scope(\"workflow\", () => {\n // Tengo source formatter (emacs batch); the `format` script invokes it.\n fixed(\"format.el\", file(\"workflow/format.el\"));\n // The TS-test tsconfig + vitest config exist ONLY when the workflow carries\n // co-located tests (`src/**/*.test.ts`, incl. `src/test/` — e.g. mixcr's\n // workflow/src/test/columns.test.ts). They pair with the conditional\n // `vitest` devDep + `test` script in workflow-package-json. tsconfig is\n // `fixed` (structural: types:[] keeps the isomorphic workflow free of\n // ambient Node/DOM types); vitest.config is `scaffold` (author-tunable once\n // present). A test-less workflow gets neither and stays a refresh fixpoint.\n //\n // Skipped entirely for sdk-internal (in-monorepo) blocks: they own their\n // test config under the monorepo's shared infrastructure (e.g. a bespoke\n // `vitest run --coverage` + `createVitestConfig`), which the structurer\n // must neither scaffold nor remove. See workflow-package-json.\n when(\n ({ ctx }) => !ctx.isSdkInternal,\n () =>\n when(\n whenFilesExist(COLOCATED_TEST_GLOB),\n () => {\n fixed(\"tsconfig.json\", file(\"workflow/tsconfig.json\"));\n scaffold(\"vitest.config.mts\", file(\"workflow/vitest.config.mts\"));\n },\n () => {\n remove(\"tsconfig.json\");\n remove(\"vitest.config.mts\");\n },\n ),\n );\n // No workflow facade (index.js / index.d.ts): the block loader resolves the\n // workflow via the `block:` components dist path (workflow/dist/.../main.plj.gz),\n // never the JS facade. Removed so blocks that carry one get cleaned\n // (idempotent on absence).\n remove(\"index.js\");\n remove(\"index.d.ts\");\n\n seed(\n \"src/main.tpl.tengo\",\n tpl(\"workflow/src/main.tpl.tengo\", (ctx) => ({\n shortName: ctx.blockVars.shortName,\n })),\n );\n\n managed(\n \"package.json\",\n generate((ctx) => workflowPackageJsonInitial(ctx)),\n () => {\n workflowPackageJsonRules();\n },\n );\n });\n}\n","// Test `package.json`: the initial generator and the drift-correcting body\n// rules, co-located.\n\nimport {\n ensureField,\n ensureScript,\n ensureDevDeps,\n ensurePeerDeps,\n removeDep,\n removeScript,\n enforceAlphabeticalOrder,\n enforceFieldOrder,\n type RunContext,\n} from \"../engine/api\";\nimport { canonicalPackageJsonOrder } from \"./shared/key-order\";\nimport { removeRetiredToolchainDeps } from \"./shared/retired-deps\";\n\nexport function testPackageJsonInitial(ctx: RunContext): Record<string, unknown> {\n const v = ctx.blockVars;\n return {\n name: `${v.facadeName}.test`,\n private: true,\n type: \"module\",\n scripts: {\n fmt: \"ts-builder format\",\n // `ts-builder check` runs type-check + lint (oxlint) + fmt-check (oxfmt).\n check: \"ts-builder check --target block-test\",\n test: \"vitest run --passWithNoTests\",\n },\n peerDependencies: {\n typescript: \"*\",\n },\n devDependencies: {\n \"@platforma-sdk/test\": \"sdk:\",\n \"@milaboratories/ts-builder\": \"sdk:\",\n \"@milaboratories/ts-configs\": \"sdk:\",\n vitest: \"catalog:\",\n },\n };\n}\n\nexport function testPackageJsonRules(): void {\n // Controlled sibling — workspace-only, never published. (The initial already\n // seeds `private: true`; the body re-asserts it. The `version` is kept —\n // changesets-owned — so the packed template's lib carries a version.)\n ensureField(\"private\", true);\n\n ensureField(\"type\", \"module\");\n\n ensureScript(\"fmt\", \"ts-builder format\");\n // `ts-builder check` runs type-check + lint (oxlint) + fmt-check (oxfmt).\n ensureScript(\"check\", \"ts-builder check --target block-test\");\n ensureScript(\"test\", \"vitest run --passWithNoTests\");\n // Linting runs inside `ts-builder check` — no separate `lint` script.\n removeScript(\"lint\");\n\n ensureDevDeps({\n \"@platforma-sdk/test\": \"sdk:\",\n \"@milaboratories/ts-builder\": \"sdk:\",\n \"@milaboratories/ts-configs\": \"sdk:\",\n vitest: \"catalog:\",\n });\n\n // The test tsconfig (@milaboratories/ts-configs/block/test) supplies the\n // ambient types, so only the `typescript` peer is needed — no `@types/node`.\n ensurePeerDeps({\n typescript: \"*\",\n });\n removeDep(\"@types/node\");\n removeRetiredToolchainDeps();\n\n enforceAlphabeticalOrder(\"dependencies\");\n enforceAlphabeticalOrder(\"devDependencies\");\n enforceAlphabeticalOrder(\"peerDependencies\");\n enforceAlphabeticalOrder(\"optionalDependencies\");\n enforceFieldOrder([...canonicalPackageJsonOrder]);\n}\n","// Test-scope rules.\n\nimport { scope, fixed, managed, scaffold, seed, file, text, generate } from \"../engine/api\";\nimport { testPackageJsonInitial, testPackageJsonRules } from \"./test-package-json\";\n\nexport function testRules(): void {\n scope(\"test\", () => {\n // tsconfig carries `files: []` alongside `include: [\"src/**/*\"]`: tsc\n // errors TS18003 when an `include` matches nothing, so an empty `files`\n // lets the check pass on a test-less block while `include` still\n // type-checks real tests once present.\n fixed(\"tsconfig.json\", file(\"test/tsconfig.json\"));\n // Block-local oxlint/oxfmt config — test sources are lint + fmt-checked\n // (the `check` script runs `ts-builder check --target block-test`).\n fixed(\".oxlintrc.json\", file(\"test/.oxlintrc.json\"));\n fixed(\".oxfmtrc.json\", file(\"test/.oxfmtrc.json\"));\n // scaffold (not fixed): integration tests legitimately tune timeout /\n // retry per block. Write the canonical default if absent; never\n // overwrite an author's config.\n scaffold(\"vitest.config.mts\", file(\"test/vitest.config.mts\"));\n\n // A trivial, backend-free demo test so a freshly-init'd block ships a\n // runnable suite (`pnpm test` green out of the box) rather than an empty\n // scope. Author-owned seed: written once at init, untouched on refresh.\n seed(\n \"src/demo.test.ts\",\n text(\n `import { expect, test } from \"vitest\";\\n\\n` +\n `test(\"scaffolded block sanity check\", () => {\\n` +\n ` expect(true).toBe(true);\\n` +\n `});\\n`,\n ),\n );\n\n managed(\n \"package.json\",\n generate((ctx) => testPackageJsonInitial(ctx)),\n () => {\n testPackageJsonRules();\n },\n );\n });\n}\n","// Software `package.json`: the initial generator and the drift-correcting\n// body rules, co-located. One body, N modules — fan-out is driven by\n// `ctx.modules`.\n//\n// Drift-correctors only: identity (name/version), `description`, and the\n// `block-software` descriptor are author-owned / opaque and left untouched\n// — re-asserting them would clobber real multi-software blocks on refresh.\n// The body enforces the structural essentials: ESM type, the publish\n// `files` glob, the lifecycle scripts, and the canonical devDeps.\n\nimport {\n ensureField,\n removeField,\n ensureScript,\n removeScript,\n ensureDevDep,\n removeDep,\n enforceAlphabeticalOrder,\n enforceFieldOrder,\n type RunContext,\n} from \"../engine/api\";\nimport { canonicalPackageJsonOrder } from \"./shared/key-order\";\n\n// The software-build build/pack commands, shared by the generator and the reconciler. block-tools\n// bundles the build engine, so these are the only build-tool commands a software-build block runs.\nconst BUILD_CMD = \"block-tools software build\";\nconst DO_PACK_CMD =\n \"shx rm -f *.tgz && block-tools software build && pnpm pack && shx mv platforma-open*.tgz package.tgz\";\n\n/** The `block-software` package-builder descriptor for a python\n * entrypoint. Kept opaque by the engine; rule authors edit it via\n * `transformAt(\"block-software\", ...)`. The `:3.12.10` tag inside\n * `environment` is the runenv artifact tag (python version), distinct\n * from the npm catalog version. */\nfunction pythonBlockSoftware(): Record<string, unknown> {\n return {\n entrypoints: {\n main: {\n binary: {\n artifact: {\n type: \"python\",\n registry: \"platforma-open\",\n environment: \"@platforma-open/milaboratories.runenv-python-3:3.12.10\",\n dependencies: { toolset: \"pip\", requirements: \"requirements.txt\" },\n root: \"./src\",\n },\n cmd: [\"python\", \"{pkg}/main.py\"],\n },\n },\n },\n };\n}\n\nexport function softwarePackageJsonInitial(ctx: RunContext): Record<string, unknown> {\n const v = ctx.blockVars;\n\n return {\n name: `${v.facadeName}.software`,\n type: \"module\",\n description: \"Block Software\",\n files: [\"./dist/**/*\"],\n scripts: {\n build: BUILD_CMD,\n \"do-pack\": DO_PACK_CMD,\n changeset: \"changeset\",\n \"version-packages\": \"changeset version\",\n },\n \"block-software\": pythonBlockSoftware(),\n devDependencies: {\n \"@platforma-open/milaboratories.runenv-python-3\": \"catalog:\",\n \"@platforma-sdk/block-tools\": \"sdk:\",\n },\n };\n}\n\nexport function softwarePackageJsonRules(): void {\n // Software packages must never be private: `pl-pkg` gates docker image\n // auto-push on `!isPrivate`, so a private software package builds its image\n // but never pushes it — the block then 404s pulling it at runtime. Strip it\n // so a `structure refresh` heals any block that has it.\n removeField(\"private\");\n\n ensureField(\"type\", \"module\");\n ensureField(\"files\", [\"./dist/**/*\"]);\n\n // Lifecycle scripts. block-tools builds and packs; a block migrated off pl-pkg converges on\n // refresh — the old `pl-pkg prepublish` upload step is dropped (build + push happen in `build`).\n ensureScript(\"build\", BUILD_CMD);\n ensureScript(\"do-pack\", DO_PACK_CMD);\n removeScript(\"prepublishOnly\");\n ensureScript(\"changeset\", \"changeset\");\n ensureScript(\"version-packages\", \"changeset version\");\n\n // Canonical devDeps. block-tools bundles the build engine, so the pl-pkg\n // `@platforma-sdk/package-builder` dependency is dropped.\n ensureDevDep(\"@platforma-open/milaboratories.runenv-python-3\", \"catalog:\");\n ensureDevDep(\"@platforma-sdk/block-tools\", \"sdk:\");\n removeDep(\"@platforma-sdk/package-builder\");\n\n enforceAlphabeticalOrder(\"dependencies\");\n enforceAlphabeticalOrder(\"devDependencies\");\n enforceAlphabeticalOrder(\"peerDependencies\");\n enforceAlphabeticalOrder(\"optionalDependencies\");\n enforceFieldOrder([...canonicalPackageJsonOrder]);\n}\n","// Software-scope rules. One scope body, N modules — the engine fans out\n// once per discovered software module. Zero software modules → entire\n// scope body no-ops.\n//\n// Seeds (`software/src/main.py` + `requirements.txt`) are written once by\n// `init` and never touched again — the block author owns them.\n\nimport { scope, managed, seed, generate, text } from \"../engine/api\";\nimport { softwarePackageJsonInitial, softwarePackageJsonRules } from \"./software-package-json\";\n\nconst MAIN_PY_SEED = `import sys\n\nprint(\"Hello from Python, \" + sys.argv[1] + \"!\")\n`;\n\nconst REQUIREMENTS_SEED = `# No dependencies specified for this script\n`;\n\nexport function softwareRules(): void {\n scope(\"software\", () => {\n seed(\"src/main.py\", text(MAIN_PY_SEED));\n seed(\"src/requirements.txt\", text(REQUIREMENTS_SEED));\n\n managed(\n \"package.json\",\n generate((ctx) => softwarePackageJsonInitial(ctx)),\n () => {\n softwarePackageJsonRules();\n },\n );\n });\n}\n","// Migrations + legacy cleanup live here.\n//\n// Two patterns coexist:\n//\n// 1. One-shot migrations gated on filesystem state. Folder renames,\n// cross-cutting one-time transforms. Use `when(pathExists/pathMissing)`\n// so the migration fires once and is idempotent on subsequent runs.\n//\n// 2. Legacy cleanup primitives. Unconditional `removeScript`,\n// `removeDep`, `remove(path)` calls naming artefacts the canonical\n// layout never produces. Idempotent by definition (no-op on absent\n// keys/paths). Each line is a one-way decision: every block converges.\n\nimport { scope, remove, managed, generate, removeScript, removeDep } from \"../engine/api\";\nimport { rootPackageJsonInitial } from \"./root-package-json\";\n\nexport function testFrameworkMigration(): void {\n // No active rename-bearing migration yet. Reserved for the test\n // framework rollout.\n}\n\n// Unconditional legacy-cleanup rules. Each is a no-op on an\n// already-canonical block (remove on an absent path, removeScript /\n// removeDep on an absent key) and idempotent, so they sit at top level\n// with no `when` gate.\n//\n// Root-scope cleanup is skipped for `--sdk-internal` blocks (no root\n// module in that mode), so it never touches in-monorepo blocks.\nexport function legacyCleanup(): void {\n // Retired per-scope config files: flat eslint configs and vite-era build /\n // split-tsconfig files, replaced by the oxlint/oxfmt + ts-builder layout.\n scope(\"model\", () => {\n remove(\"eslint.config.mjs\");\n remove(\"vite.config.mts\");\n });\n scope(\"ui\", () => {\n remove(\"eslint.config.mjs\");\n remove(\"vite.config.ts\");\n remove(\"tsconfig.app.json\");\n remove(\"tsconfig.node.json\");\n });\n scope(\"test\", () => {\n remove(\"eslint.config.mjs\");\n });\n\n // Root-scope cleanup. The second `managed(\"package.json\")` body composes\n // after rootRules.\n scope(\"root\", () => {\n remove(\".prettierrc\");\n managed(\n \"package.json\",\n generate(() => rootPackageJsonInitial()),\n () => {\n // `pretty` (prettier) is superseded by `fmt` (oxfmt); the standalone\n // deps-updater is now part of block-tools.\n removeScript(\"pretty\");\n removeDep(\"@platforma-sdk/blocks-deps-updater\");\n },\n );\n });\n}\n","// Catalog version-resolution + seeding rules. The single `onInitOrUpdate(...)`\n// frame here resolves the SDK catalog families to npm latest AND seeds any\n// missing standard catalog keys (SDK families + the curated infra floor +\n// the python runenv pin). Its leaves fire on `init` AND\n// `refresh --update-deps-only` (mode \"init\" + \"updateDeps\") — both mean\n// \"write current versions\" — and are skipped on a default refresh/check,\n// which leaves catalog versions exactly as the author/lockfile has them.\n//\n// The network value lives in `ensureCatalogLatest`, which reads prefetched\n// \"latest\" versions from the runner's `registryLookup` (the CLI / init\n// constructor prefetches the SDK catalog membership list before the run;\n// unit tests pass a mock). Seeding the SDK keys from the membership list\n// (not the on-disk catalog) is what fixes the install failures: a\n// migrated block that never carried `@milaboratories/ts-builder` etc. now\n// gets them ADDED on `--update-deps-only`, no manual catalog seed required.\n//\n// Wrapped in the same root-scope `when(!isSdkInternal)` guard as the rest of\n// the root rules — internal blocks get their catalog from the parent\n// monorepo, so catalog resolution never applies there.\n\nimport {\n onInitOrUpdate,\n scope,\n when,\n managed,\n generate,\n ensureCatalogLatest,\n ensureCatalogVersion,\n pinCatalogToDependencyOf,\n} from \"../engine/api\";\nimport {\n rootPnpmWorkspaceInitial,\n SDK_CATALOG_PACKAGES,\n INFRA_CATALOG_FLOOR,\n DERIVED_CATALOG_PINS,\n RUNENV_PYTHON,\n RUNENV_PYTHON_VERSION,\n} from \"./root-pnpm-workspace\";\n\nexport function rootCatalogBumpRules(): void {\n onInitOrUpdate(() => {\n scope(\"root\", () => {\n when(\n ({ ctx }) => !ctx.isSdkInternal,\n () => {\n // On init, the default root rules create pnpm-workspace.yaml from\n // this same generator (the curated SDK placeholders + infra\n // floor); this leaf then overwrites the SDK entries with npm\n // latest (the floor entries are add-if-absent no-ops). On\n // update-deps the file already exists, so `initial` is not\n // exercised — but a ContentForm is required, so reuse the\n // generator.\n managed(\n \"pnpm-workspace.yaml\",\n generate((ctx) => rootPnpmWorkspaceInitial(ctx)),\n (ctx) => {\n // SDK families → npm latest, ADD-IF-ABSENT (seeds a migrated\n // block's missing standard keys + overwrites the init\n // placeholder).\n for (const name of SDK_CATALOG_PACKAGES) ensureCatalogLatest(name);\n // Derived catalog pins → the EXACT version their source package\n // declares (e.g. `vue` from `@platforma-sdk/ui-vue`). OVERWRITES\n // (seeds when absent, tightens a loose on-disk entry). Resolved\n // by the prefetched `derivedPinLookup`; a no-op when absent\n // (default refresh passes none). Must run AFTER ensureCatalogLatest\n // — the source package's own version is bumped there first.\n for (const pin of DERIVED_CATALOG_PINS) {\n pinCatalogToDependencyOf(pin.entry, { of: pin.of, ofVersion: pin.ofVersion });\n }\n // Curated infra floor → fixed version, ADD-IF-ABSENT (seeds\n // shx/turbo/vitest/changesets when missing; never touches a\n // version the block already pins).\n for (const [name, version] of Object.entries(INFRA_CATALOG_FLOOR)) {\n ensureCatalogVersion(name, version);\n }\n // The python runenv pin is relevant only to software-bearing\n // blocks; seed it add-if-absent when one is present.\n if (ctx.modules.some((m) => m.scope === \"software\")) {\n ensureCatalogVersion(RUNENV_PYTHON, RUNENV_PYTHON_VERSION);\n }\n },\n );\n },\n );\n });\n });\n}\n","// Canonical block structure — composes every scope's `*Rules()` function\n// inside a single `defineStructure(() => { ... })`. Re-evaluated by the\n// engine on every run; rule modules are imported by name so the\n// structure stays inspectable and the dep graph is explicit.\n\nimport { defineStructure } from \"./engine/api\";\nimport { rootRules } from \"./rules/root\";\nimport { rootCiRules } from \"./rules/root-ci\";\nimport { blockRules } from \"./rules/block\";\nimport { modelRules } from \"./rules/model\";\nimport { uiRules } from \"./rules/ui\";\nimport { workflowRules } from \"./rules/workflow\";\nimport { testRules } from \"./rules/test\";\nimport { softwareRules } from \"./rules/software\";\nimport { testFrameworkMigration, legacyCleanup } from \"./rules/migrations\";\nimport { rootCatalogBumpRules } from \"./rules/root-catalog-bump\";\n\nexport const STRUCTURE = defineStructure(() => {\n rootRules();\n rootCiRules();\n blockRules();\n modelRules();\n uiRules();\n workflowRules();\n testRules();\n softwareRules();\n testFrameworkMigration();\n legacyCleanup();\n rootCatalogBumpRules();\n});\n","// Shared driver for the `structure check` and `structure refresh`\n// commands. Wraps DISCOVERY (discover-fs) + the engine runner for\n// one block path, handling the standalone vs `--sdk-internal` split, the\n// `--update-deps-only` registry prefetch, and the post-run recheck's\n// fresh re-discovery. Each block path is processed independently (no\n// cross-block state).\n\nimport path from \"node:path\";\nimport { NodeFileSystem } from \"../engine/fs/node\";\nimport { NodeTemplateProvider } from \"../engine/templates\";\nimport { run as engineRun, type Change } from \"../engine/runner\";\nimport { discoverRunContext } from \"../engine/discovery-fs\";\nimport { STRUCTURE } from \"../structure-definition\";\nimport {\n matchesBumpPattern,\n buildRegistryLookupForNames,\n buildDerivedPinLookupForPins,\n} from \"../engine/registry-client\";\nimport { SDK_CATALOG_PACKAGES, DERIVED_CATALOG_PINS } from \"../rules/root-pnpm-workspace\";\n\nexport type StructureMode = \"check\" | \"refresh\";\n\nexport type RunStructureInput = {\n /** User-supplied block path (resolved against cwd). */\n blockPath: string;\n isSdkInternal: boolean;\n updateDepsOnly: boolean;\n mode: StructureMode;\n /** `<block-tools>/src/structure/templates`. */\n templatesRoot: string;\n log: (msg: string) => void;\n};\n\nexport type RunStructureResult = {\n blockPath: string;\n changes: Change[];\n};\n\n/** Resolve the registry lookup for `--update-deps-only`: prefetch npm\n * \"latest\" for the SDK catalog MEMBERSHIP list (`SDK_CATALOG_PACKAGES`),\n * not the on-disk catalog keys, so the sync `ensureCatalogLatest` builder\n * can SEED a standard SDK key the block does not yet carry — reading\n * the on-disk catalog could never resolve an absent key. Mirrors\n * the `runInit` prefetch. A network failure during prefetch propagates. */\nasync function buildRegistryLookup(): Promise<(name: string) => string | undefined> {\n // Every SDK_CATALOG_PACKAGES entry matches a bump pattern (enforced at\n // load time in root-pnpm-workspace); filter defensively all the same.\n const names = SDK_CATALOG_PACKAGES.filter(matchesBumpPattern);\n return buildRegistryLookupForNames(names);\n}\n\nexport async function runStructureForPath(input: RunStructureInput): Promise<RunStructureResult> {\n const root = path.resolve(input.blockPath);\n const dryRun = input.mode === \"check\";\n\n const fs = new NodeFileSystem(root);\n const templates = new NodeTemplateProvider(input.templatesRoot);\n\n const ctx = discoverRunContext({\n fs,\n isSdkInternal: input.isSdkInternal,\n updateDepsOnly: input.updateDepsOnly,\n dryRun,\n });\n\n const registryLookup = input.updateDepsOnly ? await buildRegistryLookup() : undefined;\n // Derived catalog pins (e.g. vue ← ui-vue's declared dep) resolve on the\n // same prefetch budget as the SDK latest bump; absent on a default refresh.\n const derivedPinLookup = input.updateDepsOnly\n ? await buildDerivedPinLookupForPins(DERIVED_CATALOG_PINS)\n : undefined;\n\n const result = engineRun(STRUCTURE, fs, ctx, {\n templates,\n registryLookup,\n derivedPinLookup,\n // Fresh re-discovery for the post-run recheck (default refresh only)\n // — re-reads the just-written tree so a rename that shifted the\n // module map is observed.\n rediscover: () =>\n discoverRunContext({\n fs,\n isSdkInternal: input.isSdkInternal,\n updateDepsOnly: false,\n dryRun: true,\n }),\n });\n\n return { blockPath: input.blockPath, changes: result.changes };\n}\n\n/** One-line-per-change summary for CLI output. */\nexport function formatChanges(blockPath: string, changes: Change[]): string {\n if (changes.length === 0) return ` ${blockPath}: up to date (0 changes)`;\n const lines = changes.map(\n (c) => ` ${c.action.padEnd(6)} ${c.primitive.padEnd(8)} ${c.path} [${c.scope}]`,\n );\n return ` ${blockPath}: ${changes.length} change(s)\\n${lines.join(\"\\n\")}`;\n}\n","import { Command } from \"commander\";\nimport path from \"node:path\";\nimport type { MiLogger } from \"@milaboratories/ts-helpers\";\nimport { ConsoleLoggerAdapter } from \"@milaboratories/ts-helpers\";\nimport { runStructureForPath, formatChanges } from \"../../structure/cli/run-structure\";\n\n// Shared by `structure refresh` and the deprecated `update-deps` alias.\nexport async function runRefresh(opts: {\n paths: string[];\n isSdkInternal: boolean;\n updateDepsOnly: boolean;\n templatesRoot: string;\n logger: MiLogger;\n}): Promise<void> {\n for (const p of opts.paths) {\n const res = await runStructureForPath({\n blockPath: p,\n isSdkInternal: opts.isSdkInternal,\n updateDepsOnly: opts.updateDepsOnly,\n mode: \"refresh\",\n templatesRoot: opts.templatesRoot,\n log: (m) => opts.logger.info(m),\n });\n opts.logger.info(formatChanges(p, res.changes));\n }\n}\n\nexport function structureRefreshCommand(packageRoot: string): Command {\n const cmd = new Command(\"refresh\").description(\n \"Bring block(s) up to date with the canonical structure. Applies rules, writes files, bumps .structure version. Default mode is offline; --update-deps-only fires only catalog-bump rules (network).\",\n );\n\n cmd.argument(\"[paths...]\", \"block path(s); defaults to the current directory\");\n cmd.option(\"--sdk-internal\", \"block(s) live inside the SDK monorepo; skip root-scope rules\");\n cmd.option(\n \"--update-deps-only\",\n \"fire ONLY catalog-bump rules (npm network). Follow with `pnpm install` then a plain refresh.\",\n );\n\n cmd.action(async (argv: string[], flags) => {\n const paths = argv.length > 0 ? argv : [\".\"];\n const templatesRoot = path.join(packageRoot, \"src\", \"structure\", \"templates\");\n await runRefresh({\n paths,\n isSdkInternal: Boolean(flags.sdkInternal),\n updateDepsOnly: Boolean(flags.updateDepsOnly),\n templatesRoot,\n logger: new ConsoleLoggerAdapter(),\n });\n });\n\n return cmd;\n}\n","import { Command } from \"commander\";\nimport path from \"node:path\";\nimport { ConsoleLoggerAdapter } from \"@milaboratories/ts-helpers\";\nimport { runRefresh } from \"./structure/refresh\";\n\n/**\n * Deprecated. Phase-2 forwarding alias (spec.md § \"Coexistence And\n * Retirement\"): delegates to `structure refresh --update-deps-only`,\n * which lands at parity with the old `blocks-deps-updater` catalog-bump\n * semantics. Prints a deprecation warning; will be removed once the\n * structurer path has been live without surprises.\n */\nexport function updateDepsCommand(packageRoot: string): Command {\n const cmd = new Command(\"update-deps\").description(\n \"[DEPRECATED] Use `block-tools structure refresh --update-deps-only`. This alias delegates to it.\",\n );\n\n cmd.action(async () => {\n const logger = new ConsoleLoggerAdapter();\n logger.warn(\n \"`block-tools update-deps` is deprecated and will be removed in a future release. \" +\n \"Use `block-tools structure refresh --update-deps-only` instead. Delegating now.\",\n );\n const templatesRoot = path.join(packageRoot, \"src\", \"structure\", \"templates\");\n await runRefresh({\n paths: [\".\"],\n isSdkInternal: false,\n updateDepsOnly: true,\n templatesRoot,\n logger,\n });\n });\n\n return cmd;\n}\n","import { Command, Option } from \"commander\";\nimport { BlockRegistryV2 } from \"../v2/registry/registry\";\nimport { storageByUrl } from \"../io/storage\";\nimport { ConsoleLoggerAdapter } from \"@milaboratories/ts-helpers\";\n\nexport function listOverviewSnapshotsCommand(): Command {\n const cmd = new Command(\"list-overview-snapshots\").description(\n \"List all available global overview snapshots in the registry\",\n );\n\n cmd.addOption(\n new Option(\"-r, --registry <address>\", \"full address of the registry\")\n .env(\"PL_REGISTRY\")\n .makeOptionMandatory(),\n );\n cmd.option(\"--json\", \"output in JSON format\", false);\n\n cmd.action(async (flags) => {\n const logger = new ConsoleLoggerAdapter();\n const storage = storageByUrl(flags.registry);\n const registry = new BlockRegistryV2(storage, logger);\n\n const snapshots = await registry.listGlobalOverviewSnapshots();\n\n if (flags.json) {\n logger.info(JSON.stringify(snapshots, null, 2));\n } else {\n if (snapshots.length === 0) {\n logger.info(\"No snapshots found.\");\n } else {\n logger.info(`Found ${snapshots.length} snapshot(s):\\n`);\n for (const snapshot of snapshots) {\n logger.info(` ${snapshot.timestamp}`);\n logger.info(` Path: ${snapshot.path}`);\n logger.info(\"\");\n }\n }\n }\n });\n\n return cmd;\n}\n","import { Command, Option } from \"commander\";\nimport { BlockRegistryV2 } from \"../v2/registry/registry\";\nimport { storageByUrl } from \"../io/storage\";\nimport { ConsoleLoggerAdapter } from \"@milaboratories/ts-helpers\";\n\nexport function restoreOverviewFromSnapshotCommand(): Command {\n const cmd = new Command(\"restore-overview-from-snapshot\").description(\n \"Restore global overview from a snapshot\",\n );\n\n cmd.addOption(\n new Option(\"-r, --registry <address>\", \"full address of the registry\")\n .env(\"PL_REGISTRY\")\n .makeOptionMandatory(),\n );\n cmd.requiredOption(\"-s, --snapshot <timestamp>\", \"snapshot timestamp ID to restore from\");\n cmd.option(\"--skip-confirmation\", \"skip confirmation prompt (use with caution)\", false);\n\n cmd.action(async (flags) => {\n const logger = new ConsoleLoggerAdapter();\n const storage = storageByUrl(flags.registry);\n const registry = new BlockRegistryV2(storage, logger);\n\n // Check if snapshot exists\n const snapshots = await registry.listGlobalOverviewSnapshots();\n const targetSnapshot = snapshots.find((s) => s.timestamp === flags.snapshot);\n\n if (!targetSnapshot) {\n throw new Error(\n `Snapshot '${flags.snapshot}' not found. Available snapshots:\\n${\n snapshots.map((s) => ` - ${s.timestamp}`).join(\"\\n\") || \" (none)\"\n }`,\n );\n }\n\n // Confirmation prompt (unless skipped)\n if (!flags.skipConfirmation) {\n const readline = await import(\"node:readline\");\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n const answer = await new Promise<string>((resolve) => {\n rl.question(\n `⚠️ This will overwrite the current global overview with snapshot '${flags.snapshot}'.\\n` +\n `Are you sure you want to continue? (y/N): `,\n resolve,\n );\n });\n\n rl.close();\n\n if (answer.toLowerCase() !== \"y\" && answer.toLowerCase() !== \"yes\") {\n logger.info(\"Restore cancelled.\");\n return;\n }\n }\n\n // Perform restore\n try {\n await registry.restoreGlobalOverviewFromSnapshot(flags.snapshot);\n logger.info(`✅ Successfully restored global overview from snapshot '${flags.snapshot}'`);\n } catch (error) {\n throw new Error(`Failed to restore from snapshot: ${String(error)}`);\n }\n });\n\n return cmd;\n}\n","import { Option } from \"commander\";\nimport path from \"node:path\";\n\nexport interface TargetFile {\n src: string;\n destName: string;\n}\n\nfunction parseTargetFile(arg: string): TargetFile {\n const match = arg.match(/(?<destName>[^/\\\\]+)=(?<src>.*)/);\n if (match) {\n const { src, destName } = match.groups!;\n return { src, destName };\n } else {\n return { src: arg, destName: path.basename(arg) };\n }\n}\n\n// Repeatable `file_path | package_name=file_path` option.\nexport function targetFileOption(flags: string, summary: string): Option {\n return new Option(flags, summary)\n .argParser((arg: string, prev?: TargetFile[]) => [...(prev ?? []), parseTargetFile(arg)])\n .default([] as TargetFile[]);\n}\n","import { Command, Option } from \"commander\";\nimport { getConfig } from \"../registry_v1/config\";\nimport { targetFileOption } from \"../registry_v1/flags\";\nimport fs from \"node:fs\";\nimport YAML from \"yaml\";\nimport { PlRegPackageConfigDataShard } from \"../registry_v1/config_schema\";\nimport { ConsoleLoggerAdapter } from \"@milaboratories/ts-helpers\";\n\ntype BasicConfigField = keyof PlRegPackageConfigDataShard &\n (\"registry\" | \"organization\" | \"package\" | \"version\");\nconst BasicConfigFields: BasicConfigField[] = [\"registry\", \"organization\", \"package\", \"version\"];\n\nexport function uploadPackageV1Command(): Command {\n const cmd = new Command(\"upload-package-v1\").description(\n \"Uploads V1 package and refreshes the registry\",\n );\n\n cmd.addOption(\n new Option(\n \"-r, --registry <address|alias>\",\n \"full address of the registry or alias from .pl.reg\",\n ).env(\"PL_REGISTRY\"),\n );\n cmd.addOption(\n new Option(\"-o, --organization <organization>\", \"target organisation\").env(\n \"PL_PACKAGE_ORGANIZATION\",\n ),\n );\n cmd.addOption(new Option(\"-p, --package <package>\", \"target package\").env(\"PL_PACKAGE_NAME\"));\n cmd.addOption(new Option(\"-v, --version <version>\", \"target version\").env(\"PL_PACKAGE_VERSION\"));\n cmd.option(\n \"-m, --meta <path>\",\n \"json file containing meta information to associate with tha package\",\n );\n cmd.addOption(targetFileOption(\"-f, --file <file>\", \"package files\"));\n cmd.addOption(\n new Option(\"--refresh\", \"refresh repository after adding the package\")\n .default(true)\n .env(\"PL_REGISTRY_REFRESH\"),\n );\n cmd.option(\"--no-refresh\", \"do not refresh repository after adding the package\");\n\n cmd.action(async (flags) => {\n const logger = new ConsoleLoggerAdapter();\n const configFromFlags: PlRegPackageConfigDataShard = PlRegPackageConfigDataShard.parse({});\n\n for (const field of BasicConfigFields) if (flags[field]) configFromFlags[field] = flags[field];\n\n if (flags.meta) {\n if (flags.meta.endsWith(\".json\"))\n configFromFlags.meta = JSON.parse(\n await fs.promises.readFile(flags.meta, { encoding: \"utf-8\" }),\n ) as Record<string, unknown>;\n else if (flags.meta.endsWith(\".yaml\"))\n configFromFlags.meta = YAML.parse(\n await fs.promises.readFile(flags.meta, { encoding: \"utf-8\" }),\n ) as Record<string, unknown>;\n }\n\n for (const targetFile of flags.file) {\n configFromFlags.files[targetFile.destName] = targetFile.src;\n }\n\n const conf = await getConfig(configFromFlags);\n\n logger.info(YAML.stringify(conf.conf));\n\n const registry = conf.createRegistry(logger);\n const name = conf.fullPackageName;\n\n const builder = registry.constructNewPackage(name);\n\n for (const [dst, src] of Object.entries(conf.conf.files)) {\n logger.info(`Uploading ${src} -> ${dst} ...`);\n const content = await fs.promises.readFile(src);\n await builder.addFile(dst, content);\n }\n\n logger.info(`Uploading meta information...`);\n await builder.writeMeta(conf.conf.meta);\n await builder.finish();\n\n if (flags.refresh) await registry.updateIfNeeded();\n });\n\n return cmd;\n}\n","import { Command } from \"commander\";\nimport path from \"node:path\";\nimport { ConsoleLoggerAdapter } from \"@milaboratories/ts-helpers\";\nimport { runStructureForPath, formatChanges } from \"../../structure/cli/run-structure\";\n\nexport function structureCheckCommand(packageRoot: string): Command {\n const cmd = new Command(\"check\").description(\n \"Check block(s) against the canonical structure (read-only). Exits non-zero if any diff would land — used as the CI gate.\",\n );\n\n // Variadic positional block paths (shell-expanded globs).\n cmd.argument(\"[paths...]\", \"block path(s); defaults to the current directory\");\n cmd.option(\"--sdk-internal\", \"block(s) live inside the SDK monorepo; skip root-scope rules\");\n\n cmd.action(async (argv: string[], flags) => {\n const logger = new ConsoleLoggerAdapter();\n const paths = argv.length > 0 ? argv : [\".\"];\n const templatesRoot = path.join(packageRoot, \"src\", \"structure\", \"templates\");\n\n let anyChanged = false;\n for (const p of paths) {\n const res = await runStructureForPath({\n blockPath: p,\n isSdkInternal: Boolean(flags.sdkInternal),\n updateDepsOnly: false,\n mode: \"check\",\n templatesRoot,\n log: (m) => logger.info(m),\n });\n logger.info(formatChanges(p, res.changes));\n if (res.changes.length > 0) anyChanged = true;\n }\n\n if (anyChanged) {\n throw new Error(\n \"Structure check failed: one or more blocks are out of date. Run `structure refresh`.\",\n );\n }\n });\n\n return cmd;\n}\n","// `block-tools structure init` constructor: collects BlockVars from CLI\n// flags (prompting for any missing field unless --non-interactive),\n// assembles `ctx.modules` via the shared `modulesForInit`, and runs the\n// engine in init mode against a NodeFileSystem rooted at the target dir.\n//\n// Replaces the manual `git clone platforma-block-boilerplate` workflow\n// and `pl-dev create-block`. `--platform` is single-valued: a\n// freshly-init'd block has at most one software module.\n\nimport { confirm, input, select } from \"@inquirer/prompts\";\nimport { NodeFileSystem } from \"./engine/fs/node\";\nimport { NodeTemplateProvider } from \"./engine/templates\";\nimport { run as engineRun } from \"./engine/runner\";\nimport { createRunContext, modulesForInit } from \"./engine/ctx\";\nimport { STRUCTURE } from \"./structure-definition\";\nimport { STRUCTURE_VERSION } from \"./engine/version\";\nimport {\n matchesBumpPattern,\n buildRegistryLookupForNames,\n buildDerivedPinLookupForPins,\n} from \"./engine/registry-client\";\nimport { SDK_CATALOG_PACKAGES, DERIVED_CATALOG_PINS } from \"./rules/root-pnpm-workspace\";\nimport type { BlockVars } from \"./engine/api\";\n\n/** Platform choices `init` can scaffold a software module for. Python is\n * the only platform with a real, buildable scaffold at v1; any other\n * value is rejected rather than scaffolded as a non-buildable placeholder,\n * which would defeat the \"init must produce a working block\" intent.\n * `softwarePlatform` stays in BlockVars for when another platform gets a\n * real scaffold. (Note: Tengo is the workflow language, not a software\n * platform.) */\nexport const SUPPORTED_PLATFORMS = [\"python\"] as const;\n\nexport type InitFlagValues = {\n npmOrg?: string;\n orgScope?: string;\n shortName?: string;\n /** Tri-state: true (--with-software), false (--no-software),\n * undefined (unspecified → prompt or, non-interactive, default off). */\n withSoftware?: boolean;\n platform?: string;\n nonInteractive: boolean;\n};\n\nexport type InitInput = {\n /** Resolved BlockVars (from `resolveBlockVars`). */\n vars: BlockVars;\n /** Resolved absolute target directory. */\n blockPath: string;\n /** `<block-tools>/src/structure/templates`. */\n templatesRoot: string;\n log: (msg: string) => void;\n};\n\nclass InitFlagError extends Error {\n constructor(flag: string) {\n super(\n `Missing required flag --${flag} in --non-interactive mode. ` +\n `Supply every BlockVars flag, or drop --non-interactive to be prompted.`,\n );\n this.name = \"InitFlagError\";\n }\n}\n\nasync function need(\n value: string | undefined,\n flag: string,\n nonInteractive: boolean,\n prompt: () => Promise<string>,\n): Promise<string> {\n if (value !== undefined && value !== \"\") return value;\n if (nonInteractive) throw new InitFlagError(flag);\n return prompt();\n}\n\n/** Resolve the full BlockVars (incl. softwarePlatform) from flags +\n * prompts. */\nexport async function resolveBlockVars(flags: InitFlagValues): Promise<BlockVars> {\n const npmOrg = await need(flags.npmOrg, \"npm-org\", flags.nonInteractive, () =>\n input({ message: \"npm org (e.g. @platforma-open):\", default: \"@platforma-open\" }),\n );\n const orgScope = await need(flags.orgScope, \"org-scope\", flags.nonInteractive, () =>\n input({ message: \"org scope (e.g. my-org):\" }),\n );\n const shortName = await need(flags.shortName, \"short-name\", flags.nonInteractive, () =>\n input({ message: \"block short name (e.g. mixcr-clonotyping):\" }),\n );\n\n // Software: explicit flag wins; otherwise prompt (interactive) or\n // default off (non-interactive).\n let hasSoftware: boolean;\n if (flags.withSoftware !== undefined) {\n hasSoftware = flags.withSoftware;\n } else if (flags.nonInteractive) {\n hasSoftware = false;\n } else {\n hasSoftware = await confirm({ message: \"Include a software module?\", default: false });\n }\n\n let softwarePlatform: string | undefined;\n if (hasSoftware) {\n softwarePlatform = await need(flags.platform, \"platform\", flags.nonInteractive, () =>\n select({\n message: \"Software platform:\",\n choices: SUPPORTED_PLATFORMS.map((p) => ({ name: p, value: p })),\n }),\n );\n if (!(SUPPORTED_PLATFORMS as readonly string[]).includes(softwarePlatform)) {\n throw new Error(\n `Unsupported --platform '${softwarePlatform}'. ` +\n `Only ${SUPPORTED_PLATFORMS.join(\", \")} ${\n SUPPORTED_PLATFORMS.length === 1 ? \"is\" : \"are\"\n } supported at v1.`,\n );\n }\n } else if (flags.platform) {\n throw new Error(\"--platform was given but software is disabled (--no-software).\");\n }\n\n const facadeName = `${npmOrg}/${orgScope}.${shortName}`;\n return {\n facadeName,\n baseName: `${orgScope}.${shortName}`,\n npmOrg,\n orgScope,\n shortName,\n softwarePlatform,\n };\n}\n\nexport async function runInit(init: InitInput): Promise<BlockVars> {\n const vars = init.vars;\n const modules = modulesForInit(vars);\n\n const fs = new NodeFileSystem(init.blockPath);\n const templates = new NodeTemplateProvider(init.templatesRoot);\n const ctx = createRunContext({\n blockVars: vars,\n modules,\n isSdkInternal: false,\n version: STRUCTURE_VERSION,\n dryRun: false,\n });\n\n // Init REQUIRES network: resolve the SDK catalog families to npm latest\n // before the run, so the generated block carries real current versions\n // (no placeholders). The names come from the SDK catalog package list —\n // there is no on-disk pnpm-workspace.yaml to read yet. A registry failure\n // aborts init rather than silently shipping an unresolved placeholder.\n const sdkNames = SDK_CATALOG_PACKAGES.filter(matchesBumpPattern);\n let registryLookup: (name: string) => string | undefined;\n let derivedPinLookup: (entry: string) => string | undefined;\n try {\n registryLookup = await buildRegistryLookupForNames(sdkNames);\n // Derived catalog pins (e.g. vue ← ui-vue's declared dep) are resolved on\n // init too, so a freshly-scaffolded block pins vue exactly from the start.\n derivedPinLookup = await buildDerivedPinLookupForPins(DERIVED_CATALOG_PINS);\n } catch (err) {\n throw new Error(\n `init requires network access to resolve SDK catalog versions from npm, ` +\n `but the registry lookup failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n engineRun(STRUCTURE, fs, ctx, {\n templates,\n initMode: true,\n registryLookup,\n derivedPinLookup,\n });\n init.log(\n `Initialised block '${vars.facadeName}'${\n vars.softwarePlatform ? ` (software: ${vars.softwarePlatform})` : \" (no software)\"\n } at ${init.blockPath}`,\n );\n return vars;\n}\n","import { Command, Option } from \"commander\";\nimport path from \"node:path\";\nimport { ConsoleLoggerAdapter } from \"@milaboratories/ts-helpers\";\nimport {\n resolveBlockVars,\n runInit,\n SUPPORTED_PLATFORMS,\n type InitFlagValues,\n} from \"../../structure/init-block-constructor\";\n\nexport function structureInitCommand(packageRoot: string): Command {\n const cmd = new Command(\"init\").description(\n \"Scaffold a fresh Platforma block from the canonical structure. Missing flags are prompted unless --non-interactive.\",\n );\n\n cmd.argument(\"[path]\", \"target directory (default: <short-name> under the current directory)\");\n cmd.option(\"--npm-org <org>\", \"npm org, e.g. @platforma-open\");\n cmd.option(\"--org-scope <scope>\", \"org scope, e.g. my-org\");\n cmd.option(\"--short-name <name>\", \"block short name, e.g. mixcr-clonotyping\");\n cmd.option(\"--with-software\", \"include a software module\");\n cmd.option(\"--no-software\", \"omit the software module\");\n cmd.addOption(\n new Option(\"--platform <platform>\", \"software platform (single-valued)\").choices([\n ...SUPPORTED_PLATFORMS,\n ]),\n );\n cmd.option(\"--non-interactive\", \"error on any missing flag instead of prompting\");\n\n cmd.action(async (argPath: string | undefined, flags) => {\n const logger = new ConsoleLoggerAdapter();\n\n // commander maps `--with-software` -> flags.withSoftware===true and\n // `--no-software` -> flags.software===false\n const withSoftwareFlag = flags.withSoftware === true;\n const noSoftwareFlag = flags.software === false;\n if (withSoftwareFlag && noSoftwareFlag) {\n throw new Error(\"--with-software and --no-software are mutually exclusive.\");\n }\n const withSoftware = withSoftwareFlag ? true : noSoftwareFlag ? false : undefined;\n\n const flagValues: InitFlagValues = {\n npmOrg: flags.npmOrg,\n orgScope: flags.orgScope,\n shortName: flags.shortName,\n withSoftware,\n platform: flags.platform,\n nonInteractive: flags.nonInteractive,\n };\n\n const vars = await resolveBlockVars(flagValues);\n const blockPath = argPath ? path.resolve(argPath) : path.resolve(process.cwd(), vars.shortName);\n const templatesRoot = path.join(packageRoot, \"src\", \"structure\", \"templates\");\n\n await runInit({ vars, blockPath, templatesRoot, log: (m) => logger.info(m) });\n });\n\n return cmd;\n}\n","import { util } from \"@platforma-sdk/package-builder-lib\";\n\nexport const channels = [\"dev\", \"release\"] as const;\nexport const variants = [\"docker\", \"binary\", \"all\", \"none\"] as const;\nexport const locations = [\"local\", \"remote\"] as const;\n\nexport type Channel = (typeof channels)[number];\nexport type Variant = (typeof variants)[number];\nexport type Location = (typeof locations)[number];\n\n// Raw CLI flags, each independently optional; parseScenario narrows them to a supported Scenario.\nexport type Knobs = {\n channel?: Channel;\n variant?: Variant;\n location?: Location;\n usePublished?: boolean;\n};\n\n// The variant a resolved target actually builds — \"none\" is its own scenario, never a target.\nexport type TargetVariant = Exclude<Variant, \"none\">;\n\n// The closed set of scenarios runBuild executes; parseScenario rejects anything else. `target`\n// carries the resolved knobs as enums (not pre-derived booleans) — runBuild derives the flags.\nexport type Scenario =\n // `build:dev-binary-existing` (PL_BUILD_USE_PUBLISHED): reference the published binary; no build/push.\n | { kind: \"binary-existing\" }\n // `build:dev-no-software` (PL_BUILD_VARIANT=none): placeholder descriptors; nothing built or pushed.\n | { kind: \"no-software\" }\n // no build:* script — the scriptless default (direct call / `do-pack`); drop-in `pl-pkg build`.\n | { kind: \"bare\" }\n // `build:dev-local` / `build:dev-remote` / `build:release` / `test`: build for a target.\n | { kind: \"target\"; channel: Channel; variant: TargetVariant; location: Location };\n\n// Collapse the raw knobs to a supported Scenario; the one place bad combinations are rejected.\nexport function parseScenario(knobs: Knobs): Scenario {\n if (knobs.usePublished) {\n // A published binary can be referenced; docker (and `all`, which includes it) cannot.\n if (knobs.variant === \"docker\" || knobs.variant === \"all\") {\n throw util.CLIError(\n `--use-published is binary-only and cannot be combined with --variant ${knobs.variant}`,\n );\n }\n return { kind: \"binary-existing\" };\n }\n\n if (knobs.variant === \"none\") {\n return { kind: \"no-software\" };\n }\n\n if (knobs.location === undefined) {\n return { kind: \"bare\" };\n }\n\n // `all` (the default) builds every declared variant; the engine skips the kinds the software omits.\n return {\n kind: \"target\",\n channel: knobs.channel ?? \"release\",\n variant: knobs.variant ?? \"all\",\n location: knobs.location,\n };\n}\n","import { spawnSync } from \"node:child_process\";\nimport * as os from \"node:os\";\nimport {\n ECRPUBLICClient as EcrPublicClient,\n GetAuthorizationTokenCommand,\n} from \"@aws-sdk/client-ecr-public\";\nimport { util, defaults, type Logger } from \"@platforma-sdk/package-builder-lib\";\n\nconst PUBLIC_ECR_HOST = \"public.ecr.aws\";\n// ECR Public's API is served only from us-east-1, independent of where images are pulled.\nconst PUBLIC_ECR_REGION = \"us-east-1\";\n\n// Pin AWS_PROFILE once so the ECR client and the S3 upload resolve identical credentials.\n// Env credentials (CI) and an explicit AWS_PROFILE take precedence and skip this.\nexport function ensureAwsProfile(logger?: Logger): void {\n if (process.env.AWS_ACCESS_KEY_ID || process.env.AWS_PROFILE) return;\n const profile = process.env.PL_AWS_PROFILE ?? defaults.AWS_DEV_PROFILE;\n process.env.AWS_PROFILE = profile;\n logger?.debug(`Using AWS profile '${profile}' for dev push credentials`);\n}\n\n// Host of a scheme-less registry ref: public.ecr.aws/u5p1x5q2/pl-containers -> public.ecr.aws\nfunction registryHost(registry: string): string {\n return new URL(`https://${registry}`).hostname;\n}\n\nfunction ssoLoginHint(): string {\n const profile = process.env.AWS_PROFILE ?? process.env.PL_AWS_PROFILE ?? defaults.AWS_DEV_PROFILE;\n return ` aws sso login --profile ${profile}`;\n}\n\n// docker login to public ECR with an SDK-fetched token. No cached-auth check — re-authenticates\n// every call, so an expired/absent session fails here with a recoverable hint, not opaquely at push.\nexport async function ensureEcrLogin(registry: string, logger?: Logger): Promise<void> {\n const host = registryHost(registry);\n if (host !== PUBLIC_ECR_HOST) {\n // Public ECR is the only dev docker registry; reject a mis-set ecr:// override.\n throw util.CLIError(\n `automatic docker login is only supported for '${PUBLIC_ECR_HOST}', not '${host}'.\\n` +\n `Log in manually, or drop the ecr:// scheme from the push target to opt out.`,\n );\n }\n\n logger?.info(`Logging in to ECR registry '${host}'...`);\n\n let user: string;\n let password: string;\n try {\n const client = new EcrPublicClient({ region: PUBLIC_ECR_REGION });\n const res = await client.send(new GetAuthorizationTokenCommand({}));\n const token = res.authorizationData?.authorizationToken;\n if (!token) throw new Error(\"empty authorization token\");\n // Token decodes to \"AWS:<password>\"; password may contain ':', so split on the first only.\n const decoded = Buffer.from(token, \"base64\").toString(\"utf8\");\n const sep = decoded.indexOf(\":\");\n if (sep < 0) throw new Error(`malformed authorization token (no ':' separator)`);\n user = decoded.slice(0, sep);\n password = decoded.slice(sep + 1);\n } catch (e) {\n throw util.CLIError(\n `failed to obtain an ECR login token for '${host}': ${e instanceof Error ? e.message : String(e)}\\n` +\n `Your AWS/SSO session is likely expired or absent — log in and retry:\\n` +\n ssoLoginHint(),\n );\n }\n\n const login = spawnSync(\"docker\", [\"login\", \"--username\", user, \"--password-stdin\", host], {\n input: password,\n stdio: [\"pipe\", \"inherit\", \"inherit\"],\n env: { ...process.env, HOME: process.env.HOME || os.homedir() },\n });\n if (login.error || login.status !== 0) {\n throw util.CLIError(`'docker login ${host}' failed`);\n }\n}\n","import {\n util,\n envs,\n defaults,\n type Builder,\n type Logger,\n} from \"@platforma-sdk/package-builder-lib\";\nimport type { Channel, Scenario } from \"./knobs\";\nimport { ensureAwsProfile, ensureEcrLogin } from \"./ecr-login\";\n\n// Pass-through controls mirroring `pl-pkg build`. Empty means \"engine default\". The --docker-/\n// --conda- flag pairs are already collapsed to decisions at the CLI boundary (build.ts): only the\n// `bare` scenario reads buildDocker/pushDocker; condaBuild applies to every binary build.\nexport type BuildOptions = {\n ids?: string[];\n force?: boolean;\n contentRoot?: string;\n storageUrl?: string;\n dockerRegistry?: string;\n dockerPushTo?: string;\n buildDocker?: boolean;\n pushDocker?: boolean;\n condaBuild?: boolean;\n};\n\n// Build a scenario in one pass: build, push when remote, then write the descriptor last —\n// \"ready ⟺ the descriptor exists\". The pre-configured builder is injected; runBuild sets the\n// scenario's build mode and drives it.\nexport async function runBuild(params: {\n core: Builder;\n scenario: Scenario;\n options?: BuildOptions;\n logger?: Logger;\n}): Promise<void> {\n const { core, scenario, options: opts = {}, logger } = params;\n const ids = opts.ids;\n core.buildMode = buildModeForScenario(scenario);\n\n const buildBinary = () =>\n core.buildSoftwareArchives({\n ids,\n forceBuild: Boolean(opts.force),\n contentRoot: opts.contentRoot,\n // Tolerate a package with no archives only on a build-all run; when specific ids are\n // requested, an empty build is a real error the caller wants to hear about.\n skipIfEmpty: !ids,\n condaBuild: opts.condaBuild,\n });\n\n switch (scenario.kind) {\n case \"binary-existing\":\n // Descriptor points at an already-published release artifact; nothing is built or pushed.\n core.writePublishedArtifactInfo({ ids });\n break;\n\n case \"no-software\":\n // Nothing built or pushed; the placeholder descriptor is written below.\n break;\n\n case \"bare\": {\n // Bare pl-pkg-parity invocation; buildDocker/pushDocker were resolved at the CLI boundary.\n if (opts.buildDocker) {\n core.buildDockerImages({\n ids,\n registry: opts.dockerRegistry,\n strictPlatformMatching: envs.isCI(),\n });\n }\n await buildBinary();\n if (opts.pushDocker) {\n core.publishDockerImages({\n ids,\n pushTo: opts.dockerPushTo,\n strictPlatformMatching: envs.isCI(),\n });\n }\n break;\n }\n\n case \"target\": {\n const { channel, variant, location } = scenario;\n const docker = variant !== \"binary\";\n const binary = variant !== \"docker\";\n const remote = location === \"remote\";\n const addr = resolveDockerAddresses(channel, opts);\n\n // BUILD (descriptor not written yet).\n if (docker) {\n core.buildDockerImages({ ids, registry: addr.pull, strictPlatformMatching: envs.isCI() });\n }\n if (binary) await buildBinary();\n\n // PUSH when remote. Pin the AWS credential chain once (docker login + S3 upload share it), but\n // only for dev — the fallback profile is the dev SSO one.\n if (remote && channel === \"dev\" && (docker || binary)) ensureAwsProfile(logger);\n if (docker && remote) {\n if (addr.autoLogin && addr.push) await ensureEcrLogin(addr.push, logger);\n core.publishDockerImages({ ids, pushTo: addr.push, strictPlatformMatching: envs.isCI() });\n }\n if (binary && remote) {\n // storageURL falls through to the engine, which resolves the dev/release endpoint.\n await core.publishPackages({ ids, storageURL: opts.storageUrl });\n }\n break;\n }\n\n default:\n util.assertNever(scenario);\n }\n\n // DESCRIPTOR LAST — only after build + push have succeeded.\n core.buildSwJsonFiles({ packageIds: ids, noSoftware: scenario.kind === \"no-software\" });\n}\n\nfunction buildModeForScenario(scenario: Scenario): util.BuildMode {\n if (scenario.kind !== \"target\") return \"release\";\n if (scenario.channel === \"release\") return \"release\";\n // Only a remote binary build needs dev-remote (it uploads an archive). Docker-only, or any\n // local build, uses dev-local — docker naming is content-addressed by image ID regardless.\n const binaryRemote = scenario.variant !== \"docker\" && scenario.location === \"remote\";\n return binaryRemote ? \"dev-remote\" : \"dev-local\";\n}\n\n// Bare registry ref (host[:port]/path) with any URL scheme removed.\nfunction stripScheme(raw: string): string {\n if (!raw.includes(\"://\")) return raw; // already bare\n const url = new URL(raw);\n return url.host + url.pathname;\n}\n\n// A push target may carry a scheme selecting auto docker-login: `ecr://` opts in, anything else out.\nfunction parsePushTarget(raw: string): { registry: string; autoLogin: boolean } {\n return { registry: stripScheme(raw), autoLogin: raw.startsWith(\"ecr://\") };\n}\n\n// Docker push target + the pull address embedded in the descriptor. Precedence flag > channel env >\n// dev default (release has none). Pull default is channel-specific: dev pulls from where it pushed\n// (one ECR host), but release push (quay) and pull (containers.pl-open.science, GA-fronted proxy) are\n// different locations by design, so release pull defaults to the built-in registry, NOT the push\n// target. autoLogin follows the push target's ecr://.\nfunction resolveDockerAddresses(\n channel: Channel,\n opts: BuildOptions,\n): { pull?: string; push?: string; autoLogin: boolean } {\n const isDev = channel === \"dev\";\n const channelPush =\n process.env[isDev ? envs.PL_DEV_DOCKER_PUSH_URL : envs.PL_RELEASE_DOCKER_PUSH_URL];\n const channelPull =\n process.env[isDev ? envs.PL_DEV_DOCKER_PULL_URL : envs.PL_RELEASE_DOCKER_PULL_URL];\n\n const rawPush =\n opts.dockerPushTo ?? channelPush ?? (isDev ? defaults.DEV_DOCKER_PUSH_TARGET : undefined);\n const parsed = rawPush ? parsePushTarget(rawPush) : { registry: undefined, autoLogin: false };\n\n const rawPull =\n opts.dockerRegistry ?? channelPull ?? (isDev ? rawPush : defaults.DOCKER_REGISTRY);\n const pull = rawPull ? stripScheme(rawPull) : undefined;\n\n return { pull, push: parsed.registry, autoLogin: parsed.autoLogin };\n}\n","import { envs } from \"@platforma-sdk/package-builder-lib\";\n\n// The `software build` knob env vars (the flag/env pairs the scenario scripts set).\nexport const PL_BUILD_CHANNEL = \"PL_BUILD_CHANNEL\";\nexport const PL_BUILD_VARIANT = \"PL_BUILD_VARIANT\";\nexport const PL_BUILD_LOCATION = \"PL_BUILD_LOCATION\";\nexport const PL_BUILD_USE_PUBLISHED = \"PL_BUILD_USE_PUBLISHED\";\n\n// Every env var that changes `block-tools software build` output, so must key the turbo build cache.\nexport const softwareBuildCacheEnv: readonly string[] = [\n PL_BUILD_CHANNEL,\n PL_BUILD_VARIANT,\n PL_BUILD_LOCATION,\n PL_BUILD_USE_PUBLISHED,\n envs.PL_DOCKER_REGISTRY_PUSH_TO,\n envs.PL_DEV_DOCKER_PUSH_URL,\n envs.PL_DEV_DOCKER_PULL_URL,\n envs.PL_DEV_BINARY_UPLOAD_URL,\n envs.PL_RELEASE_DOCKER_PUSH_URL,\n envs.PL_RELEASE_DOCKER_PULL_URL,\n envs.PL_RELEASE_BINARY_UPLOAD_URL,\n];\n","import { Command, Option } from \"commander\";\nimport { util, envs, createBuilder } from \"@platforma-sdk/package-builder-lib\";\nimport { parseScenario, channels, variants, locations } from \"./knobs\";\nimport { runBuild } from \"./run-build\";\nimport {\n PL_BUILD_CHANNEL,\n PL_BUILD_VARIANT,\n PL_BUILD_LOCATION,\n PL_BUILD_USE_PUBLISHED,\n} from \"./env\";\n\n// Build a software module in one pass — build, push when remote, then write the descriptor\n// last. With no knobs it reproduces `pl-pkg build`.\nexport function softwareBuildCommand(): Command {\n const cmd = new Command(\"build\").description(\n \"Build a software module for a target and write its .sw.json descriptor (build + push in one pass)\",\n );\n\n // The three target knobs (env-backed; flag wins on conflict).\n cmd.addOption(\n new Option(\"--channel <channel>\", \"registry channel to build for\")\n .choices([...channels])\n .env(PL_BUILD_CHANNEL),\n );\n cmd.addOption(\n new Option(\"--variant <variant>\", \"artifact kind to build (default: all declared)\")\n .choices([...variants])\n .env(PL_BUILD_VARIANT),\n );\n cmd.addOption(\n new Option(\"--location <location>\", \"where the artifact lands (local = no push)\")\n .choices([...locations])\n .env(PL_BUILD_LOCATION),\n );\n cmd.addOption(\n new Option(\n \"--use-published\",\n \"do not build or push; emit a descriptor pointing at the already-published release artifact\",\n ).env(PL_BUILD_USE_PUBLISHED),\n );\n\n // Pass-through build options, mirroring `pl-pkg build` so this is a drop-in replacement.\n cmd.addOption(\n new Option(\"--log-level <level>\", \"logging level\")\n .choices([\"error\", \"warn\", \"info\", \"debug\"])\n .default(\"info\"),\n );\n cmd.addOption(new Option(\"--package-root <path>\", \"path to directory with package.json file\"));\n cmd.addOption(\n new Option(\"--force\", \"force action, ignoring automatic safety checks\").default(false),\n );\n cmd.addOption(new Option(\"--version <value>\", \"override package version (ignore package.json)\"));\n cmd.addOption(\n new Option(\"--platform <os-arch>\", \"{os}-{arch} pair; no effect on cross-platform packages\")\n .choices([...util.AllPlatforms])\n .env(envs.PL_PKG_OS),\n );\n cmd.addOption(new Option(\"--all-platforms\", \"build for all supported platforms\").default(false));\n cmd.addOption(\n new Option(\"--full-dir-hash\", \"hash file contents (not metadata) for the dev content hash\")\n .env(envs.PL_PKG_FULL_HASH)\n .default(false),\n );\n cmd.addOption(new Option(\"--package-id <id...>\", \"act only on selected packages\"));\n cmd.addOption(\n new Option(\"--content-root <path>\", \"override software content root\").env(\n envs.PL_PKG_CONTENT_ROOT,\n ),\n );\n cmd.addOption(\n new Option(\"--storage-url <url>\", \"override binary upload registry URL\").env(\n envs.PL_PKG_STORAGE_URL,\n ),\n );\n cmd.addOption(\n new Option(\n \"--docker-registry <registry>\",\n \"docker pull registry embedded in the descriptor\",\n ).env(envs.PL_DOCKER_REGISTRY),\n );\n cmd.addOption(\n new Option(\"--docker-push-to <registry>\", \"alternative registry for docker push\").env(\n envs.PL_DOCKER_REGISTRY_PUSH_TO,\n ),\n );\n cmd.addOption(\n new Option(\"--docker-build\", \"build docker images\").env(envs.PL_DOCKER_BUILD).default(false),\n );\n cmd.addOption(\n new Option(\"--docker-no-build\", \"do not build docker images\")\n .env(envs.PL_DOCKER_NO_BUILD)\n .default(false),\n );\n cmd.addOption(\n new Option(\"--docker-autopush\", \"push docker images after build\")\n .env(envs.PL_DOCKER_AUTOPUSH)\n .default(false),\n );\n cmd.addOption(\n new Option(\"--docker-no-autopush\", \"do not push docker images\")\n .env(envs.PL_DOCKER_NO_AUTOPUSH)\n .default(false),\n );\n cmd.addOption(\n new Option(\"--conda-build\", \"build conda environment before packing\")\n .env(envs.PL_CONDA_BUILD)\n .default(false),\n );\n cmd.addOption(\n new Option(\"--conda-no-build\", \"do not build conda environment\")\n .env(envs.PL_CONDA_NO_BUILD)\n .default(false),\n );\n\n cmd.action(async (o) => {\n const logger = util.createLogger(o.logLevel);\n\n try {\n const scenario = parseScenario({\n channel: o.channel,\n variant: o.variant,\n location: o.location,\n usePublished: Boolean(o.usePublished),\n });\n\n const core = createBuilder(logger, { packageRoot: o.packageRoot });\n core.version = o.version;\n core.targetPlatform = o.platform as util.PlatformType;\n core.allPlatforms = Boolean(o.allPlatforms);\n core.fullDirHash = Boolean(o.fullDirHash);\n\n // Collapse the pl-pkg-parity --{docker,conda}-{,no-}* flag pairs to decisions here, at the CLI\n // boundary, so runBuild receives resolved booleans (docker defaults to on in CI, push unless private).\n const buildDocker = util.shouldDoAction({\n default: envs.isCI(),\n enable: o.dockerBuild,\n disable: o.dockerNoBuild,\n });\n const pushDocker =\n buildDocker &&\n util.shouldDoAction({\n default: envs.isCI() && !core.isPrivate,\n enable: o.dockerAutopush,\n disable: o.dockerNoAutopush,\n });\n\n await runBuild({\n core,\n scenario,\n logger,\n options: {\n ids: o.packageId,\n force: o.force,\n contentRoot: o.contentRoot,\n storageUrl: o.storageUrl,\n dockerRegistry: o.dockerRegistry,\n dockerPushTo: o.dockerPushTo,\n buildDocker,\n pushDocker,\n condaBuild: util.shouldDoAction({\n default: true,\n enable: o.condaBuild,\n disable: o.condaNoBuild,\n }),\n },\n });\n } catch (e) {\n logger.debug(e);\n if (e instanceof Error) logger.debug(e.stack);\n throw e;\n }\n });\n\n return cmd;\n}\n","import { Command } from \"commander\";\nimport { softwareBuildCommand } from \"./build\";\n\n// `software` parent command: per-target software build (and future software subcommands).\nexport function softwareCommand(): Command {\n const cmd = new Command(\"software\").description(\"Build and publish a block's software modules\");\n cmd.addCommand(softwareBuildCommand());\n return cmd;\n}\n","import { Command } from \"commander\";\nimport { buildMetaCommand } from \"./cmd/build-meta\";\nimport { buildModelCommand } from \"./cmd/build-model\";\nimport { packCommand } from \"./cmd/pack\";\nimport { publishCommand } from \"./cmd/publish\";\nimport { refreshRegistryCommand } from \"./cmd/refresh-registry\";\nimport { markStableCommand } from \"./cmd/mark-stable\";\nimport { updateDepsCommand } from \"./cmd/update-deps\";\nimport { listOverviewSnapshotsCommand } from \"./cmd/list-overview-snapshots\";\nimport { restoreOverviewFromSnapshotCommand } from \"./cmd/restore-overview-from-snapshot\";\nimport { uploadPackageV1Command } from \"./cmd/upload-package-v1\";\nimport { structureCheckCommand } from \"./cmd/structure/check\";\nimport { structureInitCommand } from \"./cmd/structure/init\";\nimport { structureRefreshCommand } from \"./cmd/structure/refresh\";\nimport { softwareCommand } from \"./cmd/software\";\n\n// `packageRoot` is the package install root (the dir containing `src/` and\n// `bin/`); the `structure` commands resolve their templates under it. bin/run.js\n// passes it in; defaults to cwd for tests/introspection.\nexport function buildProgram(packageRoot: string = process.cwd()): Command {\n const program = new Command();\n program\n .name(\"block-tools\")\n .description(\"Utility to manipulate Platforma Blocks and Block Registry\");\n\n program.addCommand(buildMetaCommand());\n program.addCommand(buildModelCommand());\n program.addCommand(packCommand());\n program.addCommand(publishCommand());\n program.addCommand(refreshRegistryCommand());\n program.addCommand(markStableCommand());\n program.addCommand(updateDepsCommand(packageRoot));\n program.addCommand(listOverviewSnapshotsCommand());\n program.addCommand(restoreOverviewFromSnapshotCommand());\n program.addCommand(uploadPackageV1Command());\n program.addCommand(softwareCommand());\n\n // `structure` subcommands: check | init | refresh.\n const structure = new Command(\"structure\").description(\n \"Manage block scaffolding against the canonical structure (check / init / refresh)\",\n );\n structure.addCommand(structureCheckCommand(packageRoot));\n structure.addCommand(structureInitCommand(packageRoot));\n structure.addCommand(structureRefreshCommand(packageRoot));\n program.addCommand(structure);\n\n return program;\n}\n\nexport async function run(argv: string[], packageRoot: string): Promise<void> {\n await buildProgram(packageRoot).parseAsync(argv);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.mjs","names":[],"sources":["../src/cmd/build-meta.ts","../src/cmd/build-model.ts","../src/cmd/build-kind-manifest.ts","../src/cmd/pack.ts","../src/cmd/publish.ts","../src/cmd/refresh-registry.ts","../src/cmd/mark-stable.ts","../src/structure/engine/fs/node.ts","../src/structure/engine/templates.ts","../src/structure/engine/flatten.ts","../src/structure/engine/glob.ts","../src/structure/engine/builders.ts","../src/structure/engine/parsers/json.ts","../src/structure/engine/parsers/lines.ts","../src/structure/engine/content-rules.ts","../src/structure/engine/parsers/yaml.ts","../src/structure/engine/version.ts","../src/structure/engine/runner.ts","../src/structure/engine/discovery.ts","../src/structure/engine/ctx.ts","../src/structure/engine/discovery-fs.ts","../src/structure/rules/shared/key-order.ts","../src/structure/rules/root-package-json.ts","../src/structure/rules/root-turbo-json.ts","../src/structure/engine/registry-client.ts","../src/structure/rules/shared/retired-deps.ts","../src/structure/rules/root-pnpm-workspace.ts","../src/structure/rules/root-gitignore.ts","../src/structure/rules/root.ts","../src/structure/rules/root-ci.ts","../src/structure/rules/block-package-json.ts","../src/structure/rules/shared/pascal-case.ts","../src/structure/rules/block.ts","../src/structure/rules/shared/colocated-tests.ts","../src/structure/rules/model-package-json.ts","../src/structure/rules/model.ts","../src/structure/rules/kind-package-json.ts","../src/structure/rules/kind.ts","../src/structure/rules/ui-package-json.ts","../src/structure/rules/ui.ts","../src/structure/rules/workflow-package-json.ts","../src/structure/rules/workflow.ts","../src/structure/rules/test-package-json.ts","../src/structure/rules/test.ts","../src/structure/rules/software-package-json.ts","../src/structure/rules/software.ts","../src/structure/rules/migrations.ts","../src/structure/rules/root-catalog-bump.ts","../src/structure/structure-definition.ts","../src/structure/cli/run-structure.ts","../src/cmd/structure/refresh.ts","../src/cmd/update-deps.ts","../src/cmd/list-overview-snapshots.ts","../src/cmd/restore-overview-from-snapshot.ts","../src/registry_v1/flags.ts","../src/cmd/upload-package-v1.ts","../src/cmd/structure/check.ts","../src/structure/init-block-constructor.ts","../src/cmd/structure/init.ts","../src/cmd/software/knobs.ts","../src/cmd/software/ecr-login.ts","../src/cmd/software/run-build.ts","../src/cmd/software/env.ts","../src/cmd/software/build.ts","../src/cmd/software/index.ts","../src/cli.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport path from \"node:path\";\nimport fs from \"node:fs\";\nimport { loadPackDescriptionRaw } from \"../v2\";\nimport { embedBlockPackMetaAbsoluteBase64, resolveBlockPackMeta } from \"../v2/model/block_meta\";\n\nexport function buildMetaCommand(): Command {\n const cmd = new Command(\"build-meta\").description(\n \"Extracts meta information from blocks package.json and outputs meta.json with embedded binary \" +\n \"and textual information linked from the meta section.\",\n );\n\n cmd.option(\"-i, --modulePath <path>\", \"input module path\", \".\");\n cmd.requiredOption(\"-o, --destination <path>\", \"output meta.json file\");\n\n cmd.action(async (flags) => {\n const modulePath = path.resolve(flags.modulePath);\n const descriptionRaw = await loadPackDescriptionRaw(modulePath);\n const metaEmbedded = await embedBlockPackMetaAbsoluteBase64(\n await resolveBlockPackMeta(descriptionRaw.meta, modulePath),\n );\n\n await fs.promises.writeFile(path.resolve(flags.destination), JSON.stringify(metaEmbedded));\n });\n\n return cmd;\n}\n","import { Command } from \"commander\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nasync function getFileContent(path: string) {\n try {\n return await fs.promises.readFile(path, \"utf8\");\n } catch (error: unknown) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n return undefined;\n }\n throw error;\n }\n}\n\nexport function buildModelCommand(): Command {\n const cmd = new Command(\"build-model\").description(\n \"Extracts and outputs block model JSON from pre-built block model module\",\n );\n\n cmd.option(\"-i, --modulePath <path>\", \"input module path\", \".\");\n cmd.option(\n \"-b, --sourceBundle <path>\",\n \"bundled model code to embed into the model for callback-based rendering to work\",\n \"./dist/bundle.js\",\n );\n cmd.option(\"-o, --destination <path>\", \"output model file\", \"./dist/model.json\");\n\n cmd.action(async (flags) => {\n const modulePath = path.resolve(flags.modulePath); // i.e. folder with package.json file\n let { model, platforma } = require(modulePath);\n\n if (!model) model = platforma;\n if (!model) throw new Error('\"model\" export not found');\n\n const { config } = model;\n\n if (!config)\n throw new Error(\n 'Malformed \"model\" object, check it is created with \"BlockModel\" ' +\n 'and \".done()\" is executed as the call in the chain.',\n );\n\n if (!(\"outputs\" in config) || !(\"sections\" in config))\n throw new Error('\"config\" has unexpected structure');\n\n const code = await getFileContent(flags.sourceBundle);\n if (code !== undefined) {\n config.code = {\n type: \"plain\",\n content: code,\n };\n }\n\n await fs.promises.writeFile(path.resolve(flags.destination), JSON.stringify(config));\n });\n\n return cmd;\n}\n","import { Command } from \"commander\";\nimport { buildKindDist } from \"../v2/build_kind_dist\";\n\n// @todo: disscuss why we need manifest for kind\n\n/**\n * Thin commander wrapper (build-model.ts shape) delegating to the commander-free\n * `buildKindDist` core. Bundles the compiled kind's identity + src source-hash\n * into `dist/manifest.json`.\n */\nexport function buildKindManifestCommand(): Command {\n const cmd = new Command(\"build-kind-manifest\").description(\n \"Writes the block-kind dist manifest (identity + src source-hash) from a pre-built kind bundle\",\n );\n\n cmd.option(\n \"-i, --modulePath <path>\",\n \"kind package dir (contains package.json, src/, dist/)\",\n \".\",\n );\n cmd.option(\n \"-s, --srcDir <path>\",\n \"source dir hashed into sourceHash, relative to modulePath\",\n \"src\",\n );\n cmd.option(\n \"-o, --dst <path>\",\n \"output dir with the compiled bundle, relative to modulePath\",\n \"dist\",\n );\n\n cmd.action(async (flags) => {\n await buildKindDist({\n modulePath: flags.modulePath,\n srcDir: flags.srcDir,\n dst: flags.dst,\n });\n });\n\n return cmd;\n}\n","import { Command } from \"commander\";\nimport { loadPackDescription } from \"../v2/source_package\";\nimport path from \"node:path\";\nimport { buildBlockPackDist } from \"../v2/build_dist\";\n\nexport function packCommand(): Command {\n const cmd = new Command(\"pack\").description(\n \"Builds block pack and outputs a block pack manifest consolidating all \" +\n \"references assets into a single folder\",\n );\n\n cmd.option(\"-i, --modulePath <path>\", \"input module path\", \".\");\n cmd.option(\"-o, --destinationPath <path>\", \"output folder\", \"./block-pack\");\n\n cmd.action(async (flags) => {\n const description = await loadPackDescription(path.resolve(flags.modulePath));\n await buildBlockPackDist(description, path.resolve(flags.destinationPath));\n });\n\n return cmd;\n}\n","import { Command, Option } from \"commander\";\nimport fs from \"node:fs\";\nimport { ConsoleLoggerAdapter } from \"@milaboratories/ts-helpers\";\nimport { ManifestFileName } from \"../v2/registry/schema_public\";\nimport {\n BlockPackManifest,\n overrideManifestVersion,\n StableChannel,\n} from \"@milaboratories/pl-model-middle-layer\";\nimport { storageByUrl } from \"../io/storage\";\nimport { BlockRegistryV2 } from \"../v2/registry/registry\";\nimport { publishBlock } from \"../v2/publish-block\";\nimport { buildPublishedCoords, writePublishedCoords } from \"../v2/resolve_to_registry\";\nimport path from \"node:path\";\n\nfunction simpleDeepMerge<T extends Record<string, unknown>>(\n target: Record<string, unknown>,\n source: T,\n): T {\n const result = { ...target };\n\n for (const key in source) {\n if (source[key] && typeof source[key] === \"object\" && !Array.isArray(source[key])) {\n if (result[key] && typeof result[key] === \"object\" && !Array.isArray(result[key])) {\n result[key] = simpleDeepMerge(\n result[key] as Record<string, unknown>,\n source[key] as Record<string, unknown>,\n );\n } else {\n result[key] = source[key];\n }\n } else {\n result[key] = source[key];\n }\n }\n\n return result as T;\n}\n\nexport function publishCommand(): Command {\n const cmd = new Command(\"publish\").description(\n \"Publishes the block package and refreshes the registry (for v2 block-pack schema)\",\n );\n\n cmd.addOption(\n new Option(\"-r, --registry <address>\", \"full address of the registry\")\n .env(\"PL_REGISTRY\")\n .makeOptionMandatory(),\n );\n cmd.addOption(\n new Option(\n \"--registry-serve-url <url>\",\n \"CDN serve URL written into block-pack/published.json (npm-consumed blocks)\",\n )\n .env(\"PL_REGISTRY_SERVE_URL\")\n .makeOptionMandatory(),\n );\n cmd.option(\"-m, --manifest <path>\", \"manifest file path\", `./block-pack/${ManifestFileName}`);\n cmd.option(\"-v, --version-override <path>\", \"override package version\");\n cmd.addOption(\n new Option(\"--refresh\", \"refresh repository after adding the package\")\n .default(true)\n .env(\"PL_REGISTRY_REFRESH\"),\n );\n cmd.option(\"--no-refresh\", \"do not refresh repository after adding the package\");\n cmd.addOption(\n new Option(\"--unstable\", \"do not add the published package to stable channel\")\n .default(false)\n .env(\"PL_PUBLISH_UNSTABLE\"),\n );\n\n cmd.action(async (flags) => {\n const logger = new ConsoleLoggerAdapter();\n\n const manifestPath = path.resolve(flags.manifest);\n const rawManifest = JSON.parse(\n await fs.promises.readFile(manifestPath, { encoding: \"utf-8\" }),\n ) as Record<string, unknown>;\n let manifest = BlockPackManifest.parse(rawManifest);\n // To keep extra fields from the manifest and keep coerced fields\n manifest = simpleDeepMerge(\n rawManifest,\n manifest as BlockPackManifest & Record<string, unknown>,\n );\n const manifestRoot = path.dirname(manifestPath);\n // The facade package root holds `package.json` (with the direct kind\n // dependency the kind-first publish reads); the manifest sits one level down\n // in `block-pack/`. `readFacadeKindDependency`/`resolveFacadeKind` need the\n // package root, not the block-pack dir.\n const facadeDir = path.dirname(manifestRoot);\n\n logger.info(`Manifest root = ${manifestRoot}`);\n logger.info(`Facade root = ${facadeDir}`);\n\n if (flags.versionOverride) manifest = overrideManifestVersion(manifest, flags.versionOverride);\n\n const storage = storageByUrl(flags.registry);\n const registry = new BlockRegistryV2(storage, logger);\n\n // Kind-first publish: resolve refs -> version-match gate (before any S3\n // write) -> publishKind (if the block declares a kind) -> publishPackage.\n await publishBlock(registry, manifest, facadeDir, async (file) =>\n Buffer.from(await fs.promises.readFile(path.resolve(manifestRoot, file))),\n );\n\n if (!flags.unstable) {\n logger.info(`Adding package to ${StableChannel} channel...`);\n await registry.addPackageToChannel(manifest.description.id, StableChannel);\n }\n\n // Write registry coordinates next to the manifest so npm consumers can\n // resolve the published block via `resolveToRegistry`. Written before\n // returning so `npm publish`'s tarball generation (after prepublishOnly)\n // picks it up.\n const coords = buildPublishedCoords({\n registryUrl: flags.registryServeUrl,\n id: manifest.description.id,\n });\n await writePublishedCoords(manifestRoot, coords);\n logger.info(`Wrote published coordinates to ${path.resolve(manifestRoot, \"published.json\")}`);\n\n if (flags.refresh) await registry.updateIfNeeded();\n });\n\n return cmd;\n}\n","import { Command, Option } from \"commander\";\nimport { BlockRegistryV2 } from \"../v2\";\nimport { storageByUrl } from \"../io\";\nimport { ConsoleLoggerAdapter } from \"@milaboratories/ts-helpers\";\n\nexport function refreshRegistryCommand(): Command {\n const cmd = new Command(\"refresh-registry\").description(\n \"Refresh overview files based on published but not proecessed artefacts\",\n );\n\n cmd.addOption(\n new Option(\"-r, --registry <address>\", \"full address of the registry\")\n .env(\"PL_REGISTRY\")\n .makeOptionMandatory(),\n );\n cmd.addOption(\n new Option(\"-m, --mode <mode>\", 'refresh mode (allowed valiues: \"force\", \"normal\", \"dry-run\")')\n .choices([\"force\", \"normal\", \"dry-run\"])\n .env(\"PL_REGISTRY_REFRESH_DRY_RUN\")\n .default(\"normal\"),\n );\n\n cmd.action(async (flags) => {\n const storage = storageByUrl(flags.registry);\n const registry = new BlockRegistryV2(storage, new ConsoleLoggerAdapter());\n await registry.updateIfNeeded(flags.mode as \"force\" | \"normal\" | \"dry-run\");\n });\n\n return cmd;\n}\n","import { Command, Option } from \"commander\";\nimport { BlockRegistryV2, loadPackDescriptionRaw } from \"../v2\";\nimport path from \"node:path\";\nimport { overrideDescriptionVersion, StableChannel } from \"@milaboratories/pl-model-middle-layer\";\nimport { storageByUrl } from \"../io\";\nimport { ConsoleLoggerAdapter } from \"@milaboratories/ts-helpers\";\n\nexport function markStableCommand(): Command {\n const cmd = new Command(\"mark-stable\").description(\"Mark target block stable\");\n\n cmd.option(\"-i, --modulePath <path>\", \"input module path\", \".\");\n cmd.addOption(\n new Option(\"-c, --channel <channel name>\", \"custom channel\").default(StableChannel).hideHelp(),\n );\n cmd.option(\"-v, --version-override <path>\", \"override package version\");\n cmd.addOption(\n new Option(\"-r, --registry <address>\", \"full address of the registry\")\n .env(\"PL_REGISTRY\")\n .makeOptionMandatory(),\n );\n cmd.addOption(\n new Option(\"--refresh\", \"refresh repository after adding the package\")\n .default(true)\n .env(\"PL_REGISTRY_REFRESH\"),\n );\n cmd.option(\"--no-refresh\", \"do not refresh repository after adding the package\");\n cmd.option(\n \"--unmark\",\n 'reverses meaning of this command, flag can be used to remove \"stable\" flag from the package',\n false,\n );\n\n cmd.action(async (flags) => {\n let description = await loadPackDescriptionRaw(path.resolve(flags.modulePath));\n if (flags.versionOverride)\n description = overrideDescriptionVersion(description, flags.versionOverride);\n const storage = storageByUrl(flags.registry);\n const registry = new BlockRegistryV2(storage, new ConsoleLoggerAdapter());\n\n if (flags.unmark) await registry.removePackageFromChannel(description.id, flags.channel);\n else await registry.addPackageToChannel(description.id, flags.channel);\n\n if (flags.refresh) await registry.updateIfNeeded();\n });\n\n return cmd;\n}\n","// node:fs-backed implementation (synchronous). Anchored at a configured\n// `root`. All FileSystem methods take block-relative paths; this wrapper\n// joins them against root before touching disk.\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { DirEntry, FileSystem } from \"./api\";\n\nexport class NodeFileSystem implements FileSystem {\n constructor(private root: string) {}\n\n private abs(p: string): string {\n return path.resolve(this.root, p);\n }\n\n read(p: string): string {\n return fs.readFileSync(this.abs(p), \"utf-8\");\n }\n\n write(p: string, content: string): void {\n const a = this.abs(p);\n fs.mkdirSync(path.dirname(a), { recursive: true });\n fs.writeFileSync(a, content, \"utf-8\");\n }\n\n writeBinary(p: string, content: Uint8Array): void {\n const a = this.abs(p);\n fs.mkdirSync(path.dirname(a), { recursive: true });\n fs.writeFileSync(a, content);\n }\n\n exists(p: string): boolean {\n try {\n fs.statSync(this.abs(p));\n return true;\n } catch {\n return false;\n }\n }\n\n list(dir: string): string[] {\n const a = this.abs(dir);\n try {\n const stat = fs.statSync(a);\n if (!stat.isDirectory()) return [];\n } catch {\n return [];\n }\n const out: string[] = [];\n function walk(rel: string, absDir: string): void {\n const entries = fs.readdirSync(absDir, { withFileTypes: true });\n for (const e of entries) {\n const childRel = rel ? `${rel}/${e.name}` : e.name;\n const childAbs = path.join(absDir, e.name);\n if (e.isDirectory()) {\n walk(childRel, childAbs);\n } else if (e.isFile()) {\n out.push(childRel);\n }\n }\n }\n walk(dir === \"\" || dir === \".\" ? \"\" : dir, a);\n return out.sort();\n }\n\n listDir(dir: string): DirEntry[] {\n const a = this.abs(dir);\n let entries;\n try {\n entries = fs.readdirSync(a, { withFileTypes: true });\n } catch {\n return [];\n }\n return entries\n .map((e) => ({ name: e.name, isDirectory: e.isDirectory() }))\n .sort((x, y) => x.name.localeCompare(y.name));\n }\n\n move(from: string, to: string): void {\n const fromA = this.abs(from);\n const toA = this.abs(to);\n fs.mkdirSync(path.dirname(toA), { recursive: true });\n fs.renameSync(fromA, toA);\n }\n\n delete(p: string): void {\n fs.rmSync(this.abs(p), { recursive: true, force: true });\n }\n}\n","// Template-content provider for the runner.\n//\n// `file(path)` and `tpl(path, vars)` content forms resolve through this\n// provider. Static templates live at `<root>/static/`; templated text\n// lives at `<root>/text/`. The runner accepts a TemplateProvider via\n// `RunOptions.templates`; the production CLI wires a NodeTemplateProvider\n// rooted at the bundled `templates/` directory, and tests can use\n// `MemoryTemplateProvider` or point at the on-disk templates directory\n// during the Layer-2 zero-diff invariant.\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport interface TemplateProvider {\n /** Read a static template file (under `<root>/static/`). */\n staticRead(p: string): string;\n /** Read a static template file as raw bytes (under `<root>/static/`).\n * For binary assets (logos, images) that must not be utf-8 decoded. */\n staticReadBinary(p: string): Uint8Array;\n /** Read a text template file (under `<root>/text/`). */\n textRead(p: string): string;\n}\n\n/** Provider backed by an on-disk template tree. Reads are synchronous\n * so the runner can stay sync inside content-form resolution. */\nexport class NodeTemplateProvider implements TemplateProvider {\n constructor(private root: string) {}\n\n staticRead(p: string): string {\n return fs.readFileSync(path.resolve(this.root, \"static\", p), \"utf-8\");\n }\n\n staticReadBinary(p: string): Uint8Array {\n return fs.readFileSync(path.resolve(this.root, \"static\", p));\n }\n\n textRead(p: string): string {\n return fs.readFileSync(path.resolve(this.root, \"text\", p), \"utf-8\");\n }\n}\n\n/** In-memory provider for tests. Keyed by the same `static/...` /\n * `text/...` shape as on disk. */\nexport class MemoryTemplateProvider implements TemplateProvider {\n constructor(private files: Record<string, string>) {}\n\n staticRead(p: string): string {\n const k = `static/${p}`;\n const v = this.files[k];\n if (v === undefined) throw new Error(`MemoryTemplateProvider: missing '${k}'`);\n return v;\n }\n\n staticReadBinary(p: string): Uint8Array {\n // In-memory templates are stored as strings; expose their bytes. Real\n // binary assets are exercised through NodeTemplateProvider on disk.\n return new TextEncoder().encode(this.staticRead(p));\n }\n\n textRead(p: string): string {\n const k = `text/${p}`;\n const v = this.files[k];\n if (v === undefined) throw new Error(`MemoryTemplateProvider: missing '${k}'`);\n return v;\n }\n}\n\n/** Shell-style `${name}` substitution. Unknown names left as-is so\n * template authors notice. Backslash escape is not supported. */\nexport function substituteVars(text: string, vars: Record<string, string>): string {\n return text.replace(/\\$\\{([A-Za-z_][A-Za-z0-9_]*)\\}/g, (_m, name: string) => {\n return vars[name] ?? `\\${${name}}`;\n });\n}\n","// Flatten: DFS over the tree IR; fan out each scope frame once per\n// matching module in `ctx.modules`. Compose enclosing `when` triggers\n// (AND of all on the path from root). Track which run modes the leaf\n// fires in (its enclosing mode frame, or the `[\"default\", \"init\"]`\n// default) and emit that as `modes` on the FlatItem. No execution here —\n// execution lives in `runner.ts`.\n\nimport type { Module, RunContext, Scope } from \"./api\";\nimport type { FlatItem, LeafItem, RunMode, Structure, TreeNode, TriggerFn } from \"./ir\";\n\n/** Modes a leaf fires in when it sits outside any mode frame: default\n * refresh/check plus init. (`onUpdateDeps` / `onInitOrUpdate` frames\n * override this for their children.) */\nconst DEFAULT_MODES: RunMode[] = [\"default\", \"init\"];\n\nfunction resolveRelative(modulePath: string, fileRel: string): string {\n if (!modulePath) return fileRel;\n if (!fileRel) return modulePath;\n // Strip trailing slash on modulePath, leading slash on fileRel.\n const m = modulePath.endsWith(\"/\") ? modulePath.slice(0, -1) : modulePath;\n const f = fileRel.startsWith(\"/\") ? fileRel.slice(1) : fileRel;\n return f ? `${m}/${f}` : m;\n}\n\n/**\n * Lexicographic sort of modules by `path`.\n * Used for deterministic fan-out order.\n */\nfunction modulesByScope(modules: Module[], scope: Scope): Module[] {\n return modules\n .filter((m) => m.scope === scope)\n .slice()\n .sort((a, b) => a.path.localeCompare(b.path));\n}\n\nexport function flatten(structure: Structure, ctx: RunContext): FlatItem[] {\n const out: FlatItem[] = [];\n\n function visit(\n node: TreeNode,\n boundScope: Scope | undefined,\n boundModulePath: string | undefined,\n triggers: TriggerFn[],\n modes: RunMode[],\n ): void {\n if (node.kind === \"scope\") {\n const matches = modulesByScope(ctx.modules, node.scope);\n for (const m of matches) {\n for (const child of node.children) {\n visit(child, node.scope, m.path, triggers, modes);\n }\n }\n return;\n }\n if (node.kind === \"when\") {\n const nextTriggers = triggers.concat(node.trigger);\n for (const child of node.children) {\n visit(child, boundScope, boundModulePath, nextTriggers, modes);\n }\n return;\n }\n if (node.kind === \"mode\") {\n for (const child of node.children) {\n visit(child, boundScope, boundModulePath, triggers, node.modes);\n }\n return;\n }\n // Leaf.\n if (boundScope === undefined || boundModulePath === undefined) {\n throw new Error(`flatten: leaf '${describeLeaf(node)}' is not inside a scope() frame`);\n }\n if (node.kind === \"rename\") {\n out.push({\n leaf: node,\n scope: boundScope,\n modulePath: boundModulePath,\n resolvedPath: resolveRelative(boundModulePath, node.from),\n resolvedTo: resolveRelative(boundModulePath, node.to),\n triggers,\n modes,\n });\n return;\n }\n out.push({\n leaf: node,\n scope: boundScope,\n modulePath: boundModulePath,\n resolvedPath: resolveRelative(boundModulePath, leafPath(node)),\n triggers,\n modes,\n });\n }\n\n for (const node of structure.children) {\n visit(node, undefined, undefined, [], DEFAULT_MODES);\n }\n\n return out;\n}\n\nfunction leafPath(leaf: LeafItem): string {\n switch (leaf.kind) {\n case \"fixed\":\n case \"managed\":\n case \"scaffold\":\n case \"seed\":\n case \"remove\":\n return leaf.path;\n case \"rename\":\n return leaf.from;\n }\n}\n\nfunction describeLeaf(leaf: LeafItem): string {\n if (leaf.kind === \"rename\") return `rename ${leaf.from} -> ${leaf.to}`;\n return `${leaf.kind} ${leaf.path}`;\n}\n","// Minimal glob matcher for the structurer's file-existence triggers.\n//\n// Supports `**` (any number of path segments, including none), `*` (any\n// run of chars except `/`), and `?` (a single non-`/` char); every other\n// character is matched literally. No brace expansion / char classes — the\n// patterns we match are deliberately simple (e.g. `src/**/*.test.ts`).\n// Paths are matched whole (anchored at both ends).\n\nconst REGEXP_SPECIALS = /[.+^${}()|[\\]\\\\]/g;\n\n/** Compile a glob to an anchored RegExp. */\nexport function globToRegExp(glob: string): RegExp {\n let re = \"\";\n for (let i = 0; i < glob.length; i++) {\n const c = glob[i]!;\n if (c === \"*\") {\n if (glob[i + 1] === \"*\") {\n // `**`: any path segments. Absorb a following `/` so `**/x` also\n // matches `x` at depth 0 (zero segments).\n i++;\n if (glob[i + 1] === \"/\") {\n i++;\n re += \"(?:.*/)?\";\n } else {\n re += \".*\";\n }\n } else {\n re += \"[^/]*\";\n }\n } else if (c === \"?\") {\n re += \"[^/]\";\n } else {\n re += c.replace(REGEXP_SPECIALS, \"\\\\$&\");\n }\n }\n return new RegExp(`^${re}$`);\n}\n\n/** True if `path` matches `glob` (whole-path, anchored). */\nexport function matchesGlob(glob: string, path: string): boolean {\n return globToRegExp(glob).test(path);\n}\n","// `defineStructure` + the module-global builder set.\n//\n// Active context is a module-level mutable: `defineStructure` pushes a\n// fresh tree state, invokes the zero-arg lambda, pops, returns. Each\n// builder reads the active state and appends to the current children\n// list. Calling a builder outside `defineStructure` throws with a\n// clear message. Re-entering `defineStructure` from inside another\n// `defineStructure` lambda is rejected.\n\nimport type { Scope, RunContext, BlockVars, ContentForm } from \"./api\";\nimport type {\n ManagedBody,\n Structure,\n TriggerFn,\n TreeNode,\n ScopeFrame,\n WhenFrame,\n ModeFrame,\n RunMode,\n} from \"./ir\";\n\ntype TreeState = {\n root: TreeNode[];\n /** Stack of children-lists; top is where new nodes append. */\n stack: TreeNode[][];\n inScope: boolean;\n};\n\nlet activeTree: TreeState | undefined;\nlet activeRunContext: RunContext | undefined;\n\nfunction requireActiveTree(builder: string): TreeState {\n if (!activeTree) {\n throw new Error(\n `${builder}() called outside defineStructure(). ` +\n `Builders must run inside the lambda passed to defineStructure(...).`,\n );\n }\n return activeTree;\n}\n\nfunction appendNode(builder: string, node: TreeNode): void {\n const t = requireActiveTree(builder);\n t.stack[t.stack.length - 1]!.push(node);\n}\n\n/** Engine-internal: scope `blockVars()` lookups during a run. The body is\n * synchronous, so the module-global `activeRunContext` cannot be observed\n * by an interleaved run — a sync call stack runs to completion before any\n * other `run()` can start. The try/finally restores the previous context\n * (supporting the nested-run case the post-run recheck used to imply). */\nexport function withRunContext<T>(ctx: RunContext, fn: () => T): T {\n const prev = activeRunContext;\n activeRunContext = ctx;\n try {\n return fn();\n } finally {\n activeRunContext = prev;\n }\n}\n\n/** Engine-internal: content-rule builders that need `ctx.modules` look\n * up the active context through this accessor. Returns `undefined`\n * outside a run. */\nexport function tryGetActiveRunContext(): RunContext | undefined {\n return activeRunContext;\n}\n\n/** Get-or-die counterpart of `tryGetActiveRunContext`. Generators run\n * only inside `engine.run()`; an absent context is framework misuse, not\n * a valid state, so throw rather than emit degenerate (empty) output.\n * Mirrors `blockVars()`. */\nexport function getActiveRunContext(): RunContext {\n if (!activeRunContext) {\n throw new Error(\n \"getActiveRunContext() called outside engine.run(). \" +\n \"Generators only see the run context during a run.\",\n );\n }\n return activeRunContext;\n}\n\n/** The single entry point: build a {@link Structure} from `fn`, which calls\n * the scaffold-DSL builders (`scope`, `fixed`, `managed`, `seed`, …). Throws\n * if called nested, or if `fn` leaves an unclosed group frame. */\nexport function defineStructure(fn: () => void): Structure {\n if (activeTree) {\n throw new Error(\"defineStructure() cannot be called from inside another defineStructure().\");\n }\n const root: TreeNode[] = [];\n const state: TreeState = { root, stack: [root], inScope: false };\n activeTree = state;\n try {\n fn();\n if (state.stack.length !== 1) {\n throw new Error(\n `defineStructure: builder body left ${state.stack.length - 1} unclosed group frame(s)`,\n );\n }\n const structure: Structure = { children: root };\n // Validation: a path may not appear as both `seed` and any\n // engine-managed primitive (`fixed` / `managed` / `scaffold`) within\n // the same scope. The two contracts (write-once-and-ignore vs\n // rewrite-on-every-refresh) are mutually exclusive. Detect at\n // tree-build time.\n validateSeedDisjointness(structure);\n return structure;\n } finally {\n activeTree = undefined;\n }\n}\n\nfunction validateSeedDisjointness(structure: Structure): void {\n // (scope) → (path) → set of leaf kinds present at that path.\n const perScope = new Map<string, Map<string, Set<string>>>();\n\n function visit(node: TreeNode, scopeName: string): void {\n if (node.kind === \"scope\") {\n for (const c of node.children) visit(c, node.scope);\n return;\n }\n if (node.kind === \"when\" || node.kind === \"mode\") {\n for (const c of node.children) visit(c, scopeName);\n return;\n }\n if (node.kind === \"rename\") return; // rename works on paths; not a content leaf\n let scopeMap = perScope.get(scopeName);\n if (!scopeMap) {\n scopeMap = new Map();\n perScope.set(scopeName, scopeMap);\n }\n let kinds = scopeMap.get(node.path);\n if (!kinds) {\n kinds = new Set();\n scopeMap.set(node.path, kinds);\n }\n kinds.add(node.kind);\n }\n\n for (const n of structure.children) visit(n, \"(top-level)\");\n\n for (const [scopeName, paths] of perScope) {\n for (const [path, kinds] of paths) {\n if (\n kinds.has(\"seed\") &&\n (kinds.has(\"managed\") || kinds.has(\"fixed\") || kinds.has(\"scaffold\"))\n ) {\n const others = [...kinds]\n .filter((k) => k !== \"seed\")\n .sort()\n .join(\", \");\n throw new Error(\n `defineStructure validation: path '${path}' under scope '${scopeName}' ` +\n `is declared as both seed and ${others}. Seeds are block-author territory ` +\n `(written once at init, untouched thereafter); engine-managed primitives ` +\n `(fixed/managed/scaffold) rewrite on every refresh. The two contracts cannot ` +\n `coexist on the same path.`,\n );\n }\n }\n }\n}\n\n/** Open a scope (`root` / `block` / `model` / `ui` / `workflow` / `test` /\n * `software`); builders called inside `body` attach to it. Cannot nest. */\nexport function scope(name: Scope, body: () => void): void {\n const t = requireActiveTree(\"scope\");\n if (t.inScope) {\n throw new Error(\"scope() cannot nest. Already inside a scope.\");\n }\n const frame: ScopeFrame = { kind: \"scope\", scope: name, children: [] };\n t.stack[t.stack.length - 1]!.push(frame);\n t.stack.push(frame.children);\n t.inScope = true;\n try {\n body();\n } finally {\n t.stack.pop();\n t.inScope = false;\n }\n}\n\n/** Inner-mode `when` handler. Registered by `content-rules.ts` at\n * load time. Returns true if the call was dispatched (an inner active\n * state was present); false otherwise. Avoids a circular import. */\ntype InnerWhenHandler = (trigger: TriggerFn, body: () => void) => boolean;\nlet innerWhenHandler: InnerWhenHandler | undefined;\n\n/** Engine-internal: register the inner-mode `when` handler (set by\n * `content-rules.ts` at load time to avoid a circular import). */\nexport function registerInnerWhenHandler(h: InnerWhenHandler): void {\n innerWhenHandler = h;\n}\n\n/**\n * Conditionally run `body`, with an optional `elseBody`. One `when` symbol for\n * both layers — `dispatchWhen` picks the timing:\n * - inside `defineStructure(...)` → register a `WhenFrame`; its trigger fires\n * later, per module, at runner time.\n * - inside a `managed(...)` body → evaluate the trigger against the live block\n * now and run/skip synchronously.\n *\n * `else` is just the negated trigger dispatched the same way, so exactly one\n * branch applies (in either layer).\n */\nexport function when(trigger: TriggerFn, body: () => void, elseBody?: () => void): void {\n dispatchWhen(trigger, body);\n if (elseBody) dispatchWhen((tctx) => !trigger(tctx), elseBody);\n}\n\n/** Single-branch dispatch shared by both `when` branches. In a managed body the\n * handler runs `body` iff its trigger holds and returns whether a managed-body\n * context existed; no context — and not tree-build either — means `when()` was\n * called outside both layers, a misuse. */\nfunction dispatchWhen(trigger: TriggerFn, body: () => void): void {\n if (activeTree) {\n pushWhenFrame(trigger, body);\n return;\n }\n const handled = innerWhenHandler?.(trigger, body) ?? false;\n if (!handled) {\n throw new Error(\n \"when() called outside defineStructure() and outside any managed(...) body. \" +\n \"Place this call inside one of the two.\",\n );\n }\n}\n\nfunction pushWhenFrame(trigger: TriggerFn, body: () => void): void {\n const t = activeTree!;\n const frame: WhenFrame = { kind: \"when\", trigger, children: [] };\n t.stack[t.stack.length - 1]!.push(frame);\n t.stack.push(frame.children);\n try {\n body();\n } finally {\n t.stack.pop();\n }\n}\n\n/** Trigger factory: true when at least one file in the leaf's module\n * matches `glob` (module-relative — see `TriggerContext.filesMatch`). Use\n * to gate a rule on the presence of co-located files, e.g. add a vitest\n * `test` script only when `src/**\\/*.test.ts` exists. Pairs with `when`:\n * `when(whenFilesExist(\"src/**\\/*.test.ts\"), () => { ... })`. */\nexport function whenFilesExist(glob: string): TriggerFn {\n return (tctx) => tctx.filesMatch(glob);\n}\n\nfunction pushModeFrame(builder: string, modes: RunMode[], body: () => void): void {\n const t = requireActiveTree(builder);\n const frame: ModeFrame = { kind: \"mode\", modes, children: [] };\n t.stack[t.stack.length - 1]!.push(frame);\n t.stack.push(frame.children);\n try {\n body();\n } finally {\n t.stack.pop();\n }\n}\n\n/** Leaves inside fire ONLY under `--update-deps-only` (mode\n * `\"updateDeps\"`); they are skipped on default refresh/check and init. */\nexport function onUpdateDeps(body: () => void): void {\n pushModeFrame(\"onUpdateDeps\", [\"updateDeps\"], body);\n}\n\n/** Leaves inside fire on `init` AND `--update-deps-only`, but NOT on\n * default refresh/check. The frame for rules that resolve/write current\n * versions: both init and update-deps mean \"fetch and write latest\",\n * while a plain refresh leaves them as the author/lockfile has them. */\nexport function onInitOrUpdate(body: () => void): void {\n pushModeFrame(\"onInitOrUpdate\", [\"init\", \"updateDeps\"], body);\n}\n\n/** Engine-OWNED file: (re)written verbatim from `content` on every refresh —\n * author edits are overwritten. */\nexport function fixed(path: string, content: ContentForm): void {\n appendNode(\"fixed\", { kind: \"fixed\", path, content });\n}\n\n/** Engine-RECONCILED file: parsed from disk (or `initial` when absent),\n * mutated by `body` (the JSON/YAML/lines builders), then re-serialised.\n * Content the body does not touch is preserved. */\nexport function managed(path: string, initial: ContentForm, body: ManagedBody): void {\n appendNode(\"managed\", { kind: \"managed\", path, initial, body });\n}\n\n/** Write-once file: created from `initial` if absent (on init AND refresh),\n * never overwritten once present. For files the author subsequently owns. */\nexport function scaffold(path: string, initial: ContentForm): void {\n appendNode(\"scaffold\", { kind: \"scaffold\", path, initial });\n}\n\n/** Author-owned starter file: written from `initial` only on `init`, and only\n * if absent; `refresh` / `check` never touch it. */\nexport function seed(path: string, initial: ContentForm): void {\n appendNode(\"seed\", { kind: \"seed\", path, initial });\n}\n\n/** Delete `path` if present, on every refresh. */\nexport function remove(path: string): void {\n appendNode(\"remove\", { kind: \"remove\", path });\n}\n\n/** Rename file `from` → `to` on refresh (migrating a renamed scaffold file). */\nexport function rename(from: string, to: string): void {\n appendNode(\"rename\", { kind: \"rename\", from, to });\n}\n\n/** Content form: a UTF-8 static template read from the structurer's static\n * templates. Use inside `fixed` / `managed` / `scaffold` / `seed`. */\nexport function file(path: string): ContentForm {\n return { kind: \"file\", path };\n}\n\n/** A binary static asset (e.g. a logo) read verbatim from `<root>/static/`.\n * Unlike `file()`, the bytes are never decoded to a string — use for\n * images / archives. Only valid inside `seed()` / `scaffold()`. */\nexport function binaryFile(path: string): ContentForm {\n return { kind: \"binary\", path };\n}\n\n/** Content form: an inline literal string. */\nexport function text(value: string): ContentForm {\n return { kind: \"text\", value };\n}\n\n/** Content form: a text template (the structurer's `text/` templates) with\n * `${var}` placeholders substituted from `vars`. When `vars` is a function it\n * receives the active {@link RunContext} at resolve time. */\nexport function tpl(\n path: string,\n vars: Record<string, string> | ((ctx: RunContext) => Record<string, string>),\n): ContentForm {\n return { kind: \"tpl\", path, vars };\n}\n\n/** Content form: content computed at run time from the active\n * {@link RunContext}. The return value is serialised as JSON / YAML by the\n * target file's extension, or used verbatim if it is already a string. */\nexport function generate(fn: (ctx: RunContext) => unknown): ContentForm {\n return { kind: \"generate\", fn };\n}\n\n/** The active run's {@link BlockVars} (block name parts + software platform).\n * Valid only during a run (inside a generator or managed body); throws\n * otherwise. */\nexport function blockVars(): BlockVars {\n if (!activeRunContext) {\n throw new Error(\n \"blockVars() called outside engine.run(). \" +\n \"Generators and managed bodies only see BlockVars during a run.\",\n );\n }\n return activeRunContext.blockVars;\n}\n","// JSON parser + serialiser + jsonPath helpers + top-level key reorder.\n//\n// `parseJson`/`stringifyJson` are the canonical round-trip primitives the\n// managed pass uses. The dot-notation helpers (`getAtPath`, `setAtPath`,\n// `hasAtPath`, `deleteAtPath`) back the content-rule builders. `reorderTopLevel`\n// implements the \"known keys in declared order, unknown keys stay adjacent to\n// preceding known key\" projection.\n\nexport type JsonValue = string | number | boolean | null | JsonValue[] | { [k: string]: JsonValue };\n\nexport type JsonObject = { [k: string]: unknown };\n\n/** Parse JSON; throws on invalid input. */\nexport function parseJson(raw: string): unknown {\n return JSON.parse(raw);\n}\n\n// oxfmt formats JSON two ways, keyed on filename:\n// - package.json: every array/object fully expanded, one element per line,\n// regardless of width (what `JSON.stringify(…, 2)` already produces).\n// - any other .json (e.g. tsconfig.json): oxfmt's generic shape —\n// * objects: always expanded, one property per line (oxfmt preserves\n// the brace newline, so the expanded form is a fixpoint);\n// * arrays: collapsed onto one line when that line — its indent, the\n// `\"key\": ` prefix, the flat array, and a trailing comma if a sibling\n// follows — fits `PRINT_WIDTH` (oxfmt's default 100), else broken one\n// element per line.\n// This is exactly the form `oxfmt` itself produces, verified against\n// oxfmt 0.35 at the array boundary (≤100 collapses, 101 breaks; a\n// trailing comma counts) and across all in-mono blocks. The single-\n// element `include` array was the regression: `JSON.stringify` expanded\n// it while oxfmt collapses it.\n// `stringifyJson` defaults to the expanded form; callers serialising a\n// generic .json pass `{ collapse: true }` so the output is oxfmt-clean by\n// construction (no prior `pnpm fmt` needed for `check` — the same\n// emit-clean-by-design contract as the canonical key/dependency ordering).\nconst PRINT_WIDTH = 100;\nconst INDENT = 2;\n\n/** One-line rendering of an array, matching oxfmt's flat spacing: `[a, b]`\n * (no inner padding), nested objects inline as `{ \"k\": v }`, empty `[]`.\n * Only arrays collapse, so this is the array-fits primitive. */\nfunction flatArray(value: unknown[]): string {\n if (value.length === 0) return \"[]\";\n return \"[\" + value.map(flatValue).join(\", \") + \"]\";\n}\n\n/** One-line rendering of any value (used inside a collapsed array, where\n * contained objects render inline). */\nfunction flatValue(value: unknown): string {\n if (Array.isArray(value)) return flatArray(value);\n if (isObject(value)) {\n const entries = Object.entries(value);\n if (entries.length === 0) return \"{}\";\n return (\n \"{ \" + entries.map(([k, v]) => `${JSON.stringify(k)}: ${flatValue(v)}`).join(\", \") + \" }\"\n );\n }\n return JSON.stringify(value);\n}\n\n/** Print `value` starting at `column`. Objects always break (one property per\n * line); arrays collapse when their flat line — `column` + the flat array +\n * `reserved` (1 for a trailing comma when a sibling follows) — fits\n * `PRINT_WIDTH`, else break. `indent` is the leading-space width of the line\n * the container opens on. */\nfunction printValue(value: unknown, indent: number, column: number, reserved: number): string {\n const inner = indent + INDENT;\n const pad = \" \".repeat(inner);\n if (Array.isArray(value)) {\n const flat = flatArray(value);\n if (column + flat.length + reserved <= PRINT_WIDTH) return flat;\n const last = value.length - 1;\n const lines = value.map((item, i) => pad + printValue(item, inner, inner, i === last ? 0 : 1));\n return \"[\\n\" + lines.join(\",\\n\") + \"\\n\" + \" \".repeat(indent) + \"]\";\n }\n if (isObject(value)) {\n const entries = Object.entries(value);\n if (entries.length === 0) return \"{}\";\n const last = entries.length - 1;\n const lines = entries.map(([k, v], i) => {\n const prefix = `${pad}${JSON.stringify(k)}: `;\n return prefix + printValue(v, inner, prefix.length, i === last ? 0 : 1);\n });\n return \"{\\n\" + lines.join(\",\\n\") + \"\\n\" + \" \".repeat(indent) + \"}\";\n }\n return JSON.stringify(value);\n}\n\n/** Canonical serialiser: 2-space indent, trailing newline.\n * Default — every container expanded (the package.json shape, byte-identical\n * to `JSON.stringify(…, 2)`).\n * `{ collapse: true }` — oxfmt's generic-.json shape: containers that fit\n * `PRINT_WIDTH` collapse onto one line. Used for tsconfig.json and any other\n * non-package.json the engine emits, so `oxfmt --check` passes without a\n * prior format pass. */\nexport function stringifyJson(value: unknown, opts?: { collapse?: boolean }): string {\n if (!opts?.collapse) return JSON.stringify(value, null, 2) + \"\\n\";\n // Normalise through a round-trip so non-JSON inputs (undefined values,\n // functions) are dropped exactly as `JSON.stringify` would.\n const normalized = JSON.parse(JSON.stringify(value ?? null));\n return printValue(normalized, 0, 0, 0) + \"\\n\";\n}\n\nfunction splitPath(jsonPath: string): string[] {\n if (jsonPath === \"\" || jsonPath === undefined) return [];\n return jsonPath.split(\".\");\n}\n\nfunction isObject(v: unknown): v is JsonObject {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\n/** Get the value at `jsonPath`. Returns `undefined` if any segment is\n * missing or not an object. */\nexport function getAtPath(obj: JsonObject, jsonPath: string): unknown {\n const parts = splitPath(jsonPath);\n let cur: unknown = obj;\n for (const p of parts) {\n if (!isObject(cur)) return undefined;\n cur = cur[p];\n }\n return cur;\n}\n\n/** True if `jsonPath` resolves to a defined value (including `null`). */\nexport function hasAtPath(obj: JsonObject, jsonPath: string): boolean {\n const parts = splitPath(jsonPath);\n if (parts.length === 0) return true;\n let cur: unknown = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n if (!isObject(cur)) return false;\n cur = cur[parts[i]!];\n }\n if (!isObject(cur)) return false;\n return parts[parts.length - 1]! in cur;\n}\n\n/** Set `value` at `jsonPath`. Auto-creates intermediate objects. Throws\n * if a non-object value is on the path (would be silently overwritten\n * otherwise — caller bug). */\nexport function setAtPath(obj: JsonObject, jsonPath: string, value: unknown): void {\n const parts = splitPath(jsonPath);\n if (parts.length === 0) {\n throw new Error(\"setAtPath: jsonPath must be non-empty\");\n }\n let cur: JsonObject = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n const k = parts[i]!;\n const next = cur[k];\n if (next === undefined) {\n const fresh: JsonObject = {};\n cur[k] = fresh;\n cur = fresh;\n } else if (isObject(next)) {\n cur = next;\n } else {\n throw new Error(\n `setAtPath: cannot descend into non-object at '${parts.slice(0, i + 1).join(\".\")}'`,\n );\n }\n }\n cur[parts[parts.length - 1]!] = value;\n}\n\n/** Delete the value at `jsonPath`. No-op if any segment is missing. */\nexport function deleteAtPath(obj: JsonObject, jsonPath: string): void {\n const parts = splitPath(jsonPath);\n if (parts.length === 0) {\n throw new Error(\"deleteAtPath: jsonPath must be non-empty\");\n }\n let cur: unknown = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n if (!isObject(cur)) return;\n cur = cur[parts[i]!];\n }\n if (!isObject(cur)) return;\n delete cur[parts[parts.length - 1]!];\n}\n\n/**\n * Reorder top-level keys of `obj`:\n * - Known keys (those listed in `order`) appear in declared order.\n * - Unknown keys (not in `order`) stay adjacent to the preceding known\n * key they followed in the source. Unknown keys appearing before any\n * known key go first, in source order.\n */\nexport function reorderTopLevel(obj: JsonObject, order: readonly string[]): JsonObject {\n const known = new Set(order);\n const sourceKeys = Object.keys(obj);\n\n const adjacents = new Map<string, string[]>();\n adjacents.set(\"\", []);\n let anchor = \"\";\n for (const k of sourceKeys) {\n if (known.has(k)) {\n anchor = k;\n adjacents.set(anchor, []);\n } else {\n adjacents.get(anchor)!.push(k);\n }\n }\n\n const out: JsonObject = {};\n for (const k of adjacents.get(\"\")!) out[k] = obj[k];\n for (const k of order) {\n if (!(k in obj)) continue;\n out[k] = obj[k];\n for (const u of adjacents.get(k) ?? []) out[u] = obj[u];\n }\n return out;\n}\n","// .gitignore-style line list parser/serialiser.\n//\n// `parseLines` keeps the file verbatim as an array of lines (one per\n// \"\\n\"). `serializeLines` joins them with \"\\n\" and guarantees a trailing\n// newline. `normaliseLine` strips comments and surrounding whitespace —\n// used by the `ensureGitignoreEntries` family to compare an existing\n// line to a required entry without being fooled by inline `#` comments\n// or extra indentation.\n\nexport function parseLines(raw: string): string[] {\n // Drop the synthetic empty entry caused by a trailing newline so a\n // serialise-then-parse round-trip is stable.\n const lines = raw.split(\"\\n\");\n if (lines.length > 0 && lines[lines.length - 1] === \"\") lines.pop();\n return lines;\n}\n\nexport function serializeLines(lines: readonly string[]): string {\n return lines.join(\"\\n\") + \"\\n\";\n}\n\n/** Strip leading/trailing whitespace and trailing inline `# ...` comments.\n * Returns empty string for blank / comment-only lines. */\nexport function normaliseLine(line: string): string {\n const noComment = line.replace(/(^|\\s)#.*$/, \"$1\");\n return noComment.trim();\n}\n\n/** True if `line` (after normalisation) equals `entry` (after trim). */\nexport function lineEqualsEntry(line: string, entry: string): boolean {\n const n = normaliseLine(line);\n if (n === \"\") return false;\n return n === entry.trim();\n}\n\n/** True if any line in `lines` normalises to `entry`. */\nexport function containsEntry(lines: readonly string[], entry: string): boolean {\n for (const line of lines) {\n if (lineEqualsEntry(line, entry)) return true;\n }\n return false;\n}\n","// Content-rules DSL — builders that mutate the parsed representation\n// of a `managed(path, initial, body)` file.\n//\n// Three active-state kinds correspond to three file flavours:\n// - JSON object (package.json) → withManagedBody(obj, body)\n// - YAML Document (pnpm-workspace.yaml) → withManagedYaml(doc, body)\n// - line list (.gitignore) → withManagedLines(lines, body)\n//\n// Each builder verifies it is invoked under the matching active state\n// and throws otherwise. The full inventory: JSON\n// ensure*/remove*/require*/prune/enforce*/transform; YAML catalog\n// management + workspace module paths; gitignore line management.\n\nimport { registerInnerWhenHandler, tryGetActiveRunContext } from \"./builders\";\nimport type { RunContext, Scope } from \"./api\";\nimport type { ManagedBody, TriggerContext, TriggerFn } from \"./ir\";\nimport {\n deleteAtPath,\n getAtPath,\n hasAtPath,\n reorderTopLevel,\n setAtPath,\n type JsonObject,\n} from \"./parsers/json\";\nimport { containsEntry, normaliseLine } from \"./parsers/lines\";\nimport type { YamlDocument } from \"./parsers/yaml\";\n\nexport type { JsonObject };\n\n/** Allowed dep version strings. Specific versions live in the catalog.\n * `\"sdk:\"` is an authoring abstraction, not an on-disk value: the engine\n * resolves it at write time (`workspace:*` when `ctx.isSdkInternal`, else\n * `\"catalog:\"`) and the resolved literal is what serializes. Use it for\n * every dep that is a member of the platforma monorepo's pnpm workspace\n * (the `@platforma-sdk/*` packages + `@milaboratories/ts-builder` /\n * `ts-configs`). */\nexport type DepVersion = \"catalog:\" | \"sdk:\" | `workspace:${string}` | \"*\";\n\n/** Resolve the `\"sdk:\"` sentinel to its on-disk literal. All other\n * `DepVersion` forms pass through unchanged — `\"sdk:\"` never serializes. */\nexport function resolveDepVersion(\n version: DepVersion,\n isSdkInternal: boolean,\n): Exclude<DepVersion, \"sdk:\"> {\n if (version === \"sdk:\") return isSdkInternal ? \"workspace:*\" : \"catalog:\";\n return version;\n}\n\nconst DEP_SECTION_KEYS = [\n \"dependencies\",\n \"devDependencies\",\n \"peerDependencies\",\n \"optionalDependencies\",\n] as const;\n\n/** Resolve any `\"sdk:\"` sentinels in the dep sections of a generated\n * package.json object, in place. Mirrors `resolveDepVersion` for the\n * generator (`initial` content) path — the runner calls this on every\n * `generate()`-produced `.json` value so the sentinel never reaches disk\n * via a generator. */\nexport function resolveSdkSentinelsInJson(value: unknown, isSdkInternal: boolean): void {\n if (!isObject(value)) return;\n for (const section of DEP_SECTION_KEYS) {\n const sec = value[section];\n if (!isObject(sec)) continue;\n for (const k of Object.keys(sec)) {\n if (sec[k] === \"sdk:\") sec[k] = isSdkInternal ? \"workspace:*\" : \"catalog:\";\n }\n }\n}\n\ntype JsonState = {\n kind: \"json\";\n obj: JsonObject;\n ctx?: RunContext;\n triggerContext?: TriggerContext;\n};\n\ntype YamlState = {\n kind: \"yaml\";\n doc: YamlDocument;\n ctx?: RunContext;\n triggerContext?: TriggerContext;\n /** Synchronous accessor for prefetched npm latest versions. */\n getLatestVersion?: (packageName: string) => string | undefined;\n /** Synchronous accessor for prefetched derived catalog pins\n * (`catalogEntry → exact version`); see `pinCatalogToDependencyOf`. */\n getDerivedDependencyPin?: (catalogEntry: string) => string | undefined;\n};\n\ntype LinesState = {\n kind: \"lines\";\n lines: string[];\n ctx?: RunContext;\n triggerContext?: TriggerContext;\n};\n\ntype ActiveState = JsonState | YamlState | LinesState;\n\nlet active: ActiveState | undefined;\n\nfunction requireActive(builder: string): ActiveState {\n if (!active) {\n throw new Error(\n `${builder}() only valid inside a managed(...) body. ` +\n `Move this call inside managed(path, initial, () => {...}).`,\n );\n }\n return active;\n}\n\nfunction requireJson(builder: string): JsonState {\n const a = requireActive(builder);\n if (a.kind !== \"json\") {\n throw new Error(`${builder}() requires a JSON-managed body; got '${a.kind}'.`);\n }\n return a;\n}\n\nfunction requireYaml(builder: string): YamlState {\n const a = requireActive(builder);\n if (a.kind !== \"yaml\") {\n throw new Error(`${builder}() requires a YAML-managed body; got '${a.kind}'.`);\n }\n return a;\n}\n\nfunction requireLines(builder: string): LinesState {\n const a = requireActive(builder);\n if (a.kind !== \"lines\") {\n throw new Error(`${builder}() requires a lines-managed body; got '${a.kind}'.`);\n }\n return a;\n}\n\nfunction ctxOrThrow(state: ActiveState, builder: string): RunContext {\n const c = state.ctx ?? tryGetActiveRunContext();\n if (!c) {\n throw new Error(\n `${builder}() needs a RunContext but none is active. ` +\n `Pass { ctx } via the with-managed-* helper or run inside engine.run(...).`,\n );\n }\n return c;\n}\n\nfunction isObject(v: unknown): v is JsonObject {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\n// --- Active-context wrappers (used by the runner + Layer-1 helpers) ---\n\nexport type WithManagedOpts = {\n ctx?: RunContext;\n /** Trigger context for `when(...)` calls inside the body. The runner\n * builds this from the post-structural-pass FS snapshot + run ctx.\n * Without it, `when(...)` inside the body throws. */\n triggerContext?: TriggerContext;\n};\n\n/** Engine-internal: run `body` with `obj` as the active JSON state so the\n * JSON builders mutate it; returns the mutated object. Exported for tests —\n * the runner calls this for managed `.json` files. */\nexport function withManagedBody(\n obj: JsonObject,\n body: ManagedBody,\n opts: WithManagedOpts = {},\n): JsonObject {\n if (active) throw new Error(\"Nested managed(...) body — engine bug.\");\n active = { kind: \"json\", obj, ctx: opts.ctx, triggerContext: opts.triggerContext };\n try {\n body((opts.ctx ?? opts.triggerContext?.ctx) as RunContext);\n return obj;\n } finally {\n active = undefined;\n }\n}\n\nexport type WithManagedYamlOpts = WithManagedOpts & {\n /** Sync accessor for prefetched latest versions. Required for\n * `ensureCatalogLatest` to take effect. */\n getLatestVersion?: (packageName: string) => string | undefined;\n /** Sync accessor for prefetched derived catalog pins. Required for\n * `pinCatalogToDependencyOf` to take effect. */\n getDerivedDependencyPin?: (catalogEntry: string) => string | undefined;\n};\n\n/** Engine-internal: run `body` with `doc` as the active YAML state (for\n * `pnpm-workspace.yaml`); returns the mutated document. Exported for tests. */\nexport function withManagedYaml(\n doc: YamlDocument,\n body: ManagedBody,\n opts: WithManagedYamlOpts = {},\n): YamlDocument {\n if (active) throw new Error(\"Nested managed(...) body — engine bug.\");\n active = {\n kind: \"yaml\",\n doc,\n ctx: opts.ctx,\n triggerContext: opts.triggerContext,\n getLatestVersion: opts.getLatestVersion,\n getDerivedDependencyPin: opts.getDerivedDependencyPin,\n };\n try {\n body((opts.ctx ?? opts.triggerContext?.ctx) as RunContext);\n return doc;\n } finally {\n active = undefined;\n }\n}\n\n/** Engine-internal: run `body` with `lines` as the active line-based state\n * (for `.gitignore`); returns the mutated lines. Exported for tests. */\nexport function withManagedLines(\n lines: string[],\n body: ManagedBody,\n opts: WithManagedOpts = {},\n): string[] {\n if (active) throw new Error(\"Nested managed(...) body — engine bug.\");\n active = {\n kind: \"lines\",\n lines,\n ctx: opts.ctx,\n triggerContext: opts.triggerContext,\n };\n try {\n body((opts.ctx ?? opts.triggerContext?.ctx) as RunContext);\n return lines;\n } finally {\n active = undefined;\n }\n}\n\n// --- Inner-when handler registration ---\n//\n// `when(...)` is exported from `builders.ts`. When the active tree is\n// absent (we are inside a managed body, not inside `defineStructure`),\n// it delegates here. The handler returns true iff there is an inner\n// active state to dispatch against; the caller in `builders.ts` then\n// treats the call as handled. Outer/inner dispatch lives in one\n// exported `when` symbol — no separate inner-when builder.\n\nregisterInnerWhenHandler((trigger: TriggerFn, body: () => void): boolean => {\n if (!active) return false;\n const tctx = active.triggerContext;\n if (!tctx) {\n throw new Error(\n \"when() inside a managed(...) body requires a triggerContext. \" +\n \"The runner supplies it via the `triggerContext` opt to with-managed-*; \" +\n \"ensure your test/test helper passes one.\",\n );\n }\n if (trigger(tctx)) body();\n return true;\n});\n\n// ============================================================\n// JSON builders — `package.json` (and other JSON managed files)\n// ============================================================\n\n/** Set the value at `jsonPath` in the active managed JSON object. */\nexport function ensureField(jsonPath: string, value: unknown): void {\n setAtPath(requireJson(\"ensureField\").obj, jsonPath, value);\n}\n\n/** Remove the field at `jsonPath`. With `predicate`, only removes when\n * the predicate returns true against the current value. */\nexport function removeField(\n jsonPath: string,\n predicate?: (currentValue: unknown) => boolean,\n): void {\n const obj = requireJson(\"removeField\").obj;\n if (!hasAtPath(obj, jsonPath)) return;\n if (predicate) {\n const current = getAtPath(obj, jsonPath);\n if (!predicate(current)) return;\n }\n deleteAtPath(obj, jsonPath);\n}\n\n/** Assert a field exists; throw if absent. No mutation. */\nexport function requireField(jsonPath: string, message?: string): void {\n const obj = requireJson(\"requireField\").obj;\n if (!hasAtPath(obj, jsonPath)) {\n throw new Error(message ?? `requireField: missing field '${jsonPath}'`);\n }\n}\n\n/** Merge `entries` into the object at `jsonPath`. Auto-creates the\n * object if missing. Existing other entries preserved. */\nexport function ensureFieldEntries(jsonPath: string, entries: Record<string, unknown>): void {\n const obj = requireJson(\"ensureFieldEntries\").obj;\n const current = hasAtPath(obj, jsonPath) ? getAtPath(obj, jsonPath) : undefined;\n const base: JsonObject = isObject(current) ? current : {};\n for (const [k, v] of Object.entries(entries)) base[k] = v;\n if (!isObject(current)) setAtPath(obj, jsonPath, base);\n}\n\n/** Set `scripts.<name>` to `command`. */\nexport function ensureScript(name: string, command: string): void {\n ensureField(`scripts.${name}`, command);\n}\n\n/** Remove `scripts.<name>` if present. */\nexport function removeScript(name: string): void {\n removeField(`scripts.${name}`);\n}\n\n// --- Dependency builders ---\n\nconst DEP_SECTIONS = [\n \"dependencies\",\n \"devDependencies\",\n \"peerDependencies\",\n \"optionalDependencies\",\n] as const;\ntype DepSection = (typeof DEP_SECTIONS)[number];\n\nfunction ensureInSection(\n builder: string,\n name: string,\n version: DepVersion,\n section: DepSection,\n): void {\n const state = requireJson(builder);\n const obj = state.obj;\n // Resolve the `sdk:` sentinel against the run mode before writing — it\n // must never reach disk.\n const resolved =\n version === \"sdk:\"\n ? resolveDepVersion(version, ctxOrThrow(state, builder).isSdkInternal)\n : version;\n // Single-section invariant: remove from any other section first.\n for (const s of DEP_SECTIONS) {\n if (s === section) continue;\n const sec = obj[s];\n if (isObject(sec) && name in sec) delete sec[name];\n }\n const existing = obj[section];\n const target: JsonObject = isObject(existing) ? existing : {};\n target[name] = resolved;\n if (!isObject(existing)) obj[section] = target;\n}\n\n/** Pin `name` to `version` in `dependencies`. Enforces the single-section\n * invariant — `name` may live in only one dependency section, so it is\n * removed from the others first. A `sdk:` sentinel version is resolved\n * against the run's `--sdk-internal` flag before it reaches disk. */\nexport function ensureDep(name: string, version: DepVersion): void {\n ensureInSection(\"ensureDep\", name, version, \"dependencies\");\n}\n\n/** Pin `name` to `version` in `devDependencies` (see {@link ensureDep} for the\n * single-section + `sdk:` semantics). */\nexport function ensureDevDep(name: string, version: DepVersion): void {\n ensureInSection(\"ensureDevDep\", name, version, \"devDependencies\");\n}\n\n/** Pin `name` to `version` in `peerDependencies` (see {@link ensureDep}). */\nexport function ensurePeerDep(name: string, version: DepVersion): void {\n ensureInSection(\"ensurePeerDep\", name, version, \"peerDependencies\");\n}\n\n/** Pin `name` to `version` in `optionalDependencies` (see {@link ensureDep}). */\nexport function ensureOptionalDep(name: string, version: DepVersion): void {\n ensureInSection(\"ensureOptionalDep\", name, version, \"optionalDependencies\");\n}\n\n/** Remove `name` from every dependency section. */\nexport function removeDep(name: string): void {\n const obj = requireJson(\"removeDep\").obj;\n for (const s of DEP_SECTIONS) {\n const sec = obj[s];\n if (isObject(sec) && name in sec) delete sec[name];\n }\n}\n\n/** Bulk {@link ensureDep} for each `name → version` entry. */\nexport function ensureDeps(entries: Record<string, DepVersion>): void {\n for (const [n, v] of Object.entries(entries)) ensureDep(n, v);\n}\n\n/** Bulk {@link ensureDevDep} for each `name → version` entry. */\nexport function ensureDevDeps(entries: Record<string, DepVersion>): void {\n for (const [n, v] of Object.entries(entries)) ensureDevDep(n, v);\n}\n\n/** Bulk {@link ensurePeerDep} for each `name → version` entry. */\nexport function ensurePeerDeps(entries: Record<string, DepVersion>): void {\n for (const [n, v] of Object.entries(entries)) ensurePeerDep(n, v);\n}\n\n/** Bulk {@link ensureOptionalDep} for each `name → version` entry. */\nexport function ensureOptionalDeps(entries: Record<string, DepVersion>): void {\n for (const [n, v] of Object.entries(entries)) ensureOptionalDep(n, v);\n}\n\nfunction ensureWorkspaceScopeIn(builder: string, scope: Scope, section: DepSection): void {\n const state = requireJson(builder);\n const ctx = ctxOrThrow(state, builder);\n for (const m of ctx.modules) {\n if (m.scope === scope) {\n ensureInSection(builder, m.name, \"workspace:*\", section);\n }\n }\n}\n\n/** Add every discovered module of `scope` as a `workspace:*` entry in\n * `dependencies` — wires a block's intra-workspace links (e.g. the test\n * scope depending on the other scopes). Single-section invariant per\n * {@link ensureDep}. */\nexport function ensureWorkspaceScopeDeps(scope: Scope): void {\n ensureWorkspaceScopeIn(\"ensureWorkspaceScopeDeps\", scope, \"dependencies\");\n}\n\n/** Like {@link ensureWorkspaceScopeDeps}, into `devDependencies`. */\nexport function ensureWorkspaceScopeDevDeps(scope: Scope): void {\n ensureWorkspaceScopeIn(\"ensureWorkspaceScopeDevDeps\", scope, \"devDependencies\");\n}\n\n/** Like {@link ensureWorkspaceScopeDeps}, into `peerDependencies`. */\nexport function ensureWorkspaceScopePeerDeps(scope: Scope): void {\n ensureWorkspaceScopeIn(\"ensureWorkspaceScopePeerDeps\", scope, \"peerDependencies\");\n}\n\n// --- Prune ---\n\n/** Delete every top-level key for which `predicate(key, value)` is true. */\nexport function pruneKeysMatching(predicate: (key: string, value: unknown) => boolean): void {\n const obj = requireJson(\"pruneKeysMatching\").obj;\n for (const k of Object.keys(obj)) {\n if (predicate(k, obj[k])) delete obj[k];\n }\n}\n\n/** Delete every key of the object at `jsonPath` for which\n * `predicate(key, value)` is true. No-op if the path is not an object. */\nexport function pruneKeysMatchingAt(\n jsonPath: string,\n predicate: (key: string, value: unknown) => boolean,\n): void {\n const obj = requireJson(\"pruneKeysMatchingAt\").obj;\n const sub = getAtPath(obj, jsonPath);\n if (!isObject(sub)) return;\n for (const k of Object.keys(sub)) {\n if (predicate(k, sub[k])) delete sub[k];\n }\n}\n\n// --- Field order ---\n\nfunction applyOrderInPlace(o: JsonObject, order: readonly string[]): void {\n const reordered = reorderTopLevel(o, order);\n for (const k of Object.keys(o)) delete o[k];\n for (const k of Object.keys(reordered)) o[k] = reordered[k];\n}\n\n/** Reorder top-level keys to `orderedKeys`; keys not listed keep their\n * position relative to the preceding listed key. Typically the LAST call in\n * a managed body, projecting the canonical field order. */\nexport function enforceFieldOrder(orderedKeys: string[]): void {\n applyOrderInPlace(requireJson(\"enforceFieldOrder\").obj, orderedKeys);\n}\n\n/** Like {@link enforceFieldOrder}, applied to the object at `jsonPath`. No-op\n * if the path is not an object. */\nexport function enforceFieldOrderAt(jsonPath: string, orderedKeys: string[]): void {\n const obj = requireJson(\"enforceFieldOrderAt\").obj;\n const sub = getAtPath(obj, jsonPath);\n if (!isObject(sub)) return;\n applyOrderInPlace(sub, orderedKeys);\n}\n\nfunction sortAlphabeticalInPlace(o: JsonObject, recursive: boolean): void {\n const sorted = Object.keys(o).sort();\n const buf: JsonObject = {};\n for (const k of sorted) buf[k] = o[k];\n for (const k of Object.keys(o)) delete o[k];\n for (const k of sorted) {\n o[k] = buf[k];\n if (recursive && isObject(o[k])) sortAlphabeticalInPlace(o[k] as JsonObject, true);\n }\n}\n\n/** Sort keys alphabetically. Called with no args it is a deliberate no-op\n * (guards against accidental whole-file sorts); pass a `jsonPath` to sort one\n * object, or `{ recursive: true }` to sort the whole tree. Matches oxfmt's\n * dependency-section ordering. */\nexport function enforceAlphabeticalOrder(\n jsonPath: string = \"\",\n opts: { recursive?: boolean } = {},\n): void {\n const recursive = opts.recursive ?? false;\n // Default jsonPath=\"\" with recursive:false is a no-op (prevents accidents).\n if (jsonPath === \"\" && !recursive) return;\n const obj = requireJson(\"enforceAlphabeticalOrder\").obj;\n if (jsonPath === \"\") {\n sortAlphabeticalInPlace(obj, true);\n return;\n }\n const sub = getAtPath(obj, jsonPath);\n if (!isObject(sub)) return;\n sortAlphabeticalInPlace(sub, recursive);\n}\n\n// --- Generic transform escape hatch ---\n\n/** Escape hatch: replace the value at `jsonPath` with `transform(current)`,\n * for shapes the typed builders above do not cover. */\nexport function transformAt<T = unknown>(jsonPath: string, transform: (current: T) => T): void {\n const obj = requireJson(\"transformAt\").obj;\n const current = getAtPath(obj, jsonPath) as T;\n const next = transform(current);\n setAtPath(obj, jsonPath, next);\n}\n\n// ============================================================\n// YAML builders — `pnpm-workspace.yaml`\n// ============================================================\n\n/** Set the workspace `packages:` list to all discovered NON-root module\n * paths (sorted lex). The block root (\"\") is discovered implicitly\n * and is NEVER written to `packages:` — listing \".\" there breaks turbo's\n * task graph. Equality-guarded — skips the rewrite when the existing\n * list already matches, so a YAML round-trip on an already-canonical\n * file produces zero churn. */\nexport function ensureWorkspaceModulePaths(): void {\n const state = requireYaml(\"ensureWorkspaceModulePaths\");\n const ctx = ctxOrThrow(state, \"ensureWorkspaceModulePaths\");\n const paths = ctx.modules\n .filter((m) => m.path !== \"\")\n .map((m) => m.path)\n .sort();\n const json = state.doc.toJSON() as { packages?: unknown } | null;\n const cur = json?.packages;\n if (Array.isArray(cur) && cur.length === paths.length && cur.every((v, i) => v === paths[i])) {\n return;\n }\n state.doc.setIn([\"packages\"], paths);\n}\n\nfunction readCatalogString(state: YamlState, name: string): string | undefined {\n const node = state.doc.getIn([\"catalog\", name]);\n return typeof node === \"string\" ? node : undefined;\n}\n\n/** Add `catalog.<name>` at `version` ONLY if the key is absent. An entry\n * the block already carries is left untouched — no overwrite, no\n * downgrade. This is the seeding primitive for curated fixed versions\n * (`INFRA_CATALOG_FLOOR`, the python runenv pin): on\n * `refresh --update-deps-only` a missing standard catalog key is added,\n * while a key the block already pins keeps its own version. To force a\n * specific version regardless of what is present, use `pinCatalogTo`. */\nexport function ensureCatalogVersion(name: string, version: string): void {\n const state = requireYaml(\"ensureCatalogVersion\");\n if (readCatalogString(state, name) !== undefined) return;\n state.doc.setIn([\"catalog\", name], version);\n}\n\n/** Set `catalog.<name>` to `version` EXACTLY — creates the entry if\n * missing, overwrites it (including a downgrade) if present. Use to force\n * a specific version; with top-to-bottom declaration order a later\n * `pinCatalogTo` overrides an earlier `ensureCatalogLatest`. Distinct\n * from `ensureCatalogVersion`, which never touches a present key. */\nexport function pinCatalogTo(name: string, version: string): void {\n const state = requireYaml(\"pinCatalogTo\");\n if (readCatalogString(state, name) === version) return;\n state.doc.setIn([\"catalog\", name], version);\n}\n\n/** Resolve `catalog.<name>` to npm \"latest\" from the active state's\n * prefetched `getLatestVersion` accessor (the caller pre-resolves; no\n * network here), creating the key if absent. No-op when no latest is\n * available — default refresh passes no lookup, and a name that was not\n * prefetched resolves to `undefined`; in both cases any existing entry is\n * left untouched. This is the SDK-family resolver: on\n * `refresh --update-deps-only` it both SEEDS a missing standard SDK key\n * and refreshes a present one, and on `init` it overwrites the\n * placeholder with the real latest. */\nexport function ensureCatalogLatest(name: string): void {\n const state = requireYaml(\"ensureCatalogLatest\");\n if (!state.getLatestVersion) return;\n const latest = state.getLatestVersion(name);\n if (latest === undefined) return;\n if (readCatalogString(state, name) === latest) return;\n state.doc.setIn([\"catalog\", name], latest);\n}\n\n/** Pin `catalog.<catalogEntry>` to the EXACT version that package `opts.of`\n * declares for `catalogEntry` in its own manifest (read at npm latest, or at\n * `opts.ofVersion` if given). The value is resolved by the runner's\n * prefetched `getDerivedDependencyPin` accessor (the caller pre-resolves and\n * validates — exact-version-only — at prefetch time; no network here).\n * OVERWRITES like `pinCatalogTo` (not add-if-absent): a pre-existing loose\n * entry (`vue: ^3.5.24`) is tightened to the exact derived version. No-op\n * when no derived-pin lookup is available — default refresh/check pass none,\n * leaving the entry exactly as the lockfile has it; the resolution leaves\n * live in the `onInitOrUpdate` frame. */\nexport function pinCatalogToDependencyOf(\n catalogEntry: string,\n _opts: { of: string; ofVersion?: string },\n): void {\n const state = requireYaml(\"pinCatalogToDependencyOf\");\n if (!state.getDerivedDependencyPin) return;\n const version = state.getDerivedDependencyPin(catalogEntry);\n if (version === undefined) return;\n if (readCatalogString(state, catalogEntry) === version) return;\n state.doc.setIn([\"catalog\", catalogEntry], version);\n}\n\n/** Remove `catalog.<name>` if present; no-op when absent. */\nexport function ensureCatalogAbsent(name: string): void {\n const state = requireYaml(\"ensureCatalogAbsent\");\n if (!state.doc.hasIn([\"catalog\", name])) return;\n state.doc.deleteIn([\"catalog\", name]);\n}\n\n// ============================================================\n// Lines builders — `.gitignore`\n// ============================================================\n\n/** Append each `entry` if not already present (comment-aware equality). */\nexport function ensureGitignoreEntries(entries: string[]): void {\n const state = requireLines(\"ensureGitignoreEntries\");\n for (const e of entries) {\n if (containsEntry(state.lines, e)) continue;\n state.lines.push(e);\n }\n}\n\n/** Drop any line whose normalised form matches any of `patterns`. */\nexport function removeGitignoreEntries(patterns: RegExp[]): void {\n const state = requireLines(\"removeGitignoreEntries\");\n const kept: string[] = [];\n for (const line of state.lines) {\n const n = normaliseLine(line);\n if (n === \"\") {\n kept.push(line);\n continue;\n }\n if (patterns.some((p) => p.test(n))) continue;\n kept.push(line);\n }\n state.lines.splice(0, state.lines.length, ...kept);\n}\n","// YAML parser + serialiser, comment-preserving via the `yaml` lib's\n// Document API (CST-preserving). Wraps `parseDocument` + `Document.toString`.\n// Helpers (`yamlGet`, `yamlSet`, `yamlHas`, `yamlDelete`) operate on the\n// Document by jsonPath-style addresses, matching the JSON parser's API.\n// Comments attached to map entries survive set/delete operations as long\n// as the affected nodes are mutated in place (not reassigned wholesale).\n\nimport {\n Document,\n isMap,\n isPair,\n isSeq,\n parseDocument,\n YAMLMap,\n YAMLSeq,\n Scalar,\n Node,\n} from \"yaml\";\n\nexport type YamlDocument = Document.Parsed;\n\n/** Parse YAML into a CST-preserving Document. */\nexport function parseYaml(raw: string): YamlDocument {\n return parseDocument(raw);\n}\n\n/** Serialise back to string. Preserves comments + ordering of unchanged\n * nodes per the `yaml` library's contract. */\nexport function stringifyYaml(doc: YamlDocument): string {\n return doc.toString();\n}\n\nfunction splitPath(jsonPath: string): string[] {\n if (jsonPath === \"\" || jsonPath === undefined) return [];\n return jsonPath.split(\".\");\n}\n\n/** Get the JS value at the given jsonPath in the document. */\nexport function yamlGet(doc: YamlDocument, jsonPath: string): unknown {\n const parts = splitPath(jsonPath);\n if (parts.length === 0) return doc.toJS();\n return doc.getIn(parts, false) as unknown;\n}\n\nexport function yamlHas(doc: YamlDocument, jsonPath: string): boolean {\n const parts = splitPath(jsonPath);\n if (parts.length === 0) return true;\n return doc.hasIn(parts);\n}\n\n/** Set a value at jsonPath. Auto-creates intermediate maps. Existing\n * comments on parent map entries are preserved by the yaml library. */\nexport function yamlSet(doc: YamlDocument, jsonPath: string, value: unknown): void {\n const parts = splitPath(jsonPath);\n if (parts.length === 0) {\n throw new Error(\"yamlSet: jsonPath must be non-empty\");\n }\n doc.setIn(parts, value);\n}\n\n/** Delete a value at jsonPath. No-op if missing. */\nexport function yamlDelete(doc: YamlDocument, jsonPath: string): void {\n const parts = splitPath(jsonPath);\n if (parts.length === 0) {\n throw new Error(\"yamlDelete: jsonPath must be non-empty\");\n }\n doc.deleteIn(parts);\n}\n\n/** Re-export selected `yaml` lib types for downstream content-rule builders. */\nexport { isMap, isPair, isSeq, YAMLMap, YAMLSeq, Scalar };\nexport type { Node };\n","// `.structure` metadata file — read/write + floor check.\n//\n// Single JSON file at the block root holding the layout-version\n// integer and (in future) any other structurer metadata. Two\n// constants govern lifecycle gates:\n// - STRUCTURE_VERSION : latest known. v2 = software-build layout.\n// - STRUCTURE_MIN_SUPPORTED : floor. Initial value 0.\n// Both are bumped by structurer releases; rule predicates may consult\n// `ctx.version` for one-shot version-gated transitions.\n\nimport type { FileSystem } from \"./fs/api\";\n\nexport const STRUCTURE_VERSION = 2;\nexport const STRUCTURE_MIN_SUPPORTED = 0;\n/** Block-relative path of the structurer metadata file. */\nexport const STRUCTURE_META_FILE = \".structure\";\n\nexport type StructureMeta = { version: number };\n\n/** Read `.structure`. Missing file or invalid payload → version 0. */\nexport function readStructureMeta(fs: FileSystem): StructureMeta {\n if (!fs.exists(STRUCTURE_META_FILE)) return { version: 0 };\n try {\n const parsed = JSON.parse(fs.read(STRUCTURE_META_FILE)) as Partial<StructureMeta>;\n return { version: typeof parsed?.version === \"number\" ? parsed.version : 0 };\n } catch {\n return { version: 0 };\n }\n}\n\n/** Throw if version is below floor. */\nexport function assertVersionAboveFloor(\n version: number,\n floor: number = STRUCTURE_MIN_SUPPORTED,\n): void {\n if (version < floor) {\n throw new StructureVersionFloorError(version, floor);\n }\n}\n\nexport class StructureVersionFloorError extends Error {\n constructor(\n public readonly version: number,\n public readonly floor: number,\n ) {\n super(\n `Block .structure version is ${version}, below floor ${floor}. ` +\n `Bootstrap via the legacy-migration skill, then re-run.`,\n );\n this.name = \"StructureVersionFloorError\";\n }\n}\n\n/** Write `.structure`. Writes a fresh payload rather than merging. */\nexport function writeStructureMeta(fs: FileSystem, meta: StructureMeta): void {\n // Compact, single-line — this is a tiny machine file, no pretty-print.\n fs.write(STRUCTURE_META_FILE, JSON.stringify(meta));\n}\n","// Engine runner — structural pass, managed pass, post-run recheck.\n//\n// `run(structure, fs, ctx, opts)` drives one block through the structural\n// pass, managed pass, and post-run recheck (DISCOVERY happens in the\n// caller, which constructs `ctx.modules`). The function is shared by\n// `check`, `refresh`,\n// `refresh --update-deps-only`, and `init`. The mode (see `currentMode`)\n// selects which leaves fire — a leaf fires iff its `modes` include the\n// current one:\n// - dryRun=true → check, mode \"default\" (no\n// writes)\n// - dryRun=false, updateDepsOnly=false → refresh, mode \"default\"\n// (writes + .structure bump +\n// post-run recheck)\n// - dryRun=false, updateDepsOnly=true → refresh --update-deps-only,\n// mode \"updateDeps\" (only\n// onUpdateDeps/onInitOrUpdate\n// leaves fire; no version\n// bump; no recheck)\n// - dryRun=false, opts.initMode=true → init, mode \"init\" (default\n// + onInitOrUpdate leaves +\n// seeds; no recheck — the\n// init→check test runs an\n// explicit dry-run afterwards)\n//\n// Idempotency invariant is enforced by the post-run recheck: after a\n// successful refresh, the runner reruns the lifecycle in dry-run mode (fresh\n// rediscover when supplied) and throws `RecheckError` on any non-empty\n// change list. The error carries the failing item's\n// (scope, path, primitive, action) tuple for diagnostics.\n\nimport { stringify as yamlStringify } from \"yaml\";\nimport type { ContentForm, FlatItem, RunMode, Structure, TriggerContext, ManagedBody } from \"./ir\";\nimport type { RunContext, Scope } from \"./api\";\nimport type { FileSystem } from \"./fs/api\";\nimport type { TemplateProvider } from \"./templates\";\nimport { substituteVars } from \"./templates\";\nimport { flatten } from \"./flatten\";\nimport { matchesGlob } from \"./glob\";\nimport { withRunContext } from \"./builders\";\nimport {\n withManagedBody,\n withManagedYaml,\n withManagedLines,\n resolveSdkSentinelsInJson,\n} from \"./content-rules\";\nimport { parseJson, stringifyJson } from \"./parsers/json\";\nimport type { JsonObject } from \"./parsers/json\";\nimport { parseYaml, stringifyYaml } from \"./parsers/yaml\";\nimport { parseLines, serializeLines } from \"./parsers/lines\";\nimport { writeStructureMeta, STRUCTURE_VERSION, STRUCTURE_META_FILE } from \"./version\";\n\nexport type ChangeAction = \"create\" | \"update\" | \"delete\" | \"rename\" | \"noop\";\n\nexport type Change = {\n scope: Scope;\n /** Resolved (block-relative) path. For rename, the source path. */\n path: string;\n /** \"fixed\" | \"managed\" | \"scaffold\" | \"seed\" | \"remove\" | \"rename\" */\n primitive: string;\n action: ChangeAction;\n};\n\nexport type RunResult = {\n changes: Change[];\n};\n\nexport type RunOptions = {\n /** Called before the post-run recheck to obtain a fresh RunContext\n * reflecting the just-written FS state (re-reads `pnpm-workspace.yaml`).\n * If absent, recheck reuses the original ctx with `dryRun: true`. */\n rediscover?: (fs: FileSystem) => RunContext;\n /** Template provider used by `file(...)` and `tpl(...)` content forms.\n * Required whenever the structure references such forms. */\n templates?: TemplateProvider;\n /** Init mode: write seed leaves (only-if-missing semantics) and skip\n * the post-run recheck. The caller is expected to follow with an\n * explicit dry-run check (Layer-2 invariant). */\n initMode?: boolean;\n /** Sync accessor for prefetched npm \"latest\" versions, consumed by\n * `ensureCatalogLatest` inside `onUpdateDeps` managed bodies. The CLI\n * prefetches the catalog's package versions before the run (network)\n * and passes the resulting sync map here; unit tests pass a mock.\n * Absent → `ensureCatalogLatest` is a no-op (default refresh). */\n registryLookup?: (packageName: string) => string | undefined;\n /** Sync accessor for prefetched derived catalog pins\n * (`catalogEntry → exact version`), consumed by `pinCatalogToDependencyOf`\n * inside `onInitOrUpdate` managed bodies. The CLI / init constructor\n * prefetches + validates these before the run (network). Absent →\n * `pinCatalogToDependencyOf` is a no-op (default refresh). */\n derivedPinLookup?: (catalogEntry: string) => string | undefined;\n};\n\nexport class RecheckError extends Error {\n constructor(public readonly failing: Change) {\n super(\n `Post-run recheck: rule set not idempotent. ` +\n `Failing item: ${failing.primitive} '${failing.path}' ` +\n `(scope=${failing.scope}, action=${failing.action}). Engine bug.`,\n );\n this.name = \"RecheckError\";\n }\n}\n\n/** Resolve a `ContentForm` to its on-disk string for the given file\n * path. `file` / `tpl` resolution goes through the configured\n * `TemplateProvider`; `generate` returns parsed structure → JSON/YAML\n * or a string. */\nfunction resolveContent(\n form: ContentForm,\n filePath: string,\n templates: TemplateProvider | undefined,\n ctx: RunContext,\n): string {\n switch (form.kind) {\n case \"text\":\n return form.value;\n case \"file\": {\n if (!templates) {\n throw new Error(\n `file('${form.path}'): no TemplateProvider configured. ` +\n `Pass opts.templates to engine.run(...).`,\n );\n }\n return templates.staticRead(form.path);\n }\n case \"tpl\": {\n if (!templates) {\n throw new Error(\n `tpl('${form.path}'): no TemplateProvider configured. ` +\n `Pass opts.templates to engine.run(...).`,\n );\n }\n const raw = templates.textRead(form.path);\n const vars = typeof form.vars === \"function\" ? form.vars(ctx) : form.vars;\n return substituteVars(raw, vars);\n }\n case \"generate\": {\n const value = form.fn(ctx);\n if (filePath.endsWith(\".json\")) {\n // Resolve `sdk:` sentinels in the generated dep sections so the\n // initial content matches what the body rules re-assert.\n resolveSdkSentinelsInJson(value, ctx.isSdkInternal);\n // package.json stays fully expanded (oxfmt's package.json shape);\n // every other .json collapses to oxfmt's generic-file shape.\n return stringifyJson(value, { collapse: !filePath.endsWith(\"package.json\") });\n }\n if (filePath.endsWith(\".yaml\") || filePath.endsWith(\".yml\")) {\n return yamlStringify(value);\n }\n if (typeof value !== \"string\") {\n throw new Error(\n `generate() for '${filePath}' must return a string for non-JSON/YAML files; got ${typeof value}`,\n );\n }\n return value;\n }\n case \"binary\":\n throw new Error(\n `binary('${form.path}') cannot be resolved to a string; it is only valid ` +\n `inside seed()/scaffold(), which copy it verbatim via fs.writeBinary.`,\n );\n }\n}\n\n/** Write a leaf's content to disk, dispatching binary assets (copied\n * verbatim, never utf-8 decoded) from string content. */\nfunction writeLeafContent(\n fs: FileSystem,\n resolvedPath: string,\n form: ContentForm,\n templates: TemplateProvider | undefined,\n ctx: RunContext,\n): void {\n if (form.kind === \"binary\") {\n if (!templates) {\n throw new Error(\n `binary('${form.path}'): no TemplateProvider configured. ` +\n `Pass opts.templates to engine.run(...).`,\n );\n }\n fs.writeBinary(resolvedPath, templates.staticReadBinary(form.path));\n return;\n }\n fs.write(resolvedPath, resolveContent(form, resolvedPath, templates, ctx));\n}\n\n/** Dispatch managed-body parse → mutate → serialize by file extension /\n * basename. JSON, YAML, and lines all share the same `(initial, body,\n * triggerContext) → newRaw` shape via the active-state wrappers in\n * `content-rules.ts`. */\nfunction runManagedBody(\n path: string,\n raw: string,\n body: ManagedBody,\n tctx: TriggerContext,\n registryLookup: ((packageName: string) => string | undefined) | undefined,\n derivedPinLookup: ((catalogEntry: string) => string | undefined) | undefined,\n): string {\n const base = path.split(\"/\").pop() ?? path;\n if (path.endsWith(\".json\")) {\n const parsed = parseJson(raw) as JsonObject;\n if (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new Error(`managed: parsed value at '${path}' is not a JSON object`);\n }\n withManagedBody(parsed, body, { triggerContext: tctx });\n // package.json stays fully expanded; other .json (tsconfig, …) collapses\n // to oxfmt's generic-file shape.\n return stringifyJson(parsed, { collapse: base !== \"package.json\" });\n }\n if (path.endsWith(\".yaml\") || path.endsWith(\".yml\")) {\n const doc = parseYaml(raw);\n withManagedYaml(doc, body, {\n triggerContext: tctx,\n getLatestVersion: registryLookup,\n getDerivedDependencyPin: derivedPinLookup,\n });\n return stringifyYaml(doc);\n }\n if (base === \".gitignore\" || base.endsWith(\".gitignore\")) {\n const lines = parseLines(raw);\n withManagedLines(lines, body, { triggerContext: tctx });\n return serializeLines(lines);\n }\n throw new Error(\n `managed('${path}'): unsupported file kind. Only .json, .yaml, .yml, .gitignore are dispatched.`,\n );\n}\n\nfunction buildSnapshot(fs: FileSystem): Set<string> {\n const files = fs.list(\"\");\n const out = new Set<string>();\n for (const f of files) {\n out.add(f);\n const parts = f.split(\"/\");\n for (let i = 1; i < parts.length; i++) {\n out.add(parts.slice(0, i).join(\"/\"));\n }\n }\n return out;\n}\n\nfunction snapshotHas(snap: Set<string>, p: string): boolean {\n const n = p === \"\" ? p : p.endsWith(\"/\") ? p.slice(0, -1) : p;\n return snap.has(n);\n}\n\n/** Build the trigger context for one leaf. `pathExists`/`pathMissing` are\n * block-relative; `filesMatch` resolves its glob MODULE-RELATIVE to\n * `modulePath` so the same predicate (`whenFilesExist(\"src/*.test.ts\")`)\n * reads the right module when a scope fans out. The snapshot is shared\n * across leaves; only the resolution prefix differs per item. */\nfunction buildTriggerCtx(snap: Set<string>, ctx: RunContext, modulePath: string): TriggerContext {\n return {\n ctx,\n version: ctx.version,\n pathExists: (p: string) => snapshotHas(snap, p),\n pathMissing: (p: string) => !snapshotHas(snap, p),\n filesMatch: (glob: string) => {\n const resolved = modulePath ? `${modulePath}/${glob}` : glob;\n for (const entry of snap) {\n if (matchesGlob(resolved, entry)) return true;\n }\n return false;\n },\n };\n}\n\nfunction passesTriggers(item: FlatItem, tctx: TriggerContext): boolean {\n for (const t of item.triggers) {\n if (!t(tctx)) return false;\n }\n return true;\n}\n\n/** Derive the active run mode from the context + init flag. `check`\n * (dryRun) and `refresh` share `\"default\"` — same leaves, the `dryRun`\n * flag alone decides whether writes land. */\nfunction currentMode(ctx: RunContext, initMode: boolean): RunMode {\n if (initMode) return \"init\";\n if (ctx.updateDepsOnly) return \"updateDeps\";\n return \"default\";\n}\n\nfunction filterByMode(items: FlatItem[], mode: RunMode): FlatItem[] {\n return items.filter((i) => i.modes.includes(mode));\n}\n\nfunction applyStructural(\n item: FlatItem,\n fs: FileSystem,\n dryRun: boolean,\n templates: TemplateProvider | undefined,\n initMode: boolean,\n ctx: RunContext,\n): Change | undefined {\n const leaf = item.leaf;\n if (leaf.kind === \"fixed\") {\n const desired = resolveContent(leaf.content, item.resolvedPath, templates, ctx);\n const exists = fs.exists(item.resolvedPath);\n if (!exists) {\n if (!dryRun) fs.write(item.resolvedPath, desired);\n return {\n scope: item.scope,\n path: item.resolvedPath,\n primitive: \"fixed\",\n action: \"create\",\n };\n }\n const current = fs.read(item.resolvedPath);\n if (current === desired) return undefined;\n if (!dryRun) fs.write(item.resolvedPath, desired);\n return {\n scope: item.scope,\n path: item.resolvedPath,\n primitive: \"fixed\",\n action: \"update\",\n };\n }\n if (leaf.kind === \"scaffold\") {\n if (fs.exists(item.resolvedPath)) return undefined;\n if (!dryRun) {\n writeLeafContent(fs, item.resolvedPath, leaf.initial, templates, ctx);\n }\n return {\n scope: item.scope,\n path: item.resolvedPath,\n primitive: \"scaffold\",\n action: \"create\",\n };\n }\n if (leaf.kind === \"seed\") {\n // Init mode: write seeds once if missing (same shape as scaffold).\n // Refresh / check: seeds are off-limits to the engine — they belong\n // to the block author. Layer-2 init→check parity relies on the\n // init action depositing canonical seed content, then the check\n // pass simply skipping seeds (vacuously fine).\n if (!initMode) return undefined;\n if (fs.exists(item.resolvedPath)) return undefined;\n if (!dryRun) {\n writeLeafContent(fs, item.resolvedPath, leaf.initial, templates, ctx);\n }\n return {\n scope: item.scope,\n path: item.resolvedPath,\n primitive: \"seed\",\n action: \"create\",\n };\n }\n if (leaf.kind === \"remove\") {\n if (!fs.exists(item.resolvedPath)) return undefined;\n if (!dryRun) fs.delete(item.resolvedPath);\n return {\n scope: item.scope,\n path: item.resolvedPath,\n primitive: \"remove\",\n action: \"delete\",\n };\n }\n if (leaf.kind === \"rename\") {\n if (!fs.exists(item.resolvedPath)) return undefined;\n const to = item.resolvedTo!;\n if (fs.exists(to)) {\n // dest exists — treat as already-renamed; no change.\n return undefined;\n }\n if (!dryRun) fs.move(item.resolvedPath, to);\n return {\n scope: item.scope,\n path: item.resolvedPath,\n primitive: \"rename\",\n action: \"rename\",\n };\n }\n return undefined;\n}\n\nfunction applyManaged(\n item: FlatItem,\n fs: FileSystem,\n dryRun: boolean,\n tctx: TriggerContext,\n templates: TemplateProvider | undefined,\n registryLookup: ((packageName: string) => string | undefined) | undefined,\n derivedPinLookup: ((catalogEntry: string) => string | undefined) | undefined,\n ctx: RunContext,\n): Change | undefined {\n if (item.leaf.kind !== \"managed\") return undefined;\n const leaf = item.leaf;\n const path = item.resolvedPath;\n const exists = fs.exists(path);\n\n let beforeRaw: string;\n let created = false;\n\n if (!exists) {\n beforeRaw = resolveContent(leaf.initial, path, templates, ctx);\n created = true;\n } else {\n beforeRaw = fs.read(path);\n }\n\n const after = runManagedBody(path, beforeRaw, leaf.body, tctx, registryLookup, derivedPinLookup);\n\n if (created) {\n if (!dryRun) fs.write(path, after);\n return {\n scope: item.scope,\n path,\n primitive: \"managed\",\n action: \"create\",\n };\n }\n if (after === beforeRaw) return undefined;\n if (!dryRun) fs.write(path, after);\n return {\n scope: item.scope,\n path,\n primitive: \"managed\",\n action: \"update\",\n };\n}\n\n/** Execute one pass over the flattened items: structural items first\n * (declaration order), then managed items. Returns the change list. */\nfunction executePass(\n flat: FlatItem[],\n fs: FileSystem,\n ctx: RunContext,\n dryRun: boolean,\n templates: TemplateProvider | undefined,\n initMode: boolean,\n registryLookup: ((packageName: string) => string | undefined) | undefined,\n derivedPinLookup: ((catalogEntry: string) => string | undefined) | undefined,\n): Change[] {\n const items = filterByMode(flat, currentMode(ctx, initMode));\n const changes: Change[] = [];\n\n // Structural pass. The trigger context is per-item: `filesMatch` resolves\n // module-relative, so it must carry the leaf's bound module path.\n const snap1 = buildSnapshot(fs);\n for (const item of items) {\n if (item.leaf.kind === \"managed\") continue;\n const tctx1 = buildTriggerCtx(snap1, ctx, item.modulePath);\n if (!passesTriggers(item, tctx1)) continue;\n const change = applyStructural(item, fs, dryRun, templates, initMode, ctx);\n if (change) changes.push(change);\n }\n\n // Re-snapshot after structural pass — managed-body triggers see the\n // post-rename / post-delete world.\n const snap2 = buildSnapshot(fs);\n for (const item of items) {\n if (item.leaf.kind !== \"managed\") continue;\n const tctx2 = buildTriggerCtx(snap2, ctx, item.modulePath);\n if (!passesTriggers(item, tctx2)) continue;\n const change = applyManaged(\n item,\n fs,\n dryRun,\n tctx2,\n templates,\n registryLookup,\n derivedPinLookup,\n ctx,\n );\n if (change) changes.push(change);\n }\n\n return changes;\n}\n\n/**\n * Run the structurer engine end-to-end. See module header for mode\n * semantics. Throws `RecheckError` if the post-run dry-run finds any\n * leftover diff after a successful refresh.\n */\nexport function run(\n structure: Structure,\n fs: FileSystem,\n ctx: RunContext,\n opts: RunOptions = {},\n): RunResult {\n return withRunContext(ctx, () => {\n const flat = flatten(structure, ctx);\n const initMode = !!opts.initMode;\n const changes = executePass(\n flat,\n fs,\n ctx,\n ctx.dryRun,\n opts.templates,\n initMode,\n opts.registryLookup,\n opts.derivedPinLookup,\n );\n\n const isRefreshDefault = !ctx.dryRun && !ctx.updateDepsOnly && !initMode;\n\n if (isRefreshDefault) {\n // version bump\n writeStructureMeta(fs, { version: STRUCTURE_VERSION });\n\n // post-run recheck. Fresh discovery → fresh flatten →\n // dry-run. Any change list emits RecheckError on the first item.\n const recheckCtxBase = opts.rediscover ? opts.rediscover(fs) : ctx;\n const recheckCtx: RunContext = { ...recheckCtxBase, dryRun: true };\n const recheckFlat = flatten(structure, recheckCtx);\n const recheckChanges = executePass(\n recheckFlat,\n fs,\n recheckCtx,\n true,\n opts.templates,\n false,\n opts.registryLookup,\n opts.derivedPinLookup,\n );\n // Ignore .structure self-write (already up to date after\n // writeStructureMeta above).\n const filtered = recheckChanges.filter((c) => c.path !== STRUCTURE_META_FILE);\n if (filtered.length > 0) {\n throw new RecheckError(filtered[0]!);\n }\n }\n\n // Init mode: write .structure so the resulting tree carries the\n // current version (matches what `init` ships to disk).\n if (initMode && !ctx.dryRun) {\n writeStructureMeta(fs, { version: STRUCTURE_VERSION });\n }\n\n return { changes };\n });\n}\n","// Workspace-package classification — the eight scope detection rules.\n//\n// Input: the parsed package.json of every workspace member, plus its\n// block-relative path. Output: `Module[]` (scope + name + path).\n// First-match wins on the detection rules; an explicit `block-scope`\n// override on package.json skips detection.\n\nimport type { Module, Scope } from \"./api\";\n\nexport const ALL_SCOPES: Scope[] = [\n \"root\",\n \"block\",\n \"model\",\n \"ui\",\n \"workflow\",\n \"test\",\n \"software\",\n \"kind\",\n];\n\nexport type WorkspacePackage = {\n /** Block-relative path of the package — \"\" or \".\" means the\n * workspace root. */\n path: string;\n /** Parsed package.json. */\n pkg: PackageJsonLike;\n};\n\nexport type PackageJsonLike = {\n name?: string;\n main?: string;\n files?: string[];\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n optionalDependencies?: Record<string, string>;\n // Top-level `block` field — the unambiguous facade marker.\n block?: unknown;\n // Override field — value MUST be one of the seven scopes.\n \"block-scope\"?: string;\n \"block-software\"?: unknown;\n};\n\nexport class DiscoveryError extends Error {\n constructor(\n msg: string,\n public readonly path?: string,\n ) {\n super(msg);\n this.name = \"DiscoveryError\";\n }\n}\n\nfunction depKeys(pkg: PackageJsonLike): Set<string> {\n const all = new Set<string>();\n for (const section of [\n pkg.dependencies,\n pkg.devDependencies,\n pkg.peerDependencies,\n pkg.optionalDependencies,\n ]) {\n if (section) for (const k of Object.keys(section)) all.add(k);\n }\n return all;\n}\n\nfunction isRoot(p: string): boolean {\n return p === \"\" || p === \".\";\n}\n\n/**\n * Classify one package.\n *\n * @param wp The workspace package.\n * @returns Scope or `undefined` if unclassified.\n */\nexport function classifyOne(wp: WorkspacePackage): Scope | undefined {\n const override = wp.pkg[\"block-scope\"];\n if (typeof override === \"string\") {\n if (!(ALL_SCOPES as string[]).includes(override)) {\n throw new DiscoveryError(\n `package.json \"block-scope\" must be one of ${ALL_SCOPES.join(\", \")}, got '${override}'`,\n wp.path,\n );\n }\n return override as Scope;\n }\n\n // Standalone implicit root: the package at path \"\" is present\n // because pnpm-workspace.yaml lives there, so it IS the workspace root —\n // classify it as `root` unconditionally, BEFORE any detection rule. A\n // nameless root carrying legacy facade cruft (`files: [\"index.d.ts\",\n // \"index.js\"]` + block-tools, e.g. sequence-properties) must NOT fall\n // through to the rule-4 block fallback and become a nameless second\n // `block` module — root-as-facade is a forbidden anti-pattern.\n // SDK-internal enumeration never produces a path-\"\" package (it scans\n // sub-package dirs), so this only ever fires in standalone mode.\n if (isRoot(wp.path)) return \"root\";\n\n // block (facade) — a top-level `block` field is the unambiguous facade\n // marker; no non-facade workspace package carries one. MUST precede the model\n // rule: a migrated facade carries `@platforma-sdk/model` as a devDep plus\n // `main`, which would otherwise match model.\n if (wp.pkg.block !== undefined) return \"block\";\n\n const deps = depKeys(wp.pkg);\n\n // kind — @platforma-sdk/block-kind is unique to kind packages (no other scope\n // depends on it). MUST precede the model rule: a kind sets `main`, and were it\n // to carry any model-ish signal it would otherwise misclassify.\n if (deps.has(\"@platforma-sdk/block-kind\")) return \"kind\";\n\n // 1. software — top-level `block-software` field OR\n // (package-builder AND any @platforma-open/*runenv* dep).\n if (wp.pkg[\"block-software\"] !== undefined) return \"software\";\n if (deps.has(\"@platforma-sdk/package-builder\")) {\n for (const d of deps) {\n if (/^@platforma-open\\/.*runenv/.test(d)) return \"software\";\n }\n }\n\n // 2. workflow — @platforma-sdk/workflow-tengo in deps.\n if (deps.has(\"@platforma-sdk/workflow-tengo\")) return \"workflow\";\n\n // 3. ui — (ui-vue OR vue) AND main is not set.\n if ((deps.has(\"@platforma-sdk/ui-vue\") || deps.has(\"vue\")) && !wp.pkg.main) {\n return \"ui\";\n }\n\n // 4. model — @platforma-sdk/model in deps AND main is set.\n if (deps.has(\"@platforma-sdk/model\") && wp.pkg.main) return \"model\";\n\n // 5. test — @platforma-sdk/test in deps.\n if (deps.has(\"@platforma-sdk/test\")) return \"test\";\n\n // (root — the workspace root, path \"\", is classified above, before the\n // detection rules, so it can never reach this fallthrough.)\n return undefined;\n}\n\n/**\n * Classify a whole workspace. Throws on the first unclassified package\n * with a message that directs the operator to add `block-scope` to its\n * package.json.\n */\nexport function discoverModules(packages: WorkspacePackage[]): Module[] {\n const out: Module[] = [];\n for (const p of packages) {\n const scope = classifyOne(p);\n if (!scope) {\n throw new DiscoveryError(\n `Unclassified workspace package at '${p.path}'. ` +\n `Add a top-level \"block-scope\" string to its package.json.`,\n p.path,\n );\n }\n out.push({\n scope,\n name: p.pkg.name ?? p.path,\n path: isRoot(p.path) ? \"\" : p.path,\n });\n }\n return out;\n}\n","// RunContext assembly helpers + module-lookup helpers. The full\n// `RunContext` type lives in `api.ts` (rule authors see it via\n// `({ ctx }) => ...` trigger predicates). This file provides convenience\n// constructors and the scope-lookup helpers generators use.\n\nimport type { BlockVars, Module, RunContext, Scope } from \"./api\";\n\n/** All modules of `scope` (zero or more). Never throws. Use when \"zero or\n * more\" is the right intent (e.g. software). */\nexport function findModules(ctx: RunContext, scope: Scope): Module[] {\n return ctx.modules.filter((m) => m.scope === scope);\n}\n\n/** The single module of `scope`. Throws if absent OR if more than one\n * exists. Use when exactly one is required (model / ui / workflow). */\nexport function findModule(ctx: RunContext, scope: Scope): Module {\n const ms = findModules(ctx, scope);\n if (ms.length === 0) {\n throw new Error(`findModule: expected one '${scope}' module, found none`);\n }\n if (ms.length > 1) {\n throw new Error(`findModule: expected exactly one '${scope}' module, found ${ms.length}`);\n }\n return ms[0]!;\n}\n\n/** Workspace dep map `{ name: \"workspace:*\" }` for the single module of\n * `scope`. Throws if absent (via `findModule`) — guarantees the dep. */\nexport function scopeDepMap(ctx: RunContext, scope: Scope): Record<string, string> {\n return { [findModule(ctx, scope).name]: \"workspace:*\" };\n}\n\n/** Workspace dep map for ALL modules of `scope` (zero or more). Never\n * throws — use where multiple modules are legitimate (e.g. software). */\nexport function scopeDepMaps(ctx: RunContext, scope: Scope): Record<string, string> {\n const out: Record<string, string> = {};\n for (const m of findModules(ctx, scope)) out[m.name] = \"workspace:*\";\n return out;\n}\n\n/**\n * Module set produced by `init` for the given BlockVars: one module per\n * base scope (root/block/model/ui/workflow/test) plus, when a platform\n * was selected, one `software` module. `--platform` is single-valued, so\n * `init` produces at most one software module; multi-software shapes only\n * arise via DISCOVERY on existing blocks.\n *\n * Single source of truth shared by the real `init` constructor and the\n * `simulateInit` test helper — keeping them in lockstep is what makes the\n * init→check zero-diff invariant meaningful.\n */\nexport function modulesForInit(vars: BlockVars): Module[] {\n const facade = vars.facadeName;\n const mods: Module[] = [\n { scope: \"root\", name: facade, path: \"\" },\n { scope: \"block\", name: `${facade}.block`, path: \"block\" },\n { scope: \"model\", name: `${facade}.model`, path: \"model\" },\n { scope: \"kind\", name: `${facade}.kind`, path: \"kind\" },\n { scope: \"ui\", name: `${facade}.ui`, path: \"ui\" },\n { scope: \"workflow\", name: `${facade}.workflow`, path: \"workflow\" },\n { scope: \"test\", name: `${facade}.test`, path: \"test\" },\n ];\n if (vars.softwarePlatform) {\n // Single software module lives at the flat `software/` dir with name\n // `${facade}.software` — matches the boilerplate and every real\n // single-software block. Multi-software blocks arise only via\n // DISCOVERY on existing workspaces, never from `init`.\n mods.push({\n scope: \"software\",\n name: `${facade}.software`,\n path: \"software\",\n });\n }\n return mods;\n}\n\nexport type CreateRunContextInput = {\n isSdkInternal?: boolean;\n updateDepsOnly?: boolean;\n modules: Module[];\n blockVars: BlockVars;\n version?: number;\n dryRun?: boolean;\n};\n\nexport function createRunContext(input: CreateRunContextInput): RunContext {\n return {\n isSdkInternal: input.isSdkInternal ?? false,\n updateDepsOnly: input.updateDepsOnly ?? false,\n modules: input.modules,\n blockVars: input.blockVars,\n version: input.version ?? 0,\n dryRun: input.dryRun ?? false,\n };\n}\n","// Filesystem-backed DISCOVERY.\n//\n// The engine runner consumes a fully-assembled `RunContext` (modules,\n// version, blockVars). This module is the \"caller\" that builds it from a\n// block directory, working through the engine's `FileSystem` abstraction\n// — so the same code path serves the CLI (NodeFileSystem) and the\n// in-memory init→check round-trip (MemoryFileSystem), which re-discovers\n// from the just-written FS instead of reusing init's module set, so a\n// discovery/classification regression surfaces in the parity invariant.\n//\n// Two enumeration modes:\n//\n// - Standalone (default): read the block-root `pnpm-workspace.yaml`,\n// read each `packages:` member's `package.json` (literal paths only —\n// globs are a hard error), classify via `discoverModules`. This is the\n// canonical path.\n//\n// - SDK-internal (`--sdk-internal`): in-monorepo blocks (e.g.\n// `etc/blocks/*`) have NO block-local `pnpm-workspace.yaml` — they\n// are members of the parent monorepo's workspace. The block's\n// modules are therefore enumerated by scanning the block directory\n// for sub-package `package.json` files (depth-limited, skipping\n// `node_modules`).\n//\n// `.structure` version is read (missing → 0) and floor-checked. BlockVars\n// are parsed from the block-scope module's `package.json` `name` (the\n// facade name), or — for the root-as-block shape — from the root package.\n\nimport { parse as parseYamlText } from \"yaml\";\nimport type { BlockVars, Module, RunContext } from \"./api\";\nimport type { FileSystem } from \"./fs/api\";\nimport { discoverModules, type WorkspacePackage, type PackageJsonLike } from \"./discovery\";\nimport { createRunContext } from \"./ctx\";\nimport { STRUCTURE_MIN_SUPPORTED, assertVersionAboveFloor, readStructureMeta } from \"./version\";\n\nexport class StructureCliError extends Error {\n constructor(msg: string) {\n super(msg);\n this.name = \"StructureCliError\";\n }\n}\n\n/** Join two block-relative path segments (\"\" = root). */\nfunction joinRel(a: string, b: string): string {\n return a === \"\" ? b : `${a}/${b}`;\n}\n\nfunction readJsonIfExists(fs: FileSystem, rel: string): PackageJsonLike | undefined {\n try {\n return JSON.parse(fs.read(rel)) as PackageJsonLike;\n } catch {\n return undefined;\n }\n}\n\n/** Resolve a single pnpm-workspace `packages:` entry to a block-relative\n * directory path. Entries are literal paths only — the structurer does\n * not expand globs: no real block uses them, and a globbing surface\n * with no caller is dead complexity. A `*` anywhere is a hard error. */\nfunction resolvePackagePath(pattern: string): string {\n if (pattern.includes(\"*\")) {\n throw new StructureCliError(\n `pnpm-workspace.yaml 'packages:' entry '${pattern}' contains a glob. ` +\n `The structurer requires literal package paths — replace the glob ` +\n `with one entry per package directory.`,\n );\n }\n const p = pattern.replace(/^\\.\\//, \"\").replace(/\\/$/, \"\");\n return p === \".\" ? \"\" : p;\n}\n\nfunction enumerateStandalone(fs: FileSystem): WorkspacePackage[] {\n let wsRaw: string;\n try {\n wsRaw = fs.read(\"pnpm-workspace.yaml\");\n } catch {\n throw new StructureCliError(\n `No pnpm-workspace.yaml found. This directory is empty or ` +\n `unrecognisable as a block — run 'block-tools structure init' instead, ` +\n `or pass --sdk-internal for an in-monorepo block.`,\n );\n }\n const ws = (parseYamlText(wsRaw) ?? {}) as { packages?: string[] };\n const patterns = Array.isArray(ws.packages) ? ws.packages : [];\n // The block root (\"\") is ALWAYS a member, discovered implicitly.\n // pnpm treats the directory holding pnpm-workspace.yaml as the implicit\n // workspace root, so the structurer reads the root package.json directly\n // — no real block lists \".\" in `packages:` (it would break turbo's task\n // graph), and the structurer never requires or writes it. The Set\n // dedupes if a workspace did list \".\".\n const dirs = new Set<string>([\"\"]);\n for (const pat of patterns) {\n const d = resolvePackagePath(pat);\n if (d === \"\" || fs.exists(d)) dirs.add(d);\n }\n const out: WorkspacePackage[] = [];\n for (const d of dirs) {\n const pkg = readJsonIfExists(fs, joinRel(d, \"package.json\"));\n if (pkg) out.push({ path: d, pkg });\n }\n return out;\n}\n\n/** SDK-internal enumeration: scan the block directory for sub-package\n * `package.json` files. Depth-limited to two levels (covers `block/`,\n * `model/`, … and `software/<name>/`), skipping `node_modules`. */\nfunction enumerateSdkInternal(fs: FileSystem): WorkspacePackage[] {\n const out: WorkspacePackage[] = [];\n const SKIP = new Set([\"node_modules\", \".turbo\", \"dist\", \".git\", \"block-pack\"]);\n\n function scan(rel: string, depth: number): void {\n const entries = fs.listDir(rel);\n for (const e of entries) {\n if (!e.isDirectory || SKIP.has(e.name)) continue;\n const childRel = joinRel(rel, e.name);\n const pkg = readJsonIfExists(fs, joinRel(childRel, \"package.json\"));\n if (pkg) out.push({ path: childRel, pkg });\n if (depth < 2) scan(childRel, depth + 1);\n }\n }\n scan(\"\", 1);\n return out;\n}\n\n/** Parse a facade package name `@npmOrg/orgScope.shortName` into BlockVars. */\nexport function parseBlockVars(facadeName: string): BlockVars {\n const slash = facadeName.indexOf(\"/\");\n if (!facadeName.startsWith(\"@\") || slash < 0) {\n throw new StructureCliError(\n `Cannot parse block name '${facadeName}': expected '@npm-org/org-scope.short-name'.`,\n );\n }\n const npmOrg = facadeName.slice(0, slash);\n const baseName = facadeName.slice(slash + 1);\n const dot = baseName.indexOf(\".\");\n if (dot < 0) {\n throw new StructureCliError(\n `Cannot parse block name '${facadeName}': base name '${baseName}' has no '.' separating org-scope from short-name.`,\n );\n }\n return {\n facadeName,\n baseName,\n npmOrg,\n orgScope: baseName.slice(0, dot),\n shortName: baseName.slice(dot + 1),\n };\n}\n\nexport type DiscoverInput = {\n /** Block-rooted filesystem (NodeFileSystem for the CLI, MemoryFileSystem\n * for the Layer-2 round-trip). */\n fs: FileSystem;\n isSdkInternal: boolean;\n updateDepsOnly?: boolean;\n dryRun?: boolean;\n};\n\n/**\n * Run DISCOVERY against a block filesystem and return a fully-assembled\n * `RunContext`, ready for `engine.run`. Throws `StructureCliError` /\n * `DiscoveryError` / `StructureVersionFloorError` on a non-block dir,\n * an unclassified package, or a below-floor version.\n */\nexport function discoverRunContext(input: DiscoverInput): RunContext {\n const { fs, isSdkInternal } = input;\n\n const packages = isSdkInternal ? enumerateSdkInternal(fs) : enumerateStandalone(fs);\n\n if (packages.length === 0) {\n throw new StructureCliError(\n `No workspace packages found. ` + `Run 'block-tools structure init' to scaffold a block.`,\n );\n }\n\n const modules: Module[] = discoverModules(packages);\n\n const meta = readStructureMeta(fs);\n assertVersionAboveFloor(meta.version, STRUCTURE_MIN_SUPPORTED);\n\n // BlockVars from the block-scope module's name (facade). Fall back to\n // the root module if a block has the root-as-block shape.\n const blockMod =\n modules.find((m) => m.scope === \"block\") ?? modules.find((m) => m.scope === \"root\");\n if (!blockMod) {\n throw new StructureCliError(\n `Could not find a 'block' (or root-as-block) package to derive BlockVars from.`,\n );\n }\n // This structurer names the block package `<facade>.block`\n // (block-package-json.ts). The root package carries no `name`, so DISCOVERY\n // derives BlockVars from the block module — whose `.block` suffix would\n // otherwise leak into `shortName` on refresh/check (but not init, which is\n // fed the facade directly). Strip it so `shortName` is the real short name\n // everywhere. No-op for legacy blocks whose block package IS the bare facade\n // and for the root-as-block fallback.\n const facadeName = blockMod.name.replace(/\\.block$/, \"\");\n const blockVars = parseBlockVars(facadeName);\n\n return createRunContext({\n isSdkInternal,\n updateDepsOnly: input.updateDepsOnly ?? false,\n modules,\n blockVars,\n version: meta.version,\n dryRun: input.dryRun ?? false,\n });\n}\n","// Canonical top-level key order for `package.json` files.\n// Used by `enforceFieldOrder(canonicalPackageJsonOrder)` at the end of\n// every `*-package-json.ts` body.\n// Per-block extensions: rules call\n// `enforceFieldOrder([...canonicalPackageJsonOrder, \"customKey\"])`.\n//\n// This order is derived EMPIRICALLY from oxfmt (the canonical formatter run\n// by `ts-builder check`): a freshly-refreshed package.json must pass\n// `oxfmt --check` so `pnpm check` is green without a prior `pnpm fmt`. oxfmt\n// also alphabetises the dependency sections — the `*-package-json.ts` bodies\n// call `enforceAlphabeticalOrder` on each dep section to match (scripts and\n// `exports` keep source order; oxfmt does not reorder them).\nexport const canonicalPackageJsonOrder = [\n \"name\",\n \"version\",\n \"private\",\n \"description\",\n \"keywords\",\n \"files\",\n \"type\",\n \"main\",\n \"module\",\n \"types\",\n \"exports\",\n \"scripts\",\n \"dependencies\",\n \"devDependencies\",\n \"peerDependencies\",\n \"optionalDependencies\",\n \"packageManager\",\n \"pnpm\",\n \"block\",\n \"block-software\",\n] as const;\n","// Root `package.json`: the initial generator and the drift-correcting body\n// rules, co-located. The body re-asserts the canonical scripts, devDeps,\n// peerDeps, and the final field-order projection (enforceFieldOrder is the\n// LAST call).\n\nimport {\n ensureField,\n ensureScript,\n ensureDevDeps,\n ensurePeerDeps,\n removeScript,\n removeField,\n pruneKeysMatching,\n enforceAlphabeticalOrder,\n enforceFieldOrder,\n} from \"../engine/api\";\nimport { canonicalPackageJsonOrder } from \"./shared/key-order\";\n\n// `variant=all` builds every variant the software declares — docker-vs-binary is not a per-script\n// choice. `no-software` builds placeholder software for validators.\n\nconst BUILD_SCRIPTS: Record<string, string> = {\n \"build:dev-local\":\n \"env PL_BUILD_CHANNEL=dev PL_BUILD_VARIANT=all PL_BUILD_LOCATION=local turbo run build\",\n \"build:dev-remote\":\n \"env PL_BUILD_CHANNEL=dev PL_BUILD_VARIANT=all PL_BUILD_LOCATION=remote turbo run build\",\n \"build:dev-no-software\": \"env PL_BUILD_CHANNEL=dev PL_BUILD_VARIANT=none turbo run build\",\n \"build:dev-binary-existing\":\n \"env PL_BUILD_CHANNEL=dev PL_BUILD_USE_PUBLISHED=true turbo run build\",\n \"build:release\":\n \"env PL_BUILD_CHANNEL=release PL_BUILD_VARIANT=all PL_BUILD_LOCATION=remote turbo run build\",\n};\n\n// `test` / `test:dry-run` run the build-then-test DAG in the dev-binary-local target; the live\n// backend's env reaches the integration tests via the turbo `test` task's passThroughEnv.\nconst TEST_SCRIPTS: Record<string, string> = {\n test: `env PL_BUILD_CHANNEL=dev PL_BUILD_VARIANT=binary PL_BUILD_LOCATION=local turbo run test --concurrency 1`,\n \"test:dry-run\": `env PL_BUILD_CHANNEL=dev PL_BUILD_VARIANT=binary PL_BUILD_LOCATION=local turbo run test --dry-run=json`,\n};\n\nexport function rootPackageJsonInitial(): Record<string, unknown> {\n // No `name`: the root is never published. Body rules re-assert\n // (removeField(\"name\")) as a drift-corrector.\n return {\n version: \"1.0.0\",\n private: true,\n scripts: {\n fmt: \"turbo run fmt\",\n check: \"turbo run check\",\n ...BUILD_SCRIPTS,\n ...TEST_SCRIPTS,\n \"mark-stable\": \"turbo run mark-stable\",\n \"do-pack\": \"turbo run do-pack\",\n watch: \"turbo watch build\",\n changeset: \"changeset\",\n \"version-packages\": \"changeset version\",\n // Deprecated alias of `upgrade-sdk`; kept for compatibility.\n \"update-sdk\": \"block-tools structure refresh --update-deps-only\",\n \"upgrade-sdk\":\n \"block-tools structure refresh --update-deps-only && pnpm i && block-tools structure refresh && pnpm i && pnpm fmt\",\n },\n peerDependencies: {\n oxlint: \"*\",\n oxfmt: \"*\",\n },\n devDependencies: {\n \"@changesets/cli\": \"catalog:\",\n \"@milaboratories/ts-builder\": \"sdk:\",\n \"@platforma-sdk/block-tools\": \"sdk:\",\n shx: \"catalog:\",\n turbo: \"catalog:\",\n },\n packageManager: \"pnpm@9.12.0\",\n };\n}\n\nexport function rootPackageJsonRules(): void {\n ensureField(\"packageManager\", \"pnpm@9.12.0\");\n\n // Root is never published — it carries no `name`; delete any stray one.\n removeField(\"name\");\n\n // Canonical lifecycle script set. The live backend's env reaches the\n // integration tests via the turbo `test` task's passThroughEnv (no\n // --env-mode=loose needed).\n ensureScript(\"fmt\", \"turbo run fmt\");\n ensureScript(\"check\", \"turbo run check\");\n for (const [name, command] of Object.entries(BUILD_SCRIPTS)) {\n ensureScript(name, command);\n }\n for (const [name, command] of Object.entries(TEST_SCRIPTS)) {\n ensureScript(name, command);\n }\n // No bare `build` — a developer must pick a scenario (`build:dev-local`, `build:release`,\n // …). Drop the legacy plain `build` and the old single `build:dev` so migrated blocks converge.\n removeScript(\"build\");\n removeScript(\"build:dev\");\n ensureScript(\"mark-stable\", \"turbo run mark-stable\");\n ensureScript(\"do-pack\", \"turbo run do-pack\");\n ensureScript(\"watch\", \"turbo watch build\");\n ensureScript(\"changeset\", \"changeset\");\n ensureScript(\"version-packages\", \"changeset version\");\n // `update-sdk` is a deprecated alias of `upgrade-sdk`, kept for compatibility;\n // `update` is the pre-rename name — drop it so refreshed blocks converge.\n ensureScript(\"update-sdk\", \"block-tools structure refresh --update-deps-only\");\n removeScript(\"update\");\n // Full SDK-upgrade flow: bump catalog (deps-only) → install → re-apply\n // structure against the freshly-pulled deps → install AGAIN (the structural\n // pass can add new devDeps — e.g. ts-builder/oxlint/oxfmt on a first\n // migration — that `pnpm fmt` then needs on PATH) → format. Wrapped as one\n // script. `pnpm fmt` (turbo run fmt) leaves the tree oxfmt-clean after the\n // structural rewrite so a follow-up `pnpm check` passes.\n ensureScript(\n \"upgrade-sdk\",\n \"block-tools structure refresh --update-deps-only && pnpm i && block-tools structure refresh && pnpm i && pnpm fmt\",\n );\n\n ensureDevDeps({\n \"@changesets/cli\": \"catalog:\",\n \"@milaboratories/ts-builder\": \"sdk:\",\n \"@platforma-sdk/block-tools\": \"sdk:\",\n shx: \"catalog:\",\n turbo: \"catalog:\",\n });\n\n ensurePeerDeps({\n oxlint: \"*\",\n oxfmt: \"*\",\n });\n\n // Strip committed dev-machine override clutter: keys like \"//pnpm\",\n // \"///pnpm\", \"--\" carrying a pnpm/overrides sub-object (often absolute\n // local paths). Left in place these are unknown top-level keys that oxfmt\n // shoves past the canonical sections, breaking `oxfmt --check`.\n pruneKeysMatching((key, value): boolean => {\n if (!/^(\\/\\/|--)/.test(key)) return false;\n if (typeof value !== \"object\" || value === null) return false;\n const v = value as { pnpm?: unknown; overrides?: unknown };\n return v.pnpm !== undefined || v.overrides !== undefined;\n });\n\n enforceAlphabeticalOrder(\"dependencies\");\n enforceAlphabeticalOrder(\"devDependencies\");\n enforceAlphabeticalOrder(\"peerDependencies\");\n enforceAlphabeticalOrder(\"optionalDependencies\");\n enforceFieldOrder([...canonicalPackageJsonOrder]);\n}\n","// Root `turbo.json`: the initial generator and the drift-correcting body\n// rules, co-located. Managed (not fixed) so the engine OWNS its own task\n// graph but LEAVES author-added tasks alone — `ensureFieldEntries(\"tasks\", …)`\n// merges the canonical engine tasks over whatever is there, preserving any\n// other key under `tasks`.\n//\n// Why this matters: blocks with a Python software package carry a\n// `software:reqs` task (a `requirements-sync` CI job runs `turbo run\n// software:reqs`). When turbo.json was `fixed`, every `upgrade-sdk` wiped that\n// task and CI failed with \"Could not find task software:reqs\". `software:reqs`\n// is deliberately NOT in the engine-owned set below — it (and any custom task)\n// is author-owned and survives refresh via the merge.\n\nimport { ensureField, ensureFieldEntries, removeField, enforceFieldOrder } from \"../engine/api\";\n\nconst SCHEMA = \"https://turbo.build/schema.json\";\nconst GLOBAL_DEPENDENCIES = [\"tsconfig.json\"];\n\n// The tasks the engine owns. Re-asserted on every refresh; author tasks\n// (e.g. `software:reqs`) are merged around these, never clobbered.\nconst ENGINE_TASKS: Record<string, unknown> = {\n fmt: { cache: false },\n check: { dependsOn: [\"^build\"], outputs: [] },\n build: {\n dependsOn: [\"^build\", \"check\"],\n inputs: [\"$TURBO_DEFAULT$\"],\n env: [\n \"PL_DOCKER_REGISTRY_PUSH_TO\",\n \"PL_BUILD_CHANNEL\",\n \"PL_BUILD_VARIANT\",\n \"PL_BUILD_LOCATION\",\n \"PL_BUILD_USE_PUBLISHED\",\n \"PL_DEV_DOCKER_PUSH_URL\",\n \"PL_DEV_DOCKER_PULL_URL\",\n \"PL_DEV_BINARY_UPLOAD_URL\",\n \"PL_RELEASE_DOCKER_PUSH_URL\",\n \"PL_RELEASE_DOCKER_PULL_URL\",\n \"PL_RELEASE_BINARY_UPLOAD_URL\",\n \"PL_REGISTRY_PLATFORMA_OPEN_UPLOAD_URL\",\n ],\n passThroughEnv: [\"AWS_*\", \"PL_AWS_*\"],\n outputs: [\"./dist/**\", \"./block-pack/**\", \"./pkg-*.tgz\"],\n },\n \"do-pack\": { dependsOn: [\"build\"], outputs: [\"package.tgz\"] },\n test: {\n dependsOn: [\"build\", \"check\"],\n passThroughEnv: [\"PL_ADDRESS\", \"PL_TEST_PASSWORD\", \"PL_TEST_USER\", \"PL_TEST_PROXY\", \"DEBUG\"],\n },\n \"mark-stable\": { passThroughEnv: [\"PL_REGISTRY\", \"AWS_*\"], cache: false },\n};\n\nexport function rootTurboJsonInitial(): Record<string, unknown> {\n return {\n $schema: SCHEMA,\n globalDependencies: GLOBAL_DEPENDENCIES,\n tasks: { ...ENGINE_TASKS },\n };\n}\n\nexport function rootTurboJsonRules(): void {\n ensureField(\"$schema\", SCHEMA);\n ensureField(\"globalDependencies\", GLOBAL_DEPENDENCIES);\n // Merge the engine tasks, preserving any author task (software:reqs, …).\n ensureFieldEntries(\"tasks\", ENGINE_TASKS);\n // Legacy single-dev-build task, superseded by the env-parameterised `build`\n // task + `build:dev-*` package scripts (software-build spec). The\n // root package.json rule likewise drops the `build:dev` script; drop the\n // matching turbo task so migrated blocks converge.\n removeField(\"tasks.build:dev\");\n enforceFieldOrder([\"$schema\", \"globalDependencies\", \"tasks\"]);\n}\n","// npm registry client used by the catalog ensure-family (`ensureCatalogLatest`).\n//\n// The content-rule builder is synchronous; the runner pre-resolves\n// \"latest\" versions via this client and passes a sync lookup function\n// to `withManagedYaml(..., { getLatestVersion })`. The real impl talks\n// to https://registry.npmjs.org with retry + Retry-After handling\n// ported from `tools/blocks-deps-updater/src/updater.ts`. The mock\n// impl wraps an in-memory map and is the only client used in unit\n// tests.\n\nimport { setTimeout as sleep } from \"node:timers/promises\";\n\nexport interface RegistryClient {\n getLatestVersion(packageName: string): Promise<string>;\n /** Read the version `packageName@version` declares for `depName` in its\n * published manifest. `version` may be \"latest\" (resolved via the\n * dist-tags). Looks in `dependencies` first, then `peerDependencies`.\n * Returns `undefined` when the dep is declared in neither section. */\n getDeclaredDependency(\n packageName: string,\n version: string,\n depName: string,\n ): Promise<string | undefined>;\n}\n\nconst RETRY_COUNT = 2;\nconst RETRY_BASE_MS = 500;\nconst TIMEOUT_MS = 30_000;\n\n/** Parse the HTTP Retry-After header (RFC 9110): either a delay in\n * seconds or an absolute HTTP-date. Returns the delay in ms, or null\n * if the header is missing / unparseable. */\nexport function parseRetryAfter(header: string | null): number | null {\n if (!header) return null;\n const seconds = Number(header);\n if (Number.isFinite(seconds) && seconds > 0) return seconds * 1000;\n const date = Date.parse(header);\n if (!Number.isNaN(date)) return Math.max(0, date - Date.now());\n return null;\n}\n\nasync function fetchWithRetry(url: string): Promise<Response> {\n for (let attempt = 1; ; attempt++) {\n let res: Response;\n // Only the network call is retry-eligible: a transport error\n // (timeout, DNS, reset) is transient. HTTP-status handling sits\n // OUTSIDE this catch so a non-retryable status (404/403) throws\n // immediately instead of being swallowed and retried.\n try {\n res = await fetch(url, { signal: AbortSignal.timeout(TIMEOUT_MS) });\n } catch (err) {\n if (attempt > RETRY_COUNT) throw err;\n const delay = RETRY_BASE_MS * 2 ** (attempt - 1) * (0.8 + 0.4 * Math.random());\n await sleep(delay);\n continue;\n }\n if (res.ok) return res;\n const retryable = res.status === 429 || res.status >= 500;\n if (!retryable || attempt > RETRY_COUNT) {\n throw new Error(`registry returned HTTP ${res.status}`);\n }\n const retryAfterMs = parseRetryAfter(res.headers.get(\"retry-after\"));\n if (retryAfterMs != null) {\n await sleep(retryAfterMs);\n continue;\n }\n const delay = RETRY_BASE_MS * 2 ** (attempt - 1) * (0.8 + 0.4 * Math.random());\n await sleep(delay);\n }\n}\n\n/** Shape of the per-version manifest doc fetched from\n * `https://registry.npmjs.org/<pkg>/<version>` (only the dep sections are\n * read). */\ntype PackageManifest = {\n dependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n};\n\n/** Live npm registry client. Hits the network on each call. */\nexport function createRealRegistryClient(): RegistryClient {\n return {\n async getLatestVersion(packageName: string): Promise<string> {\n const res = await fetchWithRetry(\n `https://registry.npmjs.org/-/package/${packageName}/dist-tags`,\n );\n const tags = (await res.json()) as Record<string, string>;\n const latest = tags.latest;\n if (!latest) {\n throw new Error(\"no 'latest' dist-tag in registry response\");\n }\n return latest;\n },\n async getDeclaredDependency(\n packageName: string,\n version: string,\n depName: string,\n ): Promise<string | undefined> {\n const res = await fetchWithRetry(`https://registry.npmjs.org/${packageName}/${version}`);\n const manifest = (await res.json()) as PackageManifest;\n return manifest.dependencies?.[depName] ?? manifest.peerDependencies?.[depName];\n },\n };\n}\n\n/** In-memory client backed by a fixed `name → version` map. The optional\n * `manifests` map (`pkg@version` → declared deps) backs\n * `getDeclaredDependency`; \"latest\" keys resolve via the `versions` map. */\nexport function createMockRegistryClient(\n versions: Record<string, string>,\n manifests: Record<string, Record<string, string>> = {},\n): RegistryClient {\n function resolveVersion(packageName: string, version: string): string {\n if (version !== \"latest\") return version;\n const v = versions[packageName];\n if (v === undefined) {\n throw new Error(`mock registry: no version configured for '${packageName}'`);\n }\n return v;\n }\n return {\n async getLatestVersion(packageName: string): Promise<string> {\n const v = versions[packageName];\n if (v === undefined) {\n throw new Error(`mock registry: no version configured for '${packageName}'`);\n }\n return v;\n },\n async getDeclaredDependency(\n packageName: string,\n version: string,\n depName: string,\n ): Promise<string | undefined> {\n const resolved = resolveVersion(packageName, version);\n const deps = manifests[`${packageName}@${resolved}`];\n if (deps === undefined) {\n throw new Error(`mock registry: no manifest configured for '${packageName}@${resolved}'`);\n }\n return deps[depName];\n },\n };\n}\n\n/** Resolve a batch of `name → latest` entries in parallel. */\nexport async function prefetchLatestVersions(\n client: RegistryClient,\n packageNames: readonly string[],\n): Promise<Map<string, string>> {\n const entries = await Promise.all(\n packageNames.map(async (n) => [n, await client.getLatestVersion(n)] as const),\n );\n return new Map(entries);\n}\n\n/** Build a sync lookup function (the shape `withManagedYaml` consumes)\n * from a prefetched map. Returns undefined for unknown names. */\nexport function makeSyncLookup(\n resolved: Map<string, string>,\n): (packageName: string) => string | undefined {\n return (name) => resolved.get(name);\n}\n\n/** Catalog package-name patterns the version-resolution rules\n * (`ensureCatalogLatest`) match against — the `@platforma-sdk/*` and\n * `@milaboratories/*` SDK families. Infra/runtime entries (turbo, shx,\n * …) are deliberately NOT here: they stay a curated floor, not auto-latest.\n * Shared so `init` (names from the SDK pin map) and `refresh\n * --update-deps-only` (names from the on-disk catalog) select the same\n * set. */\nexport const CATALOG_BUMP_PATTERNS: readonly RegExp[] = [/^@platforma-sdk\\//, /^@milaboratories\\//];\n\n/** True if `name` is a version-resolved SDK package (matches any bump\n * pattern). */\nexport function matchesBumpPattern(name: string): boolean {\n return CATALOG_BUMP_PATTERNS.some((p) => p.test(name));\n}\n\n/** Prefetch npm \"latest\" for `names` and return the sync lookup the\n * runner passes to the catalog ensure-family (`ensureCatalogLatest`).\n * Empty list → a lookup that\n * resolves nothing (no network). A network/registry failure REJECTS\n * (callers that require the network — `init` — let it propagate).\n * `client` defaults to the live npm client; tests inject a mock. */\nexport async function buildRegistryLookupForNames(\n names: readonly string[],\n client: RegistryClient = createRealRegistryClient(),\n): Promise<(packageName: string) => string | undefined> {\n if (names.length === 0) return () => undefined;\n const resolved = await prefetchLatestVersions(client, names);\n return makeSyncLookup(resolved);\n}\n\n/** A catalog entry whose version is DERIVED from the version another\n * package declares for it. `entry` is the catalog key (== the dep name in\n * the source manifest); `of` is the package whose manifest is read; the\n * optional `ofVersion` pins which release of `of` to read (default: npm\n * latest, the same release the catalog bump pins `of` to). Consumed by\n * `pinCatalogToDependencyOf`. */\nexport type DerivedCatalogPin = {\n entry: string;\n of: string;\n ofVersion?: string;\n};\n\n/** True iff `version` is a bare exact `x.y.z(-prerelease)?` — no range\n * modifier (`^`, `~`, `>=`, `*`, `||`, ` - `, `x`, workspace:, etc.). */\nfunction isExactVersion(version: string): boolean {\n return /^\\d+\\.\\d+\\.\\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(version);\n}\n\n/** Prefetch every derived pin and build the sync lookup the runner passes\n * to `pinCatalogToDependencyOf` (`entry → exact version`). Reads\n * `pin.of`'s manifest (at `pin.ofVersion`, default npm latest) and the\n * version it declares for `pin.entry`. Policy (b): THROWS at prefetch time\n * if the source declares the dep as a non-exact (ranged) version or does\n * not declare it at all — a derived pin must resolve to an exact version\n * or it is a configuration error. Empty list → a lookup that resolves\n * nothing (no network). A registry failure REJECTS. `client` defaults to\n * the live npm client; tests inject a mock. */\nexport async function buildDerivedPinLookupForPins(\n pins: readonly DerivedCatalogPin[],\n client: RegistryClient = createRealRegistryClient(),\n): Promise<(entry: string) => string | undefined> {\n if (pins.length === 0) return () => undefined;\n const entries = await Promise.all(\n pins.map(async (pin) => {\n const declared = await client.getDeclaredDependency(\n pin.of,\n pin.ofVersion ?? \"latest\",\n pin.entry,\n );\n if (declared === undefined) {\n throw new Error(\n `derived catalog pin '${pin.entry}': package '${pin.of}'` +\n `${pin.ofVersion ? `@${pin.ofVersion}` : \" (latest)\"} declares no ` +\n `dependency '${pin.entry}'. A derived pin requires the source to ` +\n `declare the dep as an exact version.`,\n );\n }\n if (!isExactVersion(declared)) {\n throw new Error(\n `derived catalog pin '${pin.entry}': package '${pin.of}'` +\n `${pin.ofVersion ? `@${pin.ofVersion}` : \" (latest)\"} declares ` +\n `'${pin.entry}: ${declared}', which is not an exact version. ` +\n `A derived pin requires an exact ('x.y.z') source dependency so ` +\n `the catalog can pin to it precisely.`,\n );\n }\n return [pin.entry, declared] as const;\n }),\n );\n const resolved = new Map(entries);\n return (entry) => resolved.get(entry);\n}\n","// Retired toolchain dependencies — a SINGLE source of truth.\n//\n// These packages are superseded by the canonical toolchain (ts-builder owns\n// the build, vue-tsc, and the vite plugins; oxlint/oxfmt replace eslint) and\n// must be shed from a migrated block in BOTH places at once:\n// - the root catalog → `ensureCatalogAbsent` (root-pnpm-workspace)\n// - every package.json scope → `removeDep` (via removeRetiredToolchainDeps)\n//\n// Removing from only one side is a latent bug: a catalog entry dropped while a\n// package still references `<dep>: \"catalog:\"` leaves a dangling reference that\n// breaks `pnpm install`. Driving both from this one list makes that impossible\n// — add (or un-retire) a dependency HERE, once.\n//\n// Per-entry rationale:\n// vite / tsup — bundling now goes through ts-builder + rolldown.\n// vue-tsc — ts-builder runs vue-tsc internally for `block-ui`; a\n// direct dep resolves a different version than the\n// toolchain pins, causing type clashes in main.ts.\n// @vitejs/plugin-vue — bundled by ts-builder's internal vite config.\n// vite-plugin-dts — .d.ts emit is handled by ts-builder.\n// @platforma-sdk/eslint-config — eslint is retired; linting runs via oxlint\n// inside `ts-builder check`.\n\nimport { removeDep } from \"../../engine/api\";\n\nexport const RETIRED_TOOLCHAIN_DEPS: readonly string[] = [\n \"vite\",\n \"tsup\",\n \"vue-tsc\",\n \"@vitejs/plugin-vue\",\n \"vite-plugin-dts\",\n \"@platforma-sdk/eslint-config\",\n];\n\n/** Drop every retired toolchain dep from the current package.json scope.\n * Idempotent (a `removeDep` on an absent key is a no-op), so it is safe to\n * call uniformly from every package.json rules body regardless of which deps\n * a given scope ever carried. Pairs with the catalog-side removal in\n * `rootPnpmWorkspaceRules`. */\nexport function removeRetiredToolchainDeps(): void {\n for (const name of RETIRED_TOOLCHAIN_DEPS) removeDep(name);\n}\n","// Root `pnpm-workspace.yaml`: the catalog membership, the initial generator,\n// and the drift-correcting body rules, co-located.\n//\n// The catalog is split in two:\n// - SDK packages: `SDK_CATALOG_PACKAGES` is a list of package NAMES (catalog\n// membership only — no versions). On init the `onInitOrUpdate` frame fetches\n// npm latest for each (init requires network) and writes it; the keys must\n// exist in the catalog first for that in-place bump to land, so the initial\n// generator seeds them with an obviously-invalid placeholder that the bump\n// always overwrites. No version is stored here and there is no fallback.\n// - infra / tooling: a `~`-floored set we control deliberately. No rule\n// ever fetches these — refresh leaves them untouched and update-deps\n// does not match them. Bump the floor here when authoring the scaffold.\n//\n// Default refresh is purely structural: it verifies the workspace\n// `packages:` list matches the discovered modules and leaves every catalog\n// version exactly as the author/lockfile has it. Version resolution (writing\n// npm-latest for the SDK families) lives in the separate `onInitOrUpdate`\n// frame (`rootCatalogBumpRules`), which fires on init + update-deps only.\n\nimport { ensureWorkspaceModulePaths, ensureCatalogAbsent, type RunContext } from \"../engine/api\";\nimport { matchesBumpPattern, type DerivedCatalogPin } from \"../engine/registry-client\";\nimport { RETIRED_TOOLCHAIN_DEPS } from \"./shared/retired-deps\";\n\n/** SDK packages that live in the catalog (membership only — no versions).\n * Init fetches npm latest for each; refresh leaves them as the lockfile has\n * them. */\nexport const SDK_CATALOG_PACKAGES: readonly string[] = [\n \"@platforma-sdk/model\",\n \"@platforma-sdk/ui-vue\",\n \"@platforma-sdk/workflow-tengo\",\n \"@platforma-sdk/test\",\n \"@platforma-sdk/block-tools\",\n \"@platforma-sdk/tengo-builder\",\n \"@platforma-sdk/package-builder\",\n \"@milaboratories/ts-builder\",\n \"@milaboratories/ts-configs\",\n];\n\n/** Init-only catalog seed for every SDK package: an obviously-invalid version\n * the `onInitOrUpdate` bump always overwrites with npm latest. It exists only\n * so the catalog key is present for that in-place bump. It is never a\n * fallback — a real init requires network and overwrites it; were it ever to\n * reach a lockfile, `pnpm install` fails loudly on the unresolvable version. */\nconst SDK_CATALOG_INIT_PLACEHOLDER = \"0.0.0-init-must-fetch\";\n\n// Invariant: every SDK package must be fetched on init (match a bump pattern),\n// or its placeholder would ship un-resolved. Caught at load time.\nfor (const name of SDK_CATALOG_PACKAGES) {\n if (!matchesBumpPattern(name)) {\n throw new Error(\n `SDK_CATALOG_PACKAGES entry '${name}' matches no catalog bump pattern; ` +\n `its placeholder would never be resolved to npm latest on init. ` +\n `Add it to CATALOG_BUMP_PATTERNS or move it to the infra floor.`,\n );\n }\n}\n\n/** Infra / tooling — a `~`-floored curated set. Not exact-pinned on refresh\n * and not bumped by update-deps. */\nexport const INFRA_CATALOG_FLOOR: Record<string, string> = {\n turbo: \"~2.8.11\",\n shx: \"~0.4.0\",\n \"@changesets/cli\": \"~2.29.8\",\n vitest: \"~4.0.18\",\n};\n\n/** Catalog entries whose exact version is DERIVED from the version another\n * package declares for them (see `pinCatalogToDependencyOf`). Resolved on\n * init + update-deps and OVERWRITES the on-disk entry.\n *\n * `vue`: the seeded ui depends on `vue` (catalog:). `@platforma-sdk/ui-vue`\n * pins vue as an EXACT regular dependency (not a peer), so the block must\n * pin the SAME exact version — a floated `~` lets the ui resolve a newer\n * 3.5.x than ui-vue's, yielding two vue instances and a SdkPluginV3-vs-Plugin\n * type clash in `main.ts`. Deriving the pin from ui-vue's declared dep keeps\n * the block in lockstep with whatever vue ui-vue's npm-latest pins, with no\n * hand-maintained version here.\n *\n * `@milaboratories/helpers`: the block's model/ui depend on it (catalog:) and\n * `@platforma-sdk/model` pins it as an EXACT regular dependency. A hand-pinned\n * floor that lags a model bump yields two helpers instances — the model's\n * inferred `platforma` type then references the SDK's copy, not the block's,\n * failing `tsc` with TS2742. Deriving from model keeps them in lockstep. */\nexport const DERIVED_CATALOG_PINS: readonly DerivedCatalogPin[] = [\n { entry: \"vue\", of: \"@platforma-sdk/ui-vue\" },\n { entry: \"@milaboratories/helpers\", of: \"@platforma-sdk/model\" },\n];\n\n/** Catalog name of the python runenv. Added to a block's catalog only when\n * the block carries a software module. Pinned to an EXACT version — updating\n * the python runenv is an explicit author decision, never automatic. */\nexport const RUNENV_PYTHON = \"@platforma-open/milaboratories.runenv-python-3\";\nexport const RUNENV_PYTHON_VERSION = \"1.8.2\";\n\nexport function rootPnpmWorkspaceInitial(ctx: RunContext): Record<string, unknown> {\n // Non-root module paths only. The block root (\"\") is discovered\n // implicitly and must never be written as a \".\" entry — listing it breaks\n // turbo's task graph. Root stays in ctx.modules for rule fan-out.\n const paths = ctx.modules\n .filter((m) => m.path !== \"\")\n .map((m) => m.path)\n .sort();\n // SDK packages first (placeholder, overwritten by the init bump), then the\n // infra floor — matching the order the catalog is written.\n const catalog: Record<string, string> = {};\n for (const name of SDK_CATALOG_PACKAGES) catalog[name] = SDK_CATALOG_INIT_PLACEHOLDER;\n Object.assign(catalog, INFRA_CATALOG_FLOOR);\n if (ctx.modules.some((m) => m.scope === \"software\")) {\n catalog[RUNENV_PYTHON] = RUNENV_PYTHON_VERSION;\n }\n return {\n packages: paths,\n catalog,\n };\n}\n\nexport function rootPnpmWorkspaceRules(): void {\n ensureWorkspaceModulePaths();\n // Catalog side of the retired-dep cleanup — the per-package side sheds the\n // matching `catalog:` references.\n for (const name of RETIRED_TOOLCHAIN_DEPS) ensureCatalogAbsent(name);\n}\n","// Root `.gitignore` content rules.\n// The static template under templates/static/root/.gitignore carries the\n// canonical line set; the body re-asserts the same set via\n// `ensureGitignoreEntries` so any future edit that drops a required line\n// is restored.\n\nimport { ensureGitignoreEntries } from \"../engine/api\";\n\nexport const GITIGNORE_REQUIRED_LINES = [\n \".test_auth.json\",\n \"node_modules/\",\n \"dist/\",\n \"block-pack/\",\n \"dev/\",\n \"work/\",\n \"log/\",\n \".turbo\",\n \"vite.config.*.timestamp-*\",\n \"software/**/*.tgz\",\n \".DS_Store\",\n \".vscode/sftp.json\",\n \"test-dry-run.json\",\n];\n\nexport function rootGitignoreRules(): void {\n ensureGitignoreEntries(GITIGNORE_REQUIRED_LINES);\n}\n","// Root-scope rules — apply only to the standalone block layout (the\n// pnpm workspace + tooling around the block). `--sdk-internal` blocks\n// skip this whole scope: the parent monorepo owns root files. Hence the\n// `when(({ ctx }) => !ctx.isSdkInternal, ...)` wrapper.\n\nimport { scope, when, fixed, managed, file, generate } from \"../engine/api\";\nimport { rootPackageJsonInitial, rootPackageJsonRules } from \"./root-package-json\";\nimport { rootTurboJsonInitial, rootTurboJsonRules } from \"./root-turbo-json\";\nimport { rootPnpmWorkspaceInitial, rootPnpmWorkspaceRules } from \"./root-pnpm-workspace\";\nimport { rootGitignoreRules } from \"./root-gitignore\";\n\nexport function rootRules(): void {\n scope(\"root\", () => {\n when(\n ({ ctx }) => !ctx.isSdkInternal,\n () => {\n managed(\n \"turbo.json\",\n generate(() => rootTurboJsonInitial()),\n () => {\n rootTurboJsonRules();\n },\n );\n fixed(\".vscode/settings.json\", file(\"root/.vscode/settings.json\"));\n\n managed(\n \"package.json\",\n generate(() => rootPackageJsonInitial()),\n () => {\n rootPackageJsonRules();\n },\n );\n\n managed(\n \"pnpm-workspace.yaml\",\n generate((ctx) => rootPnpmWorkspaceInitial(ctx)),\n () => {\n rootPnpmWorkspaceRules();\n },\n );\n\n managed(\".gitignore\", file(\"root/.gitignore\"), () => {\n rootGitignoreRules();\n });\n },\n );\n });\n}\n","// Root-scope CI workflows — the block's GitHub Actions `build.yaml` and\n// `mark-stable.yaml`. Engine-OWNED (`fixed`): rewritten verbatim on every\n// refresh, generated from the block's identity (short name); everything else\n// is a constant baked into the templates.\n//\n// Why fixed, not managed: previously each block carried a hand-copied\n// workflow pinning the shared reusable workflow at `@v4` (a moving branch),\n// so a breaking shared-CI change was absorbed silently and per-block edits\n// drifted. Engine-owning the file makes the pin + job wiring centrally\n// refreshable; the only per-block bits are derived (app-name, slug), so\n// nothing author-tunable is clobbered.\n//\n// Standalone blocks only — `--sdk-internal` blocks (`etc/blocks/*`) carry no\n// per-block workflow (the monorepo owns their CI), hence the\n// `when(!isSdkInternal)` guard, matching the rest of the root scope.\n\nimport { scope, when, fixed, tpl } from \"../engine/api\";\n\n/** Readable default CI label from a short name (`mixcr-clonotyping-2` →\n * `Mixcr Clonotyping 2`). Dash/underscore words, title-cased. Human-curated\n * casing (e.g. `MiXCR`) is not recoverable from the slug — this is a\n * generated label, not the marketing name. */\nfunction humanizeShortName(shortName: string): string {\n return shortName\n .split(/[-_]+/)\n .filter((w) => w.length > 0)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(\" \");\n}\n\nexport function rootCiRules(): void {\n scope(\"root\", () => {\n when(\n ({ ctx }) => !ctx.isSdkInternal,\n () => {\n fixed(\n \".github/workflows/build.yaml\",\n tpl(\"workflows/build.tpl.yaml\", (ctx) => {\n const shortName = ctx.blockVars.shortName;\n return {\n appName: `Block: ${humanizeShortName(shortName)}`,\n appNameSlug: `block-${shortName}`,\n };\n }),\n );\n fixed(\n \".github/workflows/mark-stable.yaml\",\n tpl(\"workflows/mark-stable.tpl.yaml\", (ctx) => ({\n appName: `Block: ${humanizeShortName(ctx.blockVars.shortName)} - Mark Stable`,\n })),\n );\n },\n );\n });\n}\n","// Facade `package.json`: the initial generator and the drift-correcting body\n// rules, co-located. The facade is the only sibling of a block that publishes,\n// and it ships SLIM: `dependencies` is empty (the consumer's install pulls zero\n// `@platforma-sdk/*` transitive runtime deps), siblings are build-time\n// `workspace:*` devDeps, and the built `dist/` + `block-pack/` carry everything\n// the loader needs.\n\nimport {\n ensureField,\n ensureScript,\n ensureDevDep,\n ensureWorkspaceScopeDevDeps,\n requireField,\n removeScript,\n enforceAlphabeticalOrder,\n enforceFieldOrder,\n type RunContext,\n} from \"../engine/api\";\nimport { findModules, scopeDepMaps } from \"../engine/ctx\";\nimport { canonicalPackageJsonOrder } from \"./shared/key-order\";\n\n/** Per-org publish coordinates: the S3 upload bucket and the public registry\n * serve URL the facade's `prepublishOnly` script passes to `block-tools\n * publish`. One block-registry bucket serves both orgs; only the public read\n * hostname differs by org. Safe for the never-published `etc/blocks` test\n * blocks — the script never runs for them. Extend the map per new org. */\nconst ORG_PUBLISH_TARGETS: Record<string, { s3: string; serveUrl: string }> = {\n \"@platforma-open\": {\n s3: \"s3://milab-euce1-prod-pkgs-s3-block-registry/pub/releases/?region=eu-central-1\",\n serveUrl: \"https://blocks.pl-open.science\",\n },\n \"@milaboratories\": {\n s3: \"s3://milab-euce1-prod-pkgs-s3-block-registry/pub/releases/?region=eu-central-1\",\n serveUrl: \"https://block.registry.platforma.bio/releases\",\n },\n};\n\n/** Fallback for an org not in the table — keeps the generated script valid\n * (and inert until published) rather than throwing during a refresh. */\nconst FALLBACK_PUBLISH_TARGET = {\n s3: \"s3://milab-euce1-prod-pkgs-s3-block-registry/pub/releases/?region=eu-central-1\",\n serveUrl: \"https://blocks.pl-open.science\",\n};\n\n/** Where the in-SDK blocks (`etc/blocks/*`) publish: the aux/dev registry, not\n * production `pub/releases/`. These are the monorepo's test/example blocks, so\n * one target regardless of org — their `@milaboratories` scope must NOT route\n * them to the real catalog alongside standalone blocks. */\nconst SDK_INTERNAL_PUBLISH_TARGET = {\n s3: \"s3://milab-euce1-prod-pkgs-s3-block-registry/aux/dev/?region=eu-central-1\",\n serveUrl: \"https://aux-blocks.pl-open.science\",\n};\n\nfunction prepublishScript(npmOrg: string, isSdkInternal: boolean): string {\n const t = isSdkInternal\n ? SDK_INTERNAL_PUBLISH_TARGET\n : (ORG_PUBLISH_TARGETS[npmOrg] ?? FALLBACK_PUBLISH_TARGET);\n return `block-tools publish -r ${t.s3} --registry-serve-url ${t.serveUrl}`;\n}\n\n/** The facade's `block.components` map: the dist artifact each module build\n * emits, keyed by role. Fully determined by the discovered modules — the body\n * rule re-asserts this exact value, so it is engine-managed (NOT an author\n * seed). Mirrors the artifact paths produced by each scope's build:\n * workflow → pl-tengo, model → build-model, ui → ts-builder. */\nexport function blockComponents(ctx: RunContext): Record<string, string> {\n const components: Record<string, string> = {};\n for (const m of findModules(ctx, \"workflow\"))\n components.workflow = `${m.name}/dist/tengo/tpl/main.plj.gz`;\n for (const m of findModules(ctx, \"model\")) components.model = `${m.name}/dist/model.json`;\n for (const m of findModules(ctx, \"ui\")) components.ui = `${m.name}/dist`;\n return components;\n}\n\n/** The slim facade's canonical scripts (build / check / prepublishOnly /\n * do-pack). Shared by the initial generator and the body rule so they cannot\n * drift apart. `prepublishOnly` routes by block kind: in-SDK blocks publish to\n * the aux/dev registry, standalone blocks to their per-org production target. */\nfunction blockScripts(npmOrg: string, isSdkInternal: boolean): Record<string, string> {\n return {\n build: \"ts-builder build --target block-facade && block-tools pack\",\n check: \"ts-builder type-check --target block-facade\",\n prepublishOnly: prepublishScript(npmOrg, isSdkInternal),\n \"do-pack\": \"shx rm -f package.tgz && pnpm pack && shx mv *.tgz package.tgz\",\n };\n}\n\n/** The facade's build/publish devDependencies (the workspace `model`/`ui`/\n * `workflow` siblings are added separately, from discovery). `sdk:` resolves\n * to `workspace:*` for in-monorepo blocks and `catalog:` for standalone — the\n * body rule re-asserts the same set. */\nconst FACADE_DEV_DEPS = {\n \"@milaboratories/ts-builder\": \"sdk:\",\n \"@milaboratories/ts-configs\": \"sdk:\",\n \"@platforma-sdk/block-tools\": \"sdk:\",\n \"@platforma-sdk/model\": \"sdk:\",\n shx: \"catalog:\",\n typescript: \"catalog:\",\n} as const;\n\n/** The facade's `exports` map: a single `.` entry. `sources` keeps monorepo IDE\n * go-to-definition pointing at `src/` (external consumers don't enable it);\n * `types`/`default` carry the bundled `.d.ts` / `.js` from `dist/`. No\n * `./AGENTS` subpath — that surface ships as a registry-side component. */\nconst FACADE_EXPORTS = {\n \".\": {\n sources: \"./src/index.ts\",\n types: \"./dist/index.d.ts\",\n default: \"./dist/index.js\",\n },\n};\n\n/** Fail loudly if any required `block.*` field is empty — a missing\n * title / description / logo / organization or empty components map would\n * otherwise produce an init block that `block-tools pack` rejects only\n * later. Asserted at generation time so the failure is immediate. */\nfunction assertBlockFieldsFilled(block: {\n components: Record<string, string>;\n meta: Record<string, unknown>;\n}): void {\n if (Object.keys(block.components).length === 0) {\n throw new Error(\"block.components is empty — no workflow/model/ui module was discovered\");\n }\n const meta = block.meta as {\n title?: unknown;\n description?: unknown;\n logo?: unknown;\n organization?: { name?: unknown; url?: unknown; logo?: unknown };\n };\n const required: [string, unknown][] = [\n [\"block.meta.title\", meta.title],\n [\"block.meta.description\", meta.description],\n [\"block.meta.logo\", meta.logo],\n [\"block.meta.organization.name\", meta.organization?.name],\n [\"block.meta.organization.url\", meta.organization?.url],\n [\"block.meta.organization.logo\", meta.organization?.logo],\n ];\n for (const [path, value] of required) {\n if (typeof value !== \"string\" || value === \"\") {\n throw new Error(`required block field '${path}' is empty`);\n }\n }\n}\n\nexport function blockPackageJsonInitial(ctx: RunContext): Record<string, unknown> {\n const v = ctx.blockVars;\n // The facade's siblings are build-time devDeps, never runtime deps — the\n // facade ships its content bundled inside dist/ + block-pack/, so the\n // consumer needs no runtime resolution into siblings. Software/test are\n // excluded (the workflow owns software; a test→facade dep would be a cycle).\n const devDeps: Record<string, string> = {\n ...FACADE_DEV_DEPS,\n ...scopeDepMaps(ctx, \"model\"),\n ...scopeDepMaps(ctx, \"ui\"),\n ...scopeDepMaps(ctx, \"workflow\"),\n // The kind is a fourth block component the facade depends on directly (the\n // tetrad); like its siblings it is a build-time workspace devDep, never a\n // runtime dependency, and it is NOT a bundled `block.component` (its content\n // publishes to the `kinds/` registry tree, not into block-pack).\n ...scopeDepMaps(ctx, \"kind\"),\n };\n // `block-tools pack` requires both `block.components` and `block.meta`. The\n // author edits the placeholder meta before publishing.\n const block = {\n components: blockComponents(ctx),\n meta: {\n title: v.shortName,\n description: `${v.shortName} block`,\n logo: \"file:logos/block-logo.png\",\n organization: {\n name: v.orgScope,\n url: \"https://example.com\",\n logo: \"file:logos/organization-logo.png\",\n },\n },\n };\n assertBlockFieldsFilled(block);\n return {\n name: `${v.facadeName}.block`,\n version: \"1.0.0\",\n // Facade is ESM: rolldown-plugin-dts requires it, and the BlockPointer's\n // `import.meta.url` path math needs it.\n type: \"module\",\n // Drives the npm tarball: only the built outputs ship; sources, tsconfig,\n // and node_modules stay out.\n files: [\"dist\", \"block-pack\"],\n main: \"./dist/index.js\",\n module: \"./dist/index.js\",\n types: \"./dist/index.d.ts\",\n exports: FACADE_EXPORTS,\n scripts: blockScripts(v.npmOrg, ctx.isSdkInternal),\n // Slim invariant: zero runtime deps reach the consumer.\n dependencies: {},\n devDependencies: devDeps,\n block,\n };\n}\n\nexport function blockPackageJsonRules(ctx: RunContext): void {\n const v = ctx.blockVars;\n\n // The kind is a MANDATORY block component: every block must declare exactly\n // one sibling `kind/` package. Fail loudly otherwise — a kind-less block is\n // invalid, and this is what surfaces the not-yet-migrated blocks.\n const kindModules = findModules(ctx, \"kind\");\n if (kindModules.length !== 1) {\n throw new Error(\n kindModules.length === 0\n ? `block '${v.facadeName}' declares no kind — every block must have a sibling kind/ package`\n : `block '${v.facadeName}' declares ${kindModules.length} kinds; exactly one is required`,\n );\n }\n\n ensureField(\"type\", \"module\");\n ensureField(\"files\", [\"dist\", \"block-pack\"]);\n ensureField(\"main\", \"./dist/index.js\");\n ensureField(\"module\", \"./dist/index.js\");\n ensureField(\"types\", \"./dist/index.d.ts\");\n ensureField(\"exports\", FACADE_EXPORTS);\n\n const scripts = blockScripts(v.npmOrg, ctx.isSdkInternal);\n for (const [name, command] of Object.entries(scripts)) ensureScript(name, command);\n removeScript(\"mark-stable\");\n\n // Slim invariant: the facade carries ZERO runtime dependencies. The siblings\n // and the SDK build/publish deps are all devDeps, so `dependencies` ends\n // empty. Software/test are excluded (the workflow owns software; a\n // test→facade dep would be a cycle).\n ensureWorkspaceScopeDevDeps(\"model\");\n ensureWorkspaceScopeDevDeps(\"ui\");\n ensureWorkspaceScopeDevDeps(\"workflow\");\n ensureWorkspaceScopeDevDeps(\"kind\");\n ensureDevDep(\"@milaboratories/ts-builder\", \"sdk:\");\n ensureDevDep(\"@milaboratories/ts-configs\", \"sdk:\");\n ensureDevDep(\"@platforma-sdk/block-tools\", \"sdk:\");\n ensureDevDep(\"@platforma-sdk/model\", \"sdk:\");\n ensureDevDep(\"shx\", \"catalog:\");\n ensureDevDep(\"typescript\", \"catalog:\");\n\n // `block.components` is fully determined by the discovered modules — keep it\n // in sync on refresh. `block.meta` is deliberately NOT touched: it is an\n // author-owned seed (set once in the init package.json), so refresh must\n // never overwrite the author's title / description / logo.\n ensureField(\"block.components\", blockComponents(ctx));\n\n // The author owns `name` and `version`; `version` MUST be present (the\n // facade publishes).\n requireField(\"version\", \"facade package.json must carry a 'version' (the facade publishes)\");\n\n enforceAlphabeticalOrder(\"dependencies\");\n enforceAlphabeticalOrder(\"devDependencies\");\n enforceAlphabeticalOrder(\"peerDependencies\");\n enforceAlphabeticalOrder(\"optionalDependencies\");\n enforceFieldOrder([...canonicalPackageJsonOrder]);\n}\n","// `pascalCase(shortName)` → the block-named alias prefix the facade entry\n// template emits (`<PascalName>BlockContract`, …). Splits on any run of\n// non-alphanumeric characters and capitalises each segment's first char:\n// test-sum-numbers → TestSumNumbersV3\n// mixcr-clonotyping-2 → MixcrClonotyping2\n// samples-and-data → SamplesAndData\nexport function pascalCase(s: string): string {\n const joined = s\n .split(/[^A-Za-z0-9]+/)\n .filter((seg) => seg.length > 0)\n .map((seg) => seg.charAt(0).toUpperCase() + seg.slice(1))\n .join(\"\");\n // A leading digit (e.g. `3d-viewer` → `3dViewer`) is not a valid identifier\n // start — the prefix becomes `const 3dViewerBlockPointer = …`. Prepend `_`.\n return /^[0-9]/.test(joined) ? `_${joined}` : joined;\n}\n","// Block-scope rules — the facade package at `block/`. The facade is the\n// only sibling of a block that publishes: a slim 4-file `src/` surface\n// (engine-owned `index.ts` + `AGENTS.ts`, author-owned `block-extra.ts` +\n// `agents-extra.ts`), a facade `tsconfig.json`, and a slim publishable\n// `package.json`. Workspace-scope deps in the body resolve from ctx.modules.\n\nimport {\n scope,\n fixed,\n scaffold,\n managed,\n seed,\n remove,\n file,\n tpl,\n binaryFile,\n generate,\n} from \"../engine/api\";\nimport { blockPackageJsonInitial, blockPackageJsonRules } from \"./block-package-json\";\nimport { pascalCase } from \"./shared/pascal-case\";\n\nexport function blockRules(): void {\n scope(\"block\", () => {\n // `remove` is idempotent (absent file → no-op), so this is safe on a block\n // that has no such entry files.\n remove(\"index.js\");\n remove(\"index.d.ts\");\n\n // Four-file source surface. `index.ts` is engine-owned and per-block\n // (model import path + `<PascalName>` aliases) → text-templated. `AGENTS.ts`\n // is engine-owned and identical for every block → static. The two `*-extra`\n // files are author scaffolds (`scaffold`: create-if-missing on every refresh,\n // never overwritten).\n fixed(\n \"src/index.ts\",\n tpl(\"block/src/index.tpl.ts\", (ctx) => ({\n facadeName: ctx.blockVars.facadeName,\n pascalName: pascalCase(ctx.blockVars.shortName),\n })),\n );\n fixed(\"src/AGENTS.ts\", file(\"block/src/AGENTS.ts\"));\n scaffold(\"src/block-extra.ts\", file(\"block/src/block-extra.ts\"));\n scaffold(\"src/agents-extra.ts\", file(\"block/src/agents-extra.ts\"));\n\n fixed(\"tsconfig.json\", file(\"block/tsconfig.json\"));\n\n // Placeholder logos referenced by `block.meta` (logo + organization.logo).\n // Binary seeds: written once at init, author-owned thereafter — refresh\n // never overwrites them, so a custom logo survives. `block-tools pack`\n // embeds these into the block pack; without them pack would fail on the\n // `file:logos/...` meta references.\n seed(\"logos/block-logo.png\", binaryFile(\"block/logos/block-logo.png\"));\n seed(\"logos/organization-logo.png\", binaryFile(\"block/logos/organization-logo.png\"));\n\n managed(\n \"package.json\",\n generate((ctx) => blockPackageJsonInitial(ctx)),\n (ctx) => {\n blockPackageJsonRules(ctx);\n },\n );\n });\n}\n","// Shared definition for co-located unit-test handling.\n//\n// A block's model / ui / workflow scope MAY carry co-located vitest unit\n// tests (`src/**/*.test.ts`, including nested `src/test/*.test.ts`). The\n// structurer wires the vitest `test` script and (for ui/model) node ambient\n// types into a scope ONLY when such files are present — so a test-less scope\n// stays free of a `test` script it would never run, and a freshly-init'd\n// (test-less) block remains a refresh fixpoint.\n\n/** Glob (module-relative) for co-located unit tests in a scope's `src/`. */\nexport const COLOCATED_TEST_GLOB = \"src/**/*.test.ts\";\n","// Model `package.json`: the initial generator and the drift-correcting body\n// rules, co-located. Identity (name/version) stays untouched; the body\n// enforces type/main/types/exports + canonical scripts + canonical dep sets,\n// then projects canonical field / dependency order.\n//\n// Authored oxfmt-clean: the model is one of the two scopes `ts-builder\n// check` runs oxfmt on, so neither half enforces field / dependency ordering\n// beyond what oxfmt itself produces — the enforce* calls match oxfmt's order\n// exactly, so refreshing a legacy block yields oxfmt-clean output and the\n// build→check gate (oxfmt --check) passes without a prior `pnpm fmt`.\n\nimport {\n ensureField,\n ensureScript,\n ensureDep,\n ensureDevDep,\n ensureDevDeps,\n ensureWorkspaceScopeDeps,\n removeDep,\n removeScript,\n removeField,\n ensurePeerDeps,\n enforceAlphabeticalOrder,\n enforceFieldOrder,\n when,\n whenFilesExist,\n type RunContext,\n} from \"../engine/api\";\nimport { scopeDepMaps } from \"../engine/ctx\";\nimport { canonicalPackageJsonOrder } from \"./shared/key-order\";\nimport { COLOCATED_TEST_GLOB } from \"./shared/colocated-tests\";\nimport { removeRetiredToolchainDeps } from \"./shared/retired-deps\";\n\nexport function modelPackageJsonInitial(ctx: RunContext): Record<string, unknown> {\n const v = ctx.blockVars;\n return {\n name: `${v.facadeName}.model`,\n private: true,\n type: \"module\",\n // The block-model build emits both index.cjs and index.js. `main` is\n // the CommonJS entry (require fallback); `module` the ESM entry.\n main: \"dist/index.cjs\",\n module: \"dist/index.js\",\n types: \"dist/index.d.ts\",\n exports: {\n \".\": {\n types: \"./dist/index.d.ts\",\n sources: \"./src/index.ts\",\n import: \"./dist/index.js\",\n },\n \"./dist/*\": \"./dist/*\",\n },\n scripts: {\n fmt: \"ts-builder format\",\n watch: \"ts-builder build --target block-model --watch\",\n build: \"ts-builder build --target block-model && block-tools build-model\",\n check: \"ts-builder check --target block-model\",\n },\n dependencies: {\n \"@platforma-sdk/model\": \"sdk:\",\n // The model imports its block's kind (to bake the kind reference into\n // model.json), so it depends on the sibling kind package directly.\n ...scopeDepMaps(ctx, \"kind\"),\n },\n devDependencies: {\n \"@milaboratories/ts-builder\": \"sdk:\",\n \"@milaboratories/ts-configs\": \"sdk:\",\n \"@platforma-sdk/block-tools\": \"sdk:\",\n },\n peerDependencies: {\n \"@types/node\": \"*\",\n typescript: \"*\",\n },\n };\n}\n\nexport function modelPackageJsonRules(): void {\n // Controlled sibling — workspace-only, never published. `private: true` makes\n // npm refuse to publish it; the `version` is kept (changesets-owned) so the\n // packed template's lib carries a version.\n ensureField(\"private\", true);\n\n ensureField(\"type\", \"module\");\n // build emits both; main = CJS entry, module = ESM entry (prod convention).\n ensureField(\"main\", \"dist/index.cjs\");\n ensureField(\"module\", \"dist/index.js\");\n ensureField(\"types\", \"dist/index.d.ts\");\n ensureField(\"exports\", {\n \".\": {\n types: \"./dist/index.d.ts\",\n sources: \"./src/index.ts\",\n import: \"./dist/index.js\",\n },\n \"./dist/*\": \"./dist/*\",\n });\n\n ensureScript(\"fmt\", \"ts-builder format\");\n ensureScript(\"watch\", \"ts-builder build --target block-model --watch\");\n ensureScript(\"build\", \"ts-builder build --target block-model && block-tools build-model\");\n ensureScript(\"check\", \"ts-builder check --target block-model\");\n\n ensureDep(\"@platforma-sdk/model\", \"sdk:\");\n // The model imports its block's kind to bake the kind reference — direct\n // dependency on the sibling kind package.\n ensureWorkspaceScopeDeps(\"kind\");\n\n ensureDevDeps({\n \"@milaboratories/ts-builder\": \"sdk:\",\n \"@milaboratories/ts-configs\": \"sdk:\",\n \"@platforma-sdk/block-tools\": \"sdk:\",\n });\n\n ensurePeerDeps({\n \"@types/node\": \"*\",\n typescript: \"*\",\n });\n\n // The vitest `test` script, the `vitest` devDep, and node ambient types are\n // wired ONLY when the model carries co-located unit tests (`src/**/*.test.ts`).\n // A test-less model gets none — turbo simply has no `test` task for it, and\n // the scope stays a refresh fixpoint. When tests ARE present, `@types/node`\n // is promoted from peer to a devDep (the single-section invariant drops the\n // peer) so the tests' `node:*` imports resolve under the `types: [\"node\"]`\n // that model/tsconfig adds under the same predicate. Runs AFTER ensurePeerDeps\n // so the promotion is not reverted.\n //\n // Skipped entirely for sdk-internal (in-monorepo) blocks: those live inside\n // the platforma monorepo's own test infrastructure (build-configs, shared\n // catalog, coverage providers) and own their test wiring — the structurer\n // must not impose or strip standalone-block test conventions on them.\n when(\n ({ ctx }) => !ctx.isSdkInternal,\n () =>\n when(\n whenFilesExist(COLOCATED_TEST_GLOB),\n () => {\n ensureScript(\"test\", \"vitest run --passWithNoTests\");\n ensureDevDep(\"vitest\", \"catalog:\");\n ensureDevDep(\"@types/node\", \"*\");\n },\n () => removeDep(\"vitest\"),\n ),\n );\n\n removeRetiredToolchainDeps();\n removeField(\"tsup\");\n removeScript(\"lint\");\n\n enforceAlphabeticalOrder(\"dependencies\");\n enforceAlphabeticalOrder(\"devDependencies\");\n enforceAlphabeticalOrder(\"peerDependencies\");\n enforceAlphabeticalOrder(\"optionalDependencies\");\n enforceFieldOrder([...canonicalPackageJsonOrder]);\n}\n","// Model-scope rules. Static config files + managed package.json; the\n// `src/index.ts` seed is dropped by `init` and never touched again\n// (block author owns it).\n\nimport {\n scope,\n fixed,\n managed,\n seed,\n file,\n tpl,\n generate,\n when,\n whenFilesExist,\n} from \"../engine/api\";\nimport { modelPackageJsonInitial, modelPackageJsonRules } from \"./model-package-json\";\nimport { COLOCATED_TEST_GLOB } from \"./shared/colocated-tests\";\n\nexport function modelRules(): void {\n scope(\"model\", () => {\n when(\n whenFilesExist(COLOCATED_TEST_GLOB),\n () => fixed(\"tsconfig.json\", file(\"model/tsconfig.node.json\")),\n () => fixed(\"tsconfig.json\", file(\"model/tsconfig.json\")),\n );\n fixed(\".oxlintrc.json\", file(\"model/.oxlintrc.json\"));\n fixed(\".oxfmtrc.json\", file(\"model/.oxfmtrc.json\"));\n\n seed(\n \"src/index.ts\",\n tpl(\"model/src/index.tpl.ts\", (ctx) => ({ kindPkg: `${ctx.blockVars.facadeName}.kind` })),\n );\n\n managed(\n \"package.json\",\n generate((ctx) => modelPackageJsonInitial(ctx)),\n () => {\n modelPackageJsonRules();\n },\n );\n });\n}\n","// Kind `package.json`: the initial generator and the drift-correcting body,\n// co-located. A kind is a private workspace sibling (like the model): its\n// content ships to the `kinds/` registry tree via `build-kind-manifest`, not to\n// npm. Identity (name/version) stays untouched; the body enforces\n// type/main/exports + canonical scripts + canonical dep sets, then projects\n// canonical field / dependency order (oxfmt-clean, so build->check passes with\n// no prior `pnpm fmt`).\n//\n// A kind builds TWICE, like the model: `dist/index.{js,cjs}` with dependencies\n// external — what a block imports — and the self-contained `dist/kind.js` that\n// the registry publishes and `build-kind-manifest` hashes. The `exports` map\n// points at the externalized pair only, so a kind and the block implementing it\n// share one copy of any dependency they both use; the self-contained bundle is\n// read off disk by the manifest builder and needs no export.\n//\n// All three of `import` / `require` / `default` are spelled out: `block-tools\n// build-model` loads the model via `require()`, and the model `require`s its\n// kind, so the CJS arm has to resolve to real CJS.\n\nimport {\n ensureField,\n ensureScript,\n ensureDep,\n ensureDevDeps,\n ensurePeerDeps,\n removeScript,\n enforceAlphabeticalOrder,\n enforceFieldOrder,\n type RunContext,\n} from \"../engine/api\";\nimport { canonicalPackageJsonOrder } from \"./shared/key-order\";\n\nconst KIND_EXPORTS = {\n \".\": {\n types: \"./dist/index.d.ts\",\n sources: \"./src/index.ts\",\n import: \"./dist/index.js\",\n require: \"./dist/index.cjs\",\n default: \"./dist/index.js\",\n },\n};\n\nexport function kindPackageJsonInitial(ctx: RunContext): Record<string, unknown> {\n const v = ctx.blockVars;\n return {\n name: `${v.facadeName}.kind`,\n private: true,\n type: \"module\",\n // `main` is the CommonJS entry (require fallback), `module` the ESM one —\n // the model's convention. `dist/kind.js`, the self-contained bundle, is\n // deliberately not an entry: it exists for the registry, not for importers.\n main: \"./dist/index.cjs\",\n module: \"./dist/index.js\",\n types: \"./dist/index.d.ts\",\n exports: KIND_EXPORTS,\n scripts: {\n fmt: \"ts-builder format\",\n watch: \"ts-builder build --target block-kind --watch\",\n build: \"ts-builder build --target block-kind && block-tools build-kind-manifest\",\n check: \"ts-builder check --target block-kind\",\n },\n // A kind ships a runtime params check, so it is not a types-only package — but the\n // check is plain TypeScript, held to the contract by its return type, so nothing but\n // the SDK is needed to write one. An author whose params shape earns a schema library\n // adds it here themselves; seeding one would make every kind carry it to be deleted.\n dependencies: {\n \"@platforma-sdk/block-kind\": \"sdk:\",\n },\n devDependencies: {\n \"@milaboratories/ts-builder\": \"sdk:\",\n \"@milaboratories/ts-configs\": \"sdk:\",\n \"@platforma-sdk/block-tools\": \"sdk:\",\n },\n peerDependencies: {\n \"@types/node\": \"*\",\n typescript: \"*\",\n },\n };\n}\n\nexport function kindPackageJsonRules(): void {\n // Controlled sibling — workspace-only, never published to npm. `private: true`\n // makes npm refuse to publish it; the `version` is kept (changesets-owned) and\n // is what the kind's on-wire `{name}@{version}` reference is baked from.\n ensureField(\"private\", true);\n\n ensureField(\"type\", \"module\");\n ensureField(\"main\", \"./dist/index.cjs\");\n ensureField(\"module\", \"./dist/index.js\");\n ensureField(\"types\", \"./dist/index.d.ts\");\n ensureField(\"exports\", KIND_EXPORTS);\n\n ensureScript(\"fmt\", \"ts-builder format\");\n ensureScript(\"watch\", \"ts-builder build --target block-kind --watch\");\n ensureScript(\"build\", \"ts-builder build --target block-kind && block-tools build-kind-manifest\");\n ensureScript(\"check\", \"ts-builder check --target block-kind\");\n removeScript(\"lint\");\n\n ensureDep(\"@platforma-sdk/block-kind\", \"sdk:\");\n\n ensureDevDeps({\n \"@milaboratories/ts-builder\": \"sdk:\",\n \"@milaboratories/ts-configs\": \"sdk:\",\n \"@platforma-sdk/block-tools\": \"sdk:\",\n });\n\n ensurePeerDeps({\n \"@types/node\": \"*\",\n typescript: \"*\",\n });\n\n enforceAlphabeticalOrder(\"dependencies\");\n enforceAlphabeticalOrder(\"devDependencies\");\n enforceAlphabeticalOrder(\"peerDependencies\");\n enforceAlphabeticalOrder(\"optionalDependencies\");\n enforceFieldOrder([...canonicalPackageJsonOrder]);\n}\n","// Kind-scope rules. Static config files + managed package.json; the\n// `src/index.ts` seed is dropped by `init` and never touched again (the block\n// author owns the BlockParams contract). The seed is a deliberate non-building\n// sentinel — its BlockParams is undefined, so a scaffolded-but-unmigrated block\n// fails to typecheck until the params contract is chosen on purpose.\n\nimport { scope, fixed, managed, seed, file, generate } from \"../engine/api\";\nimport { kindPackageJsonInitial, kindPackageJsonRules } from \"./kind-package-json\";\n\nexport function kindRules(): void {\n scope(\"kind\", () => {\n fixed(\"tsconfig.json\", file(\"kind/tsconfig.json\"));\n fixed(\".oxlintrc.json\", file(\"kind/.oxlintrc.json\"));\n fixed(\".oxfmtrc.json\", file(\"kind/.oxfmtrc.json\"));\n\n // Minimal-but-real kind: identity imported from the package's own\n // package.json, plus a non-building BlockParams sentinel the block author\n // must resolve (via the migration recipe or by hand) before the block builds.\n seed(\"src/index.ts\", file(\"kind/src/index.ts\"));\n\n managed(\n \"package.json\",\n generate((ctx) => kindPackageJsonInitial(ctx)),\n () => {\n kindPackageJsonRules();\n },\n );\n });\n}\n","// UI `package.json`: the initial generator and the drift-correcting body\n// rules, co-located.\n//\n// Authored oxfmt-clean: the ui is one of the two scopes `ts-builder check`\n// runs oxfmt on, so neither half enforces ordering beyond what oxfmt\n// produces — the enforce* calls match oxfmt's order exactly, so refreshing a\n// legacy block yields oxfmt-clean output and the build→check gate (oxfmt\n// --check) passes without a prior `pnpm fmt`.\n\nimport {\n ensureField,\n ensureScript,\n ensureDep,\n ensureDevDep,\n ensureDevDeps,\n ensurePeerDeps,\n ensureWorkspaceScopeDeps,\n removeDep,\n removeScript,\n enforceAlphabeticalOrder,\n enforceFieldOrder,\n when,\n whenFilesExist,\n type RunContext,\n} from \"../engine/api\";\nimport { scopeDepMap } from \"../engine/ctx\";\nimport { canonicalPackageJsonOrder } from \"./shared/key-order\";\nimport { COLOCATED_TEST_GLOB } from \"./shared/colocated-tests\";\nimport { removeRetiredToolchainDeps } from \"./shared/retired-deps\";\n\nexport function uiPackageJsonInitial(ctx: RunContext): Record<string, unknown> {\n const v = ctx.blockVars;\n return {\n name: `${v.facadeName}.ui`,\n private: true,\n type: \"module\",\n scripts: {\n fmt: \"ts-builder format\",\n dev: \"ts-builder serve --target block-ui\",\n watch: \"ts-builder build --target block-ui --watch\",\n build: \"ts-builder build --target block-ui\",\n check: \"ts-builder check --target block-ui\",\n },\n dependencies: {\n \"@platforma-sdk/ui-vue\": \"sdk:\",\n vue: \"catalog:\",\n // The seeded ui (app.ts) imports the block's model package; depend on\n // it — mirrors the body rule's `ensureWorkspaceScopeDeps(\"model\")`.\n ...scopeDepMap(ctx, \"model\"),\n },\n devDependencies: {\n \"@milaboratories/ts-builder\": \"sdk:\",\n \"@milaboratories/ts-configs\": \"sdk:\",\n },\n peerDependencies: {\n \"@types/node\": \"*\",\n typescript: \"*\",\n },\n };\n}\n\nexport function uiPackageJsonRules(): void {\n // Controlled sibling — workspace-only, never published, but kept versioned\n // (changesets-owned) so the packed template's lib carries a version.\n ensureField(\"private\", true);\n\n ensureField(\"type\", \"module\");\n\n ensureScript(\"fmt\", \"ts-builder format\");\n ensureScript(\"dev\", \"ts-builder serve --target block-ui\");\n ensureScript(\"watch\", \"ts-builder build --target block-ui --watch\");\n ensureScript(\"build\", \"ts-builder build --target block-ui\");\n ensureScript(\"check\", \"ts-builder check --target block-ui\");\n\n ensureDep(\"@platforma-sdk/ui-vue\", \"sdk:\");\n // The seeded ui (main.ts) imports `createApp` from vue.\n ensureDep(\"vue\", \"catalog:\");\n // The seeded ui (app.ts) imports the block's model package.\n ensureWorkspaceScopeDeps(\"model\");\n\n ensureDevDeps({\n \"@milaboratories/ts-builder\": \"sdk:\",\n \"@milaboratories/ts-configs\": \"sdk:\",\n });\n\n removeRetiredToolchainDeps();\n removeScript(\"preview\");\n removeScript(\"lint\");\n\n // `@types/node` is declared as a peer by default — mirrors the model scope\n // (the block author resolves it from the workspace root). The ui builds with\n // `--target block-ui` (types: []), so it pulls no node ambient types into the\n // build; the peer only satisfies IDE / type resolution, alongside `typescript`.\n ensurePeerDeps({\n \"@types/node\": \"*\",\n typescript: \"*\",\n });\n\n // A ui WITH co-located unit tests (`src/**/*.test.ts`) needs the vitest\n // `test` script, the `vitest` devDep, AND node ambient types promoted from\n // peer to a devDep (the single-section invariant drops the peer) so that\n // `types: [\"node\"]` in ui/tsconfig — wired under the same predicate —\n // resolves the tests' `node:*` imports. A test-less ui keeps `@types/node`\n // as a peer and carries no vitest, staying a refresh fixpoint.\n //\n // Skipped entirely for sdk-internal (in-monorepo) blocks: they own their test\n // wiring under the monorepo's shared infrastructure — see model-package-json.\n when(\n ({ ctx }) => !ctx.isSdkInternal,\n () =>\n when(\n whenFilesExist(COLOCATED_TEST_GLOB),\n () => {\n ensureScript(\"test\", \"vitest run --passWithNoTests\");\n ensureDevDep(\"vitest\", \"catalog:\");\n ensureDevDep(\"@types/node\", \"*\");\n },\n () => removeDep(\"vitest\"),\n ),\n );\n\n enforceAlphabeticalOrder(\"dependencies\");\n enforceAlphabeticalOrder(\"devDependencies\");\n enforceAlphabeticalOrder(\"peerDependencies\");\n enforceAlphabeticalOrder(\"optionalDependencies\");\n enforceFieldOrder([...canonicalPackageJsonOrder]);\n}\n","// UI-scope rules. Author owns src/main.ts and components; static config\n// files are engine-managed.\n\nimport {\n scope,\n fixed,\n managed,\n scaffold,\n seed,\n file,\n tpl,\n generate,\n when,\n whenFilesExist,\n} from \"../engine/api\";\nimport { uiPackageJsonInitial, uiPackageJsonRules } from \"./ui-package-json\";\nimport { COLOCATED_TEST_GLOB } from \"./shared/colocated-tests\";\n\nexport function uiRules(): void {\n scope(\"ui\", () => {\n // Two static end states by co-located-test presence: a test-bearing ui gets\n // node ambient types (`.node.json`) so tests' `node:*` imports type-check\n // under vue-tsc — `@types/node` is wired alongside by the package.json rule;\n // a test-less ui stays bare. `fixed` (engine-owned, whole-file overwrite)\n // not `managed`, so refresh is idempotent by construction — no key-order drift.\n when(\n whenFilesExist(COLOCATED_TEST_GLOB),\n () => fixed(\"tsconfig.json\", file(\"ui/tsconfig.node.json\")),\n () => fixed(\"tsconfig.json\", file(\"ui/tsconfig.json\")),\n );\n fixed(\".oxlintrc.json\", file(\"ui/.oxlintrc.json\"));\n // Block-local oxfmt config — the ui is oxfmt-checked (`ts-builder check\n // --target block-ui`).\n fixed(\".oxfmtrc.json\", file(\"ui/.oxfmtrc.json\"));\n // scaffold (not fixed): index.html carries a block-specific CSP. Write\n // the canonical default only when absent; never overwrite an author's.\n scaffold(\"index.html\", file(\"ui/index.html\"));\n\n // A minimal-but-real UI: mount (main.ts), app wiring the block model\n // (app.ts), and a landing page (MainPage.vue). An empty main.ts would\n // trip oxlint `unicorn(no-empty-file)`. Author-owned seeds: written once\n // at init, untouched on refresh.\n seed(\"src/main.ts\", file(\"ui/src/main.ts\"));\n seed(\n \"src/app.ts\",\n tpl(\"ui/src/app.tpl.ts\", (ctx) => ({ modelPkg: `${ctx.blockVars.facadeName}.model` })),\n );\n seed(\n \"src/MainPage.vue\",\n tpl(\"ui/src/MainPage.tpl.vue\", (ctx) => ({ shortName: ctx.blockVars.shortName })),\n );\n\n managed(\n \"package.json\",\n generate((ctx) => uiPackageJsonInitial(ctx)),\n () => {\n uiPackageJsonRules();\n },\n );\n });\n}\n","// Workflow `package.json`: the initial generator and the drift-correcting\n// body rules, co-located. Workflow packages reference software modules at\n// workspace level when the block has any; the generator fills them from the\n// discovered modules and the body rule re-asserts them.\n\nimport {\n ensureField,\n ensureScript,\n ensureDep,\n ensureDevDeps,\n removeDep,\n ensureWorkspaceScopeDeps,\n enforceAlphabeticalOrder,\n enforceFieldOrder,\n when,\n whenFilesExist,\n type RunContext,\n} from \"../engine/api\";\nimport { scopeDepMaps } from \"../engine/ctx\";\nimport { canonicalPackageJsonOrder } from \"./shared/key-order\";\nimport { COLOCATED_TEST_GLOB } from \"./shared/colocated-tests\";\nimport { removeRetiredToolchainDeps } from \"./shared/retired-deps\";\n\nexport function workflowPackageJsonInitial(ctx: RunContext): Record<string, unknown> {\n const v = ctx.blockVars;\n return {\n name: `${v.facadeName}.workflow`,\n private: true,\n type: \"module\",\n scripts: {\n // No `fmt`: the workflow is Tengo, not TS — nothing for oxlint/oxfmt\n // to process. Tengo is built and checked by pl-tengo.\n build: \"shx rm -rf dist && pl-tengo build\",\n check: \"pl-tengo check\",\n // No `test`: the vitest `test` script is wired by the body rule ONLY\n // when co-located test files exist (a freshly-init'd workflow has none).\n // Tengo source formatter (emacs batch). Falls back to a notice when\n // emacs is absent, so the script never hard-fails the environment.\n format: \"/usr/bin/env emacs --script ./format.el || echo 'No emacs.'\",\n },\n dependencies: {\n \"@platforma-sdk/workflow-tengo\": \"sdk:\",\n // Every block-local software module as a workspace dep (zero or more).\n ...scopeDepMaps(ctx, \"software\"),\n },\n devDependencies: {\n \"@platforma-sdk/tengo-builder\": \"sdk:\",\n \"@platforma-sdk/test\": \"sdk:\",\n // `vitest` is NOT seeded here — it's wired by the body rule only when the\n // workflow carries co-located tests (a freshly-init'd workflow has none).\n shx: \"catalog:\",\n },\n };\n}\n\nexport function workflowPackageJsonRules(): void {\n // Controlled sibling — workspace-only, never published, but kept versioned\n // (changesets-owned) so the packed template's lib carries a version.\n ensureField(\"private\", true);\n\n ensureField(\"type\", \"module\");\n\n // No `fmt` script: the workflow is Tengo, not TS — build + check run via\n // pl-tengo; `format` runs the emacs-batch Tengo formatter (no-op when absent).\n ensureScript(\"build\", \"shx rm -rf dist && pl-tengo build\");\n ensureScript(\"check\", \"pl-tengo check\");\n ensureScript(\"format\", \"/usr/bin/env emacs --script ./format.el || echo 'No emacs.'\");\n // The vitest `test` script AND the `vitest` devDep are wired ONLY when the\n // workflow carries co-located integration tests (`src/**/*.test.ts`, incl.\n // `src/test/`). A test-less workflow gets neither — no `test` task, no\n // vitest dep — and stays a refresh fixpoint. (Workflow tests type-check via\n // the standalone workflow/tsconfig with `types: []` — they pull their types\n // from `@platforma-sdk/test` — so no node-types wiring is needed here,\n // unlike model/ui.)\n //\n // Skipped entirely for sdk-internal (in-monorepo) blocks: they own their test\n // wiring under the monorepo's shared infrastructure — see model-package-json.\n when(\n ({ ctx }) => !ctx.isSdkInternal,\n () =>\n when(\n whenFilesExist(COLOCATED_TEST_GLOB),\n () => {\n ensureScript(\"test\", \"vitest run --passWithNoTests\");\n ensureDevDeps({ vitest: \"catalog:\" });\n },\n () => removeDep(\"vitest\"),\n ),\n );\n\n ensureDep(\"@platforma-sdk/workflow-tengo\", \"sdk:\");\n\n // Pulls in every block-local software module as a workspace dep so the\n // workflow can reference the produced runenv assets.\n ensureWorkspaceScopeDeps(\"software\");\n\n // @platforma-sdk/test: workflow integration tests (e.g. mixcr's\n // workflow/src/test/columns.test.ts) import it.\n ensureDevDeps({\n \"@platforma-sdk/tengo-builder\": \"sdk:\",\n \"@platforma-sdk/test\": \"sdk:\",\n shx: \"catalog:\",\n });\n\n // No-op for a canonical Tengo workflow; called uniformly across every scope\n // for safety.\n removeRetiredToolchainDeps();\n\n enforceAlphabeticalOrder(\"dependencies\");\n enforceAlphabeticalOrder(\"devDependencies\");\n enforceAlphabeticalOrder(\"peerDependencies\");\n enforceAlphabeticalOrder(\"optionalDependencies\");\n enforceFieldOrder([...canonicalPackageJsonOrder]);\n}\n","// Workflow-scope rules. The Tengo entry point is a templated seed\n// (substitutes ${shortName}); other config files are static.\n\nimport {\n scope,\n managed,\n fixed,\n scaffold,\n seed,\n file,\n tpl,\n generate,\n remove,\n when,\n whenFilesExist,\n} from \"../engine/api\";\nimport { workflowPackageJsonInitial, workflowPackageJsonRules } from \"./workflow-package-json\";\nimport { COLOCATED_TEST_GLOB } from \"./shared/colocated-tests\";\n\nexport function workflowRules(): void {\n scope(\"workflow\", () => {\n // Tengo source formatter (emacs batch); the `format` script invokes it.\n fixed(\"format.el\", file(\"workflow/format.el\"));\n // The TS-test tsconfig + vitest config exist ONLY when the workflow carries\n // co-located tests (`src/**/*.test.ts`, incl. `src/test/` — e.g. mixcr's\n // workflow/src/test/columns.test.ts). They pair with the conditional\n // `vitest` devDep + `test` script in workflow-package-json. tsconfig is\n // `fixed` (structural: types:[] keeps the isomorphic workflow free of\n // ambient Node/DOM types); vitest.config is `scaffold` (author-tunable once\n // present). A test-less workflow gets neither and stays a refresh fixpoint.\n //\n // Skipped entirely for sdk-internal (in-monorepo) blocks: they own their\n // test config under the monorepo's shared infrastructure (e.g. a bespoke\n // `vitest run --coverage` + `createVitestConfig`), which the structurer\n // must neither scaffold nor remove. See workflow-package-json.\n when(\n ({ ctx }) => !ctx.isSdkInternal,\n () =>\n when(\n whenFilesExist(COLOCATED_TEST_GLOB),\n () => {\n fixed(\"tsconfig.json\", file(\"workflow/tsconfig.json\"));\n scaffold(\"vitest.config.mts\", file(\"workflow/vitest.config.mts\"));\n },\n () => {\n remove(\"tsconfig.json\");\n remove(\"vitest.config.mts\");\n },\n ),\n );\n // No workflow facade (index.js / index.d.ts): the block loader resolves the\n // workflow via the `block:` components dist path (workflow/dist/.../main.plj.gz),\n // never the JS facade. Removed so blocks that carry one get cleaned\n // (idempotent on absence).\n remove(\"index.js\");\n remove(\"index.d.ts\");\n\n seed(\n \"src/main.tpl.tengo\",\n tpl(\"workflow/src/main.tpl.tengo\", (ctx) => ({\n shortName: ctx.blockVars.shortName,\n })),\n );\n\n managed(\n \"package.json\",\n generate((ctx) => workflowPackageJsonInitial(ctx)),\n () => {\n workflowPackageJsonRules();\n },\n );\n });\n}\n","// Test `package.json`: the initial generator and the drift-correcting body\n// rules, co-located.\n\nimport {\n ensureField,\n ensureScript,\n ensureDevDeps,\n ensurePeerDeps,\n removeDep,\n removeScript,\n enforceAlphabeticalOrder,\n enforceFieldOrder,\n type RunContext,\n} from \"../engine/api\";\nimport { canonicalPackageJsonOrder } from \"./shared/key-order\";\nimport { removeRetiredToolchainDeps } from \"./shared/retired-deps\";\n\nexport function testPackageJsonInitial(ctx: RunContext): Record<string, unknown> {\n const v = ctx.blockVars;\n return {\n name: `${v.facadeName}.test`,\n private: true,\n type: \"module\",\n scripts: {\n fmt: \"ts-builder format\",\n // `ts-builder check` runs type-check + lint (oxlint) + fmt-check (oxfmt).\n check: \"ts-builder check --target block-test\",\n test: \"vitest run --passWithNoTests\",\n },\n peerDependencies: {\n typescript: \"*\",\n },\n devDependencies: {\n \"@platforma-sdk/test\": \"sdk:\",\n \"@milaboratories/ts-builder\": \"sdk:\",\n \"@milaboratories/ts-configs\": \"sdk:\",\n vitest: \"catalog:\",\n },\n };\n}\n\nexport function testPackageJsonRules(): void {\n // Controlled sibling — workspace-only, never published. (The initial already\n // seeds `private: true`; the body re-asserts it. The `version` is kept —\n // changesets-owned — so the packed template's lib carries a version.)\n ensureField(\"private\", true);\n\n ensureField(\"type\", \"module\");\n\n ensureScript(\"fmt\", \"ts-builder format\");\n // `ts-builder check` runs type-check + lint (oxlint) + fmt-check (oxfmt).\n ensureScript(\"check\", \"ts-builder check --target block-test\");\n ensureScript(\"test\", \"vitest run --passWithNoTests\");\n // Linting runs inside `ts-builder check` — no separate `lint` script.\n removeScript(\"lint\");\n\n ensureDevDeps({\n \"@platforma-sdk/test\": \"sdk:\",\n \"@milaboratories/ts-builder\": \"sdk:\",\n \"@milaboratories/ts-configs\": \"sdk:\",\n vitest: \"catalog:\",\n });\n\n // The test tsconfig (@milaboratories/ts-configs/block/test) supplies the\n // ambient types, so only the `typescript` peer is needed — no `@types/node`.\n ensurePeerDeps({\n typescript: \"*\",\n });\n removeDep(\"@types/node\");\n removeRetiredToolchainDeps();\n\n enforceAlphabeticalOrder(\"dependencies\");\n enforceAlphabeticalOrder(\"devDependencies\");\n enforceAlphabeticalOrder(\"peerDependencies\");\n enforceAlphabeticalOrder(\"optionalDependencies\");\n enforceFieldOrder([...canonicalPackageJsonOrder]);\n}\n","// Test-scope rules.\n\nimport { scope, fixed, managed, scaffold, seed, file, text, generate } from \"../engine/api\";\nimport { testPackageJsonInitial, testPackageJsonRules } from \"./test-package-json\";\n\nexport function testRules(): void {\n scope(\"test\", () => {\n // tsconfig carries `files: []` alongside `include: [\"src/**/*\"]`: tsc\n // errors TS18003 when an `include` matches nothing, so an empty `files`\n // lets the check pass on a test-less block while `include` still\n // type-checks real tests once present.\n fixed(\"tsconfig.json\", file(\"test/tsconfig.json\"));\n // Block-local oxlint/oxfmt config — test sources are lint + fmt-checked\n // (the `check` script runs `ts-builder check --target block-test`).\n fixed(\".oxlintrc.json\", file(\"test/.oxlintrc.json\"));\n fixed(\".oxfmtrc.json\", file(\"test/.oxfmtrc.json\"));\n // scaffold (not fixed): integration tests legitimately tune timeout /\n // retry per block. Write the canonical default if absent; never\n // overwrite an author's config.\n scaffold(\"vitest.config.mts\", file(\"test/vitest.config.mts\"));\n\n // A trivial, backend-free demo test so a freshly-init'd block ships a\n // runnable suite (`pnpm test` green out of the box) rather than an empty\n // scope. Author-owned seed: written once at init, untouched on refresh.\n seed(\n \"src/demo.test.ts\",\n text(\n `import { expect, test } from \"vitest\";\\n\\n` +\n `test(\"scaffolded block sanity check\", () => {\\n` +\n ` expect(true).toBe(true);\\n` +\n `});\\n`,\n ),\n );\n\n managed(\n \"package.json\",\n generate((ctx) => testPackageJsonInitial(ctx)),\n () => {\n testPackageJsonRules();\n },\n );\n });\n}\n","// Software `package.json`: the initial generator and the drift-correcting\n// body rules, co-located. One body, N modules — fan-out is driven by\n// `ctx.modules`.\n//\n// Drift-correctors only: identity (name/version), `description`, and the\n// `block-software` descriptor are author-owned / opaque and left untouched\n// — re-asserting them would clobber real multi-software blocks on refresh.\n// The body enforces the structural essentials: ESM type, the publish\n// `files` glob, the lifecycle scripts, and the canonical devDeps.\n\nimport {\n ensureField,\n removeField,\n ensureScript,\n removeScript,\n ensureDevDep,\n removeDep,\n enforceAlphabeticalOrder,\n enforceFieldOrder,\n type RunContext,\n} from \"../engine/api\";\nimport { canonicalPackageJsonOrder } from \"./shared/key-order\";\n\n// The software-build build/pack commands, shared by the generator and the reconciler. block-tools\n// bundles the build engine, so these are the only build-tool commands a software-build block runs.\nconst BUILD_CMD = \"block-tools software build\";\nconst DO_PACK_CMD =\n \"shx rm -f *.tgz && block-tools software build && pnpm pack && shx mv platforma-open*.tgz package.tgz\";\n\n/** The `block-software` package-builder descriptor for a python\n * entrypoint. Kept opaque by the engine; rule authors edit it via\n * `transformAt(\"block-software\", ...)`. The `:3.12.10` tag inside\n * `environment` is the runenv artifact tag (python version), distinct\n * from the npm catalog version. */\nfunction pythonBlockSoftware(): Record<string, unknown> {\n return {\n entrypoints: {\n main: {\n binary: {\n artifact: {\n type: \"python\",\n registry: \"platforma-open\",\n environment: \"@platforma-open/milaboratories.runenv-python-3:3.12.10\",\n dependencies: { toolset: \"pip\", requirements: \"requirements.txt\" },\n root: \"./src\",\n },\n cmd: [\"python\", \"{pkg}/main.py\"],\n },\n },\n },\n };\n}\n\nexport function softwarePackageJsonInitial(ctx: RunContext): Record<string, unknown> {\n const v = ctx.blockVars;\n\n return {\n name: `${v.facadeName}.software`,\n type: \"module\",\n description: \"Block Software\",\n files: [\"./dist/**/*\"],\n scripts: {\n build: BUILD_CMD,\n \"do-pack\": DO_PACK_CMD,\n changeset: \"changeset\",\n \"version-packages\": \"changeset version\",\n },\n \"block-software\": pythonBlockSoftware(),\n devDependencies: {\n \"@platforma-open/milaboratories.runenv-python-3\": \"catalog:\",\n \"@platforma-sdk/block-tools\": \"sdk:\",\n },\n };\n}\n\nexport function softwarePackageJsonRules(): void {\n // Software packages must never be private: `pl-pkg` gates docker image\n // auto-push on `!isPrivate`, so a private software package builds its image\n // but never pushes it — the block then 404s pulling it at runtime. Strip it\n // so a `structure refresh` heals any block that has it.\n removeField(\"private\");\n\n ensureField(\"type\", \"module\");\n ensureField(\"files\", [\"./dist/**/*\"]);\n\n // Lifecycle scripts. block-tools builds and packs; a block migrated off pl-pkg converges on\n // refresh — the old `pl-pkg prepublish` upload step is dropped (build + push happen in `build`).\n ensureScript(\"build\", BUILD_CMD);\n ensureScript(\"do-pack\", DO_PACK_CMD);\n removeScript(\"prepublishOnly\");\n ensureScript(\"changeset\", \"changeset\");\n ensureScript(\"version-packages\", \"changeset version\");\n\n // Canonical devDeps. block-tools bundles the build engine, so the pl-pkg\n // `@platforma-sdk/package-builder` dependency is dropped.\n ensureDevDep(\"@platforma-open/milaboratories.runenv-python-3\", \"catalog:\");\n ensureDevDep(\"@platforma-sdk/block-tools\", \"sdk:\");\n removeDep(\"@platforma-sdk/package-builder\");\n\n enforceAlphabeticalOrder(\"dependencies\");\n enforceAlphabeticalOrder(\"devDependencies\");\n enforceAlphabeticalOrder(\"peerDependencies\");\n enforceAlphabeticalOrder(\"optionalDependencies\");\n enforceFieldOrder([...canonicalPackageJsonOrder]);\n}\n","// Software-scope rules. One scope body, N modules — the engine fans out\n// once per discovered software module. Zero software modules → entire\n// scope body no-ops.\n//\n// Seeds (`software/src/main.py` + `requirements.txt`) are written once by\n// `init` and never touched again — the block author owns them.\n\nimport { scope, managed, seed, generate, text } from \"../engine/api\";\nimport { softwarePackageJsonInitial, softwarePackageJsonRules } from \"./software-package-json\";\n\nconst MAIN_PY_SEED = `import sys\n\nprint(\"Hello from Python, \" + sys.argv[1] + \"!\")\n`;\n\nconst REQUIREMENTS_SEED = `# No dependencies specified for this script\n`;\n\nexport function softwareRules(): void {\n scope(\"software\", () => {\n seed(\"src/main.py\", text(MAIN_PY_SEED));\n seed(\"src/requirements.txt\", text(REQUIREMENTS_SEED));\n\n managed(\n \"package.json\",\n generate((ctx) => softwarePackageJsonInitial(ctx)),\n () => {\n softwarePackageJsonRules();\n },\n );\n });\n}\n","// Migrations + legacy cleanup live here.\n//\n// Two patterns coexist:\n//\n// 1. One-shot migrations gated on filesystem state. Folder renames,\n// cross-cutting one-time transforms. Use `when(pathExists/pathMissing)`\n// so the migration fires once and is idempotent on subsequent runs.\n//\n// 2. Legacy cleanup primitives. Unconditional `removeScript`,\n// `removeDep`, `remove(path)` calls naming artefacts the canonical\n// layout never produces. Idempotent by definition (no-op on absent\n// keys/paths). Each line is a one-way decision: every block converges.\n\nimport { scope, remove, managed, generate, removeScript, removeDep } from \"../engine/api\";\nimport { rootPackageJsonInitial } from \"./root-package-json\";\n\nexport function testFrameworkMigration(): void {\n // No active rename-bearing migration yet. Reserved for the test\n // framework rollout.\n}\n\n// Unconditional legacy-cleanup rules. Each is a no-op on an\n// already-canonical block (remove on an absent path, removeScript /\n// removeDep on an absent key) and idempotent, so they sit at top level\n// with no `when` gate.\n//\n// Root-scope cleanup is skipped for `--sdk-internal` blocks (no root\n// module in that mode), so it never touches in-monorepo blocks.\nexport function legacyCleanup(): void {\n // Retired per-scope config files: flat eslint configs and vite-era build /\n // split-tsconfig files, replaced by the oxlint/oxfmt + ts-builder layout.\n scope(\"model\", () => {\n remove(\"eslint.config.mjs\");\n remove(\"vite.config.mts\");\n });\n scope(\"ui\", () => {\n remove(\"eslint.config.mjs\");\n remove(\"vite.config.ts\");\n remove(\"tsconfig.app.json\");\n remove(\"tsconfig.node.json\");\n });\n scope(\"test\", () => {\n remove(\"eslint.config.mjs\");\n });\n\n // Root-scope cleanup. The second `managed(\"package.json\")` body composes\n // after rootRules.\n scope(\"root\", () => {\n remove(\".prettierrc\");\n managed(\n \"package.json\",\n generate(() => rootPackageJsonInitial()),\n () => {\n // `pretty` (prettier) is superseded by `fmt` (oxfmt); the standalone\n // deps-updater is now part of block-tools.\n removeScript(\"pretty\");\n removeDep(\"@platforma-sdk/blocks-deps-updater\");\n },\n );\n });\n}\n","// Catalog version-resolution + seeding rules. The single `onInitOrUpdate(...)`\n// frame here resolves the SDK catalog families to npm latest AND seeds any\n// missing standard catalog keys (SDK families + the curated infra floor +\n// the python runenv pin). Its leaves fire on `init` AND\n// `refresh --update-deps-only` (mode \"init\" + \"updateDeps\") — both mean\n// \"write current versions\" — and are skipped on a default refresh/check,\n// which leaves catalog versions exactly as the author/lockfile has them.\n//\n// The network value lives in `ensureCatalogLatest`, which reads prefetched\n// \"latest\" versions from the runner's `registryLookup` (the CLI / init\n// constructor prefetches the SDK catalog membership list before the run;\n// unit tests pass a mock). Seeding the SDK keys from the membership list\n// (not the on-disk catalog) is what fixes the install failures: a\n// migrated block that never carried `@milaboratories/ts-builder` etc. now\n// gets them ADDED on `--update-deps-only`, no manual catalog seed required.\n//\n// Wrapped in the same root-scope `when(!isSdkInternal)` guard as the rest of\n// the root rules — internal blocks get their catalog from the parent\n// monorepo, so catalog resolution never applies there.\n\nimport {\n onInitOrUpdate,\n scope,\n when,\n managed,\n generate,\n ensureCatalogLatest,\n ensureCatalogVersion,\n pinCatalogToDependencyOf,\n} from \"../engine/api\";\nimport {\n rootPnpmWorkspaceInitial,\n SDK_CATALOG_PACKAGES,\n INFRA_CATALOG_FLOOR,\n DERIVED_CATALOG_PINS,\n RUNENV_PYTHON,\n RUNENV_PYTHON_VERSION,\n} from \"./root-pnpm-workspace\";\n\nexport function rootCatalogBumpRules(): void {\n onInitOrUpdate(() => {\n scope(\"root\", () => {\n when(\n ({ ctx }) => !ctx.isSdkInternal,\n () => {\n // On init, the default root rules create pnpm-workspace.yaml from\n // this same generator (the curated SDK placeholders + infra\n // floor); this leaf then overwrites the SDK entries with npm\n // latest (the floor entries are add-if-absent no-ops). On\n // update-deps the file already exists, so `initial` is not\n // exercised — but a ContentForm is required, so reuse the\n // generator.\n managed(\n \"pnpm-workspace.yaml\",\n generate((ctx) => rootPnpmWorkspaceInitial(ctx)),\n (ctx) => {\n // SDK families → npm latest, ADD-IF-ABSENT (seeds a migrated\n // block's missing standard keys + overwrites the init\n // placeholder).\n for (const name of SDK_CATALOG_PACKAGES) ensureCatalogLatest(name);\n // Derived catalog pins → the EXACT version their source package\n // declares (e.g. `vue` from `@platforma-sdk/ui-vue`). OVERWRITES\n // (seeds when absent, tightens a loose on-disk entry). Resolved\n // by the prefetched `derivedPinLookup`; a no-op when absent\n // (default refresh passes none). Must run AFTER ensureCatalogLatest\n // — the source package's own version is bumped there first.\n for (const pin of DERIVED_CATALOG_PINS) {\n pinCatalogToDependencyOf(pin.entry, { of: pin.of, ofVersion: pin.ofVersion });\n }\n // Curated infra floor → fixed version, ADD-IF-ABSENT (seeds\n // shx/turbo/vitest/changesets when missing; never touches a\n // version the block already pins).\n for (const [name, version] of Object.entries(INFRA_CATALOG_FLOOR)) {\n ensureCatalogVersion(name, version);\n }\n // The python runenv pin is relevant only to software-bearing\n // blocks; seed it add-if-absent when one is present.\n if (ctx.modules.some((m) => m.scope === \"software\")) {\n ensureCatalogVersion(RUNENV_PYTHON, RUNENV_PYTHON_VERSION);\n }\n },\n );\n },\n );\n });\n });\n}\n","// Canonical block structure — composes every scope's `*Rules()` function\n// inside a single `defineStructure(() => { ... })`. Re-evaluated by the\n// engine on every run; rule modules are imported by name so the\n// structure stays inspectable and the dep graph is explicit.\n\nimport { defineStructure } from \"./engine/api\";\nimport { rootRules } from \"./rules/root\";\nimport { rootCiRules } from \"./rules/root-ci\";\nimport { blockRules } from \"./rules/block\";\nimport { modelRules } from \"./rules/model\";\nimport { kindRules } from \"./rules/kind\";\nimport { uiRules } from \"./rules/ui\";\nimport { workflowRules } from \"./rules/workflow\";\nimport { testRules } from \"./rules/test\";\nimport { softwareRules } from \"./rules/software\";\nimport { testFrameworkMigration, legacyCleanup } from \"./rules/migrations\";\nimport { rootCatalogBumpRules } from \"./rules/root-catalog-bump\";\n\nexport const STRUCTURE = defineStructure(() => {\n rootRules();\n rootCiRules();\n blockRules();\n modelRules();\n kindRules();\n uiRules();\n workflowRules();\n testRules();\n softwareRules();\n testFrameworkMigration();\n legacyCleanup();\n rootCatalogBumpRules();\n});\n","// Shared driver for the `structure check` and `structure refresh`\n// commands. Wraps DISCOVERY (discover-fs) + the engine runner for\n// one block path, handling the standalone vs `--sdk-internal` split, the\n// `--update-deps-only` registry prefetch, and the post-run recheck's\n// fresh re-discovery. Each block path is processed independently (no\n// cross-block state).\n\nimport path from \"node:path\";\nimport { NodeFileSystem } from \"../engine/fs/node\";\nimport { NodeTemplateProvider } from \"../engine/templates\";\nimport { run as engineRun, type Change } from \"../engine/runner\";\nimport { discoverRunContext } from \"../engine/discovery-fs\";\nimport { STRUCTURE } from \"../structure-definition\";\nimport {\n matchesBumpPattern,\n buildRegistryLookupForNames,\n buildDerivedPinLookupForPins,\n} from \"../engine/registry-client\";\nimport { SDK_CATALOG_PACKAGES, DERIVED_CATALOG_PINS } from \"../rules/root-pnpm-workspace\";\n\nexport type StructureMode = \"check\" | \"refresh\";\n\nexport type RunStructureInput = {\n /** User-supplied block path (resolved against cwd). */\n blockPath: string;\n isSdkInternal: boolean;\n updateDepsOnly: boolean;\n mode: StructureMode;\n /** `<block-tools>/src/structure/templates`. */\n templatesRoot: string;\n log: (msg: string) => void;\n};\n\nexport type RunStructureResult = {\n blockPath: string;\n changes: Change[];\n};\n\n/** Resolve the registry lookup for `--update-deps-only`: prefetch npm\n * \"latest\" for the SDK catalog MEMBERSHIP list (`SDK_CATALOG_PACKAGES`),\n * not the on-disk catalog keys, so the sync `ensureCatalogLatest` builder\n * can SEED a standard SDK key the block does not yet carry — reading\n * the on-disk catalog could never resolve an absent key. Mirrors\n * the `runInit` prefetch. A network failure during prefetch propagates. */\nasync function buildRegistryLookup(): Promise<(name: string) => string | undefined> {\n // Every SDK_CATALOG_PACKAGES entry matches a bump pattern (enforced at\n // load time in root-pnpm-workspace); filter defensively all the same.\n const names = SDK_CATALOG_PACKAGES.filter(matchesBumpPattern);\n return buildRegistryLookupForNames(names);\n}\n\nexport async function runStructureForPath(input: RunStructureInput): Promise<RunStructureResult> {\n const root = path.resolve(input.blockPath);\n const dryRun = input.mode === \"check\";\n\n const fs = new NodeFileSystem(root);\n const templates = new NodeTemplateProvider(input.templatesRoot);\n\n const ctx = discoverRunContext({\n fs,\n isSdkInternal: input.isSdkInternal,\n updateDepsOnly: input.updateDepsOnly,\n dryRun,\n });\n\n const registryLookup = input.updateDepsOnly ? await buildRegistryLookup() : undefined;\n // Derived catalog pins (e.g. vue ← ui-vue's declared dep) resolve on the\n // same prefetch budget as the SDK latest bump; absent on a default refresh.\n const derivedPinLookup = input.updateDepsOnly\n ? await buildDerivedPinLookupForPins(DERIVED_CATALOG_PINS)\n : undefined;\n\n const result = engineRun(STRUCTURE, fs, ctx, {\n templates,\n registryLookup,\n derivedPinLookup,\n // Fresh re-discovery for the post-run recheck (default refresh only)\n // — re-reads the just-written tree so a rename that shifted the\n // module map is observed.\n rediscover: () =>\n discoverRunContext({\n fs,\n isSdkInternal: input.isSdkInternal,\n updateDepsOnly: false,\n dryRun: true,\n }),\n });\n\n return { blockPath: input.blockPath, changes: result.changes };\n}\n\n/** One-line-per-change summary for CLI output. */\nexport function formatChanges(blockPath: string, changes: Change[]): string {\n if (changes.length === 0) return ` ${blockPath}: up to date (0 changes)`;\n const lines = changes.map(\n (c) => ` ${c.action.padEnd(6)} ${c.primitive.padEnd(8)} ${c.path} [${c.scope}]`,\n );\n return ` ${blockPath}: ${changes.length} change(s)\\n${lines.join(\"\\n\")}`;\n}\n","import { Command } from \"commander\";\nimport path from \"node:path\";\nimport type { MiLogger } from \"@milaboratories/ts-helpers\";\nimport { ConsoleLoggerAdapter } from \"@milaboratories/ts-helpers\";\nimport { runStructureForPath, formatChanges } from \"../../structure/cli/run-structure\";\n\n// Shared by `structure refresh` and the deprecated `update-deps` alias.\nexport async function runRefresh(opts: {\n paths: string[];\n isSdkInternal: boolean;\n updateDepsOnly: boolean;\n templatesRoot: string;\n logger: MiLogger;\n}): Promise<void> {\n for (const p of opts.paths) {\n const res = await runStructureForPath({\n blockPath: p,\n isSdkInternal: opts.isSdkInternal,\n updateDepsOnly: opts.updateDepsOnly,\n mode: \"refresh\",\n templatesRoot: opts.templatesRoot,\n log: (m) => opts.logger.info(m),\n });\n opts.logger.info(formatChanges(p, res.changes));\n }\n}\n\nexport function structureRefreshCommand(packageRoot: string): Command {\n const cmd = new Command(\"refresh\").description(\n \"Bring block(s) up to date with the canonical structure. Applies rules, writes files, bumps .structure version. Default mode is offline; --update-deps-only fires only catalog-bump rules (network).\",\n );\n\n cmd.argument(\"[paths...]\", \"block path(s); defaults to the current directory\");\n cmd.option(\"--sdk-internal\", \"block(s) live inside the SDK monorepo; skip root-scope rules\");\n cmd.option(\n \"--update-deps-only\",\n \"fire ONLY catalog-bump rules (npm network). Follow with `pnpm install` then a plain refresh.\",\n );\n\n cmd.action(async (argv: string[], flags) => {\n const paths = argv.length > 0 ? argv : [\".\"];\n const templatesRoot = path.join(packageRoot, \"src\", \"structure\", \"templates\");\n await runRefresh({\n paths,\n isSdkInternal: Boolean(flags.sdkInternal),\n updateDepsOnly: Boolean(flags.updateDepsOnly),\n templatesRoot,\n logger: new ConsoleLoggerAdapter(),\n });\n });\n\n return cmd;\n}\n","import { Command } from \"commander\";\nimport path from \"node:path\";\nimport { ConsoleLoggerAdapter } from \"@milaboratories/ts-helpers\";\nimport { runRefresh } from \"./structure/refresh\";\n\n/**\n * Deprecated. Phase-2 forwarding alias (spec.md § \"Coexistence And\n * Retirement\"): delegates to `structure refresh --update-deps-only`,\n * which lands at parity with the old `blocks-deps-updater` catalog-bump\n * semantics. Prints a deprecation warning; will be removed once the\n * structurer path has been live without surprises.\n */\nexport function updateDepsCommand(packageRoot: string): Command {\n const cmd = new Command(\"update-deps\").description(\n \"[DEPRECATED] Use `block-tools structure refresh --update-deps-only`. This alias delegates to it.\",\n );\n\n cmd.action(async () => {\n const logger = new ConsoleLoggerAdapter();\n logger.warn(\n \"`block-tools update-deps` is deprecated and will be removed in a future release. \" +\n \"Use `block-tools structure refresh --update-deps-only` instead. Delegating now.\",\n );\n const templatesRoot = path.join(packageRoot, \"src\", \"structure\", \"templates\");\n await runRefresh({\n paths: [\".\"],\n isSdkInternal: false,\n updateDepsOnly: true,\n templatesRoot,\n logger,\n });\n });\n\n return cmd;\n}\n","import { Command, Option } from \"commander\";\nimport { BlockRegistryV2 } from \"../v2/registry/registry\";\nimport { storageByUrl } from \"../io/storage\";\nimport { ConsoleLoggerAdapter } from \"@milaboratories/ts-helpers\";\n\nexport function listOverviewSnapshotsCommand(): Command {\n const cmd = new Command(\"list-overview-snapshots\").description(\n \"List all available global overview snapshots in the registry\",\n );\n\n cmd.addOption(\n new Option(\"-r, --registry <address>\", \"full address of the registry\")\n .env(\"PL_REGISTRY\")\n .makeOptionMandatory(),\n );\n cmd.option(\"--json\", \"output in JSON format\", false);\n\n cmd.action(async (flags) => {\n const logger = new ConsoleLoggerAdapter();\n const storage = storageByUrl(flags.registry);\n const registry = new BlockRegistryV2(storage, logger);\n\n const snapshots = await registry.listGlobalOverviewSnapshots();\n\n if (flags.json) {\n logger.info(JSON.stringify(snapshots, null, 2));\n } else {\n if (snapshots.length === 0) {\n logger.info(\"No snapshots found.\");\n } else {\n logger.info(`Found ${snapshots.length} snapshot(s):\\n`);\n for (const snapshot of snapshots) {\n logger.info(` ${snapshot.timestamp}`);\n logger.info(` Path: ${snapshot.path}`);\n logger.info(\"\");\n }\n }\n }\n });\n\n return cmd;\n}\n","import { Command, Option } from \"commander\";\nimport { BlockRegistryV2 } from \"../v2/registry/registry\";\nimport { storageByUrl } from \"../io/storage\";\nimport { ConsoleLoggerAdapter } from \"@milaboratories/ts-helpers\";\n\nexport function restoreOverviewFromSnapshotCommand(): Command {\n const cmd = new Command(\"restore-overview-from-snapshot\").description(\n \"Restore global overview from a snapshot\",\n );\n\n cmd.addOption(\n new Option(\"-r, --registry <address>\", \"full address of the registry\")\n .env(\"PL_REGISTRY\")\n .makeOptionMandatory(),\n );\n cmd.requiredOption(\"-s, --snapshot <timestamp>\", \"snapshot timestamp ID to restore from\");\n cmd.option(\"--skip-confirmation\", \"skip confirmation prompt (use with caution)\", false);\n\n cmd.action(async (flags) => {\n const logger = new ConsoleLoggerAdapter();\n const storage = storageByUrl(flags.registry);\n const registry = new BlockRegistryV2(storage, logger);\n\n // Check if snapshot exists\n const snapshots = await registry.listGlobalOverviewSnapshots();\n const targetSnapshot = snapshots.find((s) => s.timestamp === flags.snapshot);\n\n if (!targetSnapshot) {\n throw new Error(\n `Snapshot '${flags.snapshot}' not found. Available snapshots:\\n${\n snapshots.map((s) => ` - ${s.timestamp}`).join(\"\\n\") || \" (none)\"\n }`,\n );\n }\n\n // Confirmation prompt (unless skipped)\n if (!flags.skipConfirmation) {\n const readline = await import(\"node:readline\");\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n const answer = await new Promise<string>((resolve) => {\n rl.question(\n `⚠️ This will overwrite the current global overview with snapshot '${flags.snapshot}'.\\n` +\n `Are you sure you want to continue? (y/N): `,\n resolve,\n );\n });\n\n rl.close();\n\n if (answer.toLowerCase() !== \"y\" && answer.toLowerCase() !== \"yes\") {\n logger.info(\"Restore cancelled.\");\n return;\n }\n }\n\n // Perform restore\n try {\n await registry.restoreGlobalOverviewFromSnapshot(flags.snapshot);\n logger.info(`✅ Successfully restored global overview from snapshot '${flags.snapshot}'`);\n } catch (error) {\n throw new Error(`Failed to restore from snapshot: ${String(error)}`);\n }\n });\n\n return cmd;\n}\n","import { Option } from \"commander\";\nimport path from \"node:path\";\n\nexport interface TargetFile {\n src: string;\n destName: string;\n}\n\nfunction parseTargetFile(arg: string): TargetFile {\n const match = arg.match(/(?<destName>[^/\\\\]+)=(?<src>.*)/);\n if (match) {\n const { src, destName } = match.groups!;\n return { src, destName };\n } else {\n return { src: arg, destName: path.basename(arg) };\n }\n}\n\n// Repeatable `file_path | package_name=file_path` option.\nexport function targetFileOption(flags: string, summary: string): Option {\n return new Option(flags, summary)\n .argParser((arg: string, prev?: TargetFile[]) => [...(prev ?? []), parseTargetFile(arg)])\n .default([] as TargetFile[]);\n}\n","import { Command, Option } from \"commander\";\nimport { getConfig } from \"../registry_v1/config\";\nimport { targetFileOption } from \"../registry_v1/flags\";\nimport fs from \"node:fs\";\nimport YAML from \"yaml\";\nimport { PlRegPackageConfigDataShard } from \"../registry_v1/config_schema\";\nimport { ConsoleLoggerAdapter } from \"@milaboratories/ts-helpers\";\n\ntype BasicConfigField = keyof PlRegPackageConfigDataShard &\n (\"registry\" | \"organization\" | \"package\" | \"version\");\nconst BasicConfigFields: BasicConfigField[] = [\"registry\", \"organization\", \"package\", \"version\"];\n\nexport function uploadPackageV1Command(): Command {\n const cmd = new Command(\"upload-package-v1\").description(\n \"Uploads V1 package and refreshes the registry\",\n );\n\n cmd.addOption(\n new Option(\n \"-r, --registry <address|alias>\",\n \"full address of the registry or alias from .pl.reg\",\n ).env(\"PL_REGISTRY\"),\n );\n cmd.addOption(\n new Option(\"-o, --organization <organization>\", \"target organisation\").env(\n \"PL_PACKAGE_ORGANIZATION\",\n ),\n );\n cmd.addOption(new Option(\"-p, --package <package>\", \"target package\").env(\"PL_PACKAGE_NAME\"));\n cmd.addOption(new Option(\"-v, --version <version>\", \"target version\").env(\"PL_PACKAGE_VERSION\"));\n cmd.option(\n \"-m, --meta <path>\",\n \"json file containing meta information to associate with tha package\",\n );\n cmd.addOption(targetFileOption(\"-f, --file <file>\", \"package files\"));\n cmd.addOption(\n new Option(\"--refresh\", \"refresh repository after adding the package\")\n .default(true)\n .env(\"PL_REGISTRY_REFRESH\"),\n );\n cmd.option(\"--no-refresh\", \"do not refresh repository after adding the package\");\n\n cmd.action(async (flags) => {\n const logger = new ConsoleLoggerAdapter();\n const configFromFlags: PlRegPackageConfigDataShard = PlRegPackageConfigDataShard.parse({});\n\n for (const field of BasicConfigFields) if (flags[field]) configFromFlags[field] = flags[field];\n\n if (flags.meta) {\n if (flags.meta.endsWith(\".json\"))\n configFromFlags.meta = JSON.parse(\n await fs.promises.readFile(flags.meta, { encoding: \"utf-8\" }),\n ) as Record<string, unknown>;\n else if (flags.meta.endsWith(\".yaml\"))\n configFromFlags.meta = YAML.parse(\n await fs.promises.readFile(flags.meta, { encoding: \"utf-8\" }),\n ) as Record<string, unknown>;\n }\n\n for (const targetFile of flags.file) {\n configFromFlags.files[targetFile.destName] = targetFile.src;\n }\n\n const conf = await getConfig(configFromFlags);\n\n logger.info(YAML.stringify(conf.conf));\n\n const registry = conf.createRegistry(logger);\n const name = conf.fullPackageName;\n\n const builder = registry.constructNewPackage(name);\n\n for (const [dst, src] of Object.entries(conf.conf.files)) {\n logger.info(`Uploading ${src} -> ${dst} ...`);\n const content = await fs.promises.readFile(src);\n await builder.addFile(dst, content);\n }\n\n logger.info(`Uploading meta information...`);\n await builder.writeMeta(conf.conf.meta);\n await builder.finish();\n\n if (flags.refresh) await registry.updateIfNeeded();\n });\n\n return cmd;\n}\n","import { Command } from \"commander\";\nimport path from \"node:path\";\nimport { ConsoleLoggerAdapter } from \"@milaboratories/ts-helpers\";\nimport { runStructureForPath, formatChanges } from \"../../structure/cli/run-structure\";\n\nexport function structureCheckCommand(packageRoot: string): Command {\n const cmd = new Command(\"check\").description(\n \"Check block(s) against the canonical structure (read-only). Exits non-zero if any diff would land — used as the CI gate.\",\n );\n\n // Variadic positional block paths (shell-expanded globs).\n cmd.argument(\"[paths...]\", \"block path(s); defaults to the current directory\");\n cmd.option(\"--sdk-internal\", \"block(s) live inside the SDK monorepo; skip root-scope rules\");\n\n cmd.action(async (argv: string[], flags) => {\n const logger = new ConsoleLoggerAdapter();\n const paths = argv.length > 0 ? argv : [\".\"];\n const templatesRoot = path.join(packageRoot, \"src\", \"structure\", \"templates\");\n\n let anyChanged = false;\n for (const p of paths) {\n const res = await runStructureForPath({\n blockPath: p,\n isSdkInternal: Boolean(flags.sdkInternal),\n updateDepsOnly: false,\n mode: \"check\",\n templatesRoot,\n log: (m) => logger.info(m),\n });\n logger.info(formatChanges(p, res.changes));\n if (res.changes.length > 0) anyChanged = true;\n }\n\n if (anyChanged) {\n throw new Error(\n \"Structure check failed: one or more blocks are out of date. Run `structure refresh`.\",\n );\n }\n });\n\n return cmd;\n}\n","// `block-tools structure init` constructor: collects BlockVars from CLI\n// flags (prompting for any missing field unless --non-interactive),\n// assembles `ctx.modules` via the shared `modulesForInit`, and runs the\n// engine in init mode against a NodeFileSystem rooted at the target dir.\n//\n// Replaces the manual `git clone platforma-block-boilerplate` workflow\n// and `pl-dev create-block`. `--platform` is single-valued: a\n// freshly-init'd block has at most one software module.\n\nimport { confirm, input, select } from \"@inquirer/prompts\";\nimport { NodeFileSystem } from \"./engine/fs/node\";\nimport { NodeTemplateProvider } from \"./engine/templates\";\nimport { run as engineRun } from \"./engine/runner\";\nimport { createRunContext, modulesForInit } from \"./engine/ctx\";\nimport { STRUCTURE } from \"./structure-definition\";\nimport { STRUCTURE_VERSION } from \"./engine/version\";\nimport {\n matchesBumpPattern,\n buildRegistryLookupForNames,\n buildDerivedPinLookupForPins,\n} from \"./engine/registry-client\";\nimport { SDK_CATALOG_PACKAGES, DERIVED_CATALOG_PINS } from \"./rules/root-pnpm-workspace\";\nimport type { BlockVars } from \"./engine/api\";\n\n/** Platform choices `init` can scaffold a software module for. Python is\n * the only platform with a real, buildable scaffold at v1; any other\n * value is rejected rather than scaffolded as a non-buildable placeholder,\n * which would defeat the \"init must produce a working block\" intent.\n * `softwarePlatform` stays in BlockVars for when another platform gets a\n * real scaffold. (Note: Tengo is the workflow language, not a software\n * platform.) */\nexport const SUPPORTED_PLATFORMS = [\"python\"] as const;\n\nexport type InitFlagValues = {\n npmOrg?: string;\n orgScope?: string;\n shortName?: string;\n /** Tri-state: true (--with-software), false (--no-software),\n * undefined (unspecified → prompt or, non-interactive, default off). */\n withSoftware?: boolean;\n platform?: string;\n nonInteractive: boolean;\n};\n\nexport type InitInput = {\n /** Resolved BlockVars (from `resolveBlockVars`). */\n vars: BlockVars;\n /** Resolved absolute target directory. */\n blockPath: string;\n /** `<block-tools>/src/structure/templates`. */\n templatesRoot: string;\n log: (msg: string) => void;\n};\n\nclass InitFlagError extends Error {\n constructor(flag: string) {\n super(\n `Missing required flag --${flag} in --non-interactive mode. ` +\n `Supply every BlockVars flag, or drop --non-interactive to be prompted.`,\n );\n this.name = \"InitFlagError\";\n }\n}\n\nasync function need(\n value: string | undefined,\n flag: string,\n nonInteractive: boolean,\n prompt: () => Promise<string>,\n): Promise<string> {\n if (value !== undefined && value !== \"\") return value;\n if (nonInteractive) throw new InitFlagError(flag);\n return prompt();\n}\n\n/** Resolve the full BlockVars (incl. softwarePlatform) from flags +\n * prompts. */\nexport async function resolveBlockVars(flags: InitFlagValues): Promise<BlockVars> {\n const npmOrg = await need(flags.npmOrg, \"npm-org\", flags.nonInteractive, () =>\n input({ message: \"npm org (e.g. @platforma-open):\", default: \"@platforma-open\" }),\n );\n const orgScope = await need(flags.orgScope, \"org-scope\", flags.nonInteractive, () =>\n input({ message: \"org scope (e.g. my-org):\" }),\n );\n const shortName = await need(flags.shortName, \"short-name\", flags.nonInteractive, () =>\n input({ message: \"block short name (e.g. mixcr-clonotyping):\" }),\n );\n\n // Software: explicit flag wins; otherwise prompt (interactive) or\n // default off (non-interactive).\n let hasSoftware: boolean;\n if (flags.withSoftware !== undefined) {\n hasSoftware = flags.withSoftware;\n } else if (flags.nonInteractive) {\n hasSoftware = false;\n } else {\n hasSoftware = await confirm({ message: \"Include a software module?\", default: false });\n }\n\n let softwarePlatform: string | undefined;\n if (hasSoftware) {\n softwarePlatform = await need(flags.platform, \"platform\", flags.nonInteractive, () =>\n select({\n message: \"Software platform:\",\n choices: SUPPORTED_PLATFORMS.map((p) => ({ name: p, value: p })),\n }),\n );\n if (!(SUPPORTED_PLATFORMS as readonly string[]).includes(softwarePlatform)) {\n throw new Error(\n `Unsupported --platform '${softwarePlatform}'. ` +\n `Only ${SUPPORTED_PLATFORMS.join(\", \")} ${\n SUPPORTED_PLATFORMS.length === 1 ? \"is\" : \"are\"\n } supported at v1.`,\n );\n }\n } else if (flags.platform) {\n throw new Error(\"--platform was given but software is disabled (--no-software).\");\n }\n\n const facadeName = `${npmOrg}/${orgScope}.${shortName}`;\n return {\n facadeName,\n baseName: `${orgScope}.${shortName}`,\n npmOrg,\n orgScope,\n shortName,\n softwarePlatform,\n };\n}\n\nexport async function runInit(init: InitInput): Promise<BlockVars> {\n const vars = init.vars;\n const modules = modulesForInit(vars);\n\n const fs = new NodeFileSystem(init.blockPath);\n const templates = new NodeTemplateProvider(init.templatesRoot);\n const ctx = createRunContext({\n blockVars: vars,\n modules,\n isSdkInternal: false,\n version: STRUCTURE_VERSION,\n dryRun: false,\n });\n\n // Init REQUIRES network: resolve the SDK catalog families to npm latest\n // before the run, so the generated block carries real current versions\n // (no placeholders). The names come from the SDK catalog package list —\n // there is no on-disk pnpm-workspace.yaml to read yet. A registry failure\n // aborts init rather than silently shipping an unresolved placeholder.\n const sdkNames = SDK_CATALOG_PACKAGES.filter(matchesBumpPattern);\n let registryLookup: (name: string) => string | undefined;\n let derivedPinLookup: (entry: string) => string | undefined;\n try {\n registryLookup = await buildRegistryLookupForNames(sdkNames);\n // Derived catalog pins (e.g. vue ← ui-vue's declared dep) are resolved on\n // init too, so a freshly-scaffolded block pins vue exactly from the start.\n derivedPinLookup = await buildDerivedPinLookupForPins(DERIVED_CATALOG_PINS);\n } catch (err) {\n throw new Error(\n `init requires network access to resolve SDK catalog versions from npm, ` +\n `but the registry lookup failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n engineRun(STRUCTURE, fs, ctx, {\n templates,\n initMode: true,\n registryLookup,\n derivedPinLookup,\n });\n init.log(\n `Initialised block '${vars.facadeName}'${\n vars.softwarePlatform ? ` (software: ${vars.softwarePlatform})` : \" (no software)\"\n } at ${init.blockPath}`,\n );\n return vars;\n}\n","import { Command, Option } from \"commander\";\nimport path from \"node:path\";\nimport { ConsoleLoggerAdapter } from \"@milaboratories/ts-helpers\";\nimport {\n resolveBlockVars,\n runInit,\n SUPPORTED_PLATFORMS,\n type InitFlagValues,\n} from \"../../structure/init-block-constructor\";\n\nexport function structureInitCommand(packageRoot: string): Command {\n const cmd = new Command(\"init\").description(\n \"Scaffold a fresh Platforma block from the canonical structure. Missing flags are prompted unless --non-interactive.\",\n );\n\n cmd.argument(\"[path]\", \"target directory (default: <short-name> under the current directory)\");\n cmd.option(\"--npm-org <org>\", \"npm org, e.g. @platforma-open\");\n cmd.option(\"--org-scope <scope>\", \"org scope, e.g. my-org\");\n cmd.option(\"--short-name <name>\", \"block short name, e.g. mixcr-clonotyping\");\n cmd.option(\"--with-software\", \"include a software module\");\n cmd.option(\"--no-software\", \"omit the software module\");\n cmd.addOption(\n new Option(\"--platform <platform>\", \"software platform (single-valued)\").choices([\n ...SUPPORTED_PLATFORMS,\n ]),\n );\n cmd.option(\"--non-interactive\", \"error on any missing flag instead of prompting\");\n\n cmd.action(async (argPath: string | undefined, flags) => {\n const logger = new ConsoleLoggerAdapter();\n\n // commander maps `--with-software` -> flags.withSoftware===true and\n // `--no-software` -> flags.software===false\n const withSoftwareFlag = flags.withSoftware === true;\n const noSoftwareFlag = flags.software === false;\n if (withSoftwareFlag && noSoftwareFlag) {\n throw new Error(\"--with-software and --no-software are mutually exclusive.\");\n }\n const withSoftware = withSoftwareFlag ? true : noSoftwareFlag ? false : undefined;\n\n const flagValues: InitFlagValues = {\n npmOrg: flags.npmOrg,\n orgScope: flags.orgScope,\n shortName: flags.shortName,\n withSoftware,\n platform: flags.platform,\n nonInteractive: flags.nonInteractive,\n };\n\n const vars = await resolveBlockVars(flagValues);\n const blockPath = argPath ? path.resolve(argPath) : path.resolve(process.cwd(), vars.shortName);\n const templatesRoot = path.join(packageRoot, \"src\", \"structure\", \"templates\");\n\n await runInit({ vars, blockPath, templatesRoot, log: (m) => logger.info(m) });\n });\n\n return cmd;\n}\n","import { util } from \"@platforma-sdk/package-builder-lib\";\n\nexport const channels = [\"dev\", \"release\"] as const;\nexport const variants = [\"docker\", \"binary\", \"all\", \"none\"] as const;\nexport const locations = [\"local\", \"remote\"] as const;\n\nexport type Channel = (typeof channels)[number];\nexport type Variant = (typeof variants)[number];\nexport type Location = (typeof locations)[number];\n\n// Raw CLI flags, each independently optional; parseScenario narrows them to a supported Scenario.\nexport type Knobs = {\n channel?: Channel;\n variant?: Variant;\n location?: Location;\n usePublished?: boolean;\n};\n\n// The variant a resolved target actually builds — \"none\" is its own scenario, never a target.\nexport type TargetVariant = Exclude<Variant, \"none\">;\n\n// The closed set of scenarios runBuild executes; parseScenario rejects anything else. `target`\n// carries the resolved knobs as enums (not pre-derived booleans) — runBuild derives the flags.\nexport type Scenario =\n // `build:dev-binary-existing` (PL_BUILD_USE_PUBLISHED): reference the published binary; no build/push.\n | { kind: \"binary-existing\" }\n // `build:dev-no-software` (PL_BUILD_VARIANT=none): placeholder descriptors; nothing built or pushed.\n | { kind: \"no-software\" }\n // no build:* script — the scriptless default (direct call / `do-pack`); drop-in `pl-pkg build`.\n | { kind: \"bare\" }\n // `build:dev-local` / `build:dev-remote` / `build:release` / `test`: build for a target.\n | { kind: \"target\"; channel: Channel; variant: TargetVariant; location: Location };\n\n// Collapse the raw knobs to a supported Scenario; the one place bad combinations are rejected.\nexport function parseScenario(knobs: Knobs): Scenario {\n if (knobs.usePublished) {\n // A published binary can be referenced; docker (and `all`, which includes it) cannot.\n if (knobs.variant === \"docker\" || knobs.variant === \"all\") {\n throw util.CLIError(\n `--use-published is binary-only and cannot be combined with --variant ${knobs.variant}`,\n );\n }\n return { kind: \"binary-existing\" };\n }\n\n if (knobs.variant === \"none\") {\n return { kind: \"no-software\" };\n }\n\n if (knobs.location === undefined) {\n return { kind: \"bare\" };\n }\n\n // `all` (the default) builds every declared variant; the engine skips the kinds the software omits.\n return {\n kind: \"target\",\n channel: knobs.channel ?? \"release\",\n variant: knobs.variant ?? \"all\",\n location: knobs.location,\n };\n}\n","import { spawnSync } from \"node:child_process\";\nimport * as os from \"node:os\";\nimport {\n ECRPUBLICClient as EcrPublicClient,\n GetAuthorizationTokenCommand,\n} from \"@aws-sdk/client-ecr-public\";\nimport { util, defaults, type Logger } from \"@platforma-sdk/package-builder-lib\";\n\nconst PUBLIC_ECR_HOST = \"public.ecr.aws\";\n// ECR Public's API is served only from us-east-1, independent of where images are pulled.\nconst PUBLIC_ECR_REGION = \"us-east-1\";\n\n// Pin AWS_PROFILE once so the ECR client and the S3 upload resolve identical credentials.\n// Env credentials (CI) and an explicit AWS_PROFILE take precedence and skip this.\nexport function ensureAwsProfile(logger?: Logger): void {\n if (process.env.AWS_ACCESS_KEY_ID || process.env.AWS_PROFILE) return;\n const profile = process.env.PL_AWS_PROFILE ?? defaults.AWS_DEV_PROFILE;\n process.env.AWS_PROFILE = profile;\n logger?.debug(`Using AWS profile '${profile}' for dev push credentials`);\n}\n\n// Host of a scheme-less registry ref: public.ecr.aws/u5p1x5q2/pl-containers -> public.ecr.aws\nfunction registryHost(registry: string): string {\n return new URL(`https://${registry}`).hostname;\n}\n\nfunction ssoLoginHint(): string {\n const profile = process.env.AWS_PROFILE ?? process.env.PL_AWS_PROFILE ?? defaults.AWS_DEV_PROFILE;\n return ` aws sso login --profile ${profile}`;\n}\n\n// docker login to public ECR with an SDK-fetched token. No cached-auth check — re-authenticates\n// every call, so an expired/absent session fails here with a recoverable hint, not opaquely at push.\nexport async function ensureEcrLogin(registry: string, logger?: Logger): Promise<void> {\n const host = registryHost(registry);\n if (host !== PUBLIC_ECR_HOST) {\n // Public ECR is the only dev docker registry; reject a mis-set ecr:// override.\n throw util.CLIError(\n `automatic docker login is only supported for '${PUBLIC_ECR_HOST}', not '${host}'.\\n` +\n `Log in manually, or drop the ecr:// scheme from the push target to opt out.`,\n );\n }\n\n logger?.info(`Logging in to ECR registry '${host}'...`);\n\n let user: string;\n let password: string;\n try {\n const client = new EcrPublicClient({ region: PUBLIC_ECR_REGION });\n const res = await client.send(new GetAuthorizationTokenCommand({}));\n const token = res.authorizationData?.authorizationToken;\n if (!token) throw new Error(\"empty authorization token\");\n // Token decodes to \"AWS:<password>\"; password may contain ':', so split on the first only.\n const decoded = Buffer.from(token, \"base64\").toString(\"utf8\");\n const sep = decoded.indexOf(\":\");\n if (sep < 0) throw new Error(`malformed authorization token (no ':' separator)`);\n user = decoded.slice(0, sep);\n password = decoded.slice(sep + 1);\n } catch (e) {\n throw util.CLIError(\n `failed to obtain an ECR login token for '${host}': ${e instanceof Error ? e.message : String(e)}\\n` +\n `Your AWS/SSO session is likely expired or absent — log in and retry:\\n` +\n ssoLoginHint(),\n );\n }\n\n const login = spawnSync(\"docker\", [\"login\", \"--username\", user, \"--password-stdin\", host], {\n input: password,\n stdio: [\"pipe\", \"inherit\", \"inherit\"],\n env: { ...process.env, HOME: process.env.HOME || os.homedir() },\n });\n if (login.error || login.status !== 0) {\n throw util.CLIError(`'docker login ${host}' failed`);\n }\n}\n","import {\n util,\n envs,\n defaults,\n type Builder,\n type Logger,\n} from \"@platforma-sdk/package-builder-lib\";\nimport type { Channel, Scenario } from \"./knobs\";\nimport { ensureAwsProfile, ensureEcrLogin } from \"./ecr-login\";\n\n// Pass-through controls mirroring `pl-pkg build`. Empty means \"engine default\". The --docker-/\n// --conda- flag pairs are already collapsed to decisions at the CLI boundary (build.ts): only the\n// `bare` scenario reads buildDocker/pushDocker; condaBuild applies to every binary build.\nexport type BuildOptions = {\n ids?: string[];\n force?: boolean;\n contentRoot?: string;\n storageUrl?: string;\n dockerRegistry?: string;\n dockerPushTo?: string;\n buildDocker?: boolean;\n pushDocker?: boolean;\n condaBuild?: boolean;\n};\n\n// Build a scenario in one pass: build, push when remote, then write the descriptor last —\n// \"ready ⟺ the descriptor exists\". The pre-configured builder is injected; runBuild sets the\n// scenario's build mode and drives it.\nexport async function runBuild(params: {\n core: Builder;\n scenario: Scenario;\n options?: BuildOptions;\n logger?: Logger;\n}): Promise<void> {\n const { core, scenario, options: opts = {}, logger } = params;\n const ids = opts.ids;\n core.buildMode = buildModeForScenario(scenario);\n\n const buildBinary = () =>\n core.buildSoftwareArchives({\n ids,\n forceBuild: Boolean(opts.force),\n contentRoot: opts.contentRoot,\n // Tolerate a package with no archives only on a build-all run; when specific ids are\n // requested, an empty build is a real error the caller wants to hear about.\n skipIfEmpty: !ids,\n condaBuild: opts.condaBuild,\n });\n\n switch (scenario.kind) {\n case \"binary-existing\":\n // Descriptor points at an already-published release artifact; nothing is built or pushed.\n core.writePublishedArtifactInfo({ ids });\n break;\n\n case \"no-software\":\n // Nothing built or pushed; the placeholder descriptor is written below.\n break;\n\n case \"bare\": {\n // Bare pl-pkg-parity invocation; buildDocker/pushDocker were resolved at the CLI boundary.\n if (opts.buildDocker) {\n core.buildDockerImages({\n ids,\n registry: opts.dockerRegistry,\n strictPlatformMatching: envs.isCI(),\n });\n }\n await buildBinary();\n if (opts.pushDocker) {\n core.publishDockerImages({\n ids,\n pushTo: opts.dockerPushTo,\n strictPlatformMatching: envs.isCI(),\n });\n }\n break;\n }\n\n case \"target\": {\n const { channel, variant, location } = scenario;\n const docker = variant !== \"binary\";\n const binary = variant !== \"docker\";\n const remote = location === \"remote\";\n const addr = resolveDockerAddresses(channel, opts);\n\n // BUILD (descriptor not written yet).\n if (docker) {\n core.buildDockerImages({ ids, registry: addr.pull, strictPlatformMatching: envs.isCI() });\n }\n if (binary) await buildBinary();\n\n // PUSH when remote. Pin the AWS credential chain once (docker login + S3 upload share it), but\n // only for dev — the fallback profile is the dev SSO one.\n if (remote && channel === \"dev\" && (docker || binary)) ensureAwsProfile(logger);\n if (docker && remote) {\n if (addr.autoLogin && addr.push) await ensureEcrLogin(addr.push, logger);\n core.publishDockerImages({ ids, pushTo: addr.push, strictPlatformMatching: envs.isCI() });\n }\n if (binary && remote) {\n // storageURL falls through to the engine, which resolves the dev/release endpoint.\n await core.publishPackages({ ids, storageURL: opts.storageUrl });\n }\n break;\n }\n\n default:\n util.assertNever(scenario);\n }\n\n // DESCRIPTOR LAST — only after build + push have succeeded.\n core.buildSwJsonFiles({ packageIds: ids, noSoftware: scenario.kind === \"no-software\" });\n}\n\nfunction buildModeForScenario(scenario: Scenario): util.BuildMode {\n if (scenario.kind !== \"target\") return \"release\";\n if (scenario.channel === \"release\") return \"release\";\n // Only a remote binary build needs dev-remote (it uploads an archive). Docker-only, or any\n // local build, uses dev-local — docker naming is content-addressed by image ID regardless.\n const binaryRemote = scenario.variant !== \"docker\" && scenario.location === \"remote\";\n return binaryRemote ? \"dev-remote\" : \"dev-local\";\n}\n\n// Bare registry ref (host[:port]/path) with any URL scheme removed.\nfunction stripScheme(raw: string): string {\n if (!raw.includes(\"://\")) return raw; // already bare\n const url = new URL(raw);\n return url.host + url.pathname;\n}\n\n// A push target may carry a scheme selecting auto docker-login: `ecr://` opts in, anything else out.\nfunction parsePushTarget(raw: string): { registry: string; autoLogin: boolean } {\n return { registry: stripScheme(raw), autoLogin: raw.startsWith(\"ecr://\") };\n}\n\n// Docker push target + the pull address embedded in the descriptor. Precedence flag > channel env >\n// dev default (release has none). Pull default is channel-specific: dev pulls from where it pushed\n// (one ECR host), but release push (quay) and pull (containers.pl-open.science, GA-fronted proxy) are\n// different locations by design, so release pull defaults to the built-in registry, NOT the push\n// target. autoLogin follows the push target's ecr://.\nfunction resolveDockerAddresses(\n channel: Channel,\n opts: BuildOptions,\n): { pull?: string; push?: string; autoLogin: boolean } {\n const isDev = channel === \"dev\";\n const channelPush =\n process.env[isDev ? envs.PL_DEV_DOCKER_PUSH_URL : envs.PL_RELEASE_DOCKER_PUSH_URL];\n const channelPull =\n process.env[isDev ? envs.PL_DEV_DOCKER_PULL_URL : envs.PL_RELEASE_DOCKER_PULL_URL];\n\n const rawPush =\n opts.dockerPushTo ?? channelPush ?? (isDev ? defaults.DEV_DOCKER_PUSH_TARGET : undefined);\n const parsed = rawPush ? parsePushTarget(rawPush) : { registry: undefined, autoLogin: false };\n\n const rawPull =\n opts.dockerRegistry ?? channelPull ?? (isDev ? rawPush : defaults.DOCKER_REGISTRY);\n const pull = rawPull ? stripScheme(rawPull) : undefined;\n\n return { pull, push: parsed.registry, autoLogin: parsed.autoLogin };\n}\n","import { envs } from \"@platforma-sdk/package-builder-lib\";\n\n// The `software build` knob env vars (the flag/env pairs the scenario scripts set).\nexport const PL_BUILD_CHANNEL = \"PL_BUILD_CHANNEL\";\nexport const PL_BUILD_VARIANT = \"PL_BUILD_VARIANT\";\nexport const PL_BUILD_LOCATION = \"PL_BUILD_LOCATION\";\nexport const PL_BUILD_USE_PUBLISHED = \"PL_BUILD_USE_PUBLISHED\";\n\n// Every env var that changes `block-tools software build` output, so must key the turbo build cache.\nexport const softwareBuildCacheEnv: readonly string[] = [\n PL_BUILD_CHANNEL,\n PL_BUILD_VARIANT,\n PL_BUILD_LOCATION,\n PL_BUILD_USE_PUBLISHED,\n envs.PL_DOCKER_REGISTRY_PUSH_TO,\n envs.PL_DEV_DOCKER_PUSH_URL,\n envs.PL_DEV_DOCKER_PULL_URL,\n envs.PL_DEV_BINARY_UPLOAD_URL,\n envs.PL_RELEASE_DOCKER_PUSH_URL,\n envs.PL_RELEASE_DOCKER_PULL_URL,\n envs.PL_RELEASE_BINARY_UPLOAD_URL,\n];\n","import { Command, Option } from \"commander\";\nimport {\n util,\n envs,\n createBuilder,\n assertDockerPushIntent,\n} from \"@platforma-sdk/package-builder-lib\";\nimport { parseScenario, channels, variants, locations } from \"./knobs\";\nimport { runBuild } from \"./run-build\";\nimport {\n PL_BUILD_CHANNEL,\n PL_BUILD_VARIANT,\n PL_BUILD_LOCATION,\n PL_BUILD_USE_PUBLISHED,\n} from \"./env\";\n\n// Build a software module in one pass — build, push when remote, then write the descriptor\n// last. With no knobs it reproduces `pl-pkg build`.\nexport function softwareBuildCommand(): Command {\n const cmd = new Command(\"build\").description(\n \"Build a software module for a target and write its .sw.json descriptor (build + push in one pass)\",\n );\n\n // The three target knobs (env-backed; flag wins on conflict).\n cmd.addOption(\n new Option(\"--channel <channel>\", \"registry channel to build for\")\n .choices([...channels])\n .env(PL_BUILD_CHANNEL),\n );\n cmd.addOption(\n new Option(\"--variant <variant>\", \"artifact kind to build (default: all declared)\")\n .choices([...variants])\n .env(PL_BUILD_VARIANT),\n );\n cmd.addOption(\n new Option(\"--location <location>\", \"where the artifact lands (local = no push)\")\n .choices([...locations])\n .env(PL_BUILD_LOCATION),\n );\n cmd.addOption(\n new Option(\n \"--use-published\",\n \"do not build or push; emit a descriptor pointing at the already-published release artifact\",\n ).env(PL_BUILD_USE_PUBLISHED),\n );\n\n // Pass-through build options, mirroring `pl-pkg build` so this is a drop-in replacement.\n cmd.addOption(\n new Option(\"--log-level <level>\", \"logging level\")\n .choices([\"error\", \"warn\", \"info\", \"debug\"])\n .default(\"info\"),\n );\n cmd.addOption(new Option(\"--package-root <path>\", \"path to directory with package.json file\"));\n cmd.addOption(\n new Option(\"--force\", \"force action, ignoring automatic safety checks\").default(false),\n );\n cmd.addOption(new Option(\"--version <value>\", \"override package version (ignore package.json)\"));\n cmd.addOption(\n new Option(\"--platform <os-arch>\", \"{os}-{arch} pair; no effect on cross-platform packages\")\n .choices([...util.AllPlatforms])\n .env(envs.PL_PKG_OS),\n );\n cmd.addOption(new Option(\"--all-platforms\", \"build for all supported platforms\").default(false));\n cmd.addOption(\n new Option(\"--full-dir-hash\", \"hash file contents (not metadata) for the dev content hash\")\n .env(envs.PL_PKG_FULL_HASH)\n .default(false),\n );\n cmd.addOption(new Option(\"--package-id <id...>\", \"act only on selected packages\"));\n cmd.addOption(\n new Option(\"--content-root <path>\", \"override software content root\").env(\n envs.PL_PKG_CONTENT_ROOT,\n ),\n );\n cmd.addOption(\n new Option(\"--storage-url <url>\", \"override binary upload registry URL\").env(\n envs.PL_PKG_STORAGE_URL,\n ),\n );\n cmd.addOption(\n new Option(\n \"--docker-registry <registry>\",\n \"docker pull registry embedded in the descriptor\",\n ).env(envs.PL_DOCKER_REGISTRY),\n );\n cmd.addOption(\n new Option(\"--docker-push-to <registry>\", \"alternative registry for docker push\").env(\n envs.PL_DOCKER_REGISTRY_PUSH_TO,\n ),\n );\n cmd.addOption(\n new Option(\"--docker-build\", \"build docker images\").env(envs.PL_DOCKER_BUILD).default(false),\n );\n cmd.addOption(\n new Option(\"--docker-no-build\", \"do not build docker images\")\n .env(envs.PL_DOCKER_NO_BUILD)\n .default(false),\n );\n cmd.addOption(\n new Option(\"--docker-autopush\", \"push docker images after build\")\n .env(envs.PL_DOCKER_AUTOPUSH)\n .default(false),\n );\n cmd.addOption(\n new Option(\"--docker-no-autopush\", \"do not push docker images\")\n .env(envs.PL_DOCKER_NO_AUTOPUSH)\n .default(false),\n );\n cmd.addOption(\n new Option(\"--conda-build\", \"build conda environment before packing\")\n .env(envs.PL_CONDA_BUILD)\n .default(false),\n );\n cmd.addOption(\n new Option(\"--conda-no-build\", \"do not build conda environment\")\n .env(envs.PL_CONDA_NO_BUILD)\n .default(false),\n );\n\n cmd.action(async (o) => {\n const logger = util.createLogger(o.logLevel);\n\n try {\n const scenario = parseScenario({\n channel: o.channel,\n variant: o.variant,\n location: o.location,\n usePublished: Boolean(o.usePublished),\n });\n\n const core = createBuilder(logger, { packageRoot: o.packageRoot });\n core.version = o.version;\n core.targetPlatform = o.platform as util.PlatformType;\n core.allPlatforms = Boolean(o.allPlatforms);\n core.fullDirHash = Boolean(o.fullDirHash);\n\n // Collapse the pl-pkg-parity --{docker,conda}-{,no-}* flag pairs to decisions here, at the CLI\n // boundary, so runBuild receives resolved booleans (docker defaults to on in CI, push unless private).\n const buildDocker = util.shouldDoAction({\n default: envs.isCI(),\n enable: o.dockerBuild,\n disable: o.dockerNoBuild,\n });\n const pushDocker =\n buildDocker &&\n util.shouldDoAction({\n default: envs.isCI() && !core.isPrivate,\n enable: o.dockerAutopush,\n disable: o.dockerNoAutopush,\n });\n\n // Only the bare (pl-pkg-parity) scenario derives its push from isPrivate; the\n // target scenarios push on location=remote and never consult it.\n if (scenario.kind === \"bare\") {\n assertDockerPushIntent({\n buildDocker,\n pushDocker,\n pushDisabledExplicitly: Boolean(o.dockerNoAutopush),\n dockerPackageCount: core.selectedDockerPackages(o.packageId).length,\n });\n }\n\n await runBuild({\n core,\n scenario,\n logger,\n options: {\n ids: o.packageId,\n force: o.force,\n contentRoot: o.contentRoot,\n storageUrl: o.storageUrl,\n dockerRegistry: o.dockerRegistry,\n dockerPushTo: o.dockerPushTo,\n buildDocker,\n pushDocker,\n condaBuild: util.shouldDoAction({\n default: true,\n enable: o.condaBuild,\n disable: o.condaNoBuild,\n }),\n },\n });\n } catch (e) {\n logger.debug(e);\n if (e instanceof Error) logger.debug(e.stack);\n throw e;\n }\n });\n\n return cmd;\n}\n","import { Command } from \"commander\";\nimport { softwareBuildCommand } from \"./build\";\n\n// `software` parent command: per-target software build (and future software subcommands).\nexport function softwareCommand(): Command {\n const cmd = new Command(\"software\").description(\"Build and publish a block's software modules\");\n cmd.addCommand(softwareBuildCommand());\n return cmd;\n}\n","import { Command } from \"commander\";\nimport { buildMetaCommand } from \"./cmd/build-meta\";\nimport { buildModelCommand } from \"./cmd/build-model\";\nimport { buildKindManifestCommand } from \"./cmd/build-kind-manifest\";\nimport { packCommand } from \"./cmd/pack\";\nimport { publishCommand } from \"./cmd/publish\";\nimport { refreshRegistryCommand } from \"./cmd/refresh-registry\";\nimport { markStableCommand } from \"./cmd/mark-stable\";\nimport { updateDepsCommand } from \"./cmd/update-deps\";\nimport { listOverviewSnapshotsCommand } from \"./cmd/list-overview-snapshots\";\nimport { restoreOverviewFromSnapshotCommand } from \"./cmd/restore-overview-from-snapshot\";\nimport { uploadPackageV1Command } from \"./cmd/upload-package-v1\";\nimport { structureCheckCommand } from \"./cmd/structure/check\";\nimport { structureInitCommand } from \"./cmd/structure/init\";\nimport { structureRefreshCommand } from \"./cmd/structure/refresh\";\nimport { softwareCommand } from \"./cmd/software\";\n\n// `packageRoot` is the package install root (the dir containing `src/` and\n// `bin/`); the `structure` commands resolve their templates under it. bin/run.js\n// passes it in; defaults to cwd for tests/introspection.\nexport function buildProgram(packageRoot: string = process.cwd()): Command {\n const program = new Command();\n program\n .name(\"block-tools\")\n .description(\"Utility to manipulate Platforma Blocks and Block Registry\");\n\n program.addCommand(buildMetaCommand());\n program.addCommand(buildModelCommand());\n program.addCommand(buildKindManifestCommand());\n program.addCommand(packCommand());\n program.addCommand(publishCommand());\n program.addCommand(refreshRegistryCommand());\n program.addCommand(markStableCommand());\n program.addCommand(updateDepsCommand(packageRoot));\n program.addCommand(listOverviewSnapshotsCommand());\n program.addCommand(restoreOverviewFromSnapshotCommand());\n program.addCommand(uploadPackageV1Command());\n program.addCommand(softwareCommand());\n\n // `structure` subcommands: check | init | refresh.\n const structure = new Command(\"structure\").description(\n \"Manage block scaffolding against the canonical structure (check / init / refresh)\",\n );\n structure.addCommand(structureCheckCommand(packageRoot));\n structure.addCommand(structureInitCommand(packageRoot));\n structure.addCommand(structureRefreshCommand(packageRoot));\n program.addCommand(structure);\n\n return program;\n}\n\nexport async function run(argv: string[], packageRoot: string): Promise<void> {\n await buildProgram(packageRoot).parseAsync(argv);\n}\n"],"mappings":"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"}
|