Skip to content

fix(ci): clear the lint, test, and doc gates - #1476

Closed
John-David Dalton (jdalton) wants to merge 1534 commits into
mainfrom
jdalton/fix-main-ci
Closed

fix(ci): clear the lint, test, and doc gates#1476
John-David Dalton (jdalton) wants to merge 1534 commits into
mainfrom
jdalton/fix-main-ci

Conversation

@jdalton

@jdalton John-David Dalton (jdalton) commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Actions needed

  • Review and merge when CI is green. Auto-merge is deliberately NOT enabled: this repo's main ruleset has no required status checks, so --auto would merge immediately instead of waiting for CI. A CI-repair PR should not land unverified.
  • Decide on a fleet cascade run. Two of the five failures on main are NOT fixable here — see What this does not fix below. main stays red on the Check job until a cascade lands.

What was red

main has been failing since before today's merges. The same failure set appears at 0bd8b9e98 and at fb25a3ffe, so none of it came from a recent PR. Five independent causes; this PR fixes the three that live in repo-owned code.

1. lint — 18 max-comment-block-lines errors across 14 files

A newly cascaded rule caps an inline comment block at 20 lines. Nothing is suppressed and the rule is untouched — each site is restructured on its own merits:

treatment sites
relocated to a doc cmd-manifest-cdxgen.mts (~70 lines of pasted cdxgen --help)
split at paragraph boundaries bazel-repo-discovery.mts, external-tools-install.mts, meow.mts
repaired damaged content npm-packages.mts (×2), vfs-extract.mts
trimmed to the contract spawn.mts, builder.mts (×2), checkpoint-manager.mts, platform-targets.mts, compress-facts.mts, cli-execution.mts (×2), workspace-helper.mts, basics/vfs-extract.mts

Two of these turned up real defects rather than just long prose:

  • dlx/vfs-extract.mts had extractExternalTools' docblock stranded above MAX_EXTRACTION_DEPTH instead of above the function. It now sits on the function it documents.
  • npm-packages.mts had two docblocks shredded by an earlier JSDoc reflow. One lost its node_modules/ archive tree into a bogus @cyclonedx JSDoc tag, so half the tree rendered as an unknown tag's body. Both are rewritten as prose saying the same thing.
2. Test — five assertions reading the wrong argument index

perform-reachability-analysis.mts:288 calls spawnCoanaDlx(coanaArgs, { … }) with two arguments. Two test files read the options bag at mock.calls[0][2], which is always undefined, so every one threw TypeError: Cannot read properties of undefined. Production is correct; the tests move to index 1.

The diagnosis I started from named one assertion in perform-reachability-analysis-coana.test.mts. There are five, across two files — four more in the sibling perform-reachability-analysis.test.mts. Only one surfaced in CI because the Test job shards: that run executed 55 of 646 test files. A local full-suite run shows all five.

3. claude-md-repo-section-is-a-bullet-index — one over-long bullet

CLAUDE.md:151 ran 230 chars against the 200 cap. It stated two separate rules — the X.Y.Z-prerelease hint in package.json and the notes accruing under CHANGELOG's ## [Unreleased] — so it becomes two bullets, which is what the check asks for anyway ("one rule per bullet").

What this does not fix

The remaining two failures are cascade lag on fleet-canonical files, and the fixes already exist in the shared template. scripts/fleet is linguist-generated=true in this repo's .gitattributes — the marker the fleet fork guard reads — and every change to it in this repo's history arrived as a chore(wheelhouse): cascade template@<sha> commit. Hand-authoring a fix here would be a local fork that the next cascade overwrites.

check-registrations-resolve and commits-have-no-ai-attribution
  • check-registrations-resolve fails because scripts/fleet/check/tests-read-canonical-sources.mts is wired into no runner. The template already registers it, with a note that it no-ops cleanly in member repos that have no template/ tree. This repo's mirror predates that line.
  • commits-have-no-ai-attribution fails in CI for a shallow-clone reason. It cannot be fixed by fetching full history: with full history it finds 20 old, already-published commits carrying Co-authored-by: and 🤖 Generated with [Claude Code] tag lines. Rewriting published main history is out of scope. The template has already rewritten this check — its default scope now reads origin/<default> and drops every finding at or below the release boundary, with full history moved behind a new --all flag. That clears exactly this case.

