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 вручную нельзя.