Skip to content

feat(hosts): add the Dart SDK host and delegate zcode out of bootstrap (2.3.0) - #40

Merged
rldyourmnd merged 4 commits into
mainfrom
feat/dart-host-and-zcode-delegation
Aug 3, 2026
Merged

feat(hosts): add the Dart SDK host and delegate zcode out of bootstrap (2.3.0)#40
rldyourmnd merged 4 commits into
mainfrom
feat/dart-host-and-zcode-delegation

Conversation

@rldyourmnd

Copy link
Copy Markdown
Contributor

Why

Two capabilities the estate declares were delivered nowhere, and both left an MCP server in the rldyour-mcps marketplace unstartable on a desktop this adapter had just provisioned.

Dart was declared and forbidden at once. The dart-flutter MCP server runs dart mcp-server, and rldyour-claudecode stated its Dart 3.12.2 pin "matches what the bootstrap installs" — but no bootstrap path installed Dart on either platform. The string dart appeared in this repository only in ADR 0005's forbidden list and the test enforcing it.

The zcode harness stranded every layer behind it. The ZCode app creates and owns ~/.zcode on first launch; its module installer then correctly refuses an unstamped target without an explicit --adopt-unmanaged. Because install_ai_runtimes ran ahead of everything else under set -euo pipefail, that refusal aborted whole device applies. An observed Ubuntu 26.04 desktop was missing 24 of the 46 commands its own verify.sh requires — every bun language server, Go, Rust, all eight pinned scanners, and the entire CloakBrowser stack, which is what broke chrome-devtools-mcp too.

What changes

  • Dart SDK 3.12.2 as the third desktop host (ADR 0006, amending ADR 0005). Tracked stable-channel archive → receipt-verified directory → managed link, exactly like Go and Rust. macOS uses Homebrew dart-sdk. Both digests confirmed by downloading the artifacts, not copied from release notes.
  • Flutter SDK deliberately excluded. dart mcp-server runs from the Dart SDK alone; Flutter's bin/cache self-populates at runtime and would mutate a hash-verified tree, breaking the receipt contract that makes every managed host tamper-evident.
  • Permission normalization. The SDK zip records directories as 0775, and umask only clears bits it never adds, so extraction under umask 002 published 113 group-writable directories inside a receipt-verified tree whose receipt covers only the declared executables. The Bun-tree permission helper is generalized to rldyour::_managed_tree_permissions and reused — no second permission path.
  • Telemetry disabled and proven disabled. The SDK reports by default, contradicting the boundary that makes the browser wrapper reject --usage-statistics. One shared fail-closed helper runs the SDK's own switch, then reads reporting=0 back and rejects a conflicting reporting=1.
  • zcode removed, not softened. Declared harnesses.delegated with owner nddev-harnesses and a recorded reason. A warn-and-continue step would be exactly the best-effort fallback this repository forbids.
  • codex made reachable. Its module publishes the CLI only under its own target, so ${RLDYOUR_CODEX_HOME:-$HOME/.codex}/bin joins the managed PATH. Strict verification could not pass at all before this.

Evidence

Check Result
python3 -m pytest 94 passed (+2 new invariants)
scripts/ci/validate.sh ci-validate-ok
scripts/ci/lint.sh scripts-lint-ok
shellcheck -x -S warning on edited scripts clean
plan: ubuntu desktop+gui / macos exit 0, reaches Dart and skips zcode explicitly

Runtime evidence produced on a real Ubuntu 26.04 desktop:

  • extracted SDK reported Dart SDK version: 3.12.2 (stable) ... linux_x64; dart mcp-server --version0.1.4; both also verified through a ~/.local/bin symlink, since SDK-root resolution was the one novel risk;
  • dart language-server --protocol=lsp — the exact invocation rldyour-lsps/.lsp.json declares — answered a real initialize handshake with a 2646-byte capabilities reply, with --protocol=bogus → exit 64 as the negative control;
  • permission normalization measured on the real tree: 113 → 0 group-writable paths, validate passing afterwards, SDK still functional;
  • the telemetry gate exercised across five configs (as-installed, appended reporting=1, flipped value, value on an unterminated final line, no reporting line) with the expected accept/reject in each.

Not verified

macOS was not runtime-verified — no macOS host was available. That covers the dart-sdk formula entry, the shared telemetry call, and the floor version gate. A hard telemetry verify gate was deliberately not added to scripts/macos/verify.sh for that reason; macOS already carries a documented weaker-gate posture because Homebrew cannot pin exact patches.

The --profile server plan cannot complete on this host (no systemd SSH provider exists): openssh-server is absent. scripts/ubuntu/server.sh is untouched by this branch.

