115 lines
6 KiB
Markdown
115 lines
6 KiB
Markdown
# 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.
|