build: Turborepo fronts both toolchains - #9
Merged
Merged
Conversation
spwn.sh/apps/gate and spwn.sh/packages/gate both reduce to their last path component, so any tool that identifies a module by that component sees one name for two modules. Turborepo is the first to care and it refuses the whole graph over it. The host app is the cheap side of the collision: nothing imports spwn.sh/apps/gate, so this is the module line and nothing else. The directory stays apps/gate, the binary stays spwn-gate, and the JS package in the same directory keeps its own name. Gatehouse is the word because the gate is the crossing and the gatehouse is the host-side building that houses and guards it, which is exactly what apps/gate is: the container that owns cookie custody, MCP routing and the browser sidecar. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Both toolchains were walked by shell loops that started from nothing every time: golangci-lint once per module, then pnpm -r lint, then the same again for go test. Turborepo 2.11 reads go.work and pnpm-workspace.yaml into a single graph, hashes each package's inputs and replays what has not changed. Two future flags carry it. experimentalGoWorkspaces is what makes a Go module a package; experimentalTaskCommand is what keeps lint on golangci-lint instead of the go vet Turborepo maps by default, which would have dropped every rule .golangci.yml adds. The cache goes to .artifacts/turbo so one rm -rf still empties the repository. The per-task log Turborepo writes beside each package has no such setting, and left untracked it hashes itself into the next run — one task of twenty-one cached instead of twenty-one — so .gitignore names it. A root package.json is what Turborepo needs to find the package manager. It also makes tests/ a root-level test directory to @jterrazz/typescript's I2 rule, which is true and was never visible: the 63 diagnostics enter the ratchet as debt. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
lint, test, build, generate, web-build, test-web-unit and test-gate-node now call turbo run. Every target name CI invokes is unchanged, and so is what each one covers. GO_MODS goes with the loops it fed: go.work is still the single source of truth for what gets linted and tested, but Turborepo reads it now, so the Makefile has no list to derive. The comment says that rather than disappearing with the variable. Two filters encode facts about the graph. go-workspace is Turborepo's synthetic scope over every module: lint carries a command override that the scope would try to run at the repository root, so lint excludes it, while test selects the Go half by asking for the scope and everything it depends on. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The cache is only worth its wiring across runs, so each job restores .artifacts/turbo before its Makefile target and saves it after, on a key that tracks HEAD and a restore ladder that falls back to the branch, then the lockfile, then anything. The key carries the job name because two jobs saving one key race, and a job replays only the tasks it ran. The Go-only jobs gain a pnpm setup they never needed before: a Makefile target reaches turbo whatever toolchain it drives. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… cost The loop no longer describes go vet or pnpm -r lint, the toolchain table names turbo, and the sentence that said GO_MODS reads go.work now says Turborepo does. ADR-016 carries the rest: the two experimental flags the wiring depends on, the gate name collision that made turbo refuse the graph until a module moved, the module cycle that rules out ^build, and the measured before/after — warm lint 9.81s to 1.71s, warm test 2.36s to 1.40s, warm build 0.63s to 1.41s. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
PATH MOVE — every reference to tests/ in this repository now reads specs/, and the pnpm member tests is now specs. Peers holding work over the old paths must rebase. Turborepo made the repository root a package, which made tests/ a root-level test directory in the eyes of @jterrazz/test's I2 rule: 63 diagnostics, baselined as debt by the commit that landed turbo. The rule is not a false positive. It names the only two test roots the toolchain knows — sibling module tests under src/, and product specifications in specs/ — and this member holds the second kind. So the debt is paid by taking the name, not by recording it. The directory is renamed and flattened one level: tests/specs/cli/ becomes specs/cli/, tests/web/ becomes specs/web/, and the package root IS the specs root. That is what makes c1-domain-structure read every underscored folder of it as ground, which the tree already meant: _contracts/, _simulators/, _fixtures/, _catalog/, _support/, and manual/ which takes the underscore it was always owed. One file was not ground and had to move: the raw-execSync upgrade smoke, which now sits in the cli facet's smoke domain beside the scaffold smoke it runs with. Three paths were depth-sensitive and would have resolved above the repository root: the CLI runner's binary, the lint facet's grep root, and the guard's own exclude-dir. The C1 fix and the two vitest configs' F3 exemption are the only rules the new shape argued with. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The gitignore gate mapped .turbo to .artifacts/turbo/ and failed a .gitignore that said otherwise, for a path Turborepo publishes no key to move: only its cache obeys cacheDir, and the per-package <package>/.turbo/turbo-<task>.log does not. This repository escaped the rule with the spelling **/.turbo/, which the gate reads as anchored to its own file and never judges — unenforced rather than held. 10.1.10 puts .turbo on the gate's closed exception list, so .turbo/ is now a line the gate passes and a tracked file under .turbo/ still fails. The escape goes; the comment states the invariant instead of the workaround. Nothing else in 10.1.7 through 10.1.10 touches this tree: the vitest globs gained prose about *.e2e.ts and *.render.tsx without changing what they match, and the suppressions pass learned to read a rule armed only in an override. Both members report the counts they reported on 10.1.6 — apps/web 1280 diagnostics and 4 suppressions, specs 366 and 0 — so no baseline is rewritten here. The lockfile carries the version and nothing else. A plain install also flips which of the two installed typescript versions msw, shadcn and vitest peer-resolve against, in either direction and with no package changing version; the seven lines here are the bump alone, and --frozen-lockfile accepts them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The record still described a gate gap and left a question with the toolchain owner. It is answered: 10.1.10 admits the path, the plain .gitignore line holds, and the exception is the toolchain's own decision rather than this repository's. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Turborepo fronts both toolchains of this repository, on the owner's word given at review of the branch. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The root package.json turbo needs now carries packageManager, and pnpm/action-setup refuses two sources for the version: every job died at setup with 'Multiple versions of pnpm specified'. The workflow stops naming one; the action reads the field, so the version has exactly one owner. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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.
One task graph over go.work and the pnpm workspace, with caching, in place of the Makefile's sequential loops.
go vetdefault.spwn.sh/apps/gatehouse: turbo names a package by its module path's last component and refused the graph overapps/gateandpackages/gateboth deriving togate. Nothing imported the module; directory, binary and JS package keep their names.tests/workspace package becomesspecs/, flattened one level, which is where the toolchain's rule I2 puts product specifications. The move surfaced three relative paths that resolved outside the repository.@jterrazz/typescript10.1.10, whose gate admits turbo's task-log directory.make lint28.8s cold / 9.8s warm before, 16.7s / 1.7s after;make test14.7s / 2.4s before, 7.9s / 1.4s after.ADR-016 records the decision, the two experimental flags relied on, and what the graph cannot express (
^build, sinceworldandtranspilerequire each other).🤖 Generated with Claude Code