Two declared capabilities were delivered nowhere, and both left an MCP server
in the rldyour-mcps marketplace unstartable on a provisioned desktop.

Dart was declared and forbidden at the same time. The `dart-flutter` MCP server
runs `dart mcp-server`, and the marketplace pin claimed Dart 3.12.2 "matches
what the bootstrap installs", but no bootstrap path installed Dart on either
platform: the string appeared here only in ADR 0005's forbidden list and the
test enforcing it. Ubuntu now installs the tracked stable-channel SDK archive
into an owned versioned directory with a runtime receipt and a managed link,
exactly like Go and Rust; macOS uses Homebrew's dart-sdk. Both digests were
confirmed by downloading the artifacts.

Two Dart-specific hazards are handled rather than inherited. The SDK zip records
its directories as 0775 and umask only clears bits it never adds, so a naive
extraction publishes group-writable directories inside a receipt-verified tree
whose receipt covers only the declared executables — enough to swap a snapshot
beside them without invalidating it. The permission helper written for
group-writable Bun trees is generalized to rldyour::_managed_tree_permissions
and now normalizes the staged tree and re-validates a reused one, instead of a
second permission path. The SDK also reports telemetry by default, which
contradicts the boundary that makes the browser wrapper reject usage
statistics; rldyour::ensure_dart_telemetry_disabled runs the SDK's own switch
and then reads reporting=0 back, fail-closed, shared by both installers.

Verification proves the subcommand, not the binary: an SDK that resolves on
PATH but cannot serve MCP is the exact defect being replaced.

zcode is removed from bootstrap entirely. The ZCode app creates and owns
~/.zcode on first launch, and its module installer correctly refuses an
unstamped target without an explicit --adopt-unmanaged, which no unattended run
may supply. Because install_ai_runtimes ran ahead of every other layer under
set -euo pipefail, that refusal aborted whole device applies: an observed
Ubuntu 26.04 desktop was missing 24 of the 46 commands its own verify.sh
requires, including chrome-devtools-mcp. The delegation is deleted rather than
softened into warn-and-continue, which would be the best-effort fallback this
repository forbids; nddev-harnesses owns zcode through its own lifecycle.

codex is finally reachable: its module publishes the CLI only under its own
target, so ${RLDYOUR_CODEX_HOME:-$HOME/.codex}/bin joins the managed PATH.
Without it strict verification could not pass at all.
…de return

scripts/ci/validate.sh pinned the active harness set to exactly codex and
zcode, so it would now reject the contract it is meant to guard. It requires
["codex"] instead, and additionally requires that zcode stay declared under
harnesses.delegated with its owner repository and the reason it is out of
scope — a silent disappearance must read as drift, not as a decision.

dependency-check.yml previously required the zcode delegation symbols to be
present in common.sh. It now requires their absence, so no zcode install path
can return in any form, including a softened one.
Dart is covered on the same terms as Go and Rust: desktop-only planning, server
exclusion, per-architecture digest coverage, and installer-to-contract
agreement. Three Dart-specific invariants are added because each one, if it
regressed, would fail silently rather than loudly: the tree must pass through
the shared permission helper on both the fresh and reused paths, telemetry must
be disabled through one fail-closed helper that both installers call, and both
verifiers must prove `dart mcp-server` responds instead of only checking that
`dart` resolves.

The forbidden-manifest test keeps banning the `dart` apt package — ADR 0006
admits the tracked SDK archive, not a distribution package — and now also
asserts that no second permission path and no zcode installer come back.
…rface

ADR 0006 amends ADR 0005, which listed `dart` among the things that stay
forbidden, and records both decisions with the evidence behind them: why the
Flutter SDK is deliberately excluded (its bin/cache self-populates at runtime
and would mutate a hash-verified tree, which needs its own decision about where
a mutable cache may live), why the permission and telemetry hazards are handled
in-tree, and what delegating zcode gives up.

The version surface moves to 2.3.0 across VERSION, the contract, README,
docs/install.md, AGENTS.md, .claude/CLAUDE.md, SECURITY.md, and the three
browser template version files the smoke test pins together. Previously
unreleased CHANGELOG entries are promoted into the 2.3.0 section, since that is
the version they now ship in.

Two documentation claims are corrected rather than carried forward: Ubuntu GUI
mode is described as what desktop.sh actually owns (GNOME dock, Russian layout,
BrowserOS, complete snap+apt Firefox removal), and ZCode ownership is attributed
to nddev-harnesses instead of a module delegation that no longer exists.
@rldyourmnd
rldyourmnd merged commit 4ceac29 into main Aug 3, 2026
29 checks passed
@rldyourmnd
rldyourmnd deleted the feat/dart-host-and-zcode-delegation branch August 3, 2026 17:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant