Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,34 @@ cut and that this clone does not carry.

## [Unreleased]

## [0.0.77] - 2026-09-27

All seven setup systems refresh their software pins from current vendor
artifacts, with bytes and SHA256 checked for six published platforms each:
Claude Code 2.1.283, Codex 0.157.1, Grok Build 1.0.42, Pi 0.87.1,
OpenCode 1.18.32, Cursor 2026.09.26-024025f, and Antigravity CLI 1.2.12.
Grok's published line now lands under the `alpha` dist-tag; the pin follows
the current build and records the tag it was fetched under. The immediately
preceding pins remain available for rollback.

A ten-auditor review of every harness against its installed binary or vendor
documentation corrected the records the pins alone do not cover. Codex
records the 0.157.1 feature registry (150 specs, 47 stable, four stable-off
including secret_auth_storage, which stays off: it is a Windows-only
credential backend by vendor design), its project-scope surfaces, and the
full reasoning-effort enum. Grok moves default_auto_mode to config root and
places memory-v2, auth.json.lock, trusted_folders.toml and trusted-plugins
under never_touch. Claude records output-styles, routines and themes as
custody surfaces, the full plugin manifest key set, and current
session-runtime members. Cursor declines permissions.json, fixes a dangling
baseline reference, documents that ${env:NAME} is real mcp.json
interpolation, and no longer doubles hook and MCP paths in generated
references. OpenCode records remote .well-known configuration, themes, and
v2 coexistence. Pi re-measures its manager installation at 0.87.1 and
declines sessions. Every minimal posture's prose now says the autonomous
approval and sandbox posture ships in config rather than claiming product
defaults. Provider protocol, postures and ownership are unchanged.

## [0.0.76] - 2026-09-25

The shared instruction attachment now refuses unreadable or invalid
Expand Down
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ members = [
]

[workspace.package]
version = "0.0.76"
version = "0.0.77"
edition = "2024"
rust-version = "1.89"
license = "AGPL-3.0-or-later"
Expand All @@ -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.76" }
provider-v3 = { path = "crates/provider-v3", version = "0.0.76" }
harness-runtime = { path = "crates/harness-runtime", version = "0.0.76" }
setup-core = { path = "crates/setup-core", version = "0.0.77" }
provider-v3 = { path = "crates/provider-v3", version = "0.0.77" }
harness-runtime = { path = "crates/harness-runtime", version = "0.0.77" }

