lian-build/CHANGES.md

116 lines
6 KiB
Markdown
Raw Normal View History

2026-05-04 18:23:52 +01:00
# 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 <args>`.
- **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
<file.ncl>`; 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<String>`; enforces `ci/<workspace>/*` (canonical,
read-only to sessions) and `dev/<actor-id>-<workspace>/*` (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<T> { 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 `<prefix>.<workspace>.build.<event>`. 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.