Repository navigation
ci(release): decide changeset coverage from turbo's build hashes - #6
Open
systemfsoftware-maker wants to merge 5 commits into
Open
systemfsoftware-maker wants to merge 5 commits into
systemfsoftware-maker wants to merge 5 commits into
Conversation
The release gate moves from `paths` to `{ strategy: turbo, task: build }`.
`main` has carried turbo.json since b7e907a, so the comment saying the turbo
gate refuses this repository's base is stale. A publishable package now needs
an intent when its turbo `build` hash moves between base and head
(pnpm-release-management b9b4a1d change-verdict.ts verdictTouched), the gate
systemfsoftware and pnpm-release-management use. .changeset/README.md states
the same rule and keys the 0.0.0 `none` caveat on the tarball.
This was referenced Oct 13, 2026
The turbo gate asks for an intent when a package's `build` hash moves, and files outside the package can move it. turbo 2.10.12's dry run moved @systemfsoftware/api-extractor#build on a change to turbo.json's `build` task, to `globalEnv`, and to the root package.json's dependencies, and not on root metadata, a lockfile comment or another task's settings. The README now names those inputs, so a contributor can see why such a pull request owes an intent (`none` when the tarball is unchanged).
The list of outside-package inputs that move a package's `build` hash named only the three that turbo 2.10.12's dry run was measured on, but read as complete. Review named other inputs turbo also folds in (lockfile resolutions, other root dependency fields). The sentence now gives the measured inputs as examples; the gate itself compares turbo's hashes.
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.
Summary
The Changeset Check now decides which packages need an intent by turbo
buildhash, not by path.release.jsoncchanges from{ "strategy": "paths" }to{ "strategy": "turbo", "task": "build" }. pnpm-release-management is pinned atb9b4a1d. At that pin, a publishable package needs an intent when itsbuildtask hash differs between the base and the head (process-adapter/src/change-verdict.tsverdictTouched, evidence fromturbo-evidence.ts). systemfsoftware and pnpm-release-management already use the same gate.The old comment said the turbo gate dry-runs turbo at the base and refuses a base without
turbo.json. That is out of date:mainhas carriedturbo.jsonsinceb7e907a(#2)..changeset/README.mdnow states the turbo rule. Its 0.0.0 caveat now keys on a change to the tarball rather than to thepackages/api-extractorpath..changeset/README.md:12-15also says that files outside the package can move the hash, with measured examples (below), and that such a pull request names the package, withnonewhen its tarball does not change.No package, app or intent changes, and the shipped tarball is unchanged.
Turbo evidence (turbo 2.10.12, the catalog pin)
turbo query: 3 packages (//,@systemfsoftware/api-extractor,api-extractor-e2e). One graph edge: e2e → api-extractor,development. Boundaries: 0 diagnostics.affectedTasks(tasks: ["build"])over this repo's merged PRs: build: move api-extractor onto the systemfsoftware family toolchain #2 → bothbuildtasks (TaskGlobalFileChanged turbo.json); fix(release): give main's Release the version surface it needs #3, chore(release): version packages #4 and ci(mutation): run mutation testing on main through systemfsoftware's reusable workflow #5's head → none.Outside-package inputs, measured with
turbo run build --dry=jsonon a scratch copy of this tree (@systemfsoftware/api-extractor#build, base hash345f4274c3eb009e):turbo.jsontasks.build.outputs(7b29fe4c…),globalEnvadded (c74adef1…), a rootpackage.jsondevDependency (dfc029a9…).package.jsondescription, a comment line inpnpm-lock.yaml,turbo.jsontasks.lint.buildscript deleted, turbo kept the task (command<NONEXISTENT>) and its hash moved (873e9aab…), so the check still asks for an intent.Gate proof
Each run is
changeset-management check origin/main, using the release tools from this repo's dev shell (theb9b4a1dpin), against base9bd7396, which hasturbo.json. Each control was a throwaway local commit on top of this branch. The controls are deleted, and no base worktree was left behind.main)packages/api-extractor/src/mod.ts@systemfsoftware/api-extractorturbo.jsonbuild.envgains a variableapps/api-extractor-e2e/outputs.ts(private)packages/api-extractor/stryker.config.tsonly (not infiles)Under turbo
build, any file in the package's default inputs counts as a change. E shows the cost: a change outside the tarball still needs an intent, and its intent isnone. The paths gate behaves the same here, so this is not a regression.CI on this head is the proof that the gate runs inside the
devshell: truesandbox. No sibling caller runs turbo with devshell today: stryker-js-effect uses devshell withpaths.Credentials
The gate runs
turbo run build --dry=jsonwith noTURBO_TOKEN/TURBO_TEAM.ci.ymlandchangeset-check.ymlpass neither, so turbo uses only the local cache and a public-repo run gets no credentials.Code review (full path, report-only, final head
0a72fe4)ce-code-review mode:agent base:origin/main depth:fullran against head0a72fe466b7851d3392b5bc1232eeec4e55a90d4, basecd9f133d595faf51e319b4fe9990d3b1d8eede1c(mainafter #8). Run20261013-093026-84707681. CE verdict: Ready to merge. The review has no actionable finding. The one pack-rule breach is a departure the root accepted (below), and the PR waits for the root's verdict; it is not merged.Rounds on this PR:
da6d7f2: full path, run…856eb364.a2aa2cd: plain merge oforigin/main(cd9f133, chore(packs): enroll ci-wall-clock and repin compound packs to 8d07118079 #8). The merge changes only.compound-engineering/config.yaml, which pins8d071180798f9ea82ef5a4fd877152dacc02f6b6and enrollsci-wall-clock; nothing was rebased or force-pushed. Full-path delta round, run…d26930a4.12e09fe: README fix. Round…3e69dc8eis superseded, because its two findings were fixed in the next commit.0a72fe4: this receipt.Packs: resolved from this head's own
.compound-engineering/config.yaml.--declared-onlyexit 0 with no errors; full resolve exit 0 with no errors or warnings, five roots at8d071180798f9ea82ef5a4fd877152dacc02f6b6. The packs hold 50 rule files:cell-architecture15,boundary-testing6,schema-laws10,package-topology7,ci-wall-clock12. Applicability was decided by meaning (CONST-T12), and systemfsoftwareCONSTITUTION.mdoutranks pack rules (CONST-S2).Reviewers: correctness, project standards (
AGENTS.mdplus the constitution), learnings with the per-rule receipt, reliability, security, and adversarial. All six ran as omp agents, and their session logs show onlydeepseek/deepseek-v4.1-flashturns through OpenRouter, with no Claude, Grok or xAI turn. The non-Claude peer is omp'sadversarial-reviewerondeepseek-v4.1-flash(20 turns); no external peer CLI is installed. No reviewer timed out: the longest slice took 7 m 24 s, under the 15-minute bound. In thea2aa2cdround the adversarial slice took 15 m 03 s but returned a complete, schema-valid artifact.Declared breach:
ci-wall-clock/light-checks-run-the-pinned-tool(accepted by root ruling)release.jsonc:13("gate": { "strategy": "turbo", "task": "build" }) makes the check take turbo from the workspace install. pnpm-release-managementb9b4a1dpackages/process-adapter/src/turbo-evidence.ts:27readsTURBO_BIN = 'node_modules/.bin/turbo', and:106-116refuses withTurboPinUnusablewhen it is absent. So this check can never run install-free; thepathsstrategy needed only git.devshell: trueat.github/workflows/changeset-check.yml:17and repins pnpm-release-management, so the check runs install-free. Neither change belongs in this PR.changeset-check.yml:17passesdevshell: true, so the job already runs the dev shell and this repository'sbootstrapbefore the verdict, onmainas well. Measured: the check job took 7 m 44 s onda6d7f2(run 38298009147) and 8 m 28 s on ci(mutation): run mutation testing on main through systemfsoftware's reusable workflow #5's head with thepathsgate (run 38291945550); it took 6 m 39 s on this head (run 38376783369). The bootstrap dominates every one of these runs, so the switch adds no measured wall time today. The breach is structural.pathsis closed: upstream #56 (merged as2b89555) refuses the paths gate where turbo drives the comparison.Findings and dispositions
0a72fe4.changeset/README.md:15noneintent is the author's judgement.nonewithtag-integrity-mismatch, and the README's 0.0.0 bullet says so. Guidance in the refusal text belongs to pnpm-release-management (gate-changes.ts:104-118).a2aa2cd.changeset/README.md:1012e09feand0a72fe4:README.md:12-15names measured examples.a2aa2cdrelease.jsonc:13a2aa2cdrelease.jsonc:13buildtask that vanishes reads as unchanged (change-verdict.ts:35,54).<NONEXISTENT>and its hash moved.12e09fe.changeset/README.md:130a72fe4: the inputs are now given as examples.12e09ferelease.jsonc:13timeout-minuteson such a job. The bound belongs in pnpm-release-management'schangeset-check.ymlandProcessRun.ts.da6d7f2release.jsonc:13da6d7f2:244paths.Pack receipt (
0a72fe4)ci-wall-clock/light-checks-run-the-pinned-toolrelease.jsonc:13ci-wall-clock/pr-gate-runs-only-what-the-diff-affectsbuildgraph instead of a hand-kept path list, and this receipt satisfies the rule's full-path review clauserelease.jsonc:13;.changeset/README.md:10-15Not matched (48):
ci-wall-clock(10):flake-outputs-build-once-on-main,gates-share-one-job,heavy-lanes-state-their-daily-minutes,heavy-suites-judge-every-main-commit,no-dev-shell-on-verdict-lanes,no-lane-grades-the-repos-own-docs,one-stuck-job-backstop,red-main-reverts-its-culprit-same-day,release-promotes-the-staging-proven-build,setup-under-a-minute.cell-architecture(15),boundary-testing(6),schema-laws(10) andpackage-topology(7): every rule. The diff changes no code, schema, entry point, port, adapter or published surface.The
devshell: trueatchangeset-check.yml:17predates this diff.light-checks-run-the-pinned-toolandsetup-under-a-minuteboth refuse that shape on their own, and the follow-up above removes it.Still open, outside this PR
:244(this PR'sda6d7f2finding 3) and:446(chore(packs): enroll ci-wall-clock and repin compound packs to 8d07118079 #8's finding 5). The fix is a new dated plan declaringsupersedes:, or the PR bodies serve as the record.turbo.jsonchange tobuild.inputscould narrow what the gate sees.pathsgate until they mergemain.CI at
0a72fe4CI run 38376783225: all 11 jobs succeeded. Changeset Check run 38376783369: success. 12 of 12 jobs are green. The PR has no review threads and no comments.
ce-compound
ce-compoundwas evaluated for this PR (mode non-interactive) and endedDocumentation skipped. The skip stands: the lesson worth keeping, install-free light checks versus turbo-native change evidence, waits on unit R's upstream fix.