From d656162d7b7e5fc313f2c22e9494a6f71b984618 Mon Sep 17 00:00:00 2001 From: Ivan Malison Date: Thu, 30 Jul 2026 02:01:29 -0700 Subject: [PATCH] fix(nix): keep docs and CI out of the derivation sources MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both Nix derivations take the whole repository as `src` and exclude only a handful of paths, so `docs/`, `.github/`, `docker/`, the agent/editor config directories and the top-level markdown are all build inputs. None of them reach the build, but any one of them changing produces a new derivation and a full rebuild — including the Expo web export, which is the dominant cost — to arrive at a byte-identical result. The daemon's filter matters for the desktop package too, not just for the daemon: desktop-package.nix inherits `npmDeps` from it, so a docs-only commit gave a new npm-deps derivation, hence a new desktop derivation, hence a full desktop rebuild even with the desktop filter tightened on its own. Markdown is excluded at the top level only. skills/*/SKILL.md is a runtime file both derivations copy into their output, so a repository-wide `*.md` exclusion would silently ship empty skill directories. --- nix/desktop-package.nix | 15 +++++++++++++++ nix/package.nix | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/nix/desktop-package.nix b/nix/desktop-package.nix index 9703c497ae..cd9c6ca5c2 100644 --- a/nix/desktop-package.nix +++ b/nix/desktop-package.nix @@ -33,6 +33,21 @@ buildNpmPackage rec { && !(lib.hasPrefix "/packages/app/ios" relPath) # Website is unrelated to the desktop app && !(lib.hasPrefix "/packages/website" relPath) + # Documentation, CI definitions and agent/editor configuration. None of + # these reach the build, but every one of them is part of `src`, so a + # docs-only or workflow-only commit currently invalidates the whole + # desktop derivation and pays for a full Expo export to produce a + # byte-identical result. + && !(lib.hasPrefix "/docs" relPath) + && !(lib.hasPrefix "/.github" relPath) + && !(lib.hasPrefix "/.agents" relPath) + && !(lib.hasPrefix "/.claude" relPath) + && !(lib.hasPrefix "/.codex" relPath) + && !(lib.hasPrefix "/docker" relPath) + # Top-level prose only (README, CHANGELOG, AGENTS...). Deeper markdown is + # not necessarily documentation: skills/*/SKILL.md is a runtime file the + # installPhase copies into the output. + && builtins.match "/[^/]+\\.md" relPath == null # Test fixtures and build artifacts && !(lib.hasSuffix ".test.ts" baseName) && !(lib.hasSuffix ".e2e.test.ts" baseName) diff --git a/nix/package.nix b/nix/package.nix index b30665b8c9..417f3d2ad1 100644 --- a/nix/package.nix +++ b/nix/package.nix @@ -37,6 +37,21 @@ buildNpmPackage rec { && !(lib.hasPrefix "/packages/website/public" relPath) && !(lib.hasPrefix "/packages/desktop/src" relPath) && !(lib.hasPrefix "/packages/desktop/src-tauri" relPath) + # Documentation, CI definitions and agent/editor configuration. None of + # these reach the build. Excluding them here also matters for the desktop + # derivation, which inherits this package's npmDeps: leaving them in makes + # a docs-only commit produce a new npm-deps .drv, and so a new desktop + # .drv, and so a full rebuild for a byte-identical result. + && !(lib.hasPrefix "/docs" relPath) + && !(lib.hasPrefix "/.github" relPath) + && !(lib.hasPrefix "/.agents" relPath) + && !(lib.hasPrefix "/.claude" relPath) + && !(lib.hasPrefix "/.codex" relPath) + && !(lib.hasPrefix "/docker" relPath) + # Top-level prose only (README, CHANGELOG, AGENTS...). Deeper markdown is + # not necessarily documentation: skills/*/SKILL.md is a runtime file the + # daemon's trace script copies into the output. + && builtins.match "/[^/]+\\.md" relPath == null # Exclude test fixtures and debug files && !(lib.hasSuffix ".test.ts" baseName) && !(lib.hasSuffix ".e2e.test.ts" baseName)