Scope of the lag: 115 files differ between this repo's scripts/fleet and the template's copy. The last cascade in was template@79a0d8d03; the template is now at template@f6cf95d3c.

Judgment calls

The comment restructuring. The rule's own message says to keep the constraint at the code and move the discussion into a doc behind a one-line pointer, so that is what the cdxgen --help dump got — docs/references/repo/cdxgen-flags.md, next to the existing repo reference doc. Splitting a run at its existing paragraph breaks is not a dodge here: the rule already ends a block at a blank line specifically because that is how a reader sees them, and the split blocks are genuinely separate facts. Where a block was one long JSDoc, only @example bodies that restated the signature came out, with any fact unique to the example folded into @param or @returns.

compress-facts.mts looked like the one case worth an inline socket-lint: allow long-comment-block suppression — every paragraph is a distinct constraint a caller can break. That turned out to be impossible by design: no-malformed-bypass-marker requires the marker within 12 lines of the code it exempts, which a 29-line block cannot satisfy. So it was tightened instead, and all five constraints survive — why compression is streamed off-thread, why the .br is a sibling rather than a temp-dir path, that it adds no new race, and the mandatory cleanup(). No suppression was added anywhere in this PR.

Scoping the attribution check rather than unshallowing. Confirmed and left alone. Unshallowing swaps the shallow-clone failure for 20 findings in published history, and rewriting main is not on the table. Scoping is the right shape — and the template already implements it, with a release-boundary freeze that is better than the --unpushed narrowing I had been pointed at. That is why it belongs in a cascade rather than here.

Verification

Run locally against this branch:

  • pnpm run lint --allpasses, 0 errors (was 129 warnings / 18 errors).
  • pnpm run test → 7533 passed, 625 of 646 files. The single failure is constants.test.mts asserting rootPath contains socket-cli, which is false only because the verification worktree is not named that. It passes in CI and in a normal checkout. That test is coupled to the checkout directory name, which is worth fixing separately.
  • pnpm run check --alllint.mts and claude-md-repo-section-is-a-bullet-index.mts now pass. Still failing: the two cascade-lag checks above, plus dispatch-table-is-current and path-tools-are-at-pinned-version, which are local-environment artifacts and did not fail in CI.

Note

Low Risk
Comment/doc/test-only changes plus a reference doc move; no runtime behavior changes except corrected test mocks aligned with existing spawnCoanaDlx arity.

Overview
Clears three independent main failures in repo-owned code: the max-comment-block-lines lint rule, reachability unit tests, and the CLAUDE.md bullet-length check.

Lint (18 errors, 14 files) — Long comment/JSDoc blocks are shortened or relocated without disabling the rule. The pasted cdxgen 11.2.7 --help text moves from cmd-manifest-cdxgen.mts to docs/references/repo/cdxgen-flags.md, with a one-line pointer in source. Other sites are split at paragraph breaks, trimmed to the API contract, or rewritten where prior reflow damaged docs (e.g. npm-packages.mts bogus @cyclonedx tag; dlx/vfs-extract.mts docblock moved onto extractExternalTools).

Tests — Five assertions in perform-reachability-analysis*.test.mts read spawnCoanaDlx options at mock.calls[0][2]; production passes options at index 1, so they now match (coanaArgs, { … }).

