Found while building the scripts/pm/git-history.mjs helper for #9878. Reported, not fixed — #9878's dispatch scoped the census to "report them, do not fix them all".
The census
37 pre-existing history-reading call sites across 17 files in scripts/ and .github/workflows/, classified by what a shallow clone does to each:
| class | count | behaviour on a shallow clone |
|---|
| windowed date questions over a branch | 3 | silently wrong — real, plausible, exit 0, no warning |
| files already carrying an explicit shallow guard | 6 files | refuse or repair |
| range / merge-base questions | the rest | fail loudly, or degrade visibly to ? |
The sharpest result: CI is not the exposure, the agent container is
All seven workflows that ask history questions check out with fetch-depth: 0. Every remaining exposure is in seat-run tooling — run by an agent, in a shallow container:
scripts/pm/check-governed-merges.mjs:443 — git log --first-parent --since=(iso) (ref) enumerates governed merges in a window. CI runs only its --self-test; the real enumeration is a PM-seat command. Under-enumeration reads as compliance, which is the worst direction for this particular tool to be wrong in.scripts/check-engine-split-ratio.mjs:63 — the ADR-0076 D7 repo-split trigger metric. Its own workflow is fetch-depth: 0, so the scheduled run is fine; a seat running it locally gets a truncated window. Worse, total === 0 ? 0 turns an empty scan into a healthy-looking 0.0% ratio.scripts/collect-release-notes.sh:120 — --since/--until over the cloud checkout. It has no workflow caller at all; it runs at release time, from a seat.
Why this is worth a card rather than a note
The six already-guarded files include #9555's and #9408's fixes. So the repo has been closing this family one instance at a time, and the census says three are left — all in tooling whose output is evidence (compliance enumeration, an ADR trigger metric, release notes).
The remedy now exists and is one line each: scripts/pm/git-history.mjs (landing for #9878) proves window coverage, deepens only when the shallow floor intrudes, re-proves, and otherwise refuses with an empty stdout so a captured number is empty rather than plausible.
Related: #9878 (the helper and the full census) · #9555 · #9408
Generated by Claude Code
Found while building the
scripts/pm/git-history.mjshelper for #9878. Reported, not fixed — #9878's dispatch scoped the census to "report them, do not fix them all".The census
37 pre-existing history-reading call sites across 17 files in
scripts/and.github/workflows/, classified by what a shallow clone does to each:?The sharpest result: CI is not the exposure, the agent container is
All seven workflows that ask history questions check out with
fetch-depth: 0. Every remaining exposure is in seat-run tooling — run by an agent, in a shallow container:scripts/pm/check-governed-merges.mjs:443—git log --first-parent --since=(iso) (ref)enumerates governed merges in a window. CI runs only its--self-test; the real enumeration is a PM-seat command. Under-enumeration reads as compliance, which is the worst direction for this particular tool to be wrong in.scripts/check-engine-split-ratio.mjs:63— the ADR-0076 D7 repo-split trigger metric. Its own workflow isfetch-depth: 0, so the scheduled run is fine; a seat running it locally gets a truncated window. Worse,total === 0 ? 0turns an empty scan into a healthy-looking 0.0% ratio.scripts/collect-release-notes.sh:120—--since/--untilover the cloud checkout. It has no workflow caller at all; it runs at release time, from a seat.Why this is worth a card rather than a note
The six already-guarded files include #9555's and #9408's fixes. So the repo has been closing this family one instance at a time, and the census says three are left — all in tooling whose output is evidence (compliance enumeration, an ADR trigger metric, release notes).
The remedy now exists and is one line each:
scripts/pm/git-history.mjs(landing for #9878) proves window coverage, deepens only when the shallow floor intrudes, re-proves, and otherwise refuses with an empty stdout so a captured number is empty rather than plausible.Related: #9878 (the helper and the full census) · #9555 · #9408
Generated by Claude Code