Repository navigation
ci(mutation): run mutation testing on main through systemfsoftware's reusable workflow - #5
Draft
systemfsoftware-maker wants to merge 16 commits into
Draft
systemfsoftware-maker wants to merge 16 commits into
systemfsoftware-maker wants to merge 16 commits into
Conversation
Records the durable lesson from main's failed Release (run 38076109214) and its fix in #3: a public member with no <name>@v<version> tag is in the release cycle and needs a changelog for that version; "private": true is not the fix because it also drops the member's tarball; and a new repo's root package.json needs a "version" for the bump step. Marked as a candidate for the systemfsoftware release pack. Coordinates checked at pnpm-release-management b9b4a1d48cc1, cited by symbol in the doc: - packages/github-release-engine/src/cycle.ts:20-23 (cycleOf filters) - nix/lib/pnpm-workspace-packages.nix:63 (public binding) - packages/version-engine/src/bump.ts:54-57 (root manifest readSurface)
PR3 (feat/mutation) adds a thin caller of systemfsoftware's shared reusable-mutation.yml: push to main and workflow_dispatch only, pinned by SHA to the O1 commit that lets the shared job install .sfs-deps. systemfsoftware main is still feb68840, which installs without .sfs-deps, so the caller stays blocked: no workflow file lands until the O1 rev exists. The plan records <O1-rev> as the placeholder. The requirements came from the ce-brainstorm pass and the implementation planning from ce-plan, both in this file: units U1-U3 with test scenarios, Compound Pack citations, and an open question for the root. At feb68840 the shared run concludes success when a package scores below its break threshold, so the proof reads the graded summary row. The ce-doc-review findings are report-only: none are applied, and each awaits a root ruling.
Records all 14 doc-review rows in a "Doc-review rulings" section and applies them. Accepted: D1, D3 (assumptions text), D5, D6, L1, D8, D9, D10, D11, D12, F1. D7 is rejected because the shared report job requests actions: write. Root rulings: - D2: O1 (systemfsoftware #735) does not fail the run below break; #733 does. The pin order follows whichever lands first, and R4 holds either way. - D4: the caller has no tarball job. #735's sfs-deps job builds this repository's .#sfs-deps (flake.nix:113), and this repository is the caller #735's AE5 names. - KTD4: every job fits 10 minutes. target-seconds <= 480, max-jobs 20, default timeout as backstop. Two facts found while applying the rulings are recorded as open questions: - #733 requires a committed mutation-baseline.json per mutated package. - Before #733 a package's kill cap is twice target-seconds.
… O1 (#735) The row pointed at #710, which has landed. The shared reusable-mutation.yml still installs without .sfs-deps, and O1 (systemfsoftware #735) adds that input. Unit U1 of docs/plans/2026-10-10-2149-ci-mutation-caller-plan.md.
Standing rule (2026-10-11): a timeout is a backstop for a stuck job, never a budget enforced by cancelling. Budgets stay measured, with each job's wall time reported in the PR body. - ci.yml: the sfs-deps, host-bytes and host-compare jobs go from 10, 10 and 5 to 60. So do the three lanes' timeout-minutes, timeout-minutes and plan-timeout-minutes passed to reusable-checks.yml. - release.yml: the noop job goes from 1 to 60. reusable-checks.yml at the pinned 732f66a0 takes each input as an uncapped number: lanes into timeout-minutes (:212), timeout-minutes into the test job (:55-59, :239), plan-timeout-minutes into the plan and timings jobs (:60-64, :139, :316). max-seconds stays at 600, because it is a planner budget, not a timeout. The mutation-caller plan records the ruling and amends KTD4: the future caller passes timeout-minutes and report-timeout-minutes as 60.
U2 of docs/plans/2026-10-10-2149-ci-mutation-caller-plan.md. The new .github/workflows/mutation.yml calls reusable-mutation.yml at 02bf9653b1ca2b0a2951baf2743bb3f70d19fc77 (systemfsoftware #735). It was pinned once all five runs on that commit had concluded success. - Triggers: push to main and workflow_dispatch, never pull_request. - Concurrency: one group per SHA with cancel-in-progress false, so no merge's run cancels another's. - Inputs: target-seconds 480, max-jobs 20, timeout-minutes 60 and report-timeout-minutes 60. sfs-deps-installable keeps its default .#sfs-deps (flake.nix:113), so the caller has no tarball job. - Permissions: contents read, plus actions write for the report job, which also covers the plan job's actions read. Push and dispatch runs are both incremental through the reusable's stryker-incremental cache (reusable-mutation.yml:198-205, :312-328). A full-corpus input is an open item for the shared-tooling unit.
…rkflow Registration workaround from the plan's U3: GitHub dispatches only workflows it knows, and this file is not on the default branch. A push on feat/mutation registers it, and the job is skipped on that event. The next commit removes this trigger.
The registration push on 7cd02ba registered the workflow (id 381043192), and proof run 38117312976 was dispatched at that commit. The caller is back to push on main and workflow_dispatch, and the job-level if: goes with the trigger.
Proof run 38117312976 failed its dry run with Budget_RequiresTransform: Stryker's ObjectLiteral mutant wraps the recursionBudget object passed to annotate on each Schema.suspend, so effect-schema-recursion-budget injects nothing. stryker-ignorer-effect-schema-declarations 0.3.0 ignores that object; it is released at 9e81669 with stryker-js 19.0.0. The stryker-published input moves from 27b1075 (stryker-js v18.1.0) to 9e81669, and every stryker tarball comes from that one commit. The .sfs-deps overrides and pnpm-lock.yaml follow; the lockfile diff changes only stryker packages. No package file changes (R6). The plan records the run, the cause and the root ruling, plus two shared-tooling open items: the kill cap in mutation-job.ts:102-105 and stryker-config 0.1.0's ^17.0.0 peer on stryker-js.
Run 38120830653 passed its dry run (661 s) but the shared mutation-job.ts timeout wrapper killed Stryker at 960 s with 63 of 1354 mutants done. The dry-run cost comes from effect-sim-kernel's 250 seeded replays per scenario (Profile.ts:34-39), routed to unit S2. No workaround here; the PR waits on O1's fix PR and S2's release.
F2: AGENTS.md states where mutation runs: in CI only, never on pull requests, on every push to main and by manual dispatch to prove the lane on a branch. F4: the plan's KTD3 edge case now records that a second dispatch on the same commit waits and both report, and KTD3 is marked amended by the U2 rulings. F5: the flake.nix comment no longer claims stryker-config comes from the stryker-js-effect pin.
Root ruling (2026-10-12): Stryker's effective mutate set is exactly src/**/*.workflow.ts, so stryker.config.ts drops src/**/*.schema.ts. The plan records the ruling, amends R6 for this one line and no longer says schema files are mutated. The package tarball ships only dist, so its bytes do not change.
… change Root decision: the change touches only CI and the dev-only Stryker config. The shipped tarball is byte-identical to the one the v0.0.0 tag records, so nothing is released.
Review ruling (2026-10-12), from the repository's own sources: - packages/api-extractor/stryker.config.ts returns to main's bytes: workflow and schema files are the verdict-decision code AGENTS.md:12 names (CONST-T12); narrowing the graded set inside the PR it grades weakens the grader (CONST-E7); a one-file set yields fileless shards at 02bf965 (test-timings.ts:211-212,355,455). - With no path under packages/ changed, the `none` intent is deleted. - docs/plans/2026-10-12-1832-ci-mutation-caller-plan.md supersedes the started 2149 plan (plan-discipline), and lists blockers #737, #744, #733 and survivors with evidence.
This was referenced Oct 12, 2026
The caller's triggers are now a nightly schedule (14:47 UTC) and workflow_dispatch, and its job runs only on refs/heads/main. Each run has its own concurrency group, so a dispatch never replaces the nightly run. The header states the lane's daily runner-minutes, which the ci-wall-clock rule heavy-lanes-state-their-daily-minutes requires. docs/plans/2026-10-13-0641-ci-mutation-caller-plan.md supersedes the 1832 plan: nightly cadence (U7), the re-pin past systemfsoftware #733 that retires generated schema laws without replacement (U5, blocked on B6), and the proof run on a temporary branch trigger (U6). AGENTS.md and the README row restate the cadence.
systemfsoftware-maker
added a commit
that referenced
this pull request
Oct 13, 2026
…ulings (U12) Supersedes the 1737 plan. D1 named a reader refusal (MissingSource) that would have reversed ruling #5's fast-path decline; the adapters decline (fast path) and refuse before tsc (compiler). D2 said tsc refuses a shared declaration path with TS5056; tsc 7.0.2 exits 0 and writes one file, so the compiler adapter refuses it first. The DeepSeek delta review's two findings are ruled: the D1 text finding is accepted by this correction, the dropped-exit-cause finding is rejected with its reason.
systemfsoftware-maker
added a commit
that referenced
this pull request
Oct 13, 2026
…ancestry; profile harness maps .cts and counts missing emits (U13 #5, #6) The derived tsconfig sat in a bare temp directory, so tsc looked up a `types` entry naming a package (`vitest/globals`) in node_modules directories above the temp dir and refused with TS2688. Four corpus packages the earlier profile modelled were refused this way. The derived config is now written into a scoped mirror of the package config's directory, each ancestor carrying a symlink to the real node_modules, so tsc's upward walk matches the package's own. The explicit typeRoots chain this replaces is gone; derivedTsconfig becomes writeDerivedTsconfig, which writes the mirror and returns the config path. e2e: the equality journey gains a package whose tsconfig names `types: ["greeting/globals"]` from its own node_modules through an exports subpath. It fails at c4202d9 with TS2688 and passes after. Profile harness: .cts sources map to .d.cts and are discovered; null and array export targets are skipped; a file missing from the 5.9.3 output is counted apart from a printing difference; tsc's stderr is drained alongside stdout.
systemfsoftware-maker
added a commit
that referenced
this pull request
Oct 13, 2026
…mirrored node_modules learning Supersedes the 1834 plan. U13 rules every finding of the full-path review at e5ec09d: six fixed (#1, #2, #4, #5, #6, #8), the mapped-type/infer anchor-50 note fixed after reproduction, the TS2688 regression the rerun found fixed, #3 and #7 rejected with the validator's reasons, and the Diagnostic.code refusal note made a PR4 follow-up. KTD3 now describes the mirrored node_modules ancestry instead of the explicit typeRoots chain, and the policy gains isolatedDeclarations: false. docs/profiles/2026-10-13-front-end-phases: the U13 harness at 432b608 on the corpus at 732f66a0c8. 126 of 585 shared declaration files print differently between TypeScript 7 and 5.9.3 and none are missing; every package's route and outcome match the second profile. The emit-option learning gains the isolatedDeclarations case and the types-from-node_modules case, each with its gate.
systemfsoftware-maker
added a commit
that referenced
this pull request
Oct 14, 2026
Testing P3 at c25bf9a: the compiler's 'does not exist' refusal had no scenario beside its pinned 'resolves outside the package' sibling. The refusal journey analyses a package whose entry names no file: the fast path declines and the compiler refuses with a Note naming src/mod.ts. Pins existing behaviour (ruling #5).
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
Mutation testing now runs on
@systemfsoftware/api-extractorthrough systemfsoftware's sharedreusable-mutation.yml, nightly onmainand by manual dispatch onmain, never per push or per pull request (root ruling, 2026-10-13). This PR is the first hook-mode caller of that workflow. The caller is wired, but no run has produced a graded score yet, so the PR stays a draft.Status (2026-10-13, head
b86386f): draft. Six blockers stand between this head and merge. The plan's Dependencies / Blockers section holds the evidence for each.6db58a01): removes themutation-job.tstimeout wrapper that killed run 2 at 960 s, and widens stryker-config's peer range.26442627): cuts seeded replays. Run 2's dry run alone took 661 s, above the 600 s job budget.78826f9f):gate --baselinefails a run on a below-break score. At today's pin02bf965a[FAIL]row still concludessuccess, so the lane cannot fail on a survivor (CONST-T3). #733 requirespackages/api-extractor/mutation-baseline.json, which lands onmainin its own layer first.main.e2e1e71a): refuses a package that sets its ownmutate, and stops exportingshardMutate. If the re-pin includes it,stryker.config.tsdrops itsmutate(plan KTD7).mainat763fd663(#746) does not contain one. The re-pin waits for it.After the blockers: the re-pin past #733 and B6 (U5) removes the retired generated-law wiring and any in-source decode or verdict refusal property, and adds no replacement test (root ruling, plan KTD11). Then one proof run (U6) on
feat/mutation, started by a temporarypushtrigger that the next commit removes, must concludesuccesswith a graded row at or above 100 and every job at or under 600 s.Plan:
docs/plans/2026-10-13-0641-ci-mutation-caller-plan.md. It supersedesdocs/plans/2026-10-12-1832-ci-mutation-caller-plan.md, which supersededdocs/plans/2026-10-10-2149-ci-mutation-caller-plan.md. Both earlier plans stay as the contracts their executed units were verified against.Stacking waiver (operator, 2026-10-13): this PR and #7 (
feat/front-ends) both changeREADME.md,pnpm-lock.yamlandpnpm-workspace.yaml, so OP13b's overlap check fails forfeat/mutation. The overlap predatesb86386f(05f44c0already had it). The operator waived the check for theb86386fpush. Restacking is still open: whichever of #5 and #7 merges second must mergemainand resolve those three files.Caller
schedule(cron47 14 * * *) andworkflow_dispatch(mutation.yml:9-11). The mutation job runs only whengithub.ref == 'refs/heads/main'(:22), so a dispatch on any other ref skips it. There is nopush,pull_requestormerge_grouptrigger. 14:47 UTC sits inside the 14:10-15:10 window that systemfsoftware #733 measured as the org's quietest hour, 30 minutes after systemfsoftware's own nightly run starts.mutation-${{ github.run_id }},cancel-in-progress: false(:14-15). Every run has its own group, so a dispatch never replaces the nightly run and the nightly run never replaces a dispatch. The shared caches are keyed by run id.mutation.yml:1-5): at least 25 runner-min/day for the one nightly run, plus the same for each dispatch. A push starts no run, so the 7-day merge rate (5 first-parent commits onmain, 2026-10-06T06:00Z to 2026-10-13T06:00Z) does not price it. Per-run time comes from run 38120830653 (1,469 job-seconds over six jobs) and is a floor, because Stryker was killed 960 s in. The proof run's measurement replaces it.target-seconds: 480,max-jobs: 20,timeout-minutes: 60,report-timeout-minutes: 60.sfs-deps-installablekeeps its default,.#sfs-deps.contents: readat the top. The mutation job getscontents: readandactions: write, which the shared report job requests.main:src/**/*.workflow.tsandsrc/**/*.schema.ts(packages/api-extractor/stryker.config.ts:20), the verdict-decision codeAGENTS.md:12names. B5 can change this at the re-pin.packages/,apps/or.changeset/, so the PR carries no changeset intent and releases nothing. The package tarball ships onlydistand is byte-identical to the one the@systemfsoftware/api-extractor@v0.0.0tag records. On merge, Release owes nothing because thev0.0.0tag already exists for that tarball (pnpm-release-managementcycle.ts:22).AGENTS.md:24-26and the README row restate the cadence.Pins
02bf9653b1ca2b0a2951baf2743bb3f70d19fc77(#735, O1) forreusable-mutation.yml. All five systemfsoftware runs on that commit concluded success before it was pinned.packages/api-extractor/mutation-baseline.jsononmainfirst.9e81669b84711a9635eaa97b17dd13efea9f0c8cfor thestryker-publishedflake input. Every stryker tarball comes from that one commit..sfs-deps, the overrides inpnpm-workspace.yamlandpnpm-lock.yamlare regenerated, and the lockfile diff touches only stryker packages.27b1075, stryker-js v18.1.0)9e81669)Stryker-js 19.0.0 is still compatible with what the shared job calls:
--incrementalFilethe job passes (dist/main.mjs:116917,:117032).reports/mutation/mutation.json, where the job reads it (stryker-configlib/base.js:13;main.mjs:91348-91351).Proof runs
Both earlier runs ran on
feat/mutationwith no cache, so each covered the full corpus. Run 1 ran at7cd02ba, which still carried the temporary registration trigger;87b52afremoves it. Run 2 ran at1ebd34e, after the removal.Run 1, 38117312976, at
7cd02ba: failure.recursionBudget is declared on ApiItem but nothing materialized it — Budget_RequiresTransform.recursionBudgetobject passed toannotateon eachSchema.suspend, so effect-schema-recursion-budget no longer sees an object literal and injects nothing.Run 2, 38120830653, at
1ebd34e: failure.timeout --kill-after=60 <2 x target-seconds>wrapper atmutation-job.ts:102-105. Exit 130RunInterrupted.Profile.ts:34-39runs 250 seeded replays per gherkin scenario and ignores the fibers/steps budget. This suite's scenarios are single-fiber, and 50 seeds gave 1 path. A serial host run took 69.9 s at 250 seeds and 9.5 s at 25.target-secondsormax-secondschange, no localmutation-job.ts, noCONFORMANCE_PROFILEflag and no test change.Run 2's jobs, from the jobs API (wall = completed − started, queue = started − created):
The mutation and
sfs-depsjobs are both over the 600 s target. No graded row exists forpackages/api-extractoryet.Timeouts
Standing rule: every job and step timeout here is an explicit 60 minutes, a backstop for a stuck job, never a budget enforced by cancelling. Workflow lines from
git grep -n timeout-minutesatb86386f:ci.yml:52max-seconds: 600is still open (see the receipt below).Open items
Shared tooling, not this repository:
reusable-mutation.ymlsets them at:58,:74and:255.:198-205and:312-328always runs. Only a cold-cache first run covers the whole corpus.mutation-job.ts:101-117).Profile.ts:34-39: the seed budget, for S2.actions/cache/restore@v6atreusable-mutation.yml:198), so the SHA pin on the workflow does not fix what they run.:198-203).shaorjobsinput.This repository:
red-main-reverts-its-culprit-same-day). Operator: a handler workflow.packages/api-extractor/package.jsonare stale behind the overrides. They are fixed in the first-release PR, because editing the shipped manifest changes the v0.0.0 tarball. That PR must also change the vm-runner override key atpnpm-workspace.yaml:57.The branch also carries
docs/solutions/integration-issues/unversioned-public-package-is-owed-a-release.md, the lesson from main's failed Release in #3.Verification
At
b86386f:flake.locklocks (aa48d34, through--inputs-from .), not withnix run.git diff --name-only origin/main...HEAD -- packages/ apps/ .changeset/prints nothing (R3)..#workspace-tarballs'api-extractor-0.0.0.tgzequals thev0.0.0tag annotation's integrity:sha512-Xc8rNV9C…D3g==.Code review (full path, report-only, head
b86386f)ce-code-review mode:agent base:origin/main depth:fullran against headb86386f03084535cbe3f0ec2f2aecf9e8afb5abc(base9bd73962b7). Verdict: Not ready. That is expected for this draft: B1-B6 are open, and the one P1 is the cadence departure the root ruled on (#4 below). Nothing was applied in the review round.Packs loaded. This head's config declares four packs at systemfsoftware
df908ddfe4. The review also loaded the five packs #8 enrolls at8d07118079,ci-wall-clockamong them. The resolver returned no errors or warnings for either pin. 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 pack receipt, reliability, security, and adversarial. All six ran as omp agents, and their session logs show every turn served bydeepseek/deepseek-v4.1-flashthrough OpenRouter (13-30 turns each), with no Claude, Grok or xAI turn. The non-Claude peer is omp'sadversarial-revieweragent ondeepseek-v4.1-flash, 19 turns. No external peer CLI is installed. An independent validator (correctness-reviewer,deepseek-v4.1-flash) checked the three findings selected for validation..github/workflows/mutation.yml:8.github/workflows/mutation.yml:22.github/workflows/mutation.yml:1max-secondsdefault authorizes (reusable-mutation.yml:20-24at02bf965)..github/workflows/mutation.yml:9-11heavy-suites-judge-every-main-commit: a heavy lane must run on every push tomain, and this lane does not.main, never per push; plan KTD5). Recorded, not fixed..github/workflows/ci.yml:52;ci.yml:25,66,91;release.yml:31one-stuck-job-backstop:max-seconds: 600is a sub-60-minute cap, and no changed job writes its wall time to the step summary.max-secondsstays: the root's earlier ruling allows nomax-secondschange in this repository (Proof runs, run 2). The wall-time summary step is open, a fix in #5 pending the operator..github/workflows/mutation.yml:1heavy-lanes-state-their-daily-minutes: the header prices the nightly run, not a per-push run.Pack receipt (
ci-wall-clockat8d07118079, all 12 rules)flake-outputs-build-once-on-mainflake.nix:18.#sfs-deps' input (stryker-published), so a pull-request build of it passes Gate (1).gates-share-one-jobci.yml:50heavy-lanes-state-their-daily-minutesmutation.yml:1-505f44c0.heavy-suites-judge-every-main-commitmutation.yml:9-11mutation.yml:14-1505f44c0.mutation.yml:26light-checks-run-the-pinned-tooldevshell: trueatchangeset-check.yml:17predates this diff.no-dev-shell-on-verdict-lanesnix developstep added to a verdict lane.no-lane-grades-the-repos-own-docsone-stuck-job-backstopci.yml:25,50,51,53,66,91;release.yml:31;mutation.yml:30,31ci.yml:52max-seconds: 600stays by root ruling (#5).ci.yml:25,66,91;release.yml:31mutation.yml:28target-seconds: 480becomes a 960 s per-package kill. Upstream: B1.mutation.yml:26pr-gate-runs-only-what-the-diff-affectsmutation.yml:22;ci.yml:50ci-wall-clockloaded, and this is it. The earlier "violate at.compound-engineering/config.yaml:5, resolved by #8" is withdrawn: #8 is open, and this receipt is what that row was waiting for.red-main-reverts-its-culprit-same-daymutation.yml:20-24workflow_runhandler orissues: write. Operator: a handler workflow.mutation.yml:11workflow_dispatchtakes noshaorjobsinput. Upstream: callee inputs.release-promotes-the-staging-proven-buildrelease.yml:31release.yml:24setup-under-a-minuteci.yml:25.#sfs-depsbuilds before the pull-request verdicts, which the rule allows because the diff changes its inputs.Other packs.
boundary-testing/pin-dependency-semanticscomplies: the SHA pin plus the U6 graded proof stand in for a differential test (flake.nix:18-24).package-topology/surface-changes-are-versionedcomplies: nopackages/change, and the tarball equals the tag's. The rest ofcell-architecture(16, countingports-separate-from-layersatdf908ddfe4),boundary-testing,schema-lawsandpackage-topology: no match. The diff changes no code, schema, entry point or published surface.Residual risks. A missed or disabled nightly produces no run, so "no run" looks the same as "green". The U6 proof runs a head whose trigger lines differ from the ones that merge. Nothing in CI asserts the trigger set or that the pin is still an ancestor of systemfsoftware
main. The callee's tag-pinned actions run withactions: write.Earlier review
Report-only review at
8671277: correctness, project standards, security, reliability, adversarial and learnings reviewers. No cross-model reviewer ran, because no cross-model CLI is installed here; the adversarial lens ran in-process. The review's own "Ready to merge" verdict was rejected because R4 is unmet, and F0 was added. Fixes landed in7d3dbc6..github/workflows/mutation.yml:2002bf965(before #733) a run concludessuccesson a[FAIL]graded row.AGENTS.md:24mainonly" contradicts theworkflow_dispatchtrigger..github/workflows/mutation.yml:9github.run_id(reusable-mutation.yml:201), so saves never collide; the worst case is a later run restoring an older cache, which costs extra mutants, not wrong results.:234flake.nix:14README.md:22Checks at
7d3dbc6: uncachedturbo run lint --forcereports 0 warnings and 0 errors;.#packages.<system>.sfs-depsevaluates on x86_64-linux and aarch64-linux;nix flake check --no-buildpasses.Related: systemfsoftware/systemfsoftware#735
ce-compound
ce-compoundwas evaluated for this PR (mode non-interactive) and endedDocumentation skipped. Reason: the work is not verified. No graded mutation run exists, and U5 and U6 wait on B1-B6. The one solved lesson on this branch already has its document:docs/solutions/integration-issues/unversioned-public-package-is-owed-a-release.md, from #3.