# Changes Record of accepted architectural decisions and visible surface changes for `lian-build`. Format follows [Keep a Changelog]; project is pre-1.0 so the SemVer guarantee is **not** yet in force — schema and CLI shape may break between minor versions until `0.1.0` is tagged. Dates reflect the ADR acceptance date or the date the on-disk artefact was recorded; this project does not yet publish git tags or release builds. [Keep a Changelog]: https://keepachangelog.com/en/1.1.0/ --- ## [Unreleased] — 0.1.0 ### Architecture - **adr-003 — Nickel coupled via subprocess, not library linkage** *(2026-05-03)* All NCL → Rust conversions flow through `directives::nickel_export(path, &[import_paths])`, which spawns `nickel export --format json` and feeds serde. No `nickel-lang*` crate is added to `Cargo.toml`. `nickel` is a runtime requirement on `$PATH`. - **adr-002 — CLI surface is subcommand-only with stdout reserved for structured envelopes** *(2026-05-03)* `lian-build` now exposes `{build, integrate}` as clap subcommands. There is no default subcommand and no flat-arg compatibility shim. `tracing_subscriber` is pinned to `with_writer(std::io::stderr)` so stdout carries at most one envelope per invocation. **Breaking** for any caller invoking the legacy `buildkit-launcher` flat-arg form: migrate to `lian-build build `. - **adr-001 — lian-build is a standalone build substrate, not part of provisioning** *(2026-05-01)* `buildkit-launcher` and `buildkit_runner` extracted from `provisioning/platform/crates/buildkit-launcher` and `provisioning/extensions/components/buildkit_runner` into this standalone project. Binary renamed from `buildkit-launcher` to `lian-build`. ### Added - `lian-build build` subcommand. Accepts flat args **or** `--directives `; directives take precedence over flat-arg fields when both are present (`src/main.rs::resolve_build_plan`). - `lian-build integrate` subcommand. Federated probe that reads a `SecretDeliveryContext` JSON envelope from stdin and emits a single `ResultEnvelope` JSON line on stdout (`src/integration/`). - `BuildDirectives` NCL vocabulary (`schemas/build_directives.ncl`) and matching Rust types in `src/directives.rs` with serde round-trip tests. - `BuildSpec` schema (`schemas/build_spec.ncl`) with `bounded_cpu_` ≤ 256 and `bounded_time_budget_` ≤ 1440 min contract bounds; honoured by `sizing::resolve` at the explicit-spec tier. - `CachePolicy` schema (`schemas/cache_policy.ncl`) with `BuildMode` = `'ci | 'session`, `SessionActor` (`'human | 'agent | 'ci_aux`), and `SessionCacheDisposition` (`'export | 'discard | 'rollback`). - `src/cache.rs` — `build_cache_flags(workspace, mode, registry)` returning import/export `Vec`; enforces `ci//*` (canonical, read-only to sessions) and `dev/-/*` (per-session). Invariants guarded by unit tests: `ci_never_imports_dev`, `session_never_exports_ci`, `session_imports_both_layers`, `mode_switch_purity`. - `src/sizing.rs` — three-tier resolution: explicit `.build-spec.ncl` → P95 historical (×1.2, floored) → language defaults (rust=4/8/60, go=2/4/30, java|kotlin|scala=4/8/45, default=2/4/30). - `src/retry.rs` — `MAX_OOM_RETRIES = 1` (hard bound), `SIZE_TIERS` walk `cx22 → cx32 → cx42 → cx52`. OOM is detected via exit-code `137` or stderr matching `OOM` / `Killed`. - `src/orchestrator_client.rs` — HTTP client wrapping responses in `ApiResponse { success, data, error }`. Methods: `spawn_runner`, `destroy_runner`, `get_p95`, `record_metrics`. - `src/buildctl_runner.rs` — `rsync_context` and `run_buildctl` over SSH. - `src/nats_events.rs` — `BuildEventPublisher` over `platform_nats::EventStream`. Publishes `started` / `completed` / `failed` to `..build.`. Connect failures warn and disable publishing; they never fail a build. - `defaults/build_directives.ncl` — `make_*` constructors and `ci_cache_policy` / `session_cache_policy` helpers. - `examples/sample.ncl` — example `BuildDirectives` instance. - Ontoref scaffolding: `.ontology/{core,state,gate,manifest}.ncl`, `.ontoref/project.ncl`, `card.ncl`, `reflection/{backlog,qa}.ncl`, `reflection/modes/`, `catalog/{domains,modes}/`. - Repository assets: `assets/` (logo and branding), `justfile` with imports from `justfiles/{build,test,ci}.just`, `.pre-commit-config.yaml`. ### Changed - Binary target renamed `buildkit-launcher` → `lian-build`. The `tracing` env-filter directive remains the legacy crate name (`buildkit_launcher=info`) — explicitly noted in `CLAUDE.md`. - `--platforms` is now a comma-separated list (multi-platform builds); legacy single-value invocations remain valid. ### Constraints (grep-checked, ADR-001) - `no-provisioning-lib-import` — `Cargo.toml` and `src/` must not match `platform-config|provisioning|stratum-`. The `platform-nats` path-dep from `stratumiops` is explicitly allowed (it is shared infrastructure, not the provisioning workspace). - `build-directives-ncl-vocabulary` — `src/` must not match `provisioning_workspace|vapora_|woodpecker_`. ### Status (`.ontology/state.ncl`) | Dimension | Current | Desired | |------------------------------------|--------------------------|---------------------------| | provider-pluggability-maturity | hcloud-zot-only | provider-trait-stable | | session-multi-actor-maturity | ci-single-actor | multi-actor-stable | | active-active-registry-maturity | single-zot-libre-wuji | active-active-verified | | caller-integration-maturity | provisioning-only | multi-caller-stable | | peer-publishing-status | packaged | production | `ComputeProvider` / `RegistryProvider` Rust traits are **not yet declared**; the orchestrator client is currently hcloud-shaped. Compute is selected via NCL discriminant but dispatch in core is monolithic — see ADR-001 and the `provider-pluggability-maturity` dimension.