feat(hosts): add the Dart SDK host and delegate zcode out of bootstrap (2.3.0) - #40
Merged
Merged
Conversation
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Two capabilities the estate declares were delivered nowhere, and both left an MCP server in the
rldyour-mcpsmarketplace unstartable on a desktop this adapter had just provisioned.Dart was declared and forbidden at once. The
dart-flutterMCP server runsdart mcp-server, andrldyour-claudecodestated its Dart 3.12.2 pin "matches what the bootstrap installs" — but no bootstrap path installed Dart on either platform. The stringdartappeared 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
~/.zcodeon first launch; its module installer then correctly refuses an unstamped target without an explicit--adopt-unmanaged. Becauseinstall_ai_runtimesran ahead of everything else underset -euo pipefail, that refusal aborted whole device applies. An observed Ubuntu 26.04 desktop was missing 24 of the 46 commands its ownverify.shrequires — every bun language server, Go, Rust, all eight pinned scanners, and the entire CloakBrowser stack, which is what brokechrome-devtools-mcptoo.What changes
dart-sdk. Both digests confirmed by downloading the artifacts, not copied from release notes.dart mcp-serverruns from the Dart SDK alone; Flutter'sbin/cacheself-populates at runtime and would mutate a hash-verified tree, breaking the receipt contract that makes every managed host tamper-evident.0775, and umask only clears bits it never adds, so extraction underumask 002published 113 group-writable directories inside a receipt-verified tree whose receipt covers only the declared executables. The Bun-tree permission helper is generalized torldyour::_managed_tree_permissionsand reused — no second permission path.--usage-statistics. One shared fail-closed helper runs the SDK's own switch, then readsreporting=0back and rejects a conflictingreporting=1.harnesses.delegatedwith ownernddev-harnessesand a recorded reason. A warn-and-continue step would be exactly the best-effort fallback this repository forbids.codexmade reachable. Its module publishes the CLI only under its own target, so${RLDYOUR_CODEX_HOME:-$HOME/.codex}/binjoins the managed PATH. Strict verification could not pass at all before this.Evidence
python3 -m pytestscripts/ci/validate.shci-validate-okscripts/ci/lint.shscripts-lint-okshellcheck -x -S warningon edited scriptsRuntime evidence produced on a real Ubuntu 26.04 desktop:
Dart SDK version: 3.12.2 (stable) ... linux_x64;dart mcp-server --version→0.1.4; both also verified through a~/.local/binsymlink, since SDK-root resolution was the one novel risk;dart language-server --protocol=lsp— the exact invocationrldyour-lsps/.lsp.jsondeclares — answered a realinitializehandshake with a 2646-byte capabilities reply, with--protocol=bogus→ exit 64 as the negative control;validatepassing afterwards, SDK still functional;reporting=1, flipped value, value on an unterminated final line, noreportingline) with the expected accept/reject in each.Not verified
macOS was not runtime-verified — no macOS host was available. That covers the
dart-sdkformula entry, the shared telemetry call, and the floor version gate. A hard telemetry verify gate was deliberately not added toscripts/macos/verify.shfor that reason; macOS already carries a documented weaker-gate posture because Homebrew cannot pin exact patches.The
--profile serverplan cannot complete on this host (no systemd SSH provider exists):openssh-serveris absent.scripts/ubuntu/server.shis untouched by this branch.