Repository navigation
chore: adopt external static-analysis gates - #1005
Merged
Merged
Conversation
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
aviggiano
added a commit
that referenced
this pull request
Aug 31, 2026
…is job #1005 wired `external-static-analysis` into `release-validation.needs` and `release-gates.needs` but left the assertions in ci-config.test.ts expecting the previous two- and three-element arrays, so `main` is red on "runs the release validation lanes the policy script selects, on pull requests too". Both assertions live in one test, so the first failure masked the second. Unrelated to the rest of this branch; needed for its CI to be readable. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Aug 31, 2026
aviggiano
added a commit
that referenced
this pull request
Aug 31, 2026
Two independent classes of failure, both surfaced by gates that landed after this branch was written. Strict lint (ours). `eslint-plugin-diff` scopes the strict ruleset to changed lines, so new code gets rules existing code is grandfathered against. Replace console with process.stdout/stderr.write, remove non-null assertions in favour of guards that name what was missing, split two over-long functions, and move the new recency tests into their own file so history.test.ts returns to being untouched rather than dragging its pre-existing 2131 lines into max-lines. Workflow linters (inherited). Super-Linter lints only changed files but lints each in full, and the repo carried no linter config, so stock yamllint defaults applied to lines nobody wrote: eval-benchmarks.yml alone has 146 lines over 80 columns. Any workflow edit by anyone was failing. Add a config that relaxes only what prettier already owns or GitHub mandates. Suppress zizmor's dangerous-triggers on the publication workflow's workflow_run, whose trust model rejects non-default-branch and fork producers before anything executes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
aviggiano
added a commit
that referenced
this pull request
Aug 31, 2026
…of green (#1013) Benchmark history published nothing for 19 days while the producer workflow reported success on nearly every push: 29 of 29 green push runs since 08-13 were soft-failed incompletes. The publication gate was refusing correctly the whole time; nothing measured whether history was advancing. - Add a tokenless cohort reachability gate that runs before Modal spend, failing in seconds and naming the unreachable dependency rather than after a ~4h run that ends unpublishable. - Add the repo's first scheduled freshness monitor, plus an opt-in `eval history --max-age-days`; default behaviour is unchanged. - Annotate both silent publication no-ops without changing any readiness verdict, now pinned by tests. - Carry a failing command's reason into the collected artifact through the existing eval-failure-diagnostics channel, and close two paths where one collector-illegal log line discarded a pair's whole artifact set. - Satisfy the static-analysis gates #1005 added, including a yamllint config so workflow edits stop failing on pre-existing long lines. Closes #1012.
mrthankyou
pushed a commit
that referenced
this pull request
Aug 31, 2026
The external static-analysis gate added in #1005 fails on pre-existing test fixtures. `VALIDATE_ALL_CODEBASE` is false, so gitleaks scans changed *files* rather than changed lines: touching any part of one of these files fails the gate on content the change never edited, and `release-gates` fails with it. The fixtures are deliberate. `packages/artifacts/test/artifacts.test.ts` carries a catalogue of fifteen fake credentials, one per format, asserting that every one is rejected; `packages/security/test/sensitive-redaction.test.ts` carries another. They are the inputs the redaction tests exist to prove. One site already carried a `// secretlint-disable` for the same reason, so the repository already had the precedent. Every such line is marked with `gitleaks:allow` and a reason. Forty-three lines across five files: artifacts.test.ts 21 sensitive-redaction.test.ts 15 runtime.test.ts 4 generated-workflow-verifier.test.ts 2 verified-output.test.ts 1 An inline marker travels with the line. A line-numbered fingerprint in `.gitleaksignore` silently stops matching the moment anything is inserted above it, which turns a suppression into a surprise later. Excluding `packages/**/test/**` would also clear the failure, but that disables the gate for the files most likely to carry a pasted credential by accident. The rule stays active everywhere else, including elsewhere in these same files. No test input or assertion changes: `@ultrafuzz/security` reports 23/23 and `@ultrafuzz/artifacts` 312/324 both before and after, identical to main.
mrthankyou
pushed a commit
that referenced
this pull request
Aug 31, 2026
The external static-analysis gate added in #1005 fails on pre-existing fixtures. `VALIDATE_ALL_CODEBASE` is false, so gitleaks scans changed *files* rather than changed lines: touching any part of one of these files fails the gate on content the change never edited, and `release-gates` fails with it. The fixtures are deliberate. `packages/artifacts/test/artifacts.test.ts` carries a catalogue of fifteen fake credentials, one per format, asserting that each is rejected; `packages/security/test/sensitive-redaction.test.ts` carries another covering vendor formats. The `references` tests use spelled-out placeholders such as `ghs_examplereferencetokenvalue0123456789`. These are the inputs the redaction tests exist to prove. One site already carried a `// secretlint-disable` for the same reason. Forty-nine lines across eight files are marked `gitleaks:allow` with a reason: artifacts/test/artifacts.test.ts 22 security/test/sensitive-redaction.test.ts 17 runtime/test/runtime.test.ts 4 runtime/test/generated-workflow-verifier.test.ts 2 runtime/test/verified-output.test.ts 1 references/test/git-credential.test.ts 1 references/test/references.test.ts 1 references/test/vulnerability-database.test.ts 1 An inline marker travels with the line. A line-numbered fingerprint in `.gitleaksignore` silently stops matching the moment anything is inserted above it. Excluding `packages/**/test/**` would also clear the failure, but that disables the gate for the files most likely to carry a pasted credential by accident. The one finding in production source is fixed by rewording rather than suppressed. `sensitive-redaction.ts` explained the supplemental PEM pattern by quoting a BEGIN/END pair on one line, which reads as a private key; the prose now names the markers instead. Nothing is suppressed outside test fixtures. Verified by running gitleaks 8.28.0 over the tree: no tracked file reports a finding. Remaining hits are all in gitignored `dist/` and `dist-test/` output. `@ultrafuzz/security` reports 23/23 and `@ultrafuzz/references` 26/31, both identical to main; comments and one comment rewording only.
aviggiano
added a commit
that referenced
this pull request
Sep 1, 2026
The external static-analysis gate added in #1005 fails on pre-existing fixtures. `VALIDATE_ALL_CODEBASE` is false, so gitleaks scans changed *files* rather than changed lines: touching any part of one of these files fails the gate on content the change never edited, and `release-gates` fails with it. The fixtures are deliberate. `packages/artifacts/test/artifacts.test.ts` carries a catalogue of fifteen fake credentials, one per format, asserting that each is rejected; `packages/security/test/sensitive-redaction.test.ts` carries another covering vendor formats. The `references` tests use spelled-out placeholders such as `ghs_examplereferencetokenvalue0123456789`. These are the inputs the redaction tests exist to prove. One site already carried a `// secretlint-disable` for the same reason. Forty-nine lines across eight files are marked `gitleaks:allow` with a reason: artifacts/test/artifacts.test.ts 22 security/test/sensitive-redaction.test.ts 17 runtime/test/runtime.test.ts 4 runtime/test/generated-workflow-verifier.test.ts 2 runtime/test/verified-output.test.ts 1 references/test/git-credential.test.ts 1 references/test/references.test.ts 1 references/test/vulnerability-database.test.ts 1 An inline marker travels with the line. A line-numbered fingerprint in `.gitleaksignore` silently stops matching the moment anything is inserted above it. Excluding `packages/**/test/**` would also clear the failure, but that disables the gate for the files most likely to carry a pasted credential by accident. The one finding in production source is fixed by rewording rather than suppressed. `sensitive-redaction.ts` explained the supplemental PEM pattern by quoting a BEGIN/END pair on one line, which reads as a private key; the prose now names the markers instead. Nothing is suppressed outside test fixtures. Verified by running gitleaks 8.28.0 over the tree: no tracked file reports a finding. Remaining hits are all in gitignored `dist/` and `dist-test/` output. `@ultrafuzz/security` reports 23/23 and `@ultrafuzz/references` 26/31, both identical to main; comments and one comment rewording only. Co-authored-by: thankyou <> Co-authored-by: Antonio Viggiano <agfviggiano@gmail.com>
aviggiano
added a commit
that referenced
this pull request
Sep 1, 2026
#1019) * test: mark the fake credential fixtures the secret scanner flags The external static-analysis gate added in #1005 fails on pre-existing fixtures. `VALIDATE_ALL_CODEBASE` is false, so gitleaks scans changed *files* rather than changed lines: touching any part of one of these files fails the gate on content the change never edited, and `release-gates` fails with it. The fixtures are deliberate. `packages/artifacts/test/artifacts.test.ts` carries a catalogue of fifteen fake credentials, one per format, asserting that each is rejected; `packages/security/test/sensitive-redaction.test.ts` carries another covering vendor formats. The `references` tests use spelled-out placeholders such as `ghs_examplereferencetokenvalue0123456789`. These are the inputs the redaction tests exist to prove. One site already carried a `// secretlint-disable` for the same reason. Forty-nine lines across eight files are marked `gitleaks:allow` with a reason: artifacts/test/artifacts.test.ts 22 security/test/sensitive-redaction.test.ts 17 runtime/test/runtime.test.ts 4 runtime/test/generated-workflow-verifier.test.ts 2 runtime/test/verified-output.test.ts 1 references/test/git-credential.test.ts 1 references/test/references.test.ts 1 references/test/vulnerability-database.test.ts 1 An inline marker travels with the line. A line-numbered fingerprint in `.gitleaksignore` silently stops matching the moment anything is inserted above it. Excluding `packages/**/test/**` would also clear the failure, but that disables the gate for the files most likely to carry a pasted credential by accident. The one finding in production source is fixed by rewording rather than suppressed. `sensitive-redaction.ts` explained the supplemental PEM pattern by quoting a BEGIN/END pair on one line, which reads as a private key; the prose now names the markers instead. Nothing is suppressed outside test fixtures. Verified by running gitleaks 8.28.0 over the tree: no tracked file reports a finding. Remaining hits are all in gitignored `dist/` and `dist-test/` output. `@ultrafuzz/security` reports 23/23 and `@ultrafuzz/references` 26/31, both identical to main; comments and one comment rewording only. * test(runtime): create temporary roots that are canonical and removable Every fixture built its temporary root with `mkdtempSync(path.join(os.tmpdir(), ...))`, which has two problems that each call site had to solve and none did. The root was not canonical. On macOS `os.tmpdir()` is `/var/folders/...` and `/var` is a symlink to `/private/var`, so the runtime rejected the fixture's own root -- correctly, since that check exists to stop a component being swapped underneath a resolved path. The suite therefore failed against itself rather than against anything under test: 362 distinct failures on macOS before any change, 44 of them literally `must be canonical`. Linux is unaffected because `/tmp` is already canonical, which is why CI never saw it. The root was not removable. Sealed execution snapshots are left `dr-x------`, and unlinking an entry needs the write bit on its parent rather than on the entry itself, so `rmSync` could not remove a tree containing one. Of 39 files creating temporary roots, 25 attempted removal and 11 restored permissions first. One run left 1,232 directories and 567,065 files behind; repeated runs reached 11 GB, at which point the suite slowed from 2m30s to over 90 minutes and individual tests from tens of milliseconds to 55-85 seconds. `temporaryRoot` does both: it builds on a canonicalized tmpdir and registers the root for removal, restoring owner write permission on directories on the way down -- the same treatment `restoreRemovableDirectoryPermissions` applies in `clean.ts` (#985). `registerTemporaryPath` covers directories a fixture places beside its root rather than inside it, which root removal cannot reach. The two production sites are canonicalized for the same reason the tests are: the runtime requires canonical roots, so it should create them. Measured on macOS, `main` versus this change, default tmpdir throughout: distinct failures 362 -> 219 (no new failures; the remaining 219 all fail on main, 159 of them on the darwin /proc limitation tracked in #1011) `must be canonical` 44 -> 0 leaked directories 1,232 -> 0 leaked files 567,065 -> 0 The one directory that survives is a deliberately retained native-continuation controller root, which production removes through its own exit hook. --------- Co-authored-by: thankyou <> Co-authored-by: Antonio Viggiano <agfviggiano@gmail.com>
aviggiano
added a commit
that referenced
this pull request
Sep 1, 2026
…1025) * test: mark the fake credential fixtures the secret scanner flags The external static-analysis gate added in #1005 fails on pre-existing fixtures. `VALIDATE_ALL_CODEBASE` is false, so gitleaks scans changed *files* rather than changed lines: touching any part of one of these files fails the gate on content the change never edited, and `release-gates` fails with it. The fixtures are deliberate. `packages/artifacts/test/artifacts.test.ts` carries a catalogue of fifteen fake credentials, one per format, asserting that each is rejected; `packages/security/test/sensitive-redaction.test.ts` carries another covering vendor formats. The `references` tests use spelled-out placeholders such as `ghs_examplereferencetokenvalue0123456789`. These are the inputs the redaction tests exist to prove. One site already carried a `// secretlint-disable` for the same reason. Forty-nine lines across eight files are marked `gitleaks:allow` with a reason: artifacts/test/artifacts.test.ts 22 security/test/sensitive-redaction.test.ts 17 runtime/test/runtime.test.ts 4 runtime/test/generated-workflow-verifier.test.ts 2 runtime/test/verified-output.test.ts 1 references/test/git-credential.test.ts 1 references/test/references.test.ts 1 references/test/vulnerability-database.test.ts 1 An inline marker travels with the line. A line-numbered fingerprint in `.gitleaksignore` silently stops matching the moment anything is inserted above it. Excluding `packages/**/test/**` would also clear the failure, but that disables the gate for the files most likely to carry a pasted credential by accident. The one finding in production source is fixed by rewording rather than suppressed. `sensitive-redaction.ts` explained the supplemental PEM pattern by quoting a BEGIN/END pair on one line, which reads as a private key; the prose now names the markers instead. Nothing is suppressed outside test fixtures. Verified by running gitleaks 8.28.0 over the tree: no tracked file reports a finding. Remaining hits are all in gitignored `dist/` and `dist-test/` output. `@ultrafuzz/security` reports 23/23 and `@ultrafuzz/references` 26/31, both identical to main; comments and one comment rewording only. * fix: build temporary roots on a canonical system temporary directory `os.tmpdir()` is `/var/folders/...` on macOS and `/var` is a symlink to `/private/var`, so a root built directly on it is not canonical. Ultrafuzz deliberately rejects non-canonical roots -- that check exists to stop a path component being swapped underneath a resolved path -- so the code failed against its own temporary directories. Linux is unaffected because `/tmp` is already canonical, which is why CI never saw this. #1019 fixes this for `packages/runtime/test`. The same defect was present in 92 files across ten packages, the release-validation script, and the CI scripts, including seven production files. Those are worth fixing regardless of platform: they encode an assumption that the system temporary directory is canonical, and no platform guarantees that. Measured on macOS, `main` versus this change, per package: @ultrafuzz/modal 440 -> 492 passing (52 fixed) @ultrafuzz/dashboard 16 -> 34 passing (18 fixed) @ultrafuzz/artifacts 312 -> 324 passing (12 fixed) @ultrafuzz/cli 111 -> 116 passing (5 fixed) @ultrafuzz/references 26 -> 31 passing (5 fixed) 92 tests fixed, no new failures. `@ultrafuzz/config`, `@ultrafuzz/prompts`, `@ultrafuzz/topology`, `@ultrafuzz/evals`, `@ultrafuzz/evmbench` and `@ultrafuzz/security` passed before and still pass. The failures named the cause directly, for example: Error [ArtifactPathError]: generated test file root must be canonical: /var/folders/... Error: prompt schema destination crosses a symlink: /var `scripts/validate-packed-install.mjs` built its consumer and initialized project under the same root, so `pnpm validate:pack` failed on macOS with `SYMLINK_PATH: Topology path contains a symlink component: /var` before it validated anything. `packages/runtime/test/**` and the two runtime source files are left to #1019 so the two changes stay independently mergeable. --------- Co-authored-by: thankyou <> Co-authored-by: Antonio Viggiano <agfviggiano@gmail.com>
aviggiano
added a commit
that referenced
this pull request
Sep 1, 2026
…tor paths (#1016) * test: mark the fake credential fixtures the secret scanner flags The external static-analysis gate added in #1005 fails on pre-existing fixtures. `VALIDATE_ALL_CODEBASE` is false, so gitleaks scans changed *files* rather than changed lines: touching any part of one of these files fails the gate on content the change never edited, and `release-gates` fails with it. The fixtures are deliberate. `packages/artifacts/test/artifacts.test.ts` carries a catalogue of fifteen fake credentials, one per format, asserting that each is rejected; `packages/security/test/sensitive-redaction.test.ts` carries another covering vendor formats. The `references` tests use spelled-out placeholders such as `ghs_examplereferencetokenvalue0123456789`. These are the inputs the redaction tests exist to prove. One site already carried a `// secretlint-disable` for the same reason. Forty-nine lines across eight files are marked `gitleaks:allow` with a reason: artifacts/test/artifacts.test.ts 22 security/test/sensitive-redaction.test.ts 17 runtime/test/runtime.test.ts 4 runtime/test/generated-workflow-verifier.test.ts 2 runtime/test/verified-output.test.ts 1 references/test/git-credential.test.ts 1 references/test/references.test.ts 1 references/test/vulnerability-database.test.ts 1 An inline marker travels with the line. A line-numbered fingerprint in `.gitleaksignore` silently stops matching the moment anything is inserted above it. Excluding `packages/**/test/**` would also clear the failure, but that disables the gate for the files most likely to carry a pasted credential by accident. The one finding in production source is fixed by rewording rather than suppressed. `sensitive-redaction.ts` explained the supplemental PEM pattern by quoting a BEGIN/END pair on one line, which reads as a private key; the prose now names the markers instead. Nothing is suppressed outside test fixtures. Verified by running gitleaks 8.28.0 over the tree: no tracked file reports a finding. Remaining hits are all in gitignored `dist/` and `dist-test/` output. `@ultrafuzz/security` reports 23/23 and `@ultrafuzz/references` 26/31, both identical to main; comments and one comment rewording only. * feat(runtime): support darwin via volfs inode-rooted paths Workflow submission was Linux-only. Snapshot publication, cleanup, and permission sealing all anchor traversal to an open directory descriptor by way of /proc/self/fd/<n>, so that resolving root/a/b/c cannot be redirected by renaming or symlinking a component mid-flight. macOS has no /proc. Its fdesc /dev/fd/<n> entry for a directory stats with the correct inode but reports devfs's own st_dev, cannot be reopened with O_DIRECTORY, and cannot be traversed at all (/dev/fd/<n>/child is ENOENT). directoryDescriptorPath returned it anyway, on the strength of isDirectory() alone, and verifiedDirectoryDescriptorPath then rejected it with "workflow execution snapshots descriptor path changed at the controller command boundary" -- a message describing tampering, for a platform that simply has no /proc. macOS does expose volfs. /.vol/<dev>/<ino> names a path rooted at an inode rather than at a name, which is the property this code needs: renaming or symlink-swapping any component cannot redirect resolution. Traversal, mkdir, O_NOFOLLOW|O_DIRECTORY open, O_CREAT|O_EXCL, symlink, and chmod all work through it. The descriptor stays open for as long as the path is used, so the inode cannot be recycled and the volfs path resolves to exactly the directory that was opened. - Offer /.vol/<dev>/<ino> as a descriptor-path candidate, and apply the existing isDirectory + device + inode identity check during selection rather than only afterwards. Nothing is relaxed to make volfs pass: the same check that rejects /dev/fd accepts volfs. - Use volfs for the cross-process descriptor path too. A volfs path is process-independent, so unlike /proc/<pid>/fd it satisfies that requirement on macOS. - Canonicalize through the tracked lexical path where realpath(3) is needed, since volfs paths intentionally have no realpath resolution. Every such site already asserts that its access and lexical paths name the same device and inode. - Verify the sealed Bun module root by comparing the held descriptor's device and inode when /proc is absent, instead of realpath equality. Linux is unchanged: the /proc candidates are tried first and win, and the added identity check is a strengthening /proc already satisfies. Verified by running the selection logic on both platforms; Linux resolves to the same /proc/self/fd/<n> and /proc/<pid>/fd/<n> strings as before. * feat(runtime): address the detached engine snapshot by inode on darwin The controller hands the execution snapshot to the detached engine as fd 3 and rewrites paths to /proc/self/fd/3, with the parent addressing the same directory as /proc/<pid>/fd/<n>. macOS has neither, so the engine died before admission on: ENOENT: /proc/self/fd/3/controls/bunfig.toml A volfs path is process-independent, so one /.vol/<dev>/<ino> string is valid in both parent and child and needs no pid or fd number. Four helpers centralize what were nine scattered /proc literals, and ultrafuzzBunStartupArgs becomes ultrafuzzBunStartupArgsFor(root) because the root is no longer a compile-time constant. fd 3 inheritance is unchanged: the child still receives the directory atomically and the held descriptor still pins the inode against reuse. Only the spelling used to address it differs by platform. Two realpath comparisons became inode comparisons, which volfs forced but which is what those checks already meant -- realpath equality was the proxy. Because this changes the patched shape of the resume snapshot transfer, the release Ultrafuzz shipped before it has to stay recognizable. SMITHERS_CLI_RESUME_SNAPSHOT_TRANSFER_PATCH was derived from its predecessor by dropping `--preserve-symlinks`; substituting the inline bun startup arguments for a helper call removed that replacement's target, so the derivation became a no-op and the patch equalled its own predecessor. classifyRequiredSmithersPatch treats that as incompatible, and an installation patched by the current release would have failed on its next launch with "pinned workflow runner resume snapshot transfer implementation is incompatible". The predecessor keeps the inline literal it has always had, the current patch is derived from the post-0.35.0 form, and that form is registered as a second predecessor so both previously written shapes are recognized and rewritten in place. The compatibility-patcher test asserted that the patched runner contains the /proc bun-startup literals. That is the assumption this removes, so it now checks that both patches route through the helper, that the anchor defines it against a root parameter, and that the Linux spelling of that root is still /proc/self/fd/3. * test(runtime): gate the snapshot capability tests on the capability The snapshot capability tests were gated on `fs.existsSync("/proc/self/fd")`, so both of them skipped on darwin whether the runtime worked or not. That is the only reason this change appeared to fix nothing: the suite never ran the code it repairs. The /proc mount is a proxy for the capability, not the capability itself. Probe instead: open a directory, then require that the descriptor path both names that exact directory and resolves a child through it. A path that merely stats is not enough, which is what makes /dev/fd fail the probe rather than pass it and break later. On darwin these two tests now run, and they are the regression test this work was missing: pristine main 0/2 pass -- "workflow execution snapshots descriptor path changed at the controller command boundary" with this work 2/2 pass Linux is unaffected: /proc/self/fd is the first candidate and satisfies the probe, so the tests run there exactly as before. The remaining eleven /proc gates in runtime.test.ts, smithers-executable-capability.test.ts, and generated-workflow-verifier.test.ts are deliberately left alone. Those tests read /proc directly in their bodies -- enumerating /proc/self/fd, or building /proc/<pid>/fd/<n> pathnames -- so the gate is describing what the test itself needs rather than what the runtime supports. Widening it there only runs Linux-specific assertions on a platform that cannot satisfy them. --------- Co-authored-by: thankyou <> Co-authored-by: Antonio Viggiano <agfviggiano@gmail.com>
aviggiano
added a commit
that referenced
this pull request
Sep 28, 2026
Since the external static-analysis gate was adopted (#1005), super-linter lints every changed Markdown file with MD013 at 400 characters. CHANGELOG.md keeps one entry per line, and 43 existing entries are longer than that, so any change to the file fails `External static analysis`. That also fails `release-gates` and skips the release validation lanes on the pull request. No commit has changed CHANGELOG.md since the gate landed. Disable MD013 for this file only; super-linter's pinned markdownlint config otherwise passes it unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Sep 28, 2026
Merged
aviggiano
added a commit
that referenced
this pull request
Sep 29, 2026
Super-linter's markdownlint (MD013, 400 columns) validates every changed Markdown file in full. The gate landed (#1005) after CHANGELOG.md was last edited, and nearly every entry is one line longer than 400 columns, so any pull request that adds a changelog entry fails "External static analysis" on the file's existing lines. Ignore CHANGELOG.md the same way LICENSE.md already is. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
aviggiano
added a commit
that referenced
this pull request
Sep 29, 2026
Super-linter's markdownlint (MD013, 400 columns) validates every changed Markdown file in full. The gate landed (#1005) after CHANGELOG.md was last edited, and nearly every entry is one line longer than 400 columns, so any pull request that adds a changelog entry fails "External static analysis" on the file's existing lines. Line length is the only rule the file breaks under super-linter's configuration, so disable just MD013 for this file and keep every other Markdown rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Sep 29, 2026
Merged
aviggiano
added a commit
that referenced
this pull request
Sep 29, 2026
Since the external static-analysis gate was adopted (#1005), super-linter lints every changed Markdown file with MD013 at 400 characters. CHANGELOG.md keeps one entry per line, and markdownlint reports 42 existing entries on main as longer than that, so any change to the file fails `External static analysis`. That also fails `release-gates` and skips the release validation lanes on the pull request. No commit has changed CHANGELOG.md since the gate landed. Disable MD013 below the title of this file only, using the same directive line that #1169, #1172 and #1181 add, so the branches do not end up with two spellings of it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
aviggiano
added a commit
that referenced
this pull request
Sep 29, 2026
…y ceiling #1005 deliberately added no baseline or suppression registry, and #960 asks for a complexity ceiling in the style of modem-dev/hunk#861: one global maximum set at today's worst function, with nothing grandfathered, lowered as hotspots are simplified. Drop eslint-suppressions.json and the always-on size budgets, keep the diff-limited strict budgets for changed lines, and fail any function above complexity 90 (synchronizeLinkedWorkflowRun is at 90 once the pending simplification PRs land). The changelog entry moves to the consolidated release notes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
aviggiano
added a commit
that referenced
this pull request
Sep 29, 2026
…r-render cost drops (#1168) * fix(runtime): literal braces in prompt text no longer fail the workflow render renderAgentPrompt substituted the operator and task prompts into the trusted agent-prompt template and then regex-scanned the whole result for leftover `{{word}}` placeholders. Inserted text that merely contained such a sequence threw inside the Smithers render: an escaped `\{{word}}` example in a prompt template (the prompt renderer emits it as literal `{{word}}`), the same escape inside a dynamic item value (kept verbatim), or an operator `--prompt` note. Every render builds every task's prompt, so the run failed, and failed again on every resume. Check only the template's own placeholders, inside the replace callback, as renderAgentPreambleTemplate already does. A template placeholder with no value still throws, and now names the placeholder. The dynamic prompt renderer also resolves `{{...}}` inside goal-plan replacement values, and an unbound name there throws in the same render. The goal-plan contract now rejects `{{` in replacement values, which are plain-text labels, so that failure lands on goal-plan's own verify instead of on every render. The check is a zod refinement; goal-plan.schema.json is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(runtime): run the JSON validator preflight once per engine process prepareArtifactMirror spawned `ultrafuzz json validate` against the smoke fixture in every prepare, in every agent-attempt reset, when an agent is built after a controller restart, and again in the zero-retry verify task. The trusted launcher's cold start was measured at ~35 s under contention (#1026), so each spawn was another chance to fail an attempt, including one whose agent work had already finished. What the spawn proves -- that this process can launch the agent-facing validator -- does not depend on the task: materializePromptSchemas has just digest-checked the workspace's schema copy, and start-run already runs the trusted-launcher preflight at launch and resume. Remember the first success in the engine process. A failure is not remembered, so the next caller spawns again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * perf(runtime): cut per-process and per-render cost of the generated workflow agent-registry.ts and smithers.ts imported the TypeScript compiler at module load, and both are reachable from @ultrafuzz/runtime's index. Only registry analysis (validate and init) and the controller-refresh helper that only tests call ever use it. Require it at first use instead. The saving lands in processes that import the runtime without smthrs: the ultrafuzz CLI, including every agent `ultrafuzz json validate` call. Smithers engine processes still load the compiler: the generated workflow imports smthrs, whose index re-exports @smthrs/scorers, and two scorer modules import typescript at module load. Importing the built runtime index alone on this host went from 528-547 ms / 248-250 MB RSS to 409-437 ms / 196-198 MB under Node 24, and from 449-483 ms / 252-261 MB to 336-351 ms / 209-213 MB under Bun 1.3.14 (5 runs each). Changing the parameter type on topLevelNameIsBound's signature makes the strict diff lint report that function's existing complexity, so its import-clause check moves into a helper with the same conditions. materializeDynamicRuntime runs on every render and rewrote tasks.json and graph.json, with fsyncs, even when it re-derived the bytes already on disk. Skip the write in that case. taskSpecsFromCompiled looked every task up with serializedTaskSpecs.find; index the specs by id once per call instead. At the default topology's 65 static tasks the difference is not measurable. Add a test that compiles the packaged default topology and holds the generated workflow under 2.3 MB, measured with a fixed-length project root (about 2.06-2.07 MB today, depending on the checkout path), so the size #1146 describes cannot grow silently. Refs #1146 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: changelog for render robustness and runtime footprint Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: exempt CHANGELOG.md from the markdown line-length rule Since the external static-analysis gate was adopted (#1005), super-linter lints every changed Markdown file with MD013 at 400 characters. CHANGELOG.md keeps one entry per line, and markdownlint reports 42 existing entries on main as longer than that, so any change to the file fails `External static analysis`. That also fails `release-gates` and skips the release validation lanes on the pull request. No commit has changed CHANGELOG.md since the gate landed. Disable MD013 below the title of this file only, using the same directive line that #1169, #1172 and #1181 add, so the branches do not end up with two spellings of it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(runtime): the post-agent verify pass no longer preflights the validator CLI finalizeAndVerifyArtifacts calls prepareArtifactMirror with pinnedSubmodules "verify", and that pass still ran the `ultrafuzz json validate` preflight. Verify checks the finished agent's outputs in-process and never runs the agent-facing CLI, and its task has no retry. The per-process memo only helps later callers: after an engine restart, the first preflight in the new process can be the verify of an attempt whose agent had already finished, and a CLI cold start that timed out there (the trusted launcher measured ~35 s under contention in #1026) failed verification and discarded that work. Skip the preflight in the verify pass. prepare:* and the reset before each agent attempt, which run ahead of an agent that uses the CLI, keep it. The new lifecycle test runs the production preparation body with the options finalizeAndVerifyArtifacts passes. Without this change it counts three preflights instead of two. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: state where the TypeScript saving and the goal-plan brace rule apply The comments, the footprint test and the changelog said Smithers engine processes stop loading the TypeScript compiler. They do not: the generated workflow imports smthrs, whose index re-exports @smthrs/scorers, and its sideEffectAnalysis and workflowUiCompliance modules import typescript at module load. The saving lands in ultrafuzz CLI processes, including every agent `ultrafuzz json validate` call. The prompt-variables reference and the changelog also said the goal-plan@1 contract rejects `{{` in replacement values. Only goal-plan's own verification (and the evals goal-plan reader) run that zod rule; `ultrafuzz json validate` and `ultrafuzz artifact validate` accept such a plan. Say so, replace the exact generated-workflow byte count, which does not reproduce across environments, with a range, and describe the preflight as running until its first success. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(runtime): cover imported Object bindings in registry shadowing importClauseBindsName, split out of topLevelNameIsBound on this branch, had no test: the registry-shadowing test only declared Object locally. Add default, namespace, named, aliased and default-plus-named imports of Object, each of which must stop Object.freeze from being read as the global, and an unrelated named import that must not. Removing any one of the helper's three checks, or making it match every named import, fails the test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
aviggiano
added a commit
that referenced
this pull request
Sep 29, 2026
…nused agent profiles (#1179) * perf(runtime): write execution-snapshot files with their final mode and flush each once Snapshot publication wrote every file with mode 0400 and fsynced it, then the permission seal reopened every file, fchmodded it (to 0500 for executables, otherwise to the 0400 it already had) and fsynced it again. A launch of the test fixture's 12,552-file snapshot therefore issued 27,876 fsyncs, two per file plus two per directory, and launch time is fsync-bound. writeSnapshotFile now creates each file with its final mode and sets that mode through the creating descriptor (the umask can clear creation bits) before its single flush, so the bytes and the mode are durable together, as the second flush previously made them. The permission seal now only makes directories read-only; the publication verification that already follows it still checks every entry's type, mode, link count and bytes. The same fixture now issues 15,324 fsyncs (one per file plus two per directory). The new test republishes a launched run's snapshot and bounds its fsync calls at one per file plus two per directory; origin/main fails it with 27,876 flushes for 12,552 files in 1,386 directories. Refs #921 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(runtime): doctor requires only the agent CLIs a run can dispatch to doctor required the executable of every configured model profile, so a fresh `ultrafuzz init` on a Codex-only host reported "needs attention" because the scaffold's opt-in Claude, Kimi and Pi profiles were not installed, although no node would run them. It now requires an agent's CLI only when the selected topology or its [retry] agents fallback chain can dispatch to that agent (the same selection the OpenRouter credential check already used). Other configured profiles' CLIs are still probed and listed, as not required, and the human output marks them "(not required)". Agents that share a CLI (Codex and OpenRouter, Claude and DeepSeek) require it if any of them is selected. doctor also built DOCTOR_WORKFLOW_ENGINE_* diagnostics and check statuses for the project-local engine and then discarded them, reporting both checks as "unknown". The builders are deleted; layout_status and the per-patch posture are still reported, and the reference docs no longer list the five codes that were never emitted. Launch and resume install the workflow engine controller under the OS temporary directory, and a native resume keeps its install there for the detached engine (#921 cost 1: a tmpfs /tmp exhausted a host's memory). A new temporary-directory check warns, without failing the verdict, when that directory is a tmpfs or has under 2 GiB free, and reports how many ultrafuzz-controller-* directories it holds and their total size. It never removes them, because a live engine may still use them. Refs #921 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(runtime): keep refreshed controllers out of the governed target identity `resume --refresh-controller` renders its current controller into <project>/.smithers/continuations/<uuid>/, but that directory was missing from controllerOwnedGovernancePaths. Unless the project ignores .smithers, the rendered files are untracked target files: the next launch in that project records the target as dirty, which a private campaign (the default policy) and every cloud launch reject, and the changed worktree digest invalidates disclosure acknowledgements computed for the target. The directory is now controller-owned, like .smithers/workflows. The new test renders files in that layout and checks the target identity is unchanged; origin/main reports the target dirty. Refs #921 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(runtime): parse the control seal with an item limit that covers its schema Runtime documents are parsed with a 100,000-item limit that the strict JSON parser counts across the whole document. The control seal's schema admits 100,000 execution files plus three identity arrays of up to 100,000 entries each, and launch writes the seal after schema validation alone. A closure near the execution-file bound plus the run's task bindings would therefore produce a seal that every later command fails to parse. (An earlier measurement put the production closure at about 51,000 files; it was not re-measured for this change.) The seal is now parsed with a 400,000-item limit, the schema's total; its property total (four per execution file plus 35 fixed) already fits the default limit. Byte limits are unchanged. The new test parses a seal with the schema's maximum execution files and the fixture's bindings; origin/main rejects it with "JSON exceeds the item limit of 100000". Refs #921 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: changelog entry for launch I/O and doctor fixes Refs #921 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: disable only MD013 for the one-entry-per-line changelog Super-linter's markdownlint (MD013, 400 columns) validates every changed Markdown file in full. The gate landed (#1005) after CHANGELOG.md was last edited, and nearly every entry is one line longer than 400 columns, so any pull request that adds a changelog entry fails "External static analysis" on the file's existing lines. Line length is the only rule the file breaks under super-linter's configuration, so disable just MD013 for this file and keep every other Markdown rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(runtime): count only required commands in doctor's toolchain summary Doctor now lists the CLIs of configured but unselected agents with required: false, so the toolchain summary's "N required commands available" counted them too. On a fresh init with only Codex installed it reported 7 required commands when 4 are required. The selection test also gains the case the reviewers found missing: a selected Codex profile beside an unused OpenRouter profile keeps codex required. Because configured agent refs are sorted, the existing OpenRouter-only case could not tell "any requirer wins" from "last writer wins"; this case fails under the latter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor(runtime): parse every runtime document with one 400,000-item limit The previous commit gave the control seal its own limits constant, a schema-ID import and a ternary. Raising the single shared item limit is the same fix in one number: runtime documents stay bounded by the unchanged 128 MiB parse cap (and the seal by the 64 MiB control-file read cap), and 400,000 is what a seal whose arrays are all at their schema bounds holds (100,000 execution files plus three identity arrays of 100,000), with 400,035 properties under the unchanged 500,000 limit. The seal test's comment now claims only what it fills: execution_files at its bound. Filling the three identity arrays too would pin the 400,000 figure, but their schema validation grows quadratically (uniqueItems on $ref items): with 30,000 identities per array it alone took 6.1 s, and a test with every array at its bound ran for 85 s, so the test does not. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: use the changelog MD013 directive sibling PRs add #1181, #1172 and #1169 add `<!-- markdownlint-disable MD013 -->` right after the changelog title. Adding the identical hunk here instead of a disable-file comment at the end of the file means a merge of any two of these PRs keeps one directive rather than two. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(runtime): make the snapshot tests exercise the phases they name - "publishing an execution snapshot flushes each file once" now counts only fsyncs of regular-file descriptors and asserts that count equals the published file count (12,552 on the fixture; main flushes 25,104). The old total bound also encoded how directories are flushed. - The leaf-swap test's hook now fires on the write-time fchmod, since the seal no longer opens files, so it is renamed after what it checks. - The parent-swap test's hook fires only on a directory fchmod, so the swap lands in the directory seal after every file is written, as it did on main. Without that, no test swapped anything while directories were being sealed. - The seal's doc comment now says what publication verification checks for each entry type instead of "every entry's type, mode, link count, and bytes". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
aviggiano
added a commit
that referenced
this pull request
Sep 29, 2026
…chet complexity with a lint baseline (#1184) * fix(config): accept smol-toml 1.9 tables when loading project config smol-toml 1.9.0 (released 2026-09-22) builds every parsed table with Object.create(null). The config loader treats only objects whose prototype is Object.prototype as tables, and it sorts Object.entries(table) with the default comparator, which stringifies each value. A packed install has no lockfile and resolves the ^1.7.1 range to 1.9.0, so `ultrafuzz init` failed while loading the shipped defaults ("project must be a table; run must be a table; ..."). This is the packed-install failure that turned the package-gates lane red in main run 36495460966. Rebuild the parsed document with structuredClone, which returns the same data as ordinary objects, so the loader sees what it saw with 1.7. `__proto__` keys stay own data properties. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ci: run every release validation lane on pull requests and never cancel main runs Pull requests ran only the five runtime lanes. package-gates, cli and benchmark-history-typecheck (which holds the workspace typecheck) first ran after merge, so their regressions landed on main: the latest main run, 36495460966, fails package-gates. Every lane now runs on every event. The lane table keeps its test that it runs each gate scripts/validate-release.mjs defines exactly once; the pull-request filter, PULL_REQUEST_REQUIRED_GATES and the --event argument are gone. The lanes no longer wait for the build and super-linter jobs, and the PR-only runtime and CLI smoke runners are deleted because the lanes run those suites in full. release-gates still requires every job. Measured on existing runs: a pull request took about 60 minutes (8.0 min for build and smoke, then 51.5 min for the slowest lane in run 36279711018); on the latest main push the new PR lanes took 12.9 (package-gates), 41.5 (cli) and 9.8 minutes against 26.8-39.5 minutes for the runtime lanes. All pushes to main shared one concurrency group; 24 of the last 40 main push runs were cancelled (as of 2026-09-29). cancel-in-progress: false alone would not stop that, because GitHub also cancels a pending run in the group when a newer run queues, and main pushes arrive in bursts (three within 9 seconds on 2026-09-28). Runs other than pull requests now get their own group, keyed by github.run_id. Delete the ci.yml line-by-line assertions in packages/modal/test/ci-config.test.ts and the timeout_minutes === 120 change detector. The remaining guard parses ci.yml and checks that release validation is not gated off pull requests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ci: run the release validation lanes under eatmydata Every runtime and CLI test that launches a run copies a sealed execution snapshot and fsyncs each file, twice (at write and again when the snapshot is sealed). The deep analysis measured 55,998 fsyncs taking 222 s of a 163-261 s test locally; under eatmydata the same test took 23-33 s, and a CLI test went from 169 s to 35 s. A CI runner is discarded after the job, so durability across a crash buys nothing there. Install eatmydata in the release-validation job and run validate:release under it; its LD_PRELOAD reaches every child the gate commands spawn. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ci: report unused exports without blocking the build `pnpm -w knip` leaves out knip's exports, types and duplicates categories, so unused exports accumulate unseen; on this tree knip reports 52 unused exports and 38 unused exported types. Report them in a continue-on-error step that reuses the pinned knip script. Several open pull requests delete dead code; once they land, these categories can move into the blocking knip step. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: give vitest packages a 30 s default test timeout config, topology, prompts, evals, evmbench and modal run a bare `vitest run` with no config file, so every test gets vitest's 5 s default. Main went red on it in runs 34967618488 (modal ci-config and modal-documents: "Test timed out in 5000ms") and 34634052856 (modal worker-result), and #1126 raised individual cases instead. Pass --testTimeout=30000 in the six package test scripts. Cases that set their own timeout keep it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(cli): remove each test's temporary project when the test ends cli.test.ts, lifecycle-commands.test.ts and audit-profile-commands.test.ts created their project with mkdtemp and never removed it. On main, one run- launching test ("status surfaces a terminal product and live workflow lifecycle divergence") left 446 MB and 34,091 entries in TMPDIR; the sealed snapshot directories are mode dr-x, so a plain `rm -rf` cannot delete them. A CI lane accumulated every test's run directories until the job ended. temporaryRoot(prefix, t) creates the canonical directory and registers a t.after hook that restores owner write permission on the way down and removes it, together with the `<root>-fake-bin` directory the fake engine fixtures create beside it. The tests pass their context to tempProject. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * build(lint): enforce complexity and size budgets on all code against a recorded baseline The complexity and size rules ran only in the diff-limited strict lint, which reports a message only when its line changed. ESLint reports these rules on a function's first line (max-lines on the first line past the limit), so adding branches inside an over-budget function passed, while editing only its signature failed, forcing an unrelated refactor on a fix. Move complexity, max-depth, max-lines, max-lines-per-function, max-nested-callbacks, max-params and max-statements into the always-on config, with the same relaxed values for tests and templates, and record the 1,003 existing violations (197 files; 701 of them in 108 packages/*/src files) with ESLint's bulk suppressions in eslint-suppressions.json. `pnpm -w lint` now fails when a file gains a violation of a rule and when a recorded count is higher than the file's violations; `pnpm -w lint:prune` lowers the counts. The diff-limited strict lint keeps the type-aware strict rules, no-console and the TODO/FIXME check. It passes --pass-on-unpruned-suppressions because it sees only changed lines, so its counts are below the recorded ones by design. ESLint writes the suppressions file without a final newline, so prettier ignores it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: record the CI, lint baseline and smol-toml changes in the changelog Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ci: stop super-linter failing every edit to CHANGELOG.md on line length Super-Linter lints each changed Markdown file in full with its default markdownlint rules, including MD013 at 400 characters. Four of the 109 tracked Markdown files have longer lines: CHANGELOG.md keeps each entry on one line (44 such lines), and docs/reference/agent-adapter-boundaries.md, docs/explanation/provider-harness-research.md and docs/CODE_OF_CONDUCT.md have long table rows or paragraphs. Any pull request that touched one of them failed `External static analysis` on lines it did not change, and no merged pull request has edited CHANGELOG.md since Super-Linter was added. Use Super-Linter's default markdownlint rules from the pinned v8.7.0 template, with MD013 off, as .github/linters/.yamllint.yml already does for YAML line length. markdownlint-cli 0.49.0 (the version Super-Linter runs) reports 46 MD013 errors on this branch's changed Markdown with the default template and none with this file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(modal): stop pinning the package test script to an exact string The smoke-isolation test asserted `scripts.test === "vitest run"`, so adding --testTimeout=30000 failed package-gates in this pull request's first run. The property the test protects, that the unit-test script never runs the real Modal smoke, is still asserted by `not.toContain("smoke")` two lines later. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: note the Super-Linter line-length change in the changelog Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(cli): check that temporaryRoot removes a sealed tree and its fake-bin sibling The per-test cleanup was only measured, so a regression would bring the temporary-directory leak back silently. The new test builds the shape a launched run leaves (read-only files in dr-x directories) plus the `<root>-fake-bin` sibling inside a subtest and asserts both are gone once the subtest ends. It fails if the helper skips restoring owner write permission (the hook throws EACCES) or skips the sibling. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ci: stale lint suppressions no longer fail lint New violations still fail because a file's count for a rule rises above the recorded count. Fixed violations leave a stale count, which lint:prune removes; failing on them would make every parallel pull request that deletes code rewrite eslint-suppressions.json and conflict with the others. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * build(lint): lint:fix reuses lint's flags, so stale counts no longer fail it `pnpm -w lint` passes --pass-on-unpruned-suppressions, so a fixed violation whose count was not pruned is accepted. `lint:fix` repeated the file globs without that flag, so in exactly that state it applied its fixes and then exited 2 with "There are suppressions left that do not occur anymore". Defining it as `pnpm -w lint --fix` keeps the two scripts from drifting. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: describe the lint ratchet as it behaves when a fix is not pruned Since lint passes --pass-on-unpruned-suppressions, a recorded count only goes down when someone runs `pnpm -w lint:prune`. Until then the room a fixed violation leaves lets a new violation of the same rule in the same file pass. contributing.md, the eslint.config.js comment and the changelog said a new violation always fails, and contributing.md promised periodic pruning on main that nothing performs. They now state the actual rule: lint fails when a file has more violations of a rule than its recorded count. The changelog also claimed every CLI test deletes its temporary project. Only the tests in cli.test.ts, lifecycle-commands.test.ts and audit-profile-commands.test.ts do; those include every CLI test that launches a run, so the entry now says that. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ci: stop the unused-exports report annotating every run as failed The informational knip step exited 1 whenever it found anything, which is every run until the dead-code removals land. continue-on-error kept the job green, but each Build gates check still carried a "Process completed with exit code 1." failure annotation. --no-exit-code (knip 6.33.0) prints the same report (52 unused exports, 38 types, 4 duplicates on this tree) and exits 0. continue-on-error stays so a knip crash in this step still cannot block. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ci: install eatmydata only when the runner lacks it, and scope what it covers The lane comment and docs/reference/development.md said eatmydata makes fsync a no-op for the whole lane. It does so in the test processes, which is where startRun and runCli copy and fsync the sealed snapshot, but smithersCommandEnv rebuilds each Smithers engine child's environment from an allowlist that has no LD_PRELOAD, so engine processes still sync. `sudo apt-get install -y eatmydata` without `apt-get update` only worked because the current image already ships the package. GitHub's notice on this PR's Build gates job says ubuntu-latest migrates to Ubuntu 26 from 2026-10-19; on an image without eatmydata and without package lists, that install would fail every lane. The step now skips apt entirely when eatmydata is present, as it is today, and otherwise updates the index before installing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(ci): catch step-level pull-request gating of release validation The guard parsed ci.yml but checked only the release-validation job's own `if`. Adding `if: github.event_name != 'pull_request'` to the "Validate release lane" step, the step that runs the suites, still passed it; the text guard it replaced caught that. It also pinned the exact `if` string of the release-gates requirement step, so an equivalent rewrite failed it. The guard now rejects an event or pull_request condition on the job and on every one of its steps, and checks that the requirement step tests `needs.release-validation.result` without an event condition. Mutations run against the old and new test: a step-level PR `if` passes the old guard and fails the new one; a job-level PR `if` and an event-gated requirement step fail both; wrapping the requirement condition in `${{ }}` fails only the old. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * build(lint): replace the suppression baseline with a global complexity ceiling #1005 deliberately added no baseline or suppression registry, and #960 asks for a complexity ceiling in the style of modem-dev/hunk#861: one global maximum set at today's worst function, with nothing grandfathered, lowered as hotspots are simplified. Drop eslint-suppressions.json and the always-on size budgets, keep the diff-limited strict budgets for changed lines, and fail any function above complexity 90 (synchronizeLinkedWorkflowRun is at 90 once the pending simplification PRs land). The changelog entry moves to the consolidated release notes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 2, 2026
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
typescript-eslintstrict type-checked rules plus native complexity/size rules to changed code througheslint-plugin-diffThis deliberately adds no custom analyzer, baseline, suppression registry, metric snapshot, or generated checking code. The resulting patch is 245 additions and 716 deletions (net -471 lines), and all production source changes are deletions.
Validation
pnpm install --frozen-lockfilepnpm -w format:checkpnpm -w lintESLINT_PLUGIN_DIFF_COMMIT=origin/main pnpm -w lint:strict:cipnpm -w knippnpm -w buildpnpm -w sizegit diff --checkFixes #997
Greptile Summary
The PR adopts external static-analysis gates and removes declarations, files, and dependencies identified as unused.
Confidence Score: 5/5
The PR appears safe to merge.
No blocking failure remains; the previously reported masked comparison-revision failure is fixed by enabling pipeline failure propagation.
Important Files Changed
Reviews (3): Last reviewed commit: "ci: fail strict lint on invalid diff bas..." | Re-trigger Greptile