[workspace.lints.rust]
unsafe_code = "forbid"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.76 \
ghcr.io/nddev-opennetwork/opencode-setup-system:0.0.77 \
status --target /config/<dir> --json
```

Expand Down
4 changes: 4 additions & 0 deletions SUPPORT.md
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,10 @@ The user configuration home is **not** per-OS, which is why only this row is. Th

**`hooks.json`** -- **Hooks are functions a plugin module exports**, not a file. The vendor's plugin page, read 2026-08-29: *"A plugin is a JavaScript/TypeScript module that exports one or more plugin functions. Each function receives a context object and returns a hooks object."* The names -- `tool.execute.before`, `session.created`, `permission.asked` and the rest -- are keys of that returned object. There is no `hooks.json` and no `hooks` key in `opencode.json`, so a hook reaches this product through `plugins/`, which is owned and routes `plugin`. ([source](https://opencode.ai/docs/plugins/))

**`.well-known/opencode`** -- Not a path in the target: the product fetches `<provider-origin>/.well-known/opencode` when an authenticated provider carries `type: "wellknown"`, and loads the result as the **lowest** precedence layer -- every local layer overrides it. Recorded so nobody reads a shipped `opencode.json` as the only thing that can configure a run: an authenticated provider's organization defaults sit underneath it. This provider writes no remote config and cannot. (measured in the 1.18.31 linux/x86_64 binary (auth type "wellknown" -> fetch `${origin}/.well-known/opencode`), and https://opencode.ai/docs/config precedence order, 2026-09-27)

**`themes`** -- A real directory under the configuration home -- the product globs `themes/*.json` there (and under `.opencode/` project dirs) for user color themes. Deliberately not owned: themes are TUI cosmetics a person curates, and no component kind routes them, so a setup owning the directory would promise a rollback of somebody's personal theme files. (measured in the 1.18.31 linux/x86_64 binary (`scan("themes/*.json", {cwd: <each config dir>})`), 2026-09-27; documented at https://opencode.ai/docs/themes)

## Response

One maintainer. Defects are triaged as time allows; security reports are
Expand Down
2 changes: 1 addition & 1 deletion install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
# powershell -ExecutionPolicy Bypass -File install.ps1 -Version 0.1.0
[CmdletBinding()]
param(
[string]$Version = "0.0.76",
[string]$Version = "0.0.77",
[string]$InstallDir = "$env:LOCALAPPDATA\Programs\opencode-setup-system"
)
$ErrorActionPreference = "Stop"
Expand Down
2 changes: 1 addition & 1 deletion install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ set -eu

REPO="NDDev-OpenNetwork/opencode-setup-system"
BINARY="opencode-setup-system"
VERSION="${1:-0.0.76}"
VERSION="${1:-0.0.77}"
PREFIX="${OPENCODE_INSTALL_DIR:-$HOME/.local/bin}"

case "$(uname -s)" in
Expand Down
45 changes: 34 additions & 11 deletions references/opencode-baseline.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,21 +72,33 @@
"external_skills_disable_env": "OPENCODE_DISABLE_EXTERNAL_SKILLS",
"claude_compat_disable_env": "OPENCODE_DISABLE_CLAUDE_CODE",
"native_builder_projection": [
"plugins/nddev-builder.js",
"skills/nddev-builder/SKILL.md",
"skills/nddev-builder/references/native-surfaces.md",
"skills/nddev-builder/references/security-boundary.md",
"AGENTS.md",
"agents/nddev-builder.md",
"commands/nddev-orient.md",
"commands/nddev-validate.md"
"commands/nddev-setup.md",
"commands/nddev-surfaces.md",
"commands/nddev-validate.md",
"opencode.json",
"skills/nddev-builder/SKILL.md",
"skills/nddev-builder/references/ai-stp-lifecycle.md",
"skills/nddev-builder/references/authoring-agents.md",
"skills/nddev-builder/references/authoring-commands.md",
"skills/nddev-builder/references/authoring-instructions.md",
"skills/nddev-builder/references/authoring-plugins.md",
"skills/nddev-builder/references/authoring-settings.md",
"skills/nddev-builder/references/authoring-skills.md",
"skills/nddev-builder/references/lifecycle.md",
"skills/nddev-builder/references/second-target.md",
"skills/nddev-builder/references/surfaces.md",
"skills/nddev-builder/references/validation.md"
],
"marketplace": null,
"product_writes_into_target": [
".gitignore"
],
"product_writes_into_target_note": "Exercised 2026-08-31 against a temporary home: a single `debug config` -- a read-only command, and the provider's own probe -- creates `.gitignore` in the target, listing `node_modules`, `package.json`, `package-lock.json`, `bun.lock` and itself. It appears with no plugin installed and with no setup content that asks for it, so any target this product has started against has it. It is not in `native_namespaces`: this provider neither installs it nor removes it, and it is the product's, not a user's. Recorded so a target that grew one is not read as somebody's stray file.",
"permission_env": "OPENCODE_PERMISSION",
"permission_env_note": "**An inherited variable replaces the posture this provider installed, and launch passes it through.** Exercised 2026-08-31 against a temporary home with `baseline` in the target: `debug agent build` ends `edit ask, bash ask`, and the same run with `OPENCODE_PERMISSION={\"bash\":\"allow\"}` in the environment ends `edit ask, bash allow`. Whoever starts the provider decides that, not the setup.\n\n**Named and not closed, deliberately.** Launch forces two variables -- the configuration home and the update switch -- because without the first the target is not read at all and without the second the bytes this provider recorded can be replaced underneath it. Neither is a posture. Scrubbing this one would be: it is a capability the product gives a person, and taking it away silently is the same move as deleting an `opencode.jsonc` somebody put beside our file. The answer is the same as there -- say it, do not decide it -- and saying it is a launch-time report this build does not have yet. Recorded so the gap is a known one rather than a discovery."
"permission_env_note": "**An inherited variable replaces the posture this provider installed, and launch passes it through.** Exercised 2026-08-31 against a temporary home with `baseline` in the target: `debug agent build` ends `edit ask, bash ask`, and the same run with `OPENCODE_PERMISSION={\"bash\":\"allow\"}` in the environment ends `edit ask, bash allow`. Whoever starts the provider decides that, not the setup.\n\n**Named and not closed, deliberately.** Launch forces two variables -- the configuration home and the update switch -- because without the first the target is not read at all and without the second the bytes this provider recorded can be replaced underneath it. Neither is a posture. Scrubbing this one would be: it is a capability the product gives a person, and taking it away silently is the same move as deleting an `opencode.jsonc` somebody put beside our file. The answer is the same as there -- say it, do not decide it -- and saying it is a launch-time report this build does not have yet. Recorded so the gap is a known one rather than a discovery.",
"native_builder_projection_note": "The files the nddev-builder setup writes into the product home, read back from the shipped tree rather than remembered -- the previous list named a `plugins/nddev-builder.js` and `commands/nddev-orient.md` that no longer exist and omitted the authoring references. Re-derived 2026-09-27."
},
"permissions": {
"current_key": "permission",
Expand All @@ -109,7 +121,7 @@
"OPENCODE_DISABLE_PROJECT_CONFIG",
"OPENCODE_DISABLE_SHARE"
],
"verified_at": "2026-09-25T11:49:12+00:00",
"verified_at": "2026-09-27T07:42:17+00:00",
"native_surfaces": {
"verified_at": "2026-08-31",
"config_home": "~/.config/opencode",
Expand Down Expand Up @@ -254,6 +266,16 @@
"path": "hooks.json",
"reason": "**Hooks are functions a plugin module exports**, not a file. The vendor's plugin page, read 2026-08-29: *\"A plugin is a JavaScript/TypeScript module that exports one or more plugin functions. Each function receives a context object and returns a hooks object.\"* The names -- `tool.execute.before`, `session.created`, `permission.asked` and the rest -- are keys of that returned object. There is no `hooks.json` and no `hooks` key in `opencode.json`, so a hook reaches this product through `plugins/`, which is owned and routes `plugin`.",
"source": "https://opencode.ai/docs/plugins/"
},
{
"path": ".well-known/opencode",
"source": "measured in the 1.18.31 linux/x86_64 binary (auth type \"wellknown\" -> fetch `${origin}/.well-known/opencode`), and https://opencode.ai/docs/config precedence order, 2026-09-27",
"reason": "Not a path in the target: the product fetches `<provider-origin>/.well-known/opencode` when an authenticated provider carries `type: \"wellknown\"`, and loads the result as the **lowest** precedence layer -- every local layer overrides it. Recorded so nobody reads a shipped `opencode.json` as the only thing that can configure a run: an authenticated provider's organization defaults sit underneath it. This provider writes no remote config and cannot."
},
{
"path": "themes",
"source": "measured in the 1.18.31 linux/x86_64 binary (`scan(\"themes/*.json\", {cwd: <each config dir>})`), 2026-09-27; documented at https://opencode.ai/docs/themes",
"reason": "A real directory under the configuration home -- the product globs `themes/*.json` there (and under `.opencode/` project dirs) for user color themes. Deliberately not owned: themes are TUI cosmetics a person curates, and no component kind routes them, so a setup owning the directory would promise a rollback of somebody's personal theme files."
}
],
"config_home_env": "OPENCODE_CONFIG_DIR",
Expand Down Expand Up @@ -287,7 +309,8 @@
],
"projection_basis": {
"plugin": "plugins"
}
},
"v2_coexistence_note": "OpenCode maintains a `v2` documentation line (opencode.ai/v2/docs) for the next major version while the shipped CLI is 1.x. Surfaces documented only there -- `cli.json` among them -- are absent from the pinned v1.18.x binary (measured 2026-09-27: no `cli.json` reader in the linux/x86_64 artifact), so they are recorded here rather than declined as real files. Re-measure when the product line ships."
},
"software_artifacts": {
"command": "opencode",
Expand Down Expand Up @@ -331,9 +354,9 @@
}
},
"version": "1.18.32",
"verified_at": "2026-09-25T11:49:12+00:00"
"verified_at": "2026-09-27T07:42:17+00:00"
},
"setup_catalogue_digest": "sha256:e251847ceb02bd92b12fd07ba83b6ac836d37e3cbdbf9aba1607719b281ab7e8",
"setup_catalogue_digest": "sha256:da0e9f9598e8f98486c144452689946d2e4145c00b3144499fc64eea63e3fc8c",
"previous_software_artifacts": {
"command": "opencode",
"shape": "gzip-tar",
Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[toolchain]
channel = "1.98.0"
channel = "1.98.1"
components = ["rustfmt", "clippy"]
6 changes: 4 additions & 2 deletions setups/minimal/home/AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# NDDev minimal

Nothing beyond the product's own defaults. Useful as a clean state to return to,
and as the thing a restore proves it can reach.
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
configuration, not here. Useful as a clean state to return to, and as the thing
a restore proves it can reach.
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ whole, which would take or revert a neighbour's work.

## Considered and not owned

14 rows. Each records what was searched, so the next reader does not repeat the search:
16 rows. Each records what was searched, so the next reader does not repeat the search:

- **`opencode.jsonc`** — Documented, and deliberately not owned. OpenCode reads either spelling; owning both would let a target hold two documents that disagree, with the product picking one and this provider reporting the other. Owning one keeps the answer single, and a target configured the other way is preserved verbatim as any sibling overlay is.
- **`tui.jsonc`** — Documented, and deliberately not owned, for the same reason as opencode.jsonc: it is the second spelling of one file, and owning both would let a target hold two documents that disagree with the product reading one and this provider reporting the other.
Expand All @@ -75,3 +75,5 @@ whole, which would take or revert a neighbour's work.
- **`managed-config`** — Not a path in the target, and named without an extension for that reason: the managed configuration directory is a **system** path, one per operating system, and every recorded path here is relative to the target.
- **`mcp_config.json`** — MCP servers are the `mcp` key inside `opencode.json` -- `{"mcp": {"<name>": {"type": "local", "command": [...]}}}` -- confirmed on the vendor's MCP page 2026-08-29 and in the product's own built-in `customize-opencode` skill. That file is owned here and written and restored whole, so MCP is covered by the `setting` kind. **A key inside a file is not a projection surface.** No separate MCP file exists under the config home.
- **`hooks.json`** — **Hooks are functions a plugin module exports**, not a file. The vendor's plugin page, read 2026-08-29: *"A plugin is a JavaScript/TypeScript module that exports one or more plugin functions. Each function receives a context object and returns a hooks object."* The names -- `tool.execute.before`, `session.created`, `permission.asked` and the rest -- are keys of that returned object. There is no `hooks.json` and no `hooks` key in `opencode.json`, so a hook reaches this product through `plugins/`, which is owned and routes `plugin`.
- **`.well-known/opencode`** — Not a path in the target: the product fetches `<provider-origin>/.well-known/opencode` when an authenticated provider carries `type: "wellknown"`, and loads the result as the **lowest** precedence layer -- every local layer overrides it. Recorded so nobody reads a shipped `opencode.json` as the only thing that can configure a run: an authenticated provider's organization defaults sit underneath it. This provider writes no remote config and cannot.
- **`themes`** — A real directory under the configuration home -- the product globs `themes/*.json` there (and under `.opencode/` project dirs) for user color themes. Deliberately not owned: themes are TUI cosmetics a person curates, and no component kind routes them, so a setup owning the directory would promise a rollback of somebody's personal theme files.
Loading