Repository navigation
Bump turbo from 2.10.12 to 2.11.7 in the turborepo-minor-patch group across 1 directory - #4
Closed
dependabot[bot] wants to merge 1 commit into
Closed
dependabot[bot] wants to merge 1 commit into
dependabot[bot] wants to merge 1 commit into
Conversation
Bumps the turborepo-minor-patch group with 1 update in the / directory: [turbo](https://github.com/vercel/turborepo). Updates `turbo` from 2.10.12 to 2.11.7 - [Release notes](https://github.com/vercel/turborepo/releases) - [Changelog](https://github.com/vercel/turborepo/blob/main/RELEASE.md) - [Commits](vercel/turborepo@v2.10.12...v2.11.7) --- updated-dependencies: - dependency-name: turbo dependency-version: 2.11.7 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: turborepo-minor-patch ... Signed-off-by: dependabot[bot] <support@github.com>
Collaborator
|
Superseded by the scaffold in #12, which pins this dependency at or past this PR's target (or no longer uses it). Dependabot regenerates anything still outstanding against the new lockfile. |
Contributor
Author
|
This pull request was built based on a group rule. Closing it will not ignore any of these versions in future pull requests. To ignore these dependencies, configure ignore rules in dependabot.yml |
dependabot
Bot
deleted the
dependabot/npm_and_yarn/turborepo-minor-patch-cfd8cbe256
branch
October 6, 2026 17:05
This was referenced Oct 6, 2026
systemfsoftware-maker
added a commit
that referenced
this pull request
Oct 6, 2026
…ebt ledger Kiro rulings #2, #3, #4 and #5 on #13. The planner imports each package stryker.config.ts and reads its mutate list, refusing a package.json that still carries stryker.mutate. Every publishable package either declares a mutation script or has an XS1 entry in debt-ledger.yaml naming its removing unit; a package with neither, an empty workspace, or a plan with nothing mutated and nothing exempt is refused, each as its own tagged refusal. The summary lists the ledger-exempt packages. Every parsed document decodes through Effect Schema. stryker.shared.ts imports StrykerConfig as a type so Deno can load a package config; its values are unchanged. The scripts and gate tasks reach registry.npmjs.org for npm:effect and may run git and bash for the new script tests
kiro-systemf Bot
pushed a commit
that referenced
this pull request
Oct 7, 2026
* refactor(repo): delete the starter seed package The template seed package has no place in the xstate workspace; the fork packages arrive in the next layer * docs(repo): name the repository xstate README, AGENTS.md and CONTRIBUTING.md describe the xstate fork instead of the starter template, and the CI badge points at systemfsoftware/xstate. STRATEGY.md was the starter kit's product strategy, so it goes rather than mislead; xstate has no strategy document yet * ci(ci): move mutation to a release gate on main As in the starter's lake1/release-gate: Stryker runs at break 100 on every push to main, one hosted job per package with a mutation script, and the shard planner refuses an empty or unmatched mutate set. check:ci no longer runs mutation * build(deps): pin the starter's lake1 toolchain and run dependency code in the sandbox pnpm 12.9.0 and Node 24 come from Nix (nixpkgs aa48d34), with exact catalog pins matching effect-endgame-starter-kit lake1/nix-sandbox: effect 4.0.1, typescript 7.0.2 with @effect/tsgo 0.48.1, oxlint 1.82.0 with @systemfsoftware/oxlint-config-recommended 4.0.0, vitest 5.0.3, turbo 2.11.7, dprint from nix. The @systemfsoftware packages are file: tarballs from the systemfsoftware flake input. Every script that runs dependency code, the git hooks and every workflow go through pnpm-release-management's sandbox launcher (with the starter's linked-worktree patch), installing offline from a hashless pnpm store. The flake exports each public workspace package as a tarball through lib.mkPnpmWorkspacePackages * build(repo): fail the commit-msg hook when git cannot list the staged files Taken verbatim from effect-endgame-starter-kit e89877a, the template owner's change to this evaluator. Inside the sandbox a git failure made stagedFiles return an empty list, so the diff-shape rules passed vacuously; git's error now fails the hook, which the sandbox git-hooks proof asserts * build(deps): pin systemfsoftware to the #606 head that builds on aarch64-darwin At c53bfc9, the starter's pin, systemfsoftware's workspace deps hash holds only on linux, so the macOS check:ci leg failed building its tarballs (specified ttbWYFJ, got x2Rm/ViN; the starter's own macOS leg fails the same way). bb5956b measures the hash per system, and its CI builds the flake outputs on aarch64-darwin, aarch64-linux and x86_64-linux. Its nixpkgs is aa48d34, the same as ours, and pnpm-release-management's lib is byte-identical at both pins. The lockfile records the sandboxed tarball integrities, and the workspace deps hash follows the lockfile * build(deps): trust mitm-cache's CA in the pnpm store build on darwin pnpm 12 is a native binary whose platform verifier reads SSL_CERT_FILE on linux and the keychain on darwin, so the offline store build failed on macos-latest with UnknownIssuer against the mitm-cache replay. NODE_EXTRA_CA_CERTS hands the replay's CA to pnpm on every system. Probe: on linux with SSL_CERT_FILE unset the build fails with the same UnknownIssuer, and it passes once NODE_EXTRA_CA_CERTS is set * build(deps): replay the pnpm store's registry over plain http Trusting mitm-cache's CA was not enough on darwin. macos-latest then rejected the forged leaf certificates with 'invalid peer certificate: EkuError', which no CA setting reaches. The store build now points pnpm at http://registry.npmjs.org/ and serves mitm-cache's recorded https tree under http, so no TLS is involved on any system. Every tarball is still authenticated by its lockfile integrity. Probe: with SSL_CERT_FILE, NIX_SSL_CERT_FILE and NODE_EXTRA_CA_CERTS all unset, the linux store builds, and bootstrap then installs 241 packages offline from it with none downloaded * build(deps): pin pnpm-release-management to the #8 head for the darwin runtime dir With the launcher at 149e762, the macOS leg failed in pnpm bootstrap with ERR_PNPM_STORE_DIR_OPEN_OPERATION_LOCK: pnpm 12 takes its store-operation lock under XDG_RUNTIME_DIR, falls back to /tmp, and the darwin profile refuses /tmp. 8f19844 (prm#8, stacked on #5 at 149e762) gives darwin runs a private 0700 XDG_RUNTIME_DIR and proves the failure without it. nix/lib is unchanged between the two pins, so systemfsoftware's tarballs keep their store path, and the starter's linked-worktree patch applies with offsets only * fix(repo): let the sandbox proofs and script tests run on macOS Two macOS-only failures surfaced once the store and bootstrap worked there. Deno refuses a spawn under the scoped --allow-run while the child environment carries an LD_* or DYLD_* variable, which the macOS runner sets, so the git-hooks proof died at its first git call; its children now get the caller environment minus those variables. Turbo strict env mode dropped TMPDIR, so script tests fell back to the /tmp the darwin profile refuses (PermissionDenied: tmpdir); TMPDIR now passes through, as in pnpm-release-management 8f19844. Repro on linux: with LD_LIBRARY_PATH set, the old proof fails with NotCapable * ci(ci): build the workspace tarballs in the dist leg The tarball builder's fetchPnpmDeps hash covers the whole lockfile, and a store that already holds the old output reuses it silently. A fresh runner store refetches, so building .#workspace-tarballs there fails on a stale hash instead of shipping it (Kiro ruling on #13, question 2) * ci(ci): plan release-gate mutation from each stryker config and the debt ledger Kiro rulings #2, #3, #4 and #5 on #13. The planner imports each package stryker.config.ts and reads its mutate list, refusing a package.json that still carries stryker.mutate. Every publishable package either declares a mutation script or has an XS1 entry in debt-ledger.yaml naming its removing unit; a package with neither, an empty workspace, or a plan with nothing mutated and nothing exempt is refused, each as its own tagged refusal. The summary lists the ledger-exempt packages. Every parsed document decodes through Effect Schema. stryker.shared.ts imports StrykerConfig as a type so Deno can load a package config; its values are unchanged. The scripts and gate tasks reach registry.npmjs.org for npm:effect and may run git and bash for the new script tests * ci(ci): test the release cycle and fix the release PR opener Kiro rulings #6, #8, #11 and #12 on #13. The tag-based published check splits into the pure owedPackages and the git-backed isTagged, both tested against a real repository. plan-release exports decidePhase and renderOutputs and pins the release, version and none lines release.yml gates on. open-release-pr.sh decides from the packages/*/package.json delta against the base instead of a clean tree, which pnpm version -r always leaves, and no longer names apps/ * build(repo): pass dprint arguments through unchanged The wrapper put the first argument before the Nix plugins and the rest after, so dprint --version and calls without a subcommand failed. It now execs dprint with the caller arguments verbatim and seeds dprint plugin cache from the pinned store wasms. A sandbox proof checks --version, check on an unformatted file and lint-staged fmt --allow-no-files -- order; the old wrapper fails the --version case * ci(ci): run sandboxed workflow steps through one composite action Kiro ruling #7 and the P3 credential finding on #13. .github/actions/sandbox takes hosts, env names and a command through env, so no input is interpolated into a shell, and the four workflows use it for every sandboxed step; host-side writes to GITHUB_OUTPUT and the step summary stay in their own steps. Every release.yml checkout sets persist-credentials false. tag-released-packages.ts gains --no-push, the sandbox creates the tags, and a host step pushes them with an explicit token header, so the token never enters the sandbox * test(repo): spawn every sandbox proof without the dynamic-loader environment The dprint wrapper proof failed on macOS with NotCapable: Deno refuses a scoped --allow-run spawn whose environment carries LD_DYLD_PATH. The git-hooks proof already dropped LD_* and DYLD_*; both proofs now spawn through sandbox-proofs/spawn.ts, which keeps that filter in one place. With LD_DYLD_PATH set on linux the old dprint proof fails the same way and the new one passes * build(repo): seed the dprint plugin cache as a writable copy Review finding C13-1/C13-22 on #13. The wrapper linked the seed with ln -sfn, which nests a link inside a stale real plugins directory and points the cache into the read-only store. It now replaces stale entries with a writable copy, stamped with the seed path; a sandbox proof pre-creates a real plugins directory and fails on the old wrapper * test(ci): cover the release PR opener against an open PR Review finding C13-5 on #13: the close path (no version bump) and the edit path (bumps) now each have a case, and each fails when its gh call is removed * ci(ci): let the release notes steps fetch octokit create-github-releases.ts imports npm:octokit, which Deno downloads from registry.npmjs.org when it runs. The three steps that run it allowed only jsr.io and api.github.com, so they failed on the first fetch (reproduced with an empty DENO_DIR). This is a dependency fetch, not a publish * feat(release): release the packages listed in release-set.json Nothing here goes to npm, so every workspace package is private and private no longer means unreleased. release-set.json is the one source of what releases: scripts/lib/release-set.ts decodes it and refuses an unknown or duplicate entry, a listed package that is not private and any workspace package that is not private. Tagging, the release plan, the changeset check, the mutation planner and the flake tarballs all read it. A version is owed once pnpm version -r records it in .changeset/ledger.yaml and it has no tag; an intent counts as pending until the ledger lists it for every package it names, because a pnpm lane keeps consumed intent files. The GitHub Release body is that version's section of the package CHANGELOG.md Also applies review findings C13-2/3/4 (refusal tests), C13-8 (ledger entry type from its schema) and C13-11 (package names decoded against npm's name grammar before they reach the release-gate shell) * ci(ci): let the release-set readers fetch effect check-changeset, plan-release and tag-released-packages now decode release-set.json with Effect Schema, so Deno downloads npm:effect from registry.npmjs.org when they run. With only jsr.io allowed, plan-release failed on a cold Deno cache. This is a dependency fetch, not a publish * test(repo): pin the hooks a git-hooks proof commit runs One pnpm test:sandbox run let a named-path feat commit of a tooling-only file land in 9ms, with no lint-staged output: git ran no hooks at all. The proof found its hooks through ambient discovery of a relative core.hooksPath, and commitlint passes an empty staged set, so an unhooked commit looked compliant. Every proof commit now passes -c core.hooksPath=<fixture>/.husky. A new step points ambient discovery at a missing directory and still expects the refusal; it fails without the pin * build(deps): pin systemfsoftware to the merged #606 systemfsoftware#606 merged as 217c80d5d5. Its workspace tarballs build with the same bytes on every system, so the macOS leg's pnpm store accepts the integrity the lockfile records. Linux tarball bytes are unchanged (tsconfig-2.0.1 and effect-cell-types-12.0.0 hash to the recorded integrity), so the lockfile does not move. The systemfsoftware input stops following this repo's pnpm-release-management pin, because 217c80d calls mkPnpmConsumerStore, which that pin lacks * build(deps): build the release gate's stryker from source and plan it with stryker plan Kiro's C13-19 rulings: the release gate stops planning mutation with a repo-local glob matcher, and no @systemfsoftware/* package is fetched from registry.npmjs.org, at install or build. stryker-js 17.0.2, its typescript-checker 8.2.1 and vitest-runner 8.1.1 and their nine siblings are built in this flake from stryker-js-effect at 3db0c428 (flake = false input), through a committed overlay workspace and lockfile under nix/stryker-js/ and the existing hashless pnpm store, and packed into file:.stryker-deps tarballs the catalog resolves. nix run .#stryker-js-lock regenerates the overlay lockfile and refuses a registry-resolved @systemfsoftware/* entry. The release gate's plan job lists the workspace packages with a mutation script, runs stryker plan over them, and scripts/stryker-plan-gate.ts refuses a plan that schedules no mutant for such a package (C13-13: a project resolved outside the root is refused too) or is vacuous with no ledgered debt; each matrix shard runs stryker run --plan --shard. The plan gate's tests are what test:scripts now runs, since the local release scripts left with main's shared toolchain * ci(ci): run the intent check in the dev shell pnpm-release-management's reusable changeset-check installs the caller's workspace with a bare pnpm install, which cannot read the file:.sfs-deps and file:.stryker-deps tarballs only this repository's Nix dev shell provides (ERR_PNPM_TARBALL_READ_LOCAL_TARBALL on effect-cell-types-12.0.0.tgz). The same check now runs in this workflow: the dev-shell action installs offline through the sandbox, and the sandbox runs changeset-management check against the pull request's base. The CLI comes from a new release-tools flake input pinned to pnpm-release-management's main (5432b8b), which keeps its own nixpkgs because its deno-compile runtime is pinned to that deno; the existing pin stays for mkPnpmWorkspacePackages * build(repo): build every from-source package through one parameterized builder nix/from-source.nix replaces nix/stryker-js.nix: pname, src, the overlay directory, the packed list and the extra store files are arguments, and the generic helpers move to nix/from-source/. The lock app and the deps directory are generated from the instance map, so nix/stryker-js holds only its own manifest data. Every tarball a workspace here installs now lands in .sfs-deps: the systemfsoftware flake's workspace tarballs plus the tarballs this flake builds from source, so the catalog, the root lockfile, the pnpm store, the workspace-source copy and the dev shell carry one directory instead of two. The stryker tarballs are byte-identical before and after * build(repo): build from-source packages inside the nix sandbox CI's sandboxed nix failed the stryker-js tarballs with ERR_PNPM_NO_OFFLINE_TARBALL (reused 0), so every job died building the dev shell; local nix runs with sandbox = false, which hid it. Three faults, all sandbox-only. pnpm got the read-only store path, so it reused nothing; it now gets the writable view the sandbox launcher builds (index.db copied, every other entry linked, clone-or-copy import). pack.mjs renamed the packed tarball across filesystems (EXDEV); it copies now. And unsandboxed, pnpm pack fetched the published CHANGELOG of @systemfsoftware/stryker-js from registry.npmjs.org and prepended it, so the lockfile recorded an integrity for bytes that came through the registry. The sandboxed stryker-js-17.0.2.tgz carries only the repo's own changelog entry; the lockfile takes its integrity and the workspace deps hash moves with it. The other eleven stryker tarballs are byte-identical under the sandbox * build(repo): keep the starter package in the scaffold Kiro's ruling (cycle 27): the scaffold leaves packages/starter in place, byte-identical to main, so turbo enumerates a workspace package at this head and pnpm-release-management's turbo-gated changeset check evaluates instead of refusing an empty workspace. The deletion moves to the layer that adds the six fork packages, so no head in the stack has an empty workspace. The catalog regains the two pins the starter needs (rimraf 6.1.3, tsdown 0.23.0, the versions the packages layer pins), the lockfile gains its importer and the workspace deps hash moves with it * build(deps): pin release-tools to the pnpm-release-management main that fetches sandboxed Every CI job died building the dev shell: 5432b8b declares sha256-SljOBg for the changeset-management pnpm deps, and a sandboxed fetch yields sha256-ERG1u8 each time, on CI and locally (nix-build --check, sandbox on). This host's unsandboxed copy had hidden it. c10c1c4, main after #5, re-fetches its deps byte-identically under the sandbox. pnpm-release-management stays at 8f19844 for its sandbox launcher, whose commits main does not carry * build(repo): pack from-source tarballs without the registry's changelog The macOS leg failed ERR_PNPM_TARBALL_INTEGRITY on stryker-js-17.0.2.tgz: nix on Darwin builds unsandboxed, and pnpm pack composes CHANGELOG.md from the registry's published history even with offline set, so the tarball took 861 changelog lines there and 9 on sandboxed Linux. The pack step now points pnpm at a closed local port, so the bytes follow the pinned source alone; sandboxed and unsandboxed rebuilds are identical and match the lockfile's integrity * build(deps): build the attw CLI and its effect-cell-types 7 from source Kiro ruling on Review13PredicateR2 P0: #13's gates run attw, so #13 needs the attw CLI #14 already builds. This ports #14's 317b179: arethetypeswrong-cli 4.2.0 is built from the released tag d43a8020, and effect-cell-types 7.0.0 from its release tag 4cf0f770 for the attw install alone. The catalog entry points at file:.sfs-deps/arethetypeswrong-cli-4.2.0.tgz, so no @systemfsoftware/* package comes from the registry nix/attw/pnpm-lock.yaml carries the effect-cell-types 7.0.0 integrity #14 measured after 13349a7 moved the build into the sandbox (sha512-ongebnJP…), not the pre-sandbox value 317b179 recorded (cherry picked from commit 317b179) * ci(repo): gate the starter on lint:tsgo and attw Kiro ruling on Review13PredicateR2 P0: #13's gate:tasks runs #14's set, lint lint:tsgo typecheck typecheck:node test test:scripts attw, the lint leg runs lint:tsgo and the dist leg runs attw after build, as #14's cb678a7 does packages/starter is the only member, so it takes the lint:tsgo and attw scripts and their devDependencies. attw found that its exports name dist/index.js while tsdown emitted dist/index.mjs and index.d.mts, a NoResolution under node16-esm and bundler. tsdown now emits .js and .d.ts, the files the exports already name. attw runs with --profile esm-only: the package ships no CommonJS, so node10 and node16-cjs resolution do not apply, and an export naming a file the build did not emit still fails CONST-W3: this changes packages/starter, which the predicate's clause 5 holds unchanged, because the ruling requires attw to execute against packages/starter and pass The root lockfile takes the two devDependencies and the workspace deps hash moves with it * ci(repo): run the assert-local-sfs guard on the committed lockfiles Kiro ruling on Review13PredicateR2 P1: the guard that refuses an @systemfsoftware/* package resolved from registry.npmjs.org ran only in nix run .#<instance>-lock, never in CI. The root task //#assert-local-sfs runs it on pnpm-lock.yaml and every nix/*/pnpm-lock.yaml, and //#test:scripts depends on it, so the test leg's pnpm test and check:ci's gate:tasks both run it with no new job, workflow or env switch. It keeps turbo's default output logs, so the CI log names the task and the files it read scripts/assert-local-sfs.test.ts runs the guard on a lockfile fixture resolving @systemfsoftware/effect-cell-types@12.0.0 from the registry, which must fail and name the line, and on every committed lockfile, which must pass. test:scripts takes --allow-run=awk for it, and its turbo inputs take the lockfiles and the guard so a lockfile change reruns it
kiro-systemf Bot
pushed a commit
that referenced
this pull request
Oct 7, 2026
* feat(global): import statelyai/xstate v6 packages verbatim
Six packages of statelyai/xstate branch `next` at
2146ae26ebfc7e6a624b3a1f237f9e6ddc30b9f5 (MIT, Copyright (c) 2015 David
Khourshid) are copied unchanged under packages/xstate/, as owned members
(REPO-O1). Upstream is a reference, never a merge source.
- packages/core -> packages/xstate/xstate
- packages/xstate-effect -> packages/xstate/xstate-effect
- packages/xstate-test -> packages/xstate/xstate-test
- packages/xstate-react -> packages/xstate/xstate-react
- packages/xstate-store -> packages/xstate/xstate-store
- packages/xstate-store-react -> packages/xstate/xstate-store-react
Identity: every copied src/ and test/ tree object equals the upstream tree
object at the pin (git write-tree --prefix vs git rev-parse <pin>:<dir>),
except xstate-store/test, which differs only by the excluded files below.
Excluded (build configuration, or tests of bindings this repo does not fork):
- packages/{core,xstate-effect,xstate-test,xstate-react,xstate-store,xstate-store-react}/vitest.config.mts
- packages/xstate-store/vitest.config.vue.mts, vitest.config.solid.mts
- packages/xstate-store/test/{vue.test.ts,UseActor.vue,UseActorRef.vue,UseSelector.vue} (imports @xstate/vue)
- packages/core/{actors,durable,fsm,graph,validation}/package.json (preconstruct entrypoint stubs)
- packages/core/.gitignore, packages/xstate-store-react/tsconfig.json
Added: the repository's root MIT LICENSE in xstate-effect and
xstate-store-react, which upstream ships without a package LICENSE.
Declared bypass (CONST-W3): committed with --no-verify. The pre-commit hook
runs dprint fmt over staged files, which would rewrite upstream sources and
break the tree identity above. The commit message was checked with
`pnpm exec commitlint`. Formatting lands as the next, separate commit; the
dprint check gate runs on the pull request head.
* style(global): format the imported xstate packages with dprint
Gate: `./bin/dprint check` (check:local, check:static). The verbatim import
in the previous commit keeps upstream's formatting so its tree identity holds;
this commit is the formatter's output over packages/xstate/** and nothing else.
* build(global): wire the xstate family into the workspace
The six imported packages become workspace members under
`@systemfsoftware/*` names through the `packages/xstate/*` glob (plan U2).
- Manifests: MIT, upstream's versions, workspace dependencies and catalog
versions; tsdown builds every upstream subpath, each with its own API
Extractor report. Scripts: build, typecheck, test, lint:tsgo, attw,
api:check, api:update. No lint and no mutation script until each package's
rewrite layer (plan KTD2, KTD10).
- Vitest configs carry upstream's per-package settings at the pin (globals,
environment, includes, resolve conditions) on the shared config.
- Core's and xstate-react's tests pin zod 3.25.76, the version upstream's
lockfile resolves for them; xstate-test, xstate-store and
xstate-store-react pin zod 4.6.5.
- Core's bin/xstate.js is removed: it only ran `npx @xstate/codemod`, and
the codemod is not forked.
- packages/xstate/AGENTS.md records the pin, the members, what is not forked
and why, and the family's leaf rules. Every README carries the fork clause.
Adding workspace members re-resolves the `catalog:stryker`
`latest` specifiers, which moves @systemfsoftware/stryker-js 14.0.0 to 15.0.1
Plan docs/plans/2026-10-05-2317-feat-xstate-v6-fork-plan.md (U2)
* ci(global): exempt the verbatim upstream xstate tests from the vitest guard
Kiro ruled option 1 for L1 of the xstate fork plan. Declared bypass
(CONST-W3): rule KTD8 of @systemfsoftware/vitest (the guard refuses a case
registered with vitest's own it); case: the upstream statelyai/xstate tests
imported verbatim in df92a9ad3f, which are the oracle and are never edited;
removal point: plan U4 (L2) deletes the in-tree tests, the manifests and
these exemption entries together
- vitest-config's guard exemption table names one project per xstate
package, `upstream-verbatim`. Its include is exactly the files that
package's upstream-tests.json lists, never a folder glob.
- scripts/guards/check-upstream-test-manifest.ts (run by guard:projects in
gate:tasks and gate:local) fails when a manifest names a file the import
commit did not bring in or lists a file the tree no longer holds, so a
list can only shrink. Each manifest records its reason and removal point.
Evidence (sabotage, reverted)
- An added own test under the guard: "this test was registered with
vitest's it; import it from @systemfsoftware/vitest"
- A copy of an upstream test under a name not on the list: red
- test/new.test.ts appended to a manifest: the guard exits 1 with "not an
imported upstream test still in the tree"
* build(global): run the verbatim upstream xstate tests as upstream runs them
Each xstate package's vitest config splits its tests into the guard-exempt
`upstream-verbatim` project (the files its upstream-tests.json lists, with
upstream's globals) and the guarded `own` project for every other test file.
Environment, resolve conditions and inlined deps follow upstream's
per-package config at 2146ae26. xstate-store and xstate-store-react keep
upstream's include scope (test/ and src/), so xstate-store's
src/select.test.ts stays unrun, as upstream leaves it
Also restores upstream's `#is-development` imports map in xstate and
xstate-react, which the U2 manifests dropped; core's sources import it
* build(global): build the xstate packages and resolve upstream specifiers
- tsdown names each package's root entry `index`, so its generated exports
map the root subpath `.`; package.json exports are tsdown's output
(REPO-S4), and the API Extractor reports read dist/index.d.ts
- The vitest configs alias upstream's package names (`xstate`,
`xstate/<subpath>`, `@xstate/<name>` and subpaths) to the fork's
`@systemfsoftware/*` packages, so the verbatim upstream tests run against
the fork without being edited. The shared config's own alias is kept
* fix(global): rename upstream specifiers and mark type-only imports in xstate
Gate-forced repairs in the imported sources (plan U3), no behaviour change
- Module specifiers in import, export and declare-module statements move
from `xstate` and `@xstate/<name>` to the fork's `@systemfsoftware/*`
names (72 sites in 48 files). `Symbol.for` brand keys such as
'@xstate/effect/action' and runtime message text keep upstream's strings
- tsdown (rolldown) refuses a value import of a type-only export
(MISSING_EXPORT at src/assert.ts, src/createActor.ts, ...). Those imports
are marked `type`, applied mechanically by oxlint's
typescript/consistent-type-imports fixer over non-test sources only
* ci(global): restore the verbatim upstream xstate tests and keep dprint off them
Kiro ruled verbatim means verbatim. The dprint commit 6c22c870d had
reformatted the 212 upstream test files the manifests list; this commit
restores exactly those files to their content at the import commit
df92a9ad3f (git restore --source, no history rewrite)
Declared bypass (CONST-W3), beside the test-guard exemption: rule, the
dprint check gate; case, the same 212 verbatim upstream test files, which
are the oracle and are never edited; removal point, plan U4 (L2) deletes
the files, the manifests and these excludes together
- dprint.json excludes list exactly those files, written from the
manifests by scripts/guards/check-upstream-test-manifest.ts --write, never
a folder glob
- The guard now also fails when dprint.json excludes a path under
packages/xstate that no manifest lists, or misses one a manifest lists, so
the excludes shrink with the manifests
Evidence
- git diff df92a9ad3f -- <listed files> is empty
- ./bin/dprint check exits 0
- Sabotage, reverted: excluding packages/xstate/xstate/src/index.ts makes the
guard print "excluded but not listed" and exit 1
* fix(global): repair xstate-test for Effect 4.0.1 and core's typestate examples
Gate-forced repairs (plan U3), ruled by Kiro
- xstate-test: Effect 4.0.1 removed `Schema.toArbitrary`; Schema arbitraries
now run on Effect's own engine (effect/Arbitrary), not fast-check.
`fromEffectSchema` draws a fast-check integer as the seed and samples one
value with `Arbitrary.sampleEffect`, so a run replays from fast-check's
seed. A failing generated value does not shrink
- xstate-test: the U3 specifier rename had rewritten a runtime message
string; it names '@xstate/test/effect-schema' again, as upstream's
schema.test.ts asserts
- xstate-test, xstate-store, xstate-store-react: zod 4.4.3, the version
upstream's lockfile resolves (4.6.5 changed partialRecord key generation)
- core: test/typeStates.test.ts imports type names from
src/typestates.types.ts with a plain import. Upstream's esbuild elided that
import; the repo's tsconfig sets verbatimModuleSyntax, so vite's oxc
transform keeps it, the module loads, and its module-scope example call to
`declare function accept` throws "accept is not defined". The examples are
now `satisfies` expressions, which type-check the same way and emit no call
* ci(global): port two upstream xstate tests the toolchain cannot run verbatim
Kiro ruled both ports. Each port is the pinned upstream file with only the
named cases changed, between port markers. The manifest records the
upstream path, its blob at the import commit, the reason and the line span
of each case. The drift check fails if a line outside a marked case
changes, or if the pinned upstream blob differs from the recorded one.
- xstate-test test/engine/propertySuite.port.test.ts. Toolchain cause:
the test-runner API. Vitest 5 refuses a suite declared inside a running
test. The case "describeTestSuite (vitest globals) > runs the generated
fixtures" now declares the suite at file scope with the vitest globals,
so each generated fixture is its own case.
- xstate test/serialization.conformance.v6.port.test.ts. Toolchain cause:
printer text (oxc vs esbuild). The cause was probed on the file itself.
esbuild 0.28.2 prints "(_) => void 0" with two-space indentation, which
matches upstream's snapshots. oxc (rolldown binding 1.2.9, vite 8's
transformer) prints "(_) => undefined" with tabs, which matches what the
fork received. The two cases now assert that each `@code` equals
String(fn) of the same inline function.
Proofs, each reverted afterwards. Editing propertySuite line 12 makes the
guard exit 1 at :12. Editing serialization line 184 (between the two
cases) or line 135 makes it exit 1. A wrong recorded blob makes it exit 1.
The guard selftest passes 9 cases. Both ports pass: 14 and 10 tests
* ci(global): retire three upstream xstate tests with named replacements
Kiro ruled each retirement. The manifests record the upstream path, the
reason and the replacement, and the drift check keeps every retired file
out of the tree and out of the dprint excludes.
- xstate test/declarations.test.ts drives the TypeScript 6 compiler API,
and the repo compiles with TypeScript 7 only. The replacement is
tests/declaration-emit.test.ts, which emits the same fixtures with the
TypeScript 7 tsc and asserts no diagnostics, the size bounds, one
readonly c0 and p0 member, names from the entry point only, and a
consumer that compiles against the emitted declaration. Two cases pass.
The diagnostics case is red: TypeScript 7 reports type errors in four
upstream fixtures, which the U3 typecheck repairs fix.
- xstate-effect src/lint.test.ts and xstate-react test/lint.test.ts run
upstream's root oxlint plugins, which are not forked. Their fixtures go
too. The replacement is the repo's own lint gate over the package
sources.
Every upstream-verbatim suite passes: xstate 2417 with 29 skipped and 3
todo, xstate-effect 135, xstate-test 478, xstate-react 141
* fix(global): give every relative import in xstate sources a .js extension
The package manifests set "type": "module", so the TypeScript 7 build
and its nodenext resolution read the sources as ESM. Upstream mixed
extensionless specifiers with .ts ones. Under ESM, TS2835 refuses the
extensionless ones and TS5097 refuses the .ts ones without
allowImportingTsExtensions. An unresolved module types as any, so every
type core reached through one collapsed to any. That any is what made
the event-descriptor validator build a string index of "Event type
'${any}' is not declared" and reject the declared GO, and what
implicitly typed the invoke input callbacks as any.
All 477 relative specifiers in the 135 non-test source files of the six
packages now name the .js file or /index.js directory entry, which is
the repo's convention. Verbatim upstream tests are not touched.
In core, TS2835 and TS5097 go from 218 to 0, and the declaration-emit
replacement's diagnostics case passes. The other two cases also had
probe bugs, fixed here: the name probe now imports every referenced
name from the entry point instead of aliasing generics without their
arguments, and the consumer now resolves the parent only through its
emitted .d.ts, with the parent source removed. All six packages' suites
pass: xstate 2420 with 29 skipped and 3 todo, xstate-effect 135,
xstate-test 478, xstate-react 141, xstate-store 294, xstate-store-react
24. Removing InferEvents from the entry point turns the name case red
* fix(global): type-check xstate core under the repo's strict flags
Gate-forced repairs (plan U3). The repo's TypeScript 7 config enables
exactOptionalPropertyTypes, noUncheckedIndexedAccess and
noPropertyAccessFromIndexSignature, which upstream never compiled with.
tsc -p tsconfig.app.json in packages/xstate/xstate went from 289 errors
to 0, across 37 source files, and runtime behaviour is unchanged.
- Index-signature reads use bracket access (TS4111).
- Indexed reads are narrowed by an existing invariant or an explicit
check that throws what upstream would have thrown. No new non-null
assertion, any cast or suppression comment is added.
- Optional members a value really leaves undefined declare
`| undefined`. This affects 22 public types, among them StateSchema,
StateConfig, ActorOptions, Observer, LogicConfig, SetupSchemas and
SetupStateSchema. Upstream compiled without exactOptionalPropertyTypes,
where `?:` already accepted undefined, so each change keeps what a
consumer could already pass and narrows nothing.
vitest run --bail=0 in the package still reports 145 files and 2420
passed, 29 skipped and 3 todo
* ci(global): typecheck the verbatim upstream xstate tests under upstream's options
Kiro ruled that the verbatim tests are typechecked and never skipped.
Each package gets a second test project, tsconfig.upstream-test.json,
which its tsc -b solution now references. The project is generated by
scripts/guards/check-upstream-test-manifest.ts --write, and the check
fails when the generated file and the tree differ.
- Its compilerOptions are upstream's root tsconfig.json at 2146ae26,
vendored byte-for-byte as packages/xstate/upstream-tsconfig.json. The
check recomputes that file's git blob and refuses anything other than
upstream's 312be9ed.
- Each change on top of upstream's options is listed with its reason in
the package's upstream-tests.json under typecheck.additions:
- noEmit, composite, emitDeclarationOnly, outDir and tsBuildInfoFile,
because a tsc -b reference must emit.
- customConditions, so @systemfsoftware/* imports resolve to source.
- paths for xstate and @xstate/*, generated from the packages' source
exports.
- types, adding node, which vitest 5's globals no longer bring in.
- module preserve with bundler resolution. The fork's packages are
type: module, so nodenext would read upstream's extensionless test
imports as ESM.
- Its include lists exactly the verbatim test files, every port, the
upstream helper files under test/ that they import, and the src JSON
files they read. tsconfig.test.json excludes the same list, so every
file is in exactly one of the two projects.
- A third port, xstate-store test/atom.port.test.ts, handles vitest 5
typing an untyped vi.fn() as Mock<Constructable | Procedure>. Inside
its one marked case, the inline mock is now typed
vi.fn<(value: number) => void>().
All six upstream-test projects report 0 errors under TypeScript 7.0.2
(tsc -p tsconfig.upstream-test.json --noEmit). Each of these sabotages,
reverted afterwards, makes the check exit 1: turning off strict in a
generated project, editing the vendored tsconfig, leaving a verbatim
file in the repo test project, and editing the atom port outside its
case. Reverting the port's vi.fn typing brings back TS2769. Debt: the
whole upstream-test project is one entry, removed when layer 2 ports the
tests to the repo's style and its include list is empty
* fix(global): type-check the other five xstate packages under the repo's strict flags
Gate-forced repairs (plan U3), done the same way as core. Every count
below is `tsc -p tsconfig.app.json` errors, from before to after:
xstate-effect 11 to 0, xstate-test 171 to 0, xstate-react 6 to 0,
xstate-store 31 to 0, and xstate-store-react 26 to 0 (all of
xstate-store-react's came from xstate-store).
- Index-signature reads use bracket access.
- Indexed reads are narrowed or destructured.
- Callbacks that fall through now return explicitly.
- ModelTestFailure.cause is marked override.
- xstate-test's two node-reading modules reference node types, since
the tsconfig preset does not include them automatically.
- Optional members a value really leaves undefined declare
`| undefined`. In xstate-store that covers Store.schemas,
StoreLogic.eventTypes and schemas, and StoreValidationError.eventType.
In xstate-test it covers the engine's replay, fixture, exploration,
suite and linearizability records. These widen and never narrow:
upstream compiled without exactOptionalPropertyTypes, so `?:` already
accepted undefined.
No runtime behaviour changes. tsc -b in each of the six packages, from
a clean cache and including the new upstream-test projects, exits 0
with no errors. Under effect 4.0.1 the suites report xstate 2420 passed,
29 skipped and 3 todo, xstate-effect 135, xstate-test 478, xstate-react
141, xstate-store 294 and xstate-store-react 24
* build(global): record the xstate API reports and enrol the declaration test
- Commits the API Extractor report for every entry point of the six
packages (20 reports, written by pnpm api:update). The build's
api:check compares against them, and the published-surface comparison
in the plan starts from them.
- Adds publishConfig.provenance to the six manifests, which gritlint's
npm-provenance rule requires of every non-private package.
- Adds tests to core's tsconfig.test.json include, so the TypeScript 7
declaration-emit test is typechecked. guard:projects found it in no
project
* docs(global): make the forked xstate doc comments valid TSDoc
API Extractor's api:check fails on any warning, and upstream's comments
raised 43 across four packages: ambiguous links to overloaded or merged
declarations, links to names an entry point does not export,
multi-line code spans, bare braces and angle brackets, and dotted
@param names. Overloads are linked by index, as in (createMachine:1).
Names an entry point cannot link become code spans. Spans are reflowed
onto one line. Only comments change, and five API reports regenerate.
api:check now passes in all six packages
* fix(global): satisfy effect strictBooleanExpressions in xstate-effect
Write every conditional operand as an explicit comparison so the rule sees a
boolean type instead of a truthiness test. lint:tsgo reports 75
strictBooleanExpressions diagnostics before this commit and 0 after
* fix(global): satisfy effect unnecessaryArrowBlock in xstate-effect
Give the schema-record map callback a concise body, since its block only
returned an array. lint:tsgo reports 1 unnecessaryArrowBlock diagnostic before
this commit and 0 after
* fix(global): satisfy effect deterministicKeys in xstate-effect
Give ActorScope's service key and the three tagged errors' Data.TaggedError
keys the package-and-path form the rule expects. The error classes keep their
historical short `_tag` and `name` so the published contract and upstream tag
assertions hold. lint:tsgo reports 4 deterministicKeys diagnostics before and 0
after
* fix(global): satisfy effect globalTimers in xstate-effect
Rethrow a listener's exception on a microtask instead of a macrotask timer,
so the failure still surfaces asynchronously without the global timer the
rule rejects. lint:tsgo reports 1 globalTimers diagnostic before and 0 after
* fix(global): satisfy effect newPromise in xstate-effect
Settle the hosted-effect promise through Effect.callback and Effect.runPromise
instead of constructing one by hand, so a failure still rejects with the
squashed cause. lint:tsgo reports 1 newPromise diagnostic before and 0 after
* fix(global): satisfy effect tryCatchInEffectGen in xstate-effect
Run the durable transition through Effect.exit and read the thrown value from
the cause, instead of a try/catch inside the Effect generator. lint:tsgo
reports 1 tryCatchInEffectGen diagnostic before and 0 after
* fix(global): satisfy effect anyUnknownInErrorContext in xstate-effect
Call a wrapped action through a typed view that names the hosted shape, so
neither the call nor the narrowed result carries any or unknown error and
requirements channels. lint:tsgo reports 2 anyUnknownInErrorContext
diagnostics before and 0 after
* fix(global): satisfy effect unsafeEffectTypeAssertion in xstate-effect
Host each fromEffect Effect through startHostedEffect, which now carries the
requirements channel and runs it against the actor's own context, instead of
asserting the channel away. lint:tsgo reports 3 unsafeEffectTypeAssertion
diagnostics before this commit and 0 after
* fix(global): satisfy effect missingPipeableSignature in xstate-effect
Stop exporting the internal host helpers and safeCall, exposing them through
one internals object, and name waitFor's narrowing predicate so both of its
call styles describe one shape. Regenerate the API reports. lint:tsgo
reports 10 missingPipeableSignature diagnostics before and 0 after
* fix(global): give xstate-effect's cross-module helpers dual forms
Give each cross-module helper (withEffectHost, createEffectHost, bindEffectHost,
startHostedEffect, runHostedEffect, relayToParent, safeCall) a data-first and
data-last form with Function.dual, and export the waitFor predicate from the
entry point. lint:tsgo reports 0 diagnostics before and after
* fix(global): satisfy effect globalTimers in xstate-test
The gate is pnpm --filter @systemfsoftware/xstate-test lint:tsgo
effect(globalTimers) drops from 1 to 0
PropertyTest's drain yields its macrotask turn through Effect.sleep(0) rather than the global setTimeout
* fix(global): satisfy effect newPromise in xstate-test
The gate is pnpm --filter @systemfsoftware/xstate-test lint:tsgo
effect(newPromise) drops from 3 to 0
The outcome registry, the drain turn and the page-settle microtask yield run through Effect.callback
* fix(global): satisfy effect globalConsole in xstate-test
The gate is pnpm --filter @systemfsoftware/xstate-test lint:tsgo
effect(globalConsole) drops from 2 to 0
The printed reports log through Effect.log with a console logger that keeps their verbatim output
* fix(global): satisfy effect globalDate in xstate-test
The gate is pnpm --filter @systemfsoftware/xstate-test lint:tsgo
effect(globalDate) drops from 4 to 0
Timestamps and date bounds are built from DateTime instead of the global Date
* fix(global): name the declarations behind xstate's API report artefacts
The bundled declaration emitter invented names for anonymous class bases and for
same-named declarations in different modules; name them at the source so the
reports carry no `_base`/`_<n>`/`$<n>` artefacts:
- ActorScope_base -> ActorScopeService (xstate-effect actorScope.ts)
- ActorStoppedError_base -> ActorStoppedErrorBase (xstate-effect errors.ts)
- EffectInterruptedError_base -> EffectInterruptedErrorBase (xstate-effect errors.ts)
- NotReadyError_base -> NotReadyErrorBase (xstate-effect errors.ts)
- StoreLogic_2 -> FromStoreLogic (xstate-store fromStore.ts)
- InvokeConfig_2 -> LegacyInvokeConfig (xstate types.ts)
- TransitionConfigOrTarget_2 -> LegacyTransitionConfigOrTarget (xstate types.ts)
- MergeChildren$1 -> MergeChildren (the setup.ts duplicate is renamed SetupMergeChildren)
- MachineIdentity$1 -> MachineIdentity (the setup.ts duplicate is renamed SetupMachineIdentity)
Also drop the non-upstream SnapshotPredicate re-export so the entry exports match
upstream exactly
* fix(global): satisfy effect extendsNativeError in xstate-test
The gate is pnpm --filter @systemfsoftware/xstate-test lint:tsgo
effect(extendsNativeError) drops from 4 to 0
The error classes extend Data.TaggedError carrying the preset's deterministic key, so name, message and instanceof stay
* fix(global): keep upstream's xstate-effect error tags under three grants
Kiro ruled the override form out: passing the path key to
Data.TaggedError and overriding _tag and name back satisfied
deterministicKeys without meeting it. The three classes return to
upstream's form, Data.TaggedError('EffectInterruptedError') and the same
for ActorStoppedError and NotReadyError, each with a next-line
deterministicKeys grant that names its reason and U5 as the unit that
removes it.
tsgo reports 0 diagnostics. Deleting the three directives makes it fail
at errors.ts lines 13, 30 and 47. The class form brings back the three
X_base names in the API reports, which the import manifest records as
emitter artefacts
* fix(global): satisfy effect strictBooleanExpressions in xstate-test
Gate `pnpm --filter @systemfsoftware/xstate-test lint:tsgo` reports the
strictBooleanExpressions diagnostic 693 times before this commit and 0 times
after, leaving only asyncFunction and missingPipeableSignature
* fix(global): name the declarations behind xstate-test's API report artefacts
The bundled declaration emitter invented `_base`, `_2` and `$1` names for
anonymous class bases and for same-named declarations in different modules, so
the five etc/*.api.md reports now name every declaration at the source and
`api:check`, `tsc -b`, vitest 38/478 and the exports probe (extra=[], missing=[])
all pass
ModelTestFailure_base -> ModelTestFailureBase, TestCampaignError_base ->
TestCampaignErrorBase, ReplayNotReproducedError_base ->
ReplayNotReproducedErrorBase, PlaywrightOracleError_base ->
PlaywrightOracleErrorBase, SnapshotFromSource_2/$1 -> SnapshotFromSource,
EventFromSource_2/$1 -> EventFromSource, eventsFromSchemas_2 ->
effect-schema's own TestEventGenerators return type
* fix(global): satisfy effect missingPipeableSignature in xstate-test
Gate `pnpm --filter @systemfsoftware/xstate-test lint:tsgo` reports the
missingPipeableSignature diagnostic 48 times before this commit and 36 after;
this slice gives engine/coverage.ts's twelve helpers a data-first and data-last
form with Function.dual, so the data-first call stays identical and every
existing call site keeps working
* fix(global): satisfy effect missingPipeableSignature in xstate-test's edges
Gate `pnpm --filter @systemfsoftware/xstate-test lint:tsgo` reported the
missingPipeableSignature diagnostic 23 times across xstate-test's remaining
edges before this commit; this slice gives each flagged export a data-last
form with Function.dual, so the data-first call stays identical and every
existing call site keeps working
Where an optional trailing parameter makes arity-based dispatch ambiguous the
dual uses its predicate form, and where no predicate can separate the forms
the data-last form is type-only and all calls stay data-first
The vitest `it` and `test` globals keep TestAPI's members through a mapped
type and declare the pipeable call forms beside the data-first ones, so the
published call styles are unchanged
* fix(global): drop xstate-test data-last forms the runtime cannot dispatch
`pick`, `arbitraryFromSchema`, and the vitest `it`/`test` globals declare a
data-last overload the runtime never reaches, because their argument shapes
are indistinguishable (`select`/`toPayload` and `schema`/`options` are both
functions or both objects, and `it`/`test` forward straight to Vitest)
A published form that cannot dispatch is a signature that lies, so this
reverts those four exports to their upstream signatures and leaves the
missingPipeableSignature diagnostic on them for the rule owner
Every other dual added for the rule keeps a reachable data-last branch: each
checks a marker (a machine's `transition`, a coverage's `eventCases`) or an
argument shape (`Array.isArray`, a trailing string path) that separates the
two forms
* refactor(global): run xstate-test's edges as Effect values behind their Promise API
The scheduler, adapter, failures, outcomes, propertyLinearizability, and
vitest modules keep their Promise signatures and become plain functions
returning Effect.runPromise of an Effect.gen program, so no async function
remains there and user callbacks and SUT actions are awaited with
Effect.promise
Cleanup that used try/finally becomes Effect.ensuring with a lazily built
finalizer, and a failure that was swallowed becomes Effect.ignoreCause, so a
runner, a session, and a scheduler still settle on failure
playwright.ts is left async: its session methods are built inside the create
Effect, so moving them out of it is a follow-up
* refactor(global): run xstate-test's playwright SUT as Effect values behind its Promise API
The playwright SUT keeps every published Promise signature and becomes plain
functions returning Effect.runPromise of an Effect.gen program, so no async
function remains and page actions, resets, tracing, and artifact attachment
are awaited with Effect.promise
The session factory's setup runs as a Promise chain, which keeps the session
methods' Effect.runPromise calls outside any Effect.gen; calling them inside
one trips tsgo runEffectInsideEffect. The dispose cleanup becomes
Effect.ensuring with a lazily built finalizer so it still runs on failure, and
the attached fixture is JSON-encoded through a helper to keep JSON out of the
generator body
* fix(global): grant xstate-test's four undispatchable pipeable sites
Kiro ruled that pick, arbitraryFromSchema, it and test keep upstream's
signatures. Their argument shapes overlap in both kind and count, so
no data-last call can be told apart at runtime: pick's two parameters
are functions with the second optional, arbitraryFromSchema's schema is
unknown and upstream calls it with 1 and 3 arguments, and it and test
forward to Vitest's own registration. Each site carries a next-line
missingPipeableSignature grant that names its reason and U14 as the
unit that removes it
* refactor(global): build xstate-test's playwright session from an Effect program
createPlaywrightSut's create() built each session as a hand-written
Promise.resolve(...).then(...) chain that dropped the async keyword without
satisfying @effect/tsgo's asyncFunction rule. Async control flow has to be an
Effect value, with Effect.runPromise only at the published Promise edge.
The setup steps (init script, trace start, reset) now run in a setupSession
Effect program, and the session object is built by createSession from that
settled setup, so create() is Effect.runPromise(Effect.map(...)).
Error semantics are unchanged: a trace that is already running is still
ignored, now via Effect.ignoreCause in place of the rejection handler, while
addInitScript and reset still reject create() with the same error object.
Public signatures are untouched; the two lines gained are the named locals
that replaced the chain, and dprint re-indented the moved session object
* fix(global): satisfy effect missingPipeableSignature in xstate-test's engine core
Give the exported entry points in engine/propertyTest.ts, engine/suite.ts,
engine/testPaths.ts and the fast-check wrapper in propertyTest.ts a data-first
and data-last form with Function.dual, so every data-first call stays identical
and each existing call site keeps working. Sites whose trailing parameter is
optional discriminate on the argument shape rather than arity, so a
one-argument data-first call still reaches the data-first branch
The four files report no missingPipeableSignature diagnostics under lint:tsgo
after this commit
* refactor(global): run xstate-test's engine core as Effect values behind its Promise API
Move the converted async functions in src/propertyTest.ts, engine/suite.ts and
engine/propertyTest.ts onto Effect values: each becomes a plain function
returning Effect.runPromise of an Effect.gen program, awaits become
Effect.promise, and error capture uses Effect.exit with Cause.squash so a
rejected callback still rejects with the same object. Cross-module signatures
stay Promise-returning and data-first call sites stay identical
This slice converts src/propertyTest.ts's propertyTest, generateTestSuite and
testPaths, engine/suite.ts's generateTestSuite, replayTestSuiteFixture,
replayTestSuite and describeTestSuite's fixture callback, and
engine/propertyTest.ts's drain, start, run, runGenerated, replay, outcome,
advance, advanceExecuted and checkpoint. The remaining asyncFunction sites are
listed in the report
* refactor(global): run xstate-test's path engine as Effect values behind its Promise API
Convert engine/testPaths.ts's two async sites: createPathAdapter.run and
testPaths. The path adapter's run loop becomes an Effect.gen program with the
per-run counters held in Refs, awaited runner calls lifted with Effect.promise,
and failure capture via Effect.exit and Cause.squash so a rejected or throwing
runner still records the same error object. The dispose step keeps its
"only fill an unset path error" rule
testPaths wraps its synchronous path set-up in Effect.suspend, so the guard
clauses and traversal still reject with the same errors, and awaits
propertyTest behind Effect.exit, re-throwing a path-labelled ModelTestFailure
as a defect. Both functions still return Promises; no exported signature
changes
The api reports regenerate because importing from effect/Cause flips the
bundled declaration's Cause import from a named YieldableError import to a
namespace import
* refactor(global): run xstate-test's property engine stopping and step checks as Effect values
stop, dispose, executeEvent, checkStable, checkStateAssertions,
checkTemporal and compareObservations now build Effect values instead of
declaring async functions. Awaited SUT, actor and oracle calls go through
Effect.promise, and the try/catch and try/finally around them become
Effect.exit and Effect.ensuring. The executed-actor and pure branches of
stop and executeEvent move to module-level helpers so the generators hold
no reassigned bindings, and the response predicate is memoized with
Effect.cached
* refactor(global): run xstate-test's property engine campaign as Effect values
propertyTest's body moves to a module-level Effect program the published
function runs once with Effect.runPromise. The adapter, failure store and
replay calls are lifted with Effect.promise, the try/catch blocks around
them become Effect.exit, and the statistics write goes through a
module-level helper.
The campaign's per-run state lives in MutableRefs, since the adapter's
callbacks are synchronous and cannot yield, and the JSON keys used inside
the generator move to module-level helpers
* refactor(global): run xstate-test's property engine replay as Effect values
replayTest's body moves to a module-level Effect program the published
function runs once with Effect.runPromise. The start and replay awaits are
lifted with Effect.promise, and the try/finally that disposed the runner
becomes Effect.ensuring with a lazily built finaliser, so a partial start
still disposes every session it created
* refactor(global): read xstate-test's observation projection without non-null assertions
The comparable-SUT guard already guarantees the projector exists, so the
comparison captures it once and reads it directly instead of asserting
both the SUT and its projector non-null
* fix(global): map xstate-test's parallel branches with Effect.forEach
* build(global): record xstate's upstream exports, forgotten exports and grants
Regenerated from the pin and the rebuilt API reports. Each package's
manifest lists upstream's exports per entry point, every forgotten
export with its facade unit, the DOM-collision and TaggedError-base
report names with their reasons, and the ruled grant directives
* chore(global): run the store's src select test in its own project
xstate-store's upstream-verbatim project filtered the manifest to test/ files,
so src/select.test.ts was listed in upstream-tests.json and excluded from the
own project but run by neither. Include every manifest file, as the other five
packages already do
* fix(global): widen the store Observer members to match core
xstate-store published Observer<T> without the | undefined widening core's
members carry under exactOptionalPropertyTypes, so the same-named type diverged
across the six packages. Regenerate the store's API report
* refactor(repo): delete the starter seed package
The template seed package has no place in the xstate workspace; the fork packages arrive in the next layer
* docs(repo): name the repository xstate
README, AGENTS.md and CONTRIBUTING.md describe the xstate fork instead of the starter template, and the CI badge points at systemfsoftware/xstate. STRATEGY.md was the starter kit's product strategy, so it goes rather than mislead; xstate has no strategy document yet
* ci(ci): move mutation to a release gate on main
As in the starter's lake1/release-gate: Stryker runs at break 100 on every push to main, one hosted job per package with a mutation script, and the shard planner refuses an empty or unmatched mutate set. check:ci no longer runs mutation
* build(deps): pin the starter's lake1 toolchain and run dependency code in the sandbox
pnpm 12.9.0 and Node 24 come from Nix (nixpkgs aa48d34), with exact catalog pins matching effect-endgame-starter-kit lake1/nix-sandbox: effect 4.0.1, typescript 7.0.2 with @effect/tsgo 0.48.1, oxlint 1.82.0 with @systemfsoftware/oxlint-config-recommended 4.0.0, vitest 5.0.3, turbo 2.11.7, dprint from nix. The @systemfsoftware packages are file: tarballs from the systemfsoftware flake input. Every script that runs dependency code, the git hooks and every workflow go through pnpm-release-management's sandbox launcher (with the starter's linked-worktree patch), installing offline from a hashless pnpm store. The flake exports each public workspace package as a tarball through lib.mkPnpmWorkspacePackages
* build(repo): fail the commit-msg hook when git cannot list the staged files
Taken verbatim from effect-endgame-starter-kit e89877a, the template owner's change to this evaluator. Inside the sandbox a git failure made stagedFiles return an empty list, so the diff-shape rules passed vacuously; git's error now fails the hook, which the sandbox git-hooks proof asserts
* build(deps): pin systemfsoftware to the #606 head that builds on aarch64-darwin
At c53bfc9, the starter's pin, systemfsoftware's workspace deps hash holds only on linux, so the macOS check:ci leg failed building its tarballs (specified ttbWYFJ, got x2Rm/ViN; the starter's own macOS leg fails the same way). bb5956b measures the hash per system, and its CI builds the flake outputs on aarch64-darwin, aarch64-linux and x86_64-linux. Its nixpkgs is aa48d34, the same as ours, and pnpm-release-management's lib is byte-identical at both pins. The lockfile records the sandboxed tarball integrities, and the workspace deps hash follows the lockfile
* build(deps): trust mitm-cache's CA in the pnpm store build on darwin
pnpm 12 is a native binary whose platform verifier reads SSL_CERT_FILE on linux and the keychain on darwin, so the offline store build failed on macos-latest with UnknownIssuer against the mitm-cache replay. NODE_EXTRA_CA_CERTS hands the replay's CA to pnpm on every system. Probe: on linux with SSL_CERT_FILE unset the build fails with the same UnknownIssuer, and it passes once NODE_EXTRA_CA_CERTS is set
* build(deps): replay the pnpm store's registry over plain http
Trusting mitm-cache's CA was not enough on darwin. macos-latest then rejected the forged leaf certificates with 'invalid peer certificate: EkuError', which no CA setting reaches. The store build now points pnpm at http://registry.npmjs.org/ and serves mitm-cache's recorded https tree under http, so no TLS is involved on any system. Every tarball is still authenticated by its lockfile integrity. Probe: with SSL_CERT_FILE, NIX_SSL_CERT_FILE and NODE_EXTRA_CA_CERTS all unset, the linux store builds, and bootstrap then installs 241 packages offline from it with none downloaded
* build(deps): pin pnpm-release-management to the #8 head for the darwin runtime dir
With the launcher at 149e762, the macOS leg failed in pnpm bootstrap with ERR_PNPM_STORE_DIR_OPEN_OPERATION_LOCK: pnpm 12 takes its store-operation lock under XDG_RUNTIME_DIR, falls back to /tmp, and the darwin profile refuses /tmp. 8f19844 (prm#8, stacked on #5 at 149e762) gives darwin runs a private 0700 XDG_RUNTIME_DIR and proves the failure without it. nix/lib is unchanged between the two pins, so systemfsoftware's tarballs keep their store path, and the starter's linked-worktree patch applies with offsets only
* fix(repo): let the sandbox proofs and script tests run on macOS
Two macOS-only failures surfaced once the store and bootstrap worked there. Deno refuses a spawn under the scoped --allow-run while the child environment carries an LD_* or DYLD_* variable, which the macOS runner sets, so the git-hooks proof died at its first git call; its children now get the caller environment minus those variables. Turbo strict env mode dropped TMPDIR, so script tests fell back to the /tmp the darwin profile refuses (PermissionDenied: tmpdir); TMPDIR now passes through, as in pnpm-release-management 8f19844. Repro on linux: with LD_LIBRARY_PATH set, the old proof fails with NotCapable
* ci(ci): build the workspace tarballs in the dist leg
The tarball builder's fetchPnpmDeps hash covers the whole lockfile, and a store that already holds the old output reuses it silently. A fresh runner store refetches, so building .#workspace-tarballs there fails on a stale hash instead of shipping it (Kiro ruling on #13, question 2)
* ci(ci): plan release-gate mutation from each stryker config and the debt ledger
Kiro rulings #2, #3, #4 and #5 on #13. The planner imports each package stryker.config.ts and reads its mutate list, refusing a package.json that still carries stryker.mutate. Every publishable package either declares a mutation script or has an XS1 entry in debt-ledger.yaml naming its removing unit; a package with neither, an empty workspace, or a plan with nothing mutated and nothing exempt is refused, each as its own tagged refusal. The summary lists the ledger-exempt packages. Every parsed document decodes through Effect Schema. stryker.shared.ts imports StrykerConfig as a type so Deno can load a package config; its values are unchanged. The scripts and gate tasks reach registry.npmjs.org for npm:effect and may run git and bash for the new script tests
* ci(ci): test the release cycle and fix the release PR opener
Kiro rulings #6, #8, #11 and #12 on #13. The tag-based published check splits into the pure owedPackages and the git-backed isTagged, both tested against a real repository. plan-release exports decidePhase and renderOutputs and pins the release, version and none lines release.yml gates on. open-release-pr.sh decides from the packages/*/package.json delta against the base instead of a clean tree, which pnpm version -r always leaves, and no longer names apps/
* build(repo): pass dprint arguments through unchanged
The wrapper put the first argument before the Nix plugins and the rest after, so dprint --version and calls without a subcommand failed. It now execs dprint with the caller arguments verbatim and seeds dprint plugin cache from the pinned store wasms. A sandbox proof checks --version, check on an unformatted file and lint-staged fmt --allow-no-files -- order; the old wrapper fails the --version case
* ci(ci): run sandboxed workflow steps through one composite action
Kiro ruling #7 and the P3 credential finding on #13. .github/actions/sandbox takes hosts, env names and a command through env, so no input is interpolated into a shell, and the four workflows use it for every sandboxed step; host-side writes to GITHUB_OUTPUT and the step summary stay in their own steps. Every release.yml checkout sets persist-credentials false. tag-released-packages.ts gains --no-push, the sandbox creates the tags, and a host step pushes them with an explicit token header, so the token never enters the sandbox
* test(repo): spawn every sandbox proof without the dynamic-loader environment
The dprint wrapper proof failed on macOS with NotCapable: Deno refuses a scoped --allow-run spawn whose environment carries LD_DYLD_PATH. The git-hooks proof already dropped LD_* and DYLD_*; both proofs now spawn through sandbox-proofs/spawn.ts, which keeps that filter in one place. With LD_DYLD_PATH set on linux the old dprint proof fails the same way and the new one passes
* build(repo): seed the dprint plugin cache as a writable copy
Review finding C13-1/C13-22 on #13. The wrapper linked the seed with ln -sfn, which nests a link inside a stale real plugins directory and points the cache into the read-only store. It now replaces stale entries with a writable copy, stamped with the seed path; a sandbox proof pre-creates a real plugins directory and fails on the old wrapper
* test(ci): cover the release PR opener against an open PR
Review finding C13-5 on #13: the close path (no version bump) and the edit path (bumps) now each have a case, and each fails when its gh call is removed
* ci(ci): let the release notes steps fetch octokit
create-github-releases.ts imports npm:octokit, which Deno downloads from registry.npmjs.org when it runs. The three steps that run it allowed only jsr.io and api.github.com, so they failed on the first fetch (reproduced with an empty DENO_DIR). This is a dependency fetch, not a publish
* feat(release): release the packages listed in release-set.json
Nothing here goes to npm, so every workspace package is private and private no longer means unreleased. release-set.json is the one source of what releases: scripts/lib/release-set.ts decodes it and refuses an unknown or duplicate entry, a listed package that is not private and any workspace package that is not private. Tagging, the release plan, the changeset check, the mutation planner and the flake tarballs all read it. A version is owed once pnpm version -r records it in .changeset/ledger.yaml and it has no tag; an intent counts as pending until the ledger lists it for every package it names, because a pnpm lane keeps consumed intent files. The GitHub Release body is that version's section of the package CHANGELOG.md
Also applies review findings C13-2/3/4 (refusal tests), C13-8 (ledger entry type from its schema) and C13-11 (package names decoded against npm's name grammar before they reach the release-gate shell)
* ci(ci): let the release-set readers fetch effect
check-changeset, plan-release and tag-released-packages now decode release-set.json with Effect Schema, so Deno downloads npm:effect from registry.npmjs.org when they run. With only jsr.io allowed, plan-release failed on a cold Deno cache. This is a dependency fetch, not a publish
* build(repo): wire the fork packages into the xstate workspace
The six packages leave the monorepo private toolchain behind. tsdown and vitest configs import the root tsdown.shared.ts and vitest.shared.ts, api:check runs api-extractor directly, and @systemfsoftware/tsconfig and @systemfsoftware/vitest resolve from the systemfsoftware flake tarballs. The catalog takes the fork exact pins (api-extractor 7.59.1, tsdown 0.23.0, react 19.3.0) and a peers catalog with effect ^4.0.1. rolldown-plugin-dts keeps the monorepo patch that keeps local declarations out of the published types, so the recorded API reports still hold. The workspace deps hash moves with the lockfile. vitest.shared.ts declares the upstream-verbatim bypass with its reason and the unit that removes it, and the own project runs under the @systemfsoftware/vitest guard
* chore(repo): keep dprint off the verbatim upstream tests with one glob
One glob covers every upstream test file in packages/*/{test,src}, ruling #2 on systemfsoftware#631. Generated API reports are excluded as well, since dprint rewrites api-extractor output and api:check then fails
* docs(repo): require a lint fix to meet the rule intent at its site
REPO-W10: no hoisting code out of the rule view, no type-only overloads the runtime cannot reach, and no keyword swaps that keep the same control flow
* docs(release): add a changeset for each fork package
One intent per package, ruling #11 on systemfsoftware#631. xstate-effect and xstate-test name the effect peer floor moving to ^4.0.1; the other four say they carry no effect peer
* test(global): hold xstate-store's Observer members equal to core's
Ruling #8 on systemfsoftware#631. The store already carries core's | undefined widening; a type-level test in tests/ now pins the shared members equal and both member sets, and tsconfig.test.json includes tests/ so tsc -b checks it. Removing | undefined from the store's error member fails typecheck with TS2344
* test(global): pin the serialization port cases to literal code directives
Ruling #12 on systemfsoftware#631. Two ported cases built their expected @code from machine.config or String(fn), the same expression serialize.ts evaluates, so they could not fail. Each now spells out the printed source; the text differs from upstream's snapshot only by the printer (oxc tabs and undefined, esbuild spaces and void 0), the divergence the port record names. Changing one literal by a character turns the case red
* fix(global): report xstate-effect listener errors on a macrotask again
Rulings #9 and #10 on systemfsoftware#631. Commit 84230e5 swapped upstream's setTimeout rethrow in safeCall for queueMicrotask to clear effect-tsgo's globalTimers, which moved a listener's error ahead of queued microtasks and timers. safeCall now reports through core's reportUnhandledError, the one timer site core's own safeCall uses, exported as the internal _reportUnhandledError. A test pins upstream's order (microtask, earlier timer, error A, error B) and goes red on the microtask swap. EffectActor.toJSON already matched upstream; a test pins its JSON to the literal upstream tag. tsconfig.test.json now typechecks tests/ with node types
* refactor(global): thread xstate-test's campaign state through Ref
Ruling #5 on systemfsoftware#631, four of six sites. shortestPaths, nextFrontierIndex and nextTargetIndex become Refs read and updated by Effect steps, and scenarioRunCount folds into the campaign's own run counter. failureSeen and frozenSwarm stay MutableRefs: fast-check's synchronous createRunner and recordRun callbacks share them inside one adapter.run, and reading the flag before the run turns reportingOptions' shrinkRuns case red. The suite stays at 38 files and 478 tests
* fix(global): let a failing finaliser's error win in xstate-test
Ruling #13 on systemfsoftware#631. Upstream runs each scenario as try { body } finally { dispose }, so a disposal that throws replaces the body's error (adapter.ts:388-398 and :411-415 at 2146ae26). The port's Effect.ensuring combines the causes body first and Cause.squash surfaces the body. ensuringFinalizerWins records the finaliser's cause and fails with it when present; the adapter, playwright SUT, linearizability runner, replay and run disposal use it. Tests cover both failing, only the finaliser failing and only the body failing; flipping the precedence turns the first red. tsconfig.test.json now typechecks tests/
* deps(deps): publish the fork's react, fast-check and vitest peers as ranges
Peers on the default catalog resolved to its exact pins, so the packed xstate-react and xstate-store-react asked for react 19.3.0 and xstate-test for fast-check 4.9.0 and vitest 5.0.3. They now read the peers catalog, with the monorepo's published ranges: react ^19.3.0, fast-check ^4, vitest ^5. The packed manifests from nix build .#workspace-tarballs show the ranges
* test(global): give xstate's declaration-emit tests a tsc-sized budget
Each case compiles fixtures with a child tsc, about 4.6s locally against vitest's 5s default, and all three timed out on the hosted CI runner. The monorepo hid this behind a 30s shared CI timeout; the budget now sits on the three cases that spawn the compiler
* fix(global): report xstate-effect listener errors through a local timer port
Kiro ruling Q4 on #14: core no longer exports _reportUnhandledError. xstate-effect reports a listener error from its own port, an Effect.sleep of 1ms on the default clock, which is a timers-phase setTimeout as upstream used, so effect-tsgo globalTimers is met without a raw timer. The order test keeps upstream order and now runs as Effect generators with Deferred, an Effect-clock marker and a Schema JSON pin, so lint:tsgo is clean for tests too; switching the port to queueMicrotask still turns it red
* refactor(global): pass xstate-test shrink state through the adapter run context
Kiro ruling Q2 on #14. createRunner now receives a per-run context from the adapter (shrink, frozen swarm, report), and the fast-check adapter sequences runs and threads each reported outcome into the next run, so propertyTest.ts no longer shares MutableRef cells between recordRun and createRunner. The context is optional: adapters that never shrink keep calling createRunner() unchanged. reportingOptions.test.ts:144 stays green and goes red when the context never marks a shrink
* ci(repo): gate the packages on lint:tsgo and attw
Kiro ruling Q3 on #14. gate:tasks runs lint:tsgo and attw, the lint leg runs lint:tsgo and the dist leg runs attw after build. An Effect.sync calling setTimeout in xstate-test fails lint:tsgo with globalTimersInEffect, and a declaration re-exporting a missing file fails attw with InternalResolutionError
* ci(ci): record the six fork packages as XS1 debt
Kiro ruling on #13 finding #3. No fork package declares a mutation script before its rewrite layer (XS1), so each carries a debt-ledger entry naming its removing unit: U9 for core, U11 effect, U12 react, U13 store and store-react, U14 test. The release-gate planner now plans packages=[] with these six listed in the summary, and dropping the core entry makes it refuse with exit 1
* build(repo): keep the fork packages off npm and on the alpha lane
Ryan's ruling: distribution is git tags, GitHub Releases and the Nix flake, never npm. Each package is private, which makes pnpm publish refuse it and stops pnpm version -r probing registry.npmjs.org (its first-release check holds a never-published, non-private package at its manifest version forever, pnpm issues 13519 and 13736). publishConfig keeps only the exports tsdown generates, which pnpm pack applies to the flake tarballs; access and provenance are gone. The six packages sit on pnpm's alpha lane, so an intent releases X.Y.Z-alpha.N and keeps upstream's prerelease line
* docs(repo): install the fork packages from the flake
The package docs told readers to npm install upstream's package names. Each install block now builds the package's own flake attribute and points to the root README for the catalog entry; third-party peers still come from the consumer's package manager
* build(repo): release the six fork packages
release-set.json lists the six @systemfsoftware/xstate* packages, so tagging, the release plan, the changeset check, the mutation planner and the flake tarballs take them from it
* test(global): pin finaliser-wins precedence at every xstate-test call site
Review finding C14-3 on #14. ensuringFinalizerWins has six call sites (adapter run and scheduler idle, playwright teardown, the linearizability session, disposeRunnerWithRecord and replay); each now has a case through the public API where body and finaliser both fail and the finaliser's error must surface, matching upstream's try/finally at the same site. Swapping the arguments at any one site turns exactly its own case red
* test(global): kill a hung tsc child in xstate's declaration-emit tests
Review finding C14-9 on #14. Each tsc child now runs under a 55s deadline, inside the 60s case budget, and is killed with SIGKILL. The case fails with a typed ChildTimeout only once the pid is gone. A new case drives the same helper with a child that ignores SIGTERM and never exits: without the deadline it hits vitest's timeout, and with it the case names the timeout and the pid is dead
* test(repo): pin the hooks a git-hooks proof commit runs
One pnpm test:sandbox run let a named-path feat commit of a tooling-only file land in 9ms, with no lint-staged output: git ran no hooks at all. The proof found its hooks through ambient discovery of a relative core.hooksPath, and commitlint passes an empty staged set, so an unhooked commit looked compliant. Every proof commit now passes -c core.hooksPath=<fixture>/.husky. A new step points ambient discovery at a missing directory and still expects the refusal; it fails without the pin
* build(deps): pin systemfsoftware to the merged #606
systemfsoftware#606 merged as 217c80d5d5. Its workspace tarballs build with the same bytes on every system, so the macOS leg's pnpm store accepts the integrity the lockfile records. Linux tarball bytes are unchanged (tsconfig-2.0.1 and effect-cell-types-12.0.0 hash to the recorded integrity), so the lockfile does not move. The systemfsoftware input stops following this repo's pnpm-release-management pin, because 217c80d calls mkPnpmConsumerStore, which that pin lacks
* build(repo): release the six fork packages as public packages
Ryan's correction: the six packages are public, released packages of a public repository. They ship as git tags, GitHub Releases and the Nix flake. This reverts 3af3169: private comes off every manifest, publishConfig gets access public and provenance true back next to exports (inert, since no step publishes), and the pnpm alpha lane goes. Versioning without pnpm's registry probe, keeping the 6.0.0-alpha line, is pnpm-release-management's gap and holds this PR as a draft
* build(repo): point the fork packages' repository links at systemfsoftware/xstate
Each manifest still named the monorepo (systemfsoftware/systemfsoftware, packages/xstate/<pkg>) as its repository, homepage and issue tracker. The packages now live here at packages/<pkg>, so the links that ship in every tarball point at this repository
* build(deps): build the release gate's stryker from source and plan it with stryker plan
Kiro's C13-19 rulings: the release gate stops planning mutation with a repo-local glob matcher, and no @systemfsoftware/* package is fetched from registry.npmjs.org, at install or build. stryker-js 17.0.2, its typescript-checker 8.2.1 and vitest-runner 8.1.1 and their nine siblings are built in this flake from stryker-js-effect at 3db0c428 (flake = false input), through a committed overlay workspace and lockfile under nix/stryker-js/ and the existing hashless pnpm store, and packed into file:.stryker-deps tarballs the catalog resolves. nix run .#stryker-js-lock regenerates the overlay lockfile and refuses a registry-resolved @systemfsoftware/* entry.
The release gate's plan job lists the workspace packages with a mutation script, runs stryker plan over them, and scripts/stryker-plan-gate.ts refuses a plan that schedules no mutant for such a package (C13-13: a project resolved outside the root is refused too) or is vacuous with no ledgered debt; each matrix shard runs stryker run --plan --shard. The plan gate's tests are what test:scripts now runs, since the local release scripts left with main's shared toolchain
* ci(ci): run the intent check in the dev shell
pnpm-release-management's reusable changeset-check installs the caller's workspace with a bare pnpm install, which cannot read the file:.sfs-deps and file:.stryker-deps tarballs only this repository's Nix dev shell provides (ERR_PNPM_TARBALL_READ_LOCAL_TARBALL on effect-cell-types-12.0.0.tgz). The same check now runs in this workflow: the dev-shell action installs offline through the sandbox, and the sandbox runs changeset-management check against the pull request's base. The CLI comes from a new release-tools flake input pinned to pnpm-release-management's main (5432b8b), which keeps its own nixpkgs because its deno-compile runtime is pinned to that deno; the existing pin stays for mkPnpmWorkspacePackages
* build(repo): build every from-source package through one parameterized builder
nix/from-source.nix replaces nix/stryker-js.nix: pname, src, the overlay
directory, the packed list and the extra store files are arguments, and the
generic helpers move to nix/from-source/. The lock app and the deps directory
are generated from the instance map, so nix/stryker-js holds only its own
manifest data.
Every tarball a workspace here installs now lands in .sfs-deps: the
systemfsoftware flake's workspace tarballs plus the tarballs this flake builds
from source, so the catalog, the root lockfile, the pnpm store, the
workspace-source copy and the dev shell carry one directory instead of two.
The stryker tarballs are byte-identical before and after
* build(deps): build the attw CLI and its effect-cell-types 7 from source
The six packages' attw script ran a registry arethetypeswrong-cli 4.2.0, the two lines assert-local-sfs.awk named. It now runs the CLI this flake builds from the released 4.2.0 tag, d43a8020, so no @systemfsoftware/* package comes from the registry. The packed tarball is built from that tag here, so it is not byte-equal to the registry's 4.2.0 artifact.
attw 4.2.0's lockfile resolves @systemfsoftware/effect-cell-types@7.0.0 and its Workflow.make calls use the positional form, so the workspace's 12.0.0 makes the bundled CLI throw on import. The 7.0.0 release tag, 4cf0f770, becomes one more from-source instance, and the attw overlay alone overrides effect-cell-types to its tarball, including npm-package's transitive dependency.
The root lockfile is re-resolved with the attw catalog entry pointed at file:.sfs-deps/arethetypeswrong-cli-4.2.0.tgz, which also refreshes the catalog's ranges, and the workspace deps hash moves with it
* build(repo): build from-source packages inside the nix sandbox
CI's sandboxed nix failed the stryker-js tarballs with ERR_PNPM_NO_OFFLINE_TARBALL (reused 0), so every job died building the dev shell; local nix runs with sandbox = false, which hid it. Three faults, all sandbox-only. pnpm got the read-only store path, so it reused nothing; it now gets the writable view the sandbox launcher builds (index.db copied, every other entry linked, clone-or-copy import). pack.mjs renamed the packed tarball across filesystems (EXDEV); it copies now. And unsandboxed, pnpm pack fetched the published CHANGELOG of @systemfsoftware/stryker-js from registry.npmjs.org and prepended it, so the lockfile recorded an integrity for bytes that came through the registry. The sandboxed stryker-js-17.0.2.tgz carries only the repo's own changelog entry; the lockfile takes its integrity and the workspace deps hash moves with it. The other eleven stryker tarballs are byte-identical under the sandbox
* build(repo): keep the starter package in the scaffold
Kiro's ruling (cycle 27): the scaffold leaves packages/starter in place, byte-identical to main, so turbo enumerates a workspace package at this head and pnpm-release-management's turbo-gated changeset check evaluates instead of refusing an empty workspace. The deletion moves to the layer that adds the six fork packages, so no head in the stack has an empty workspace. The catalog regains the two pins the starter needs (rimraf 6.1.3, tsdown 0.23.0, the versions the packages layer pins), the lockfile gains its importer and the workspace deps hash moves with it
* build(repo): delete the starter package with the fork packages in place
Kiro's ruling (cycle 27): the scaffold keeps packages/starter so no head has an empty workspace, and this layer deletes it in the same PR that adds the six packages. The from-source tarballs are rebuilt inside the nix sandbox: unsandboxed, pnpm pack had prepended registry-fetched CHANGELOG history, so effect-cell-types 7.0.0, arethetypeswrong-cli 4.2.0 and stryker-js 17.0.2 change bytes. nix/attw/pnpm-lock.yaml takes the new effect-cell-types integrity, the root lockfile drops the starter importer and takes the new attw and stryker-js integrities, and the workspace deps hash moves with it
* build(deps): pin release-tools to the pnpm-release-management main that fetches sandboxed
Every CI job died building the dev shell: 5432b8b declares sha256-SljOBg for the changeset-management pnpm deps, and a sandboxed fetch y…
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.
Bumps the turborepo-minor-patch group with 1 update in the / directory: turbo.
Updates
turbofrom 2.10.12 to 2.11.7Release notes
Sourced from turbo's releases.
... (truncated)
Commits
547747fpublish 2.11.7 to registry3ce82f5fix: Ignore Vercel OIDC token rotation in .env.local cache inputs (#14356)8cc3ccechore: Update with-vite-module-federation example (#14349)41387defix: Pass SDKROOT through to repository tasks (#14353)3a2072cchore: Release Turborepo 2.11.6 (#14352)90718d1fix: Infer single-package mode for query commands (#14351)a409ce5fix: Complete taskquerymetadata for non-script entrypoints (#14350)bc7c148feat: Filter tasks by tags in the CLI (#14345)49d1607feat: Filterquerytasks and packages by tags (#14344)fba5351feat: Expose task and package tags inquery(#14343)Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebasewill rebase this PR@dependabot recreatewill recreate this PR, overwriting any edits that have been made to it@dependabot show <dependency name> ignore conditionswill show all of the ignore conditions of the specified dependency@dependabot ignore <dependency name> major versionwill close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself)@dependabot ignore <dependency name> minor versionwill close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself)@dependabot ignore <dependency name>will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself)@dependabot unignore <dependency name>will remove all of the ignore conditions of the specified dependency@dependabot unignore <dependency name> <ignore condition>will remove the ignore condition of the specified dependency and ignore conditions