Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1 +1,12 @@
docs/benchmarks/suite/isolation/.claude/CLAUDE.md text eol=lf

# The qualification contract is frozen by SHA-256 over raw file bytes
# (docs/qualification/freeze.json). A CRLF checkout would change those bytes and
# break the freeze on Windows, so the whole tree is pinned to LF in the working
# copy on every platform. Do not relax this to make a platform failure disappear:
# the freeze is meaningful precisely because it is byte-exact.
docs/qualification/** text eol=lf

# Seeded-defect patches must reach `git apply` byte-for-byte, so they are marked
# non-text and are never line-ending converted in either direction.
docs/qualification/patches/*.patch -text
46 changes: 46 additions & 0 deletions .github/scripts/lib/collect-cited-paths.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
'use strict'

/**
* The single definition of "which paths does a truth file cite".
*
* It lives here, in CommonJS, because both consumers need it and they cannot share an
* ESM module: `.github/scripts/validate-qualification-contract.mjs` is ESM, and
* `tests/unit/qualification-contract.test.ts` is TypeScript compiled without `allowJs`,
* so it reaches this file through `createRequire`. Node imports CommonJS from ESM
* natively, so the validator can import it directly.
*
* Both consumers previously carried their own copy of this traversal, including the
* `new_path` exemption. A change to the exemption in one copy would have left the other
* enforcing the old rule, and the test would have stopped covering the shipped guard
* while still passing.
*
* `new_path` is exempt because a plan task proposes creating files that do not exist at
* the pinned commit, so they cannot appear in the target's frozen blob manifest.
*
* @param {unknown} node - any subtree of a parsed truth file
* @returns {Set<string>} every value recorded under a `path` key, at any depth
*/
function collectCitedPaths(node) {
const cited = new Set()

const walk = (value) => {
if (Array.isArray(value)) {
value.forEach(walk)
return
}
if (value && typeof value === 'object') {
for (const [key, child] of Object.entries(value)) {
if (key === 'path' && typeof child === 'string') {
cited.add(child)
} else if (key !== 'new_path') {
walk(child)
}
}
}
}

walk(node)
return cited
}

module.exports = { collectCitedPaths }
Loading
Loading