From d2f1cf860f0c0138efcf9d17e33212a26d2cc5f7 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Sun, 20 Sep 2026 01:22:02 +0200 Subject: [PATCH 1/3] refactor(buck2): make repository checks standalone agent-identity: dev3.direct.omp.8uhgh9vt agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.2.6 agent-runtime: OMP 18.2.6 agent-model: openai-codex/gpt-5.6-sol tooling-profile: dotfiles@965ef7e-dirty --- CHANGELOG.md | 4 +++ .../2026-09-20-standalone-check-surface.md | 35 +++++++++++++++++++ context/buck2/05-composition/spec.md | 25 +++++++------ devenv.nix | 24 +++++++------ nix/devenv-modules/tasks/shared/megarepo.nix | 5 ++- scripts/devenv-task-graph-check.mjs | 32 +++++++++++++---- 6 files changed, 96 insertions(+), 29 deletions(-) create mode 100644 context/buck2/.experiments/2026-09-20-standalone-check-surface.md diff --git a/CHANGELOG.md b/CHANGELOG.md index ed8ca48cd5..d28657d90b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -233,6 +233,10 @@ All notable changes to this project will be documented in this file. ### Removed +- **Buck2 checks**: remove megarepo setup, apply, and validation gates from the + repository `check:quick` and `check:all` dependency graphs. Repository + composition remains available through explicit mr operations. + - **nix**: the repository-local pnpm source builders for the ci-tools, Genie, Genie bootstrap-closure-check, megarepo, notion-cli, notion-md, npm-release, and tui-stories CLIs are gone, together with their fixed-output dependency diff --git a/context/buck2/.experiments/2026-09-20-standalone-check-surface.md b/context/buck2/.experiments/2026-09-20-standalone-check-surface.md new file mode 100644 index 0000000000..4561486519 --- /dev/null +++ b/context/buck2/.experiments/2026-09-20-standalone-check-surface.md @@ -0,0 +1,35 @@ +# Standalone check surface + +Date: 2026-09-20 + +## Question + +Can effect-utils run its repository check graph from the standalone repository root without invoking megarepo setup, apply, or validation tasks? + +## Method + +Run every Buck, Nix, and devenv command through the shared heavy-command gate. Capture three warm `check:quick` samples before and after the task-graph change. Run `check:all` once. Inspect the evaluated task graph and require both check aggregates and every Buck-backed repository task to avoid `mr:setup`, `mr:apply`, `mr:check`, `mr:lock-sync-check`, and `mr:source-policy-check`. + +The inherited branch could not evaluate its devenv task graph because the committed Genie product descriptor and its import contract disagree about the `opentui-core-native` capability. A temporary local alignment let the task graph evaluate for structural inspection. The alignment was then reverted and is not part of this change. + +## Result + +| Probe | Samples | Result | +| --- | --- | --- | +| Before, warm `check:quick` | 68.280 s, 10.235 s, 9.012 s | REJECTED: all three failed during devenv evaluation with `javascript-product-import: external capability mismatch` | +| After, warm `check:quick` | 2.183 s, 2.081 s, 1.950 s | REJECTED: all three reused the diagnostic evaluation and failed in inherited Genie generation; the committed product reports `nixCacheSetupStep is not defined` | +| After, `check:all` | 8.701 s | REJECTED: inherited Genie, Nix flake, and Rust workspace checks failed | +| Task graph assertions | 205 assertions | PASS: `mr:setup` and the three composition checks are absent, both check aggregates avoid `mr:apply`, and standalone Buck tasks retain the `genie:check` freshness edge | +| Standalone format task | 14.654 s | INCONCLUSIVE: the task reached the repository-root Buck target without composition, but an unavailable remote-cache credential caused retries and the probe was interrupted | + +The before and after timings are failure timings. They do not support a performance comparison. They are retained to make the blocked control explicit rather than presenting rejected samples as successful evidence. + +The task graph retains `mr:bootstrap`, `mr:fetch-apply`, `mr:lock`, and `mr:apply` as explicit repository-composition operations. None is reachable from `check:quick` or `check:all`. + +## Conclusion + +The structural cut is complete: repository checks and Buck-backed check tasks no longer depend on composition. The repository-level runtime proof is blocked by an inherited stale Genie product, so this experiment does not claim a green aggregate or a speedup. The accepted evidence is the 205-assertion task-graph proof. + +## VRS Impact + +The composition spec now defines the repository root as the check root and limits mr to explicit composition operations. The three residual ledger rows for `composition-mr-check`, `composition-mr-lock-sync-check`, and `composition-mr-source-policy-check` can close when this change lands. The stale Genie product must be repaired by its owning publication slice before successful aggregate timings can replace the rejected samples above. diff --git a/context/buck2/05-composition/spec.md b/context/buck2/05-composition/spec.md index f729e29e4b..b7b68c24b7 100644 --- a/context/buck2/05-composition/spec.md +++ b/context/buck2/05-composition/spec.md @@ -148,13 +148,12 @@ manifest, and kept out of action digests by the root's `[project] ignore` This is what gives editors and typecheck actions cross-member types through the unchanged `exports` types→dist mechanism. -The workspace root is not a git repository; the owned member is, and it is -the default working directory (git, devenv, genie, and pnpm all operate from -the member; nothing operates only from the root). `buck2 build` works from -the root, the member, and package dirs alike (COMP-R06); note `buck2 root` -defaults to `--kind cell` (the member) — scripts wanting the workspace pass -`--kind project`. Teardown is an mr operation (protected mounts need a -dirs-only unprotect before removal), never a bare `rm -rf`. +The composed workspace root is not a git repository; the owned member is, and +it is the default working directory for explicit composition operations. Buck +can run from the root, owned member, or a package directory (COMP-R06); +scripts that need the composed project root pass `buck2 root --kind project`. +Teardown is an mr operation (protected mounts need a dirs-only unprotect before +removal), never a bare `rm -rf`. ## Composed-Exception Agent Workflow Contract — Revision 3 @@ -176,9 +175,9 @@ exceptional shape, agents follow these rules: create an independent composed checkout outside the store. 2. Use `repos/` as the default cwd and the only source tree mutated by the session. -3. Run git, devenv, Genie, pnpm, and package-local commands from the owned - member. A command that needs the composition root resolves it through mr or - `buck2 root --kind project`; it does not infer `../..` in application code. +3. Run git, Genie, pnpm, and package-local commands from the owned member. + Resolve a composition root through mr or `buck2 root --kind project` only + for an explicit composition operation; do not infer `../..` in application code. 4. Treat every non-owned `repos/` as immutable input. Never edit, chmod, replace, branch, or run a producer that writes there. 5. Treat ignored members as reference-only. They are excluded from Buck cells, @@ -212,6 +211,12 @@ discovery of an outer project. Effect-utils CI and devenv Buck tasks use this shape directly; a second standalone checkout at the same revision is the BUCK-R06 cache-reuse comparison context. +`devenv tasks run check:quick` and `check:all` execute their Buck aggregates, +lint actions, test actions, and editor-view publication from this root. The +check graph does not run `mr:setup`, `mr:apply`, or any `mr:*` validation gate. +Repository composition remains an explicit mr operation outside the check +surface. + The paused composed shape remains distinct until L3 cut 2: the member is mounted at `repos/` under the same canonical cell name. Action-digest parity between these two shapes must be measured rather than assumed; the diff --git a/devenv.nix b/devenv.nix index 7499fef2be..c19241faa2 100644 --- a/devenv.nix +++ b/devenv.nix @@ -680,9 +680,6 @@ in "check:devenv-eval-inputs" "lint:check" "lint:nix" - "mr:check" - "mr:lock-sync-check" - "mr:source-policy-check" "nix:flake:check" "buck2:editor:publish" "test:run" @@ -698,12 +695,21 @@ in inputs.playwright.devenvModules.default # Shared task modules taskModules.genie - (taskModules.megarepo { mrPkg = mrCli; }) + (taskModules.megarepo { + mrPkg = mrCli; + disabledTasks = [ + "mr:setup" + "mr:check" + "mr:lock-sync-check" + "mr:source-policy-check" + ]; + }) (taskModules.lint-nix { }) # No repository JavaScript package is source-built by Nix anymore. Import # the empty module contract to retain repository-wide flake validation. (taskModules.nix-cli { cliPackages = [ ]; }) (taskModules.check { + hasMegarepoCheck = false; extraChecks = [ "devenv:trace-audit" "workspace:check" @@ -980,13 +986,9 @@ in # reads RESTATE_SERVER_BIN to locate the native server, else falls back to $PATH). env.RESTATE_SERVER_BIN = "${restate}/bin/restate-server"; - # Composed development workspaces remain available until L3 cut 2, but no CI - # or repository Buck task depends on their mutators. - tasks."mr:setup".after = [ "mr:bootstrap" ]; - tasks."mr:apply".after = [ - "genie:check" - "mr:setup" - ]; + # Repository composition remains an explicit mr operation. Generated-source freshness + # is its only repository-local prerequisite; the check aggregates do not invoke it. + tasks."mr:apply".after = [ "genie:check" ]; # buck2-tools executes inside pinned Bun actions and exercises Bun.YAML/Bun.which. # Keep its package gate on that runtime rather than Vitest's Node process. diff --git a/nix/devenv-modules/tasks/shared/megarepo.nix b/nix/devenv-modules/tasks/shared/megarepo.nix index d37f01803a..7d993a1fb0 100644 --- a/nix/devenv-modules/tasks/shared/megarepo.nix +++ b/nix/devenv-modules/tasks/shared/megarepo.nix @@ -19,6 +19,7 @@ # - bootstrapMembers: Minimal members that must exist before tooling like genie # can evaluate. Uses lock-based `mr apply --only ...` and never fetches remote # refs. Default: [ ] (task becomes a no-op) +# - disabledTasks: Task names omitted from this module instance. Default: [ ]. # NOTE: No pnpm:install:megarepo dependency here — this shared module is used by # repos where megarepo may be a Nix package (no pnpm install needed). Repos that # use source-mode megarepo via pnpm should add dependencies in their devenv.nix: @@ -27,6 +28,7 @@ { syncAll ? true, bootstrapMembers ? [ ], + disabledTasks ? [ ], # Real derivation/path backing the `mr` guard. When set, the guard owns # `bin/mr` and exec's this by absolute path under passthrough (see # cli-guard.nix). Required for source-mode `mr` (no node_modules/.bin @@ -155,7 +157,7 @@ let >/dev/null 2>&1 ''; - tasks = { + allTasks = { "mr:bootstrap" = { guard = "mr"; description = "Materialize bootstrap members from megarepo.lock"; @@ -391,6 +393,7 @@ let ''; }; }; + tasks = builtins.removeAttrs allTasks disabledTasks; in { # mr shells out to git for clone/fetch/worktree operations diff --git a/scripts/devenv-task-graph-check.mjs b/scripts/devenv-task-graph-check.mjs index e0d88ebcd8..6a77b56abb 100755 --- a/scripts/devenv-task-graph-check.mjs +++ b/scripts/devenv-task-graph-check.mjs @@ -150,6 +150,12 @@ for (const name of [ name: `${name} is absent after its Buck authority cutover`, }) } +for (const name of ['mr:setup', 'mr:check', 'mr:lock-sync-check', 'mr:source-policy-check']) { + ok({ + condition: tasks.has(name) === false, + name: `${name} is absent after the standalone check-surface cut`, + }) +} for (const name of ['nix:build', 'nix:check']) { ok({ condition: tasks.has(name) === false, @@ -196,6 +202,12 @@ ok({ condition: reaches({ start: 'check:all', target: 'nix:flake:check' }), name: 'check:all retains repository-wide Nix flake validation', }) +for (const checkTask of ['check:quick', 'check:all']) { + ok({ + condition: reaches({ start: checkTask, target: 'mr:apply' }) === false, + name: `${checkTask} does not reach mr:apply`, + }) +} // `test:run` must schedule the one Buck aggregate and the source-side batches which own // packages absent from the authority plus admitted lanes' exact unbounded complements. Either // edge going missing would silently omit a disjoint side of the test partition. @@ -208,10 +220,8 @@ ok({ condition: testRunDependencies.some((name) => name.startsWith('test:run:batch:') === true), name: 'test:run executes the source-owned complement partition', }) -// `genie:check` is the source-side stage-zero guard against a graph proving its own stale -// projection. `mr apply` runs only after that proof, then reconciles the workspace and -// installs the `.buck2/capabilities` projection Buck analysis reads. Together they are the -// ordering barriers for every public task that invokes Buck. +// `genie:check` prevents a stale graph from proving itself. It is the freshness barrier for +// repository-root Buck tasks. `mr:apply` remains an explicit composition operation. const buck2TestAuthority = JSON.parse(readFileSync(`${root}/buck2-test-authority.json`, 'utf8')) if (buck2TestAuthority.schemaVersion !== 2 || Array.isArray(buck2TestAuthority.lanes) === false) { throw new Error('buck2-test-authority.json does not match schemaVersion 2') @@ -239,7 +249,7 @@ for (const name of [...buck2UnboundedTaskNames, ...buck2ExternalOwnerTaskNames]) name: `${name} exists as a source-side test owner`, }) } -for (const name of [ +const standaloneBuckTaskNames = [ 'buck2:editor:authority', 'buck2:editor:publish', 'buck2:editor:check', @@ -254,7 +264,9 @@ for (const name of [ 'workspace:check', 'test:buck2:unit', ...buck2TestLaneTaskNames, -]) { + ...buck2ExternalOwnerTaskNames, +] +for (const name of standaloneBuckTaskNames) { ok({ condition: reaches({ start: name, target: 'mr:apply' }) === false, name: `${name} remains standalone`, @@ -264,7 +276,13 @@ for (const name of [ name: `${name} waits for source-side generation freshness`, }) } -for (const name of ['buck2:check', 'buck2:quick', 'buck2:all', 'buck2:nix-bridge:check']) { +for (const name of [ + 'buck2:check', + 'buck2:quick', + 'buck2:all', + 'buck2:nix-bridge:check', + 'buck2:editor:bootstrap', +]) { ok({ condition: reaches({ start: name, target: 'mr:apply' }) === false, name: `${name} remains standalone`, From d4de91122ff4a6b9679986a1cf9b008e6c486025 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Sun, 20 Sep 2026 01:29:00 +0200 Subject: [PATCH 2/3] docs(buck2): refresh standalone graph evidence agent-identity: dev3.direct.omp.8uhgh9vt agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.2.6 agent-runtime: OMP 18.2.6 agent-model: openai-codex/gpt-5.6-sol tooling-profile: dotfiles@965ef7e-dirty --- .../buck2/.experiments/2026-09-20-standalone-check-surface.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/context/buck2/.experiments/2026-09-20-standalone-check-surface.md b/context/buck2/.experiments/2026-09-20-standalone-check-surface.md index 4561486519..95793dcc09 100644 --- a/context/buck2/.experiments/2026-09-20-standalone-check-surface.md +++ b/context/buck2/.experiments/2026-09-20-standalone-check-surface.md @@ -19,7 +19,7 @@ The inherited branch could not evaluate its devenv task graph because the commit | Before, warm `check:quick` | 68.280 s, 10.235 s, 9.012 s | REJECTED: all three failed during devenv evaluation with `javascript-product-import: external capability mismatch` | | After, warm `check:quick` | 2.183 s, 2.081 s, 1.950 s | REJECTED: all three reused the diagnostic evaluation and failed in inherited Genie generation; the committed product reports `nixCacheSetupStep is not defined` | | After, `check:all` | 8.701 s | REJECTED: inherited Genie, Nix flake, and Rust workspace checks failed | -| Task graph assertions | 205 assertions | PASS: `mr:setup` and the three composition checks are absent, both check aggregates avoid `mr:apply`, and standalone Buck tasks retain the `genie:check` freshness edge | +| Task graph assertions | 204 assertions | PASS: `mr:setup` and the three composition checks are absent, both check aggregates avoid `mr:apply`, and standalone Buck tasks retain the `genie:check` freshness edge | | Standalone format task | 14.654 s | INCONCLUSIVE: the task reached the repository-root Buck target without composition, but an unavailable remote-cache credential caused retries and the probe was interrupted | The before and after timings are failure timings. They do not support a performance comparison. They are retained to make the blocked control explicit rather than presenting rejected samples as successful evidence. @@ -28,7 +28,7 @@ The task graph retains `mr:bootstrap`, `mr:fetch-apply`, `mr:lock`, and `mr:appl ## Conclusion -The structural cut is complete: repository checks and Buck-backed check tasks no longer depend on composition. The repository-level runtime proof is blocked by an inherited stale Genie product, so this experiment does not claim a green aggregate or a speedup. The accepted evidence is the 205-assertion task-graph proof. +The structural cut is complete: repository checks and Buck-backed check tasks no longer depend on composition. The repository-level runtime proof on the original base was blocked by an inherited stale Genie product, so the before/after samples do not support a speedup claim. The accepted evidence after rebasing onto the delivery stack is the 204-assertion task-graph proof. ## VRS Impact From 63d9fa1a042171720b80bb064949a9d49ec007d5 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Wed, 23 Sep 2026 06:00:00 +0200 Subject: [PATCH 3/3] fix(devenv): close disabled task graphs agent-identity: dev3.direct.omp.t3mkm4sd agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.1.14 agent-runtime: OMP 18.1.14 tooling-profile: dotfiles@5d1e05f --- CHANGELOG.md | 3 ++ nix/devenv-modules/tasks/shared/megarepo.nix | 16 ++++++++-- .../shared/tests/devenv-task-graph.test.sh | 32 ++++++++++++++++++- scripts/devenv-task-graph-check.mjs | 1 + 4 files changed, 49 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d28657d90b..54645ebf7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ All notable changes to this project will be documented in this file. ### Fixed +- **Megarepo tasks**: Remove `after` and `before` edges to tasks omitted through + `disabledTasks`, including the optional bootstrap-to-Genie edge, so partial + task cuts always leave a closed devenv graph. - **Buck2 rules distribution**: Give the standalone rules artifact its own minimal root package for package runtimes and the TypeScript action runner, so consumer roots can resolve the configured TypeScript toolchain without diff --git a/nix/devenv-modules/tasks/shared/megarepo.nix b/nix/devenv-modules/tasks/shared/megarepo.nix index 7d993a1fb0..634bc26562 100644 --- a/nix/devenv-modules/tasks/shared/megarepo.nix +++ b/nix/devenv-modules/tasks/shared/megarepo.nix @@ -393,7 +393,19 @@ let ''; }; }; - tasks = builtins.removeAttrs allTasks disabledTasks; + taskIsEnabled = taskName: builtins.elem taskName disabledTasks == false; + removeDisabledDependencies = + task: + task + // lib.optionalAttrs (task ? after) { + after = builtins.filter taskIsEnabled task.after; + } + // lib.optionalAttrs (task ? before) { + before = builtins.filter taskIsEnabled task.before; + }; + tasks = lib.mapAttrs ( + _: task: removeDisabledDependencies task + ) (builtins.removeAttrs allTasks disabledTasks); in { # mr shells out to git for clone/fetch/worktree operations @@ -408,7 +420,7 @@ in tasks = cliGuard.stripGuards tasks - // lib.optionalAttrs (bootstrapMembers != [ ]) { + // lib.optionalAttrs (bootstrapMembers != [ ] && taskIsEnabled "mr:bootstrap") { # Repos that source-import genie helpers from bootstrap members should ensure # those members exist before any genie-backed task runs. "genie:prepare".after = lib.mkAfter [ "mr:bootstrap" ]; diff --git a/nix/devenv-modules/tasks/shared/tests/devenv-task-graph.test.sh b/nix/devenv-modules/tasks/shared/tests/devenv-task-graph.test.sh index ce01acf8ce..d77e258103 100755 --- a/nix/devenv-modules/tasks/shared/tests/devenv-task-graph.test.sh +++ b/nix/devenv-modules/tasks/shared/tests/devenv-task-graph.test.sh @@ -5,4 +5,34 @@ TESTS_DIR="$(cd "$(dirname "$0")" && pwd)" ROOT="${DEVENV_ROOT:-$(cd "$TESTS_DIR/../../../../.." && pwd)}" NODE_BIN="${NODE_BIN:-node}" -exec "$NODE_BIN" "$ROOT/scripts/devenv-task-graph-check.mjs" "$ROOT" +"$NODE_BIN" "$ROOT/scripts/devenv-task-graph-check.mjs" "$ROOT" + +fixture="$(mktemp)" +trap 'rm -f "$fixture"' EXIT +cat > "$fixture" <<'EOF' +{ + "tasks": [ + { "name": "kept", "after": ["missing-upstream"] }, + { "name": "also-kept", "before": ["missing-downstream"] } + ] +} +EOF + +if DEVENV_TASKS_JSON="$fixture" DEVENV_TASK_GRAPH_DEPENDENCIES_ONLY=1 \ + "$NODE_BIN" "$ROOT/scripts/devenv-task-graph-check.mjs" "$ROOT" +then + echo "FAIL: task graph checker accepted dependencies on undefined tasks" >&2 + exit 1 +fi + +cat > "$fixture" <<'EOF' +{ + "tasks": [ + { "name": "upstream", "before": ["downstream"] }, + { "name": "downstream", "after": ["upstream"] } + ] +} +EOF + +DEVENV_TASKS_JSON="$fixture" DEVENV_TASK_GRAPH_DEPENDENCIES_ONLY=1 \ + "$NODE_BIN" "$ROOT/scripts/devenv-task-graph-check.mjs" "$ROOT" diff --git a/scripts/devenv-task-graph-check.mjs b/scripts/devenv-task-graph-check.mjs index 6a77b56abb..ff65d658d2 100755 --- a/scripts/devenv-task-graph-check.mjs +++ b/scripts/devenv-task-graph-check.mjs @@ -94,6 +94,7 @@ ok({ name: 'every task dependency resolves to an evaluated task', detail: missingDependencies.join(', '), }) +if (process.env.DEVENV_TASK_GRAPH_DEPENDENCIES_ONLY === '1') process.exit(0) const requireTask = (name) => { const task = tasks.get(name) ok({ condition: task !== undefined, name: `evaluated graph contains ${name}` })