diff --git a/CHANGELOG.md b/CHANGELOG.md index 71f2e01..30181a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,29 @@ sibling project the same week this note was added. ## [Unreleased] +## [0.0.51] - 2026-09-01 + +`remove` names both of its cases. It said *"anything you put under +those"*, which is directory language: a person's own keys live **in** +`config.toml`, not under it, so the file half of the sentence read as not +applying to them. The consumer measured that these lines reach their approval +surface verbatim, so the sentence is the contract. It now says: your own keys +in a file it names go, your own files in a directory it names go, and the +backup slot captured first holds all of it. + +The marker between a report and its reader is held from both sides now. Every +tool prints a machine `RESULT` line; a test binds each tool to the exact keys +it prints, and — since one rename cost a scheduled run — also requires the +workflow that parses a marker to parse the key that is actually printed. The +conformance report's third state is part of the same change: a sweep that +could not run says `unmeasured=` apart from `refused=`, and nothing downstream +may read its silence as a pass. The kit check's count is `differs=` rather +than `behind=`, because a byte comparison cannot say which side moved — and +the day it was renamed, the side that had moved was the vendor's. + +The vendored provider-kit README follows the consumer's current copy, which +dropped a passage superseded on their side. + ## [0.0.50] - 2026-08-31 Each repository now tracks what its default branch is meant to diff --git a/Cargo.lock b/Cargo.lock index 930cb92..b3096c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -66,7 +66,7 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "harness-runtime" -version = "0.0.50" +version = "0.0.51" dependencies = [ "provider-v3", "serde", @@ -128,7 +128,7 @@ dependencies = [ [[package]] name = "opencode-setup-system" -version = "0.0.50" +version = "0.0.51" dependencies = [ "harness-runtime", "provider-v3", @@ -147,7 +147,7 @@ dependencies = [ [[package]] name = "provider-v3" -version = "0.0.50" +version = "0.0.51" dependencies = [ "serde", "serde_json", @@ -209,7 +209,7 @@ dependencies = [ [[package]] name = "setup-core" -version = "0.0.50" +version = "0.0.51" dependencies = [ "miniz_oxide", "serde", diff --git a/Cargo.toml b/Cargo.toml index 1c159c1..be6f06b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ members = [ ] [workspace.package] -version = "0.0.50" +version = "0.0.51" edition = "2024" rust-version = "1.89" license = "AGPL-3.0-or-later" @@ -23,9 +23,9 @@ sha2 = "0.11" # `setup-core::archive`); an inflate loop is not, because its bugs are # memory-safety bugs and it is not improved by being hand-written here. miniz_oxide = "0.9" -setup-core = { path = "crates/setup-core", version = "0.0.50" } -provider-v3 = { path = "crates/provider-v3", version = "0.0.50" } -harness-runtime = { path = "crates/harness-runtime", version = "0.0.50" } +setup-core = { path = "crates/setup-core", version = "0.0.51" } +provider-v3 = { path = "crates/provider-v3", version = "0.0.51" } +harness-runtime = { path = "crates/harness-runtime", version = "0.0.51" } [workspace.lints.rust] unsafe_code = "forbid" diff --git a/README.md b/README.md index 76bbe83..e3c7c29 100644 --- a/README.md +++ b/README.md @@ -179,7 +179,7 @@ release is a convenience, not the authorised copy. ```bash docker run --rm -v "$HOME/.config:/config" \ - ghcr.io/nddev-opennetwork/opencode-setup-system:0.0.50 \ + ghcr.io/nddev-opennetwork/opencode-setup-system:0.0.51 \ status --target /config/ --json ``` diff --git a/crates/harness-runtime/src/lib.rs b/crates/harness-runtime/src/lib.rs index c4b5b32..ce089fa 100644 --- a/crates/harness-runtime/src/lib.rs +++ b/crates/harness-runtime/src/lib.rs @@ -564,7 +564,17 @@ mod tests { let sweeps = [ ("tools/validate_setup_schemas.py", "failed="), ("tools/conformance_report.py", "refused="), - ("tools/check_vendored_kit.py", "behind="), + // And the third state beside it. A sweep that could not run reports + // `refused=0`, and without this count the workflow would close its + // issue saying every harness conforms again -- an absent instrument + // reading as a clean result, one layer up from where this estate + // usually finds it. + ("tools/conformance_report.py", "unmeasured="), + // `differs=` and not `behind=`. The word was renamed on 2026-08-31 + // because a byte comparison cannot say which side moved, and that + // day it was the vendor: their README dropped a file their own + // KIT-IDENTITY still names, while the copy here stayed correct. + ("tools/check_vendored_kit.py", "differs="), ("tools/check_authored_keys.py", "unsourced="), ]; @@ -581,6 +591,26 @@ mod tests { ); } + // **And the reader, which this guard did not hold until it cost + // something.** Renaming `behind=` to `differs=` in the kit check passed + // the loop above the moment the tool and this list agreed -- while + // `conformance.yml` still parsed the old marker with `sed` and would + // have reported "the kit check printed no RESULT line" on the next + // scheduled run. A marker is a contract between a writer and a reader, + // and a test naming only the writer holds one half of a pair. + let conformance_workflow = + std::fs::read_to_string(root.join(".github/workflows/conformance.yml")) + .expect("the conformance workflow is missing"); + for (tool, key) in sweeps { + if !conformance_workflow.contains(tool) { + continue; + } + assert!( + conformance_workflow.contains(key), + "the conformance workflow reads {tool} and does not parse {key}" + ); + } + let workflow = std::fs::read_to_string(root.join(".github/workflows/conformance.yml")) .expect("the conformance workflow is missing"); assert_eq!( diff --git a/crates/harness-runtime/src/wire.rs b/crates/harness-runtime/src/wire.rs index 33b26c1..fb654dd 100644 --- a/crates/harness-runtime/src/wire.rs +++ b/crates/harness-runtime/src/wire.rs @@ -620,7 +620,24 @@ pub(crate) fn taken_before_writing( // it on the fourth. The first version said "the capture above holds // it", which was false on the one that reads it after the fact -- a // word describing layout inside a sentence describing behaviour. - "anything you put under those goes too, and the backup slot holds it".to_owned(), + // + // **And shape-free, since 2026-08-31.** It said *"anything you put + // under those"*, which is directory language: a person's own keys are + // **in** `config.toml`, not under it, so the file half of the list read + // as not applying to them. The consumer measured that these three lines + // reach their approval point unchanged -- `InstallationView.effects` + // carries the provider's plan verbatim -- and then found the reading it + // produces: a contribution owning one key in `config.toml` is removed + // by taking the whole file, and *"config.toml goes whole"* is heard as + // *"what you installed goes"*. + // + // The list mixes files and directories and this runtime does not carry + // which is which; inferring it from an extension would be deciding by + // shape, which is the habit this estate refuses. So the sentence names + // both cases instead of assuming one. + "whatever else is in them goes too -- your own keys in a file it names, \ + your own files in a directory it names -- and the backup slot holds it" + .to_owned(), ] } diff --git a/install.ps1 b/install.ps1 index ffaf3ad..bdbbe09 100644 --- a/install.ps1 +++ b/install.ps1 @@ -7,7 +7,7 @@ # powershell -ExecutionPolicy Bypass -File install.ps1 -Version 0.1.0 [CmdletBinding()] param( - [string]$Version = "0.0.50", + [string]$Version = "0.0.51", [string]$InstallDir = "$env:LOCALAPPDATA\Programs\opencode-setup-system" ) $ErrorActionPreference = "Stop" diff --git a/install.sh b/install.sh index 953f560..0df6243 100644 --- a/install.sh +++ b/install.sh @@ -14,7 +14,7 @@ set -eu REPO="NDDev-OpenNetwork/opencode-setup-system" BINARY="opencode-setup-system" -VERSION="${1:-0.0.50}" +VERSION="${1:-0.0.51}" PREFIX="${OPENCODE_INSTALL_DIR:-$HOME/.local/bin}" case "$(uname -s)" in diff --git a/provider-kit/v3/README.md b/provider-kit/v3/README.md index e69d603..fa0d352 100644 --- a/provider-kit/v3/README.md +++ b/provider-kit/v3/README.md @@ -35,22 +35,4 @@ называет SHA-256 самого файла `SHA256SUMS` без нормализации. Для этого комплект их и несёт. -## Status response - -Всегда обязательны protocol/provider/harness identity, canonical target, -`state`, оба target digests, `cleanup_state`, `journal`, `backups`, -`provider_state` и `shadowed_by`. - -Полный flat provenance обязателен условно: только когда вложенный -`provider_state` сообщает `present=true`, `readable=true` и -`drift_state=clean`. Тогда ответ называет state schema, provider build/release, -setup definition/version/passport, components, bundle/artifact, projection/plan, -operation/precondition, native ownership, written paths, backup и previous -verified identity. Missing, foreign-schema и local-drift состояния не заполняют -эти поля выдуманными значениями. - -Эта ревизия сначала публикует schema и conformance cases. Consumer enforcement -включается только после того, как provider systems вендорят и выпускают kit; -одного присутствия файла недостаточно, чтобы считать старый status отвергнутым. - Редактировать generated JSON вручную нельзя.