DocsCLAUDE.md v1.x release bullet is split into two bullets (prerelease hint vs CHANGELOG ## [Unreleased]) to satisfy the 200-character cap.

Does not fix cascade-lag fleet checks (check-registrations-resolve, commits-have-no-ai-attribution) on main.

Reviewed by Cursor Bugbot for commit b03b5fb. Configure here.

…1 more (4 files)

- packages/cli/src/commands/ask: handle-ask.mts
- packages/cli/src/commands/repository: cmd-repository-list.mts
- packages/cli/src/commands/scan: cmd-scan-github.mts
- packages/cli/src/util/dry-run: output.mts
Cascaded from socket-wheelhouse. The type-aware pass builds
scripts/**/*.mts a DEFAULT program (no strict tsconfig discoverable
above scripts/), dropping noUncheckedIndexedAccess and false-flagging
the fleet-mandated cached-for-loop `arr[i]!` assertions as unnecessary
— reddening 🔎 Check on scripts/repo/stage-publish-cli-exe.mts and
scripts/repo/output-purls-shallow-score.mts.
Bring the fleet-canonical single-registry taze fix to socket-cli, mirroring
socket-sdk-js. taze resolves versions through fast-npm-meta's hosted endpoint
(npm.antfu.dev) by default, which fleet egress policy blocks — every lookup
times out yet taze still exits 0, a false green that silently skips the
update check. The pnpm patch drops the default-registry fast path in
getVersionsForContext so all version lookups stay on the configured registry.

- patches/taze@19.16.0.patch + patchedDependencies entry (patch_hash matches
  the fleet catalog / sdk: 77208c02...)
- scripts/fleet/check/taze-is-single-registry.mts guard, registered in the
  paths/supply-chain check steps: forbids the vetoed host in any tracked file
  and enforces taze pin <-> patch <-> patchedDependencies parity
- reword the npm.antfu.dev references in update.mts / taze-output.mts (the
  host is no longer where lookups go once patched)

Supersedes the forbidden npm.antfu.dev egress-allowlist approach (PR #1429),
which the fleet bans via the taze-is-single-registry guard.
The `socket ci` integration test hardcoded `branchName: "main"` in its
dry-run inline snapshot. The CLI resolves the branch from the ambient git
checkout (`git symbolic-ref`) or the CI env (GITHUB_HEAD_REF /
GITHUB_REF_NAME), so the emitted value is whatever branch the test runs
on. It only matched on a `main` push; on EVERY non-main PR the received
value was the PR head branch and the snapshot mismatched — reddening the
Test check across all open socket-cli PRs.

Fix at the snapshot-scrubber boundary, alongside the existing [PROJECT] /
[TIMESTAMP] / [UUID] normalizations: scrubSnapshotData now pins the
human-readable `branchName: "…"` details line to `branchName: "[BRANCH]"`
(new `branches` option, default true; only matches the details form, not
JSON `"branchName":"…"`). Snapshot updated to `[BRANCH]`.

The branch-resolution behavior itself stays covered by the unit specs
that mock `gitBranch` (handle-ci / cmd-ci unit tests assert
'develop'/'feature-branch'/'(default)'), so no real coverage is lost.

Proof: on branch `fix/cmd-ci-branch-snapshot` the raw CLI emits
`branchName: "fix/cmd-ci-branch-snapshot"` (would fail the old snapshot);
with the scrub, `vitest run --config vitest.integration.config.mts
test/integration/cli/cmd-ci.test.mts` passes (2/2). Added 5 scrubber unit
tests (main / slashed feature branch / detached-HEAD hash / JSON-form
left intact / disabled) — 35/35 pass.
…arn (#1432)

The safe-npm FAQ historically said install-time protection was npm-only,
while older READMEs mentioned pnpm/yarn wrapping — a documented
inconsistency (#999). The CLI now routes `socket npm`, `socket pnpm`, and
`socket yarn` through Socket Firewall, so all three block malicious
packages before install.

Spell this out in the README Usage section so the supported package
managers are unambiguous.

Refs #999
…ort map, coverage badge) (#1437)

* fix: repoint moved fleet script paths and wire lockstep:emit-mirror-globs

The scripts/repo migration moved check.mts and update.mts into
scripts/fleet/, but packages/cli/package.json still pointed its
"check" and "update" scripts at the old ../../scripts/*.mts paths,
failing check-script-paths-resolve.

The lockstep-emit-mirror-globs.mts script cascaded in (and its sibling
lockstep:emit-schema is wired), but the root package.json never got the
matching lockstep:emit-mirror-globs alias, so the updating-lockstep skill
docs cited a pnpm script that did not resolve, failing
check-pnpm-run-citations-resolve.

- packages/cli/package.json: check -> ../../scripts/fleet/check.mts
- packages/cli/package.json: update -> ../../scripts/fleet/update.mts
- package.json: add lockstep:emit-mirror-globs pointing at the existing
  scripts/fleet/lockstep-emit-mirror-globs.mts shim

* fix: green remaining 🔎 Check residuals (action port map + coverage badge)

Two fleet-drift 🔎 Check failures on main, independent of the
script-path/citation fix:

- action-ports-are-lock-stepped: the setup-go-toolchain composite had
  no port-map entry. Its action.yml states it is "written inline so we
  don't depend on a third-party action" and only borrows actions/setup-go's
  generic fallback ordering, porting neither its input surface nor its
  go.dev/dl download algorithm — so it is Socket-original (`[]`), not a
  lock-stepped port.

- coverage-badge-is-current: the README carried a shields.io badge with a
  decimal percent (coverage-75.08%25) that the migrator's integer-only
  matcher could not recognize, tripping the unrecognized-form gate.
  Repointed to the canonical repo-local asset badges/coverage.svg (the
  generated placeholder SVG already exists and is tracked).
`socket package shallow` (and `socket package score`) dropped the
package namespace when rendering the report card purl, so a scoped npm
package like `@axe-core/react` was printed as `pkg:npm/react@4.11.0`.
The informational log line already showed the correct purl, making the
mismatch confusing.

formatReportCard() rebuilt the purl from ecosystem/name/version but
omitted the namespace segment that preProcess() already tracks on the
deduped artifact. Add the namespace back, mirroring how preProcess and
the deep-score renderer construct purls.

Adds a focused regression test for the scoped-npm case and updates the
Go shallow snapshots (which now correctly show the module namespace).

Fixes #971
The transitive section of `socket package score --markdown` emitted
`### Capabilities` twice. The first was mislabeled: its body lists the
lowest-scoring package per score category, not capabilities.

Rename that header to `### Lowest Scoring Package Per Category` so the
two sections are distinct and correctly labeled. Snapshots updated.

Fixes #1356
)

runAgentInstall set the child's NODE_OPTIONS to only our own Node flags
(harden / no-warnings / disable-sigusr1). A child process' NODE_OPTIONS
REPLACES the parent's rather than extending it, so any NODE_OPTIONS the
user configured globally was silently dropped when `socket optimize` ran
the package-manager install.

Merge the inherited process.env.NODE_OPTIONS ahead of our added flags via
a new pure `mergeNodeOptions` helper in util/process/cmd.mts, unit-tested
in isolation. The value is left unquoted (it is assigned to an env var,
not passed through a shell).

Same class of NODE_OPTIONS-clobber bug as the v1.x shadow-npm fix for
#1160/#1036, but a different code path: this is the `socket optimize`
agent installer on main, not the `socket npm` shadow wrapper. On main
`socket npm` hands off to Socket Firewall and no longer builds Node
flags itself, so this is the remaining place on main that needed it.
…, template sha bffd4a2dbc51699e097e1e2033fea7b4292176b3, 2236 files, assets: socket-wheelhouse-fleet-1.0.14.tar.gz + release-bundle-manifest.json)
Auto-applied by socket-wheelhouse sync-scaffolding into socket-cli.
21 file(s) touched:
  - scripts/fleet/_shared/cargo-workspaces.mts
  - scripts/fleet/_shared/check-steps-release.mts
  - scripts/fleet/_shared/github-raw-url.mts
  - scripts/fleet/check/coverage-badge-is-current.mts
  - scripts/fleet/check/fuzz-tiers-are-covered.mts
  - scripts/fleet/check/publish-entrypoints-are-fleet-composed.mts
  - scripts/fleet/constants/catalog-holds.mts
  - scripts/fleet/gen/api-md.mts
  - scripts/fleet/gen/coverage-badge.mts
  - scripts/fleet/gen/llms-txt.mts
  - scripts/fleet/lib/api-docs/export-rows.mts
  - scripts/fleet/lib/coverage-badge.mts
  - scripts/fleet/publish-infra/cargo/trusted-publisher.mts
  - scripts/fleet/publish-infra/npm/auth-posture.mts
  - scripts/fleet/publish-infra/npm/placeholder.mts
  - scripts/fleet/publish-infra/npm/publish-command.mts
  - scripts/fleet/publish-infra/npm/staged-workspace.mts
  - scripts/fleet/publish-infra/npm/staged.mts
  - scripts/fleet/publish-infra/pin-readme.mts
  - scripts/fleet/socket-wheelhouse-schema/docs.mts
  ... and 1 more
Auto-applied by socket-wheelhouse sync-scaffolding into socket-cli.
4 file(s) touched:
  - .config/fleet/pnpm-workspace.fleet.yaml
  - scripts/fleet/_shared/github-raw-url.mts
  - scripts/fleet/gen/coverage-badge.mts
  - scripts/fleet/lib/coverage-badge.mts
Auto-applied by socket-wheelhouse sync-scaffolding into socket-cli.
11 file(s) touched:
  - .claude/hooks/fleet/_shared/shell-command.mts
  - .config/fleet/pnpm-workspace.fleet.yaml
  - .config/repo/rolldown/engine-gate-fold.mts
  - CLAUDE.md
  - docs/agents.md/fleet/drift-watch.md
  - scripts/fleet/_shared/check-steps-paths.mts
  - scripts/fleet/_shared/run-main.mts
  - scripts/fleet/check/setup-is-prompt-less.mts
  - scripts/fleet/check/socket-pins-never-downgrade.mts
  - scripts/fleet/constants/catalog-holds.mts
  - scripts/fleet/lib/catalog-diff.mts
Auto-applied by socket-wheelhouse sync-scaffolding into socket-cli.
4 file(s) touched:
  - CLAUDE.md
  - docs/agents.md/fleet/drift-watch.md
  - scripts/fleet/_shared/check-steps-paths.mts
  - scripts/fleet/check/socket-pins-are-never-lowered.mts
Auto-applied by socket-wheelhouse sync-scaffolding into socket-cli.
9 file(s) touched:
  - .config/fleet/oxlint-plugin/fleet/max-comment-block-lines/index.mts
  - .config/fleet/oxlint-plugin/fleet/max-comment-block-lines/package.json
  - .config/fleet/oxlint-plugin/fleet/max-file-lines/index.mts
  - .config/fleet/oxlint-plugin/fleet/no-malformed-bypass-marker/index.mts
  - .config/fleet/oxlint-plugin/fleet/no-optional-positional-trap/index.mts
  - .config/fleet/oxlint-plugin/fleet/no-optional-positional-trap/package.json
  - .config/fleet/oxlint-plugin/index.mts
  - .config/fleet/oxlint-plugin/lib/comment-markers.mts
  - .config/fleet/oxlintrc.json
- packages/cli/src/util/dlx: spawn-coana.mts, spawn.mts
- packages/cli/test/unit/util/dlx: spawn-coana.test.mts
An agent working in this repo had nothing to go on: the v1.x branch's own
CLAUDE.md covers coding conventions but not the release, and main's did not
mention v1.x at all. Records who names the version, which actions stay human,
and what the burn rule costs.
Auto-applied by socket-wheelhouse sync-scaffolding into socket-cli.
149 file(s) touched:
  - .claude/hooks/fleet/_shared/ai-attribution.mts
  - .claude/hooks/fleet/_shared/ast/comments.mts
  - .claude/hooks/fleet/_shared/gh-invocation.mts
  - .claude/hooks/fleet/_shared/git-runner.mts
  - .claude/hooks/fleet/_shared/guard.mts
  - .claude/hooks/fleet/_shared/nested-strings.mts
  - .claude/hooks/fleet/_shared/squash-sentinel.mts
  - .claude/hooks/fleet/_shared/transcript.mts
  - .claude/hooks/fleet/_shared/untrusted-instruction.mts
  - .claude/hooks/fleet/anti-prose-guard/README.md
  - .claude/hooks/fleet/anti-prose-guard/index.mts
  - .claude/hooks/fleet/anti-prose-guard/patterns.mts
  - .claude/hooks/fleet/changelog-no-empty-guard/index.mts
  - .claude/hooks/fleet/claude-md-size-guard/index.mts
  - .claude/hooks/fleet/claude-segmentation-guard/index.mts
  - .claude/hooks/fleet/disowned-dirt-guard/README.md
  - .claude/hooks/fleet/disowned-dirt-guard/index.mts
  - .claude/hooks/fleet/dont-blame-nudge/README.md
  - .claude/hooks/fleet/dont-blame-nudge/index.mts
  - .claude/hooks/fleet/excuse-detector/index.mts
  ... and 129 more
v1.x is the line customers consume, so it owns `latest`; the default
branch carries the 2.x prerelease line and the fleet guard now refuses
`latest` there. Declared via release.latestDistTagBranch rather than
hard-coded, so every other member keeps defaulting to its default branch.

Without this, socket@latest sat on 1.1.147 while 1.1.148 through 1.1.152
published under a side tag no untagged install resolves.
…red matcher

The template no longer ships the standalone hook; convo-prose-nudge and
_shared/honesty-framing.mts carry the check.
Everything under scripts/ now sits in the fleet/repo split the rest of
the tree uses. Nothing imports either directory, so the move is inert;
whether they should exist at all is a separate call.
When `socket cdxgen` failed on a CI runner it could exit 1 and print
nothing at all: no error, no hint, no way to tell whether cdxgen was
never downloaded, never started, or ran and died.

The command armed `process.exitCode = 1` before starting cdxgen, then
handled only the signal and numeric-exit-code cases. There was no
`else`, so a child that reported neither left the armed 1 standing and
printed nothing. Because cdxgen is spawned with `stdio: 'inherit'`, a
rejected spawn also reached the top level with an empty stderr, leaving
the shared formatter nothing to attach beyond a generic line.

Every way out of the run now either exits with cdxgen's own code or
prints where the CLI looked for cdxgen and what to try next. A new
`util/dlx/cdxgen-diagnostics.mts` builds those messages so the command
and the spawn helper share one wording. `spawnCdxgenDlx` also checks
`SOCKET_CLI_CDXGEN_LOCAL_PATH` on disk before spawning, so a wrong path
says so instead of surfacing as a bare ENOENT that never names the
variable.

An `InputError` message is passed through untouched rather than nested
inside a second Where/Saw/Fix block, which previously produced an outer
`Fix:` telling the user to set the very variable they had already set.
The underlying error is logged via `debugNs('error', ...)` so the
message's advice to re-run with `SOCKET_CLI_DEBUG=1` leads somewhere.

The successful path is unchanged: cdxgen's output still streams through
and its exit code is still forwarded exactly as before.

Refs SURF-1045.
The default `socket scan report` output went through `logger.dir()`,
Node's object inspector. In a CI log that printed a raw JavaScript
object with nested maps rendered literally, like

  alerts: Map(1) { 'npm' => Map(2) { 'acme-widget' => Map(1) { ... } } }

which is hard to read in a log viewer and looks nothing like the report
the Socket GitHub App posts on a pull request.

The default text path now renders a plain-text report with labelled
sections and space-padded columns. It stays ASCII-only with no colour
and no box-drawing, because a build log may be piped to a file,
replayed without a TTY, or ingested by a log aggregator, where an
uninterpreted escape code shows up as literal noise and a non-ASCII
glyph can render as a replacement box. Each alert's URL goes on its own
indented line so a long URL cannot stretch every row past a readable
width.

`logger.dir` appeared exactly once in the whole CLI, at this call site;
every other output path already builds a string and passes it to
`logger.log`, so this brings the last outlier into line.

The new `toPlainTextReport` sits beside `toJsonReport` and
`toMarkdownReport`, and all three now read their rows from one new
`flattenReportAlerts` helper. The markdown renderer previously did that
nested-map walk inline, so sharing it means the two formats cannot
drift apart in what they show.

Only the default text output changes. The `--json`, `--markdown`, and
`--short` outputs are untouched, so anything parsing this command keeps
working as before.

Refs ASK-302.
The maven-extension jar build invoked the bundled Maven wrapper with no
repository override, so every run downloaded the plugin and dependency
closure into the developer's ~/.m2/repository and the Maven distribution
into ~/.m2/wrapper/dists.

Point both at a stable directory under the OS temp dir instead. The
path is stable rather than per-run so the closure stays cached between
builds; SOCKET_CLI_MAVEN_HOME overrides it for a genuinely cold build.

Resolve that directory to an absolute path before use. Maven runs from a
subshell that cds into the extension directory, so a relative
SOCKET_CLI_MAVEN_HOME or TMPDIR would have created one tree at the
caller's cwd and then written a second one under the extension
directory.
The maven-compat smoke fixture declared commons-io, junit and hamcrest
as real artifacts from Maven Central purely to get a graph shape: an
external prod dep, a test-scope dep and its transitive. No fixture code
imports them, so they were never compiled against or executed - but they
still aged into GHSA-78wr-2p64-hpwj, a Dependabot alert, and a version
bump.

gradle-compat already solved this: make-localrepo.sh generated a tiny
file-based Maven repo of empty-jar stubs at test time. That generator
moves up a directory to test/make-stub-repo.sh, gains the ability to
give a stub its own dependency, and now serves all three fixtures.
maven-compat resolves demo.ext:tool (prod), demo.ext:harness (test) and
its transitive demo.ext:harness-core through a <repository> whose URL
smoke-test.sh passes as -Dstub.repo.url; sbt-compat resolves
demo.ext:tool and demo.ext:harness the same way.

The suites also stop using the developer's home caches.
compat-cache.sh resolves one cache root under the temp dir, overridable
by SOCKET_COMPAT_CACHE, and each tool is pointed at it: Maven by
-Dmaven.repo.local, Gradle by -g, sbt by -Dsbt.ivy.home and
COURSIER_CACHE. The root is stable so each tool's own closure is
downloaded once, but the stub artifacts are evicted before every run, so
a run can never pass on a stale copy of the thing under test. Nothing is
read from or written to ~/.m2, ~/.gradle or ~/.ivy2, and records.tsv no
longer embeds a path under the developer's home.

Assertions prove exactly what they proved before, still matching on
groupId:artifactId with no version written in any test, and still keying
on the .jar suffix rather than any path. The transitive check is now
unconditional: with a stub graph it is deterministic, so its absence is
a defect rather than a junit-version detail.

The internal reactor module's lookup now pins the field count as well as
the prefix. 'demo:lib:' is a prefix of the typed 'demo:lib:jar:1.0' as
well as the bare 'demo:lib:1.0', so on the prefix alone a regression
that stopped emitting the bare id would still have passed a check whose
message claims bare-id coverage.

maven-compat's first assertion block moves out of its heredoc into
assert-records.py, so the unit suite can run those assertions over
synthetic records without Maven or a JDK. Nothing in CI runs the compat
fixtures, so that unit test is the only automated cover the assertions
have.

Each build tool still fetches its own closure from Central - Maven's
plugins pull commons-io themselves - so this is not a fully offline
fixture. It declares no third-party dependency of its own.
main's CI has been red on three repo-owned causes since before
today's merges. All three are pre-existing; none came from a
recent PR.

The lint check reported 18 max-comment-block-lines errors across
14 files, from a newly cascaded 20-line cap on inline comment
blocks. Each is restructured on its own merits rather than
suppressed:

- The ~70 lines of pasted `cdxgen --help` output move to
  docs/references/repo/cdxgen-flags.md, leaving a one-line
  pointer above the yargs config it documents. The version in
  the heading is the point of keeping it at all.
- Comment runs holding several independent facts are split at
  the paragraph boundaries a reader already sees: the bazel
  exit-code taxonomy, the python directory layouts, and the
  meow flag-type mapping.
- Two docblocks had been shredded by an earlier JSDoc reflow.
  npm-packages.mts lost its archive tree into a bogus
  `@cyclonedx` tag; both are rewritten as prose that says the
  same thing.
- vfs-extract.mts had extractExternalTools' docblock stranded
  above MAX_EXTRACTION_DEPTH instead of above the function; it
  now sits on the function it documents.
- The rest keep their contract and drop @example blocks that
  only restated the signature, folding any fact unique to the
  example into @param or @returns.

Two unit test files read the options bag at argument index 2,
but spawnCoanaDlx is called with two arguments, so every read
was undefined and threw on property access. Production is
correct; the tests move to index 1. Five assertions across
perform-reachability-analysis.test.mts and its -coana sibling.
Only one surfaced in CI because the Test job shards.

CLAUDE.md's releasing-v1x section had one 230-char bullet
against the 200 cap. It stated two rules — the prerelease hint
and the CHANGELOG section — so it becomes two bullets.
John-David Dalton (jdalton) added a commit that referenced this pull request Aug 5, 2026
A true merge of jdalton/fix-main-ci carries 174 unsigned commits from the
old-main lineage, which the required-signatures rule refuses. This lands the
identical resolved tree — the CI-gate fixes plus the old-main work the
consolidation missed (JVM fixture stubs, Maven build isolation, cdxgen
failure reporting, plain-text scan report) — as a single signed commit.
@jdalton

Copy link
Copy Markdown
Collaborator Author

Landed on main as b513b7c — the resolved tree carries this branch's CI-gate fixes plus the old-main work (JVM fixture stubs, Maven build isolation, cdxgen failure reporting, plain-text scan report) as one signed commit; a true merge was refused by the required-signatures rule over the branch's 174 unsigned lineage commits.

John-David Dalton (jdalton) added a commit that referenced this pull request Aug 5, 2026
A true merge of jdalton/fix-main-ci carries 174 unsigned commits from the
old-main lineage, which the required-signatures rule refuses. This lands the
identical resolved tree — the CI-gate fixes plus the old-main work the
consolidation missed (JVM fixture stubs, Maven build isolation, cdxgen
failure reporting, plain-text scan report) — as a single signed commit.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant