diff --git a/README.md b/README.md index 05933ca..b2fdcaf 100644 --- a/README.md +++ b/README.md @@ -139,8 +139,9 @@ powershell -ExecutionPolicy Bypass -File install.ps1 ``` Each fetches the release artifact for this platform, checks it against the -release's own `SHA256SUMS`, and places it at a predictable path: `~/.local/bin` -on Linux and macOS, `%LOCALAPPDATA%\Programs` on Windows. Neither needs +release's own `SHA256SUMS`, and places it at a predictable path: +`~/.local/bin/opencode-setup-system` on Linux and macOS, +`%LOCALAPPDATA%\Programs\opencode-setup-system\opencode-setup-system.exe` on Windows. Neither needs privilege and neither registers anything anywhere. Somewhere else instead: diff --git a/SUPPORT.md b/SUPPORT.md index 635b2ed..52b3b2f 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -45,7 +45,7 @@ in a JSON file it owns it strips the keys it added rather than taking the file. Anything under those paths this build never wrote stays. Emptying every owned namespace is a separate, explicitly named operation: `reset`. -No credential-free command is measured writing this product's home -- the dated measurement lives in `references/` and the absence is recorded, not assumed. The receipt discipline is the same for whatever arrives later: a file this provider wrote is captured into a slot before the next `install`, withdrawn by `remove`, and returned byte for byte by `restore`. +This product does write its own configuration without credentials -- `mcp add` is one such command -- but the write lands in the real `~/.config/opencode/opencode.json` even when the configuration directory is pointed elsewhere, so the demonstration would touch a person's actual home rather than a target. It is deliberately not run for evidence. The receipt discipline is the same for whatever arrives later: a file this provider wrote is captured into a slot before the next `install`, withdrawn by `remove`, and returned byte for byte by `restore`. So: point `--target` at a home you are willing to have managed. `backups --target ` names every earlier state and which setup each preceded, and @@ -169,8 +169,9 @@ Configuration home as the product documents it: `~/.config/opencode`. | `plugins` | `plugin` | [source](https://opencode.ai/docs/plugins) | | `tui.json` | -- | [source](https://opencode.ai/docs/tui) | -A path routing no component kind is owned so a setup can carry it; -nothing compiles a component to it. +A custody row like `tui.json` routes no component kind because no setup +can ever fill it: it is owned so a backup captures it and `remove` +withdraws it, and so a posture switch does not empty it. ### A second target: `target_scope: user_root` diff --git a/crates/harness-runtime/src/catalog.rs b/crates/harness-runtime/src/catalog.rs index 2bb51c0..7ac6f2b 100644 --- a/crates/harness-runtime/src/catalog.rs +++ b/crates/harness-runtime/src/catalog.rs @@ -107,7 +107,7 @@ pub struct CatalogComponentRef { /// per-harness: `minimal` means the same thing to someone moving from codex to /// pi as it did before they moved. /// -/// A harness may carry more -- cursor and antigravity each ship a builder +/// A harness may carry more -- each of the seven also ships an `nddev-builder` /// toolkit -- but never fewer. pub const UNIVERSAL_SETUPS: &[&str] = &["baseline", "full-auto", "minimal"]; diff --git a/crates/harness-runtime/src/facts.rs b/crates/harness-runtime/src/facts.rs index e5a2dff..98eaa87 100644 --- a/crates/harness-runtime/src/facts.rs +++ b/crates/harness-runtime/src/facts.rs @@ -58,8 +58,8 @@ pub struct Harness { /// and one that can execute code the chosen setup never carried. /// /// A fact rather than a conclusion, carrying how it was established, because - /// the five that are complete are not equally well established: three were - /// measured by asking the product what it resolved, one by making it write, + /// the five that are complete are not equally well established: two were + /// measured by asking the product what it resolved, two by making it write, /// and one rests on a vendor page because no credential-free command of that /// product writes its home. pub launch_binding: LaunchBinding, diff --git a/crates/harness-runtime/src/lib.rs b/crates/harness-runtime/src/lib.rs index 4a583d7..94a600f 100644 --- a/crates/harness-runtime/src/lib.rs +++ b/crates/harness-runtime/src/lib.rs @@ -270,8 +270,9 @@ fn print_help(harness: &Harness) { println!("something to return to. The pool rolls, so a long series of changes"); println!("eventually evicts the oldest: `hold` keeps one until `release` lets"); println!("it go, which is how a baseline survives more captures than the pool."); - println!("Over the wire, install and replace arrive as a bundle and refuse --"); - println!("this build reads setups from its own catalog."); + println!("Over the wire a bundle arrives with install or replace, and this"); + println!("build applies it; this human surface refuses bundles and reads"); + println!("setups from its own catalog."); } #[cfg(test)] diff --git a/crates/harness-runtime/src/software.rs b/crates/harness-runtime/src/software.rs index 92c3a4a..fdf0d50 100644 --- a/crates/harness-runtime/src/software.rs +++ b/crates/harness-runtime/src/software.rs @@ -417,7 +417,7 @@ pub(crate) fn launch( // from one field here. Guessing produced a refusal that told cursor // callers *"this build installs no software"* -- false, it installs // and removes it, and the actual reason is that the product follows - // its variable for one of the eight surfaces this provider owns. + // its variable for one of the seven surfaces this provider owns. format!( "{} does not declare launch: {}", harness.provider_id, diff --git a/crates/harness-runtime/src/surfaces.rs b/crates/harness-runtime/src/surfaces.rs index 2e16621..90d0cbe 100644 --- a/crates/harness-runtime/src/surfaces.rs +++ b/crates/harness-runtime/src/surfaces.rs @@ -227,7 +227,11 @@ fn never_touch_is_disclaimed(harness: &Harness, baseline: &Value, found: &mut Ve /// other direction: a namespace declared, owned, routing nothing, and written /// to by nobody. /// -/// Three of them exist: claude's `rules`, opencode's `tui.json`, pi's `themes`. +/// Seventeen of them exist -- claude's `rules`, `workflows`, `output-styles`, +/// `routines` and `themes`; grok's `sandbox.toml`, `workflows`, `rules`, +/// `commands`, `personas` and `roles`; pi's `APPEND_SYSTEM.md`, `SYSTEM.md` and +/// `themes`; antigravity's `antigravity-cli/keybindings.json` and +/// `antigravity-cli/plugins`; opencode's `tui.json`. /// Each is defensible -- claude's row explains that `instruction` already /// routes to `CLAUDE.md` and the namespace is owned so a setup *could* carry a /// rule -- and the point is not to remove them. It is that the answer should be diff --git a/crates/opencode-setup-system/src/main.rs b/crates/opencode-setup-system/src/main.rs index 3ab28eb..c98173e 100644 --- a/crates/opencode-setup-system/src/main.rs +++ b/crates/opencode-setup-system/src/main.rs @@ -107,8 +107,6 @@ pub const OPENCODE: Harness = Harness { pinned binary; the collision was measured on skills", }, ], - // The product's own: credentials and runtime caches. Never read, never - // written, and never copied into a backup slot. // Owned, and nothing this build can install ever lands here: no // component kind routes to them and no setup in this catalogue // carries files there. So a posture selecting itself must not empty @@ -131,6 +129,8 @@ pub const OPENCODE: Harness = Harness { ], excluded: &["auth.json", "cache"], }], + // The product's own: credentials and runtime caches. Never read, never + // written, and never copied into a backup slot. never_touch: &["auth.json", "cache"], // No near neighbour measured for this product. A marker listed here is a // refusal waiting to happen, so nothing is listed without evidence. diff --git a/references/opencode-baseline.json b/references/opencode-baseline.json index 821537a..58fca09 100644 --- a/references/opencode-baseline.json +++ b/references/opencode-baseline.json @@ -356,7 +356,7 @@ "version": "1.18.33", "verified_at": "2026-09-28T14:27:53+00:00" }, - "setup_catalogue_digest": "sha256:7a5ac4414efe1db02165df91cabb8453b4ed8c94423154f2afdb8c9a870e980d", + "setup_catalogue_digest": "sha256:d0cf7ef9be83eba56d3d496069de6a5eba3e9f19cc7b27690c2c7860f59ef602", "previous_software_artifacts": { "command": "opencode", "shape": "gzip-tar", diff --git a/scripts/evidence.py b/scripts/evidence.py index 36eb96e..6df16e2 100644 --- a/scripts/evidence.py +++ b/scripts/evidence.py @@ -416,7 +416,7 @@ def remove_the_program( # Capture what the *same exposed command* says before removal. Not every # vendor puts its release into `--version`: Pi's two Windows standalone # builds both answer `0.0.0`, while their archive digests and provider - # manifests correctly distinguish 0.84.3 from 0.84.4. Requiring the + # manifests correctly distinguish 0.85.1 from 0.87.1. Requiring the # expected version here tests the vendor's string, not whether removing # an inactive tree moved our command. launch_before = run_text( diff --git a/setups/minimal/home/AGENTS.md b/setups/minimal/home/AGENTS.md index 7fa464e..aac49d8 100644 --- a/setups/minimal/home/AGENTS.md +++ b/setups/minimal/home/AGENTS.md @@ -1,6 +1,6 @@ # NDDev minimal Nothing beyond the product's own defaults in the instructions this setup -ships; the autonomous approval and sandbox posture travels in the setup's own +ships; the autonomous permission posture travels in the setup's own configuration, not here. Useful as a clean state to return to, and as the thing a restore proves it can reach. diff --git a/setups/nddev-builder/home/skills/nddev-builder/references/authoring-instructions.md b/setups/nddev-builder/home/skills/nddev-builder/references/authoring-instructions.md index 9701887..6c59364 100644 --- a/setups/nddev-builder/home/skills/nddev-builder/references/authoring-instructions.md +++ b/setups/nddev-builder/home/skills/nddev-builder/references/authoring-instructions.md @@ -37,7 +37,7 @@ Stopping at the command's output would have concluded this file is inert under p | `pi` | `AGENTS.md` | file | **They are not interchangeable, and the difference is not only the -name.** One of the seven takes a *directory* of rules rather than a +name.** Two of the seven take a *directory* of rules rather than a single document, so a file moved between the two is not a rename. **Some products read a neighbour's.** `references/surfaces.md` records diff --git a/setups/nddev-builder/home/skills/nddev-builder/references/authoring-settings.md b/setups/nddev-builder/home/skills/nddev-builder/references/authoring-settings.md index 05ad54e..615bf04 100644 --- a/setups/nddev-builder/home/skills/nddev-builder/references/authoring-settings.md +++ b/setups/nddev-builder/home/skills/nddev-builder/references/authoring-settings.md @@ -29,8 +29,7 @@ belongs. **A comment is not a stylistic choice.** In a strict-JSON file a `//` is a parse error, and the product does not start rather than starting -without your setting. Two of the seven take comments; the rest do not, -and one of those takes them at two spellings of the same file. +without your setting. Three of the seven take comments; the rest do not, and one of those takes them at two spellings of the same file. ## Before you write one diff --git a/setups/nddev-builder/home/skills/nddev-builder/references/second-target.md b/setups/nddev-builder/home/skills/nddev-builder/references/second-target.md index 11961f6..02ecacd 100644 --- a/setups/nddev-builder/home/skills/nddev-builder/references/second-target.md +++ b/setups/nddev-builder/home/skills/nddev-builder/references/second-target.md @@ -1,12 +1,13 @@ -# The second target this harness owns +# The scoped target this harness owns ## `target_scope: user_root`, rooted at `~/.agents` **`~/.agents` is not this product's configuration home.** It is a different target, reached by a consumer naming the scope on the -request, and every path below is relative to that root rather than -to the home -- writing the root into the path again would nest it -twice, which is a mistake this estate has made and shipped. +request, and every path below is relative to that root rather +than to the home -- writing the root into the path again would +nest it twice, which is a mistake this estate has made and +shipped. | path | routes | decided by | exercised by | |---|---|---|---| diff --git a/setups/nddev-builder/home/skills/nddev-builder/references/surfaces.md b/setups/nddev-builder/home/skills/nddev-builder/references/surfaces.md index 182e43d..5b2853b 100644 --- a/setups/nddev-builder/home/skills/nddev-builder/references/surfaces.md +++ b/setups/nddev-builder/home/skills/nddev-builder/references/surfaces.md @@ -42,10 +42,11 @@ surfaces makes a consumer's route ambiguous, and the guard in ## A second target: `target_scope: user_root` -Rooted at `~/.agents`, which is **not** this product's configuration -home. A consumer reaches it by naming the scope on the request, and -every path below is relative to that root rather than to the home -above -- writing the root into the path again would nest it twice. +Rooted at `~/.agents`, which is **not** this product's +configuration home. A consumer reaches it by naming the scope +on the request, and every path below is relative to that root +rather than to the home above -- writing the root into the +path again would nest it twice. | path | routes | shape | decided by | exercised by | | --- | --- | --- | --- | --- |