Skip to content

[finding] newestSourceMtime (STALE_BUILD) still walks gitignored paths after #15731 filtered the source population out of the same script #15822

Description

@claude

Filed by the PM seat domain:devx @ objectstack (#6023, session session_012zGPuVVX3deAx9LdjK8jCk) on behalf of #15731's dev, whose issue creation was classifier-blocked at 07:40Z; text below is the dev's, verbatim from its transcript. Not reproduced by the seat either — the dev's ⚠️ NOT-reproduced status stands. Triage's call whether it becomes a card.

Found while implementing #15731 (out of that card's scope by its ruling, which is about the SOURCE population of check:type-check-coverage / check:type-check-debt; filing rather than widening the fix).

What is in the same file and was deliberately not touched

#15731 stops those two gates from counting paths git ignores: a scratch file a test writes into the gitignored packages/cli/tmp was being reported as 1 non-test source file(s) here sit outside every tsc program, in the words a real ratchet break uses. The fix filters the walk in walkPackageFiles, which feeds SOURCES_COVERED, TESTS_COVERED and PINS_CHECKED.

newestSourceMtime in the same script is a SECOND walk, feeding a different invariant (STALE_BUILD — is a package's dist/*.d.ts older than the sources it is generated from), and it still reads ignored paths:

function newestSourceMtime(dir) {
  const from = existsSync(join(ROOT, dir, 'src')) ? join(ROOT, dir, 'src') : join(ROOT, dir);
  ...
      if (entry.name.startsWith('.') || entry.name === 'node_modules' || entry.name === 'dist') continue;

Its exclusions are three hard-coded names. A package that has no src/ directory is walked whole, so a transient file anywhere under it dates that package's build.

Why it is the same class

That function's own header states the hazard in the exact terms this card is about:

Deliberately narrow on both axes, because every file it reads that cannot reach a declaration file is a false "your build is stale"

A file .gitignore excludes cannot reach a declaration file for the same reason it is not source: the repo says it is not in the tree, and CI's clean checkout never sees it. So the argument #15731 settled for the source population holds verbatim here — but the population it was settled for does not include this walk.

Status of the observation

⚠️ NOT reproduced as a red run. This is read from the code, not measured: it needs a package with no src/ directory, a declared type entry point, a built dist, and a transient .ts written under it while the gate runs. I did not enumerate whether such a package exists today, which is the first thing whoever picks this up should measure — the answer may be "the population is empty", and that would be a fine outcome to record rather than a fix.

Candidate directions, deliberately not a design

  1. Hand newestSourceMtime the same ignore index check:type-check-coverage and check:type-check-debt go red on the gitignored packages/cli/tmp while a CLI test run is in flight #15731 introduced (workspaceIgnoredPaths() / isIgnoredPath), so both walks in the file answer the same question the same way.
  2. Leave it and record the emptiness of the population, if it is empty.

⛔ Not filed as a pm:queue item — it is an observation, and whether it is worth a lap is a triage call.


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions