Stage 4 of decision 0023, finished. The dependency swap itself compiled the whole closure on the first attempt; what did not compile was `apps/lumbridge`, and the entire API delta across a ten-month jump turned out to be three signatures over 19 call sites. `Window::focus` is now `focus(&mut self, handle: &FocusHandle, cx: &mut App)` -- 16 sites. `flex_shrink()` takes the factor it used to assume, so it is `flex_shrink(1.0)` -- 2 sites. `Application::new()` is gone with the rest of the entry point, and is `gpui_platform::application()` -- 1 site. That is all of it. Nothing else in the framework's surface moved under this product in ten months. The interesting failure was in the fix, not the framework. Adding `, cx` to every `window.focus` site is right in a method that owns a `cx` parameter and wrong inside `cx.listener(...)`, whose closure is handed its own context as a fourth argument that this code discarded as `_`. One such site capturing the outer `cx` produced 35 errors -- E0596, two E0521s, an E0500, thirty E0501s and two E0524s -- none of which named the actual mistake, and all of which vanished when the discarded parameter was given the name it should have had. Worth recording: a borrow-checker avalanche after a dependency bump is far more likely to be one wrong capture than a framework that changed its ownership model. No crate outside `apps/lumbridge` needed a single change, because none of them imports a gpui type. That boundary was not designed for this and paid for itself anyway. `scripts/workspace-guard.sh` now asserts what it exists to assert. It compared `gpui` against version 0.2.2 from the crates.io registry, which after the swap was a guard that would have failed on the correct state of the tree. It now checks that `gpui` and `gpui_platform` both carry git+https://github.com/zed-industries/zed.git at rev ce48461e -- the same rev, because the pair are one framework snapshot and a disagreement between them would compile against two. Their versions (0.2.2 and 0.1.0) are deliberately not asserted; neither has been bumped upstream in ten months and neither means anything. Both failure modes were induced before being trusted: a wrong expected rev fails on both packages, and a lockfile where only gpui_platform's rev is altered fails on that package alone. One thing to fix next, not here: `cargo deny check sources` now fails. Decision 0023 predicted the move would bring two Git sources; the resolved graph brings four. wasm_thread (via gpui_web and scheduler) and xim-rs, which supplies zed-xim, xim-ctext and xim-parser to gpui_linux, are both unallowed, and zed-industries/scap is in the lockfile too. deny.toml is named in AGENTS.md as a file a decision record governs, so it is left alone and reported rather than edited underneath this commit. The UI gate is green: workspace-guard, fmt, clippy with -D warnings over --all-targets --all-features, and 79 tests passing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SPYebLiN2w4TqnHUYGdECq
93 lines
4.4 KiB
Bash
Executable File
93 lines
4.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Structural gates that need no compiler, so they run first and finish instantly.
|
|
#
|
|
# Both of these exist because the repository has already been wrong in exactly
|
|
# these two ways, and in both cases the mistake was invisible: the build stayed
|
|
# green while the code was not being built.
|
|
#
|
|
# scripts/workspace-guard.sh
|
|
set -euo pipefail
|
|
|
|
root="$(cd "$(dirname "$0")/.." && pwd)"
|
|
cd "$root"
|
|
status=0
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 1. Every crate is a member or is explicitly excluded.
|
|
#
|
|
# A crate directory named in neither list is not a build error. Cargo simply
|
|
# never looks at it: no lints, no tests, no compilation. lumbridge-devices sat
|
|
# that way with 1,127 lines, 19 tests that had never run, and a `mod` statement
|
|
# pointing at a file that did not exist. Decision 0017 records the same failure
|
|
# a month earlier with the GPUI shell in `spikes/`. Neither was caught by a
|
|
# human reading a diff, so it is caught here instead.
|
|
members="$(sed -n '/^members = \[/,/^]/p' Cargo.toml)"
|
|
excludes="$(sed -n '/^exclude = \[/,/^]/p' Cargo.toml)"
|
|
# A single-line `exclude = [...]` does not match the range above; catch it too.
|
|
excludes="$excludes$(grep -E '^exclude = \[.*\]' Cargo.toml || true)"
|
|
|
|
while IFS= read -r manifest; do
|
|
dir="$(dirname "$manifest")"
|
|
dir="${dir#./}"
|
|
# A crate carrying its own [workspace] table is deliberately independent.
|
|
if grep -qE '^\[workspace\]' "$manifest"; then
|
|
continue
|
|
fi
|
|
if printf '%s' "$members" | grep -qF "\"$dir\""; then
|
|
continue
|
|
fi
|
|
if printf '%s' "$excludes" | grep -qF "\"$dir\""; then
|
|
continue
|
|
fi
|
|
echo "workspace-guard: $dir/Cargo.toml is in neither workspace.members nor workspace.exclude." >&2
|
|
echo " Cargo will never build it, lint it, or run its tests. See AGENTS.md." >&2
|
|
status=1
|
|
done < <(find apps crates tools -mindepth 2 -maxdepth 2 -name Cargo.toml 2>/dev/null | sort)
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 2. The GPUI dependency is the one the decision record chose.
|
|
#
|
|
# Checked against Cargo.lock rather than the manifest, because the manifest
|
|
# states an intent and the lockfile states what would actually be compiled --
|
|
# and a manifest `rev` can drift from the revision that was actually resolved,
|
|
# just as the caret requirement it replaced silently accepted a version nobody
|
|
# decided on. Asserted in the fast headless job so it gates every push, and not
|
|
# in the UI job, which is `continue-on-error` and therefore cannot fail one.
|
|
#
|
|
# Decision 0023 moved this from published crates.io 0.2.2 to a full-SHA
|
|
# revision of Zed. Two packages arrive from it, and they must arrive from the
|
|
# SAME revision: `gpui` is the framework, `gpui_platform` is the entry point and
|
|
# the Linux backends that the publishable crate no longer contains. A pair that
|
|
# disagreed would compile against two different framework snapshots. Their
|
|
# `version` fields differ (0.2.2 and 0.1.0) and mean nothing here -- neither has
|
|
# been bumped upstream in ten months -- so the revision is what is asserted.
|
|
#
|
|
# Changing these lines means writing a decision record. See AGENTS.md,
|
|
# "Dependencies that are not an agent's decision".
|
|
expected_gpui_git='https://github.com/zed-industries/zed.git'
|
|
expected_gpui_rev='ce48461eaadd16c65c31f835511ab96bd3b6e746'
|
|
expected_gpui_source="git+$expected_gpui_git?rev=$expected_gpui_rev#$expected_gpui_rev"
|
|
|
|
for pkg in gpui gpui_platform; do
|
|
block="$(awk -v pkg="$pkg" '$0 == "name = \"" pkg "\""{found=1} found{print} found&&/^$/{exit}' Cargo.lock)"
|
|
if [ -z "$block" ]; then
|
|
echo "workspace-guard: no $pkg package in Cargo.lock; the shell cannot build." >&2
|
|
status=1
|
|
continue
|
|
fi
|
|
actual_source="$(printf '%s' "$block" | sed -n 's/^source = "\(.*\)"$/\1/p')"
|
|
if [ "$actual_source" != "$expected_gpui_source" ]; then
|
|
echo "workspace-guard: the $pkg dependency is not the one the decision record chose." >&2
|
|
echo " expected $expected_gpui_source" >&2
|
|
echo " found ${actual_source:-<no source: a path or workspace override>}" >&2
|
|
echo " Both gpui crates must carry rev $expected_gpui_rev." >&2
|
|
echo " A bump is a decision record, not a commit. See AGENTS.md." >&2
|
|
status=1
|
|
fi
|
|
done
|
|
|
|
if [ "$status" = 0 ]; then
|
|
echo "workspace-guard: crate membership and the pinned UI dependency are as recorded."
|
|
fi
|
|
exit "$